* Error-names. @ 2004-02-28 12:58 Martin Klaiber 2004-02-28 13:35 ` Error-names Martin Dowie ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Martin Klaiber @ 2004-02-28 12:58 UTC (permalink / raw) Hi, this is not really a programming-problem (I hope), more a question about english terms. I write a library with an interface to C. The Ada-exceptions shall be turned into return-values for the C-functions. Like this: with Interfaces.C; package Something is -- Types: type C_Integer is new Interfaces.C.int; -- Exceptions and errors: General_Error : C_Integer := -1; Routine_Not_Defined : exception; Routine_Not_Defined_Error : C_Integer := -2; and so on... package body Something is function Do_Something return C_Integer is begin ... return 0; exception when Routine_Not_Defined => return Routine_Not_Defined_Error; when others => return General_Error; end Do_Something; end Something; My problem now is that I also want to define return values for exceptions like Constraint_Error. But I can't define something like: Constraint_Error : C_Integer := -3; as Constraint_Error is the name for the exception. And I don't want to use long names like: 'Routine_Not_Defined_Error_Constant' or similar. I also don't want to rename the exceptions, as other Ada-Programs might rely on them. Is there an english word instead of 'error' I could use? Like 'fault' for instance or 'mistake'? Constraint_Fault, Constraint_Mistake. Hm, sounds strange to me. Would it be alright though? Thanks a lot, Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 12:58 Error-names Martin Klaiber @ 2004-02-28 13:35 ` Martin Dowie 2004-02-28 15:26 ` Error-names Martin Klaiber 2004-02-28 18:29 ` Error-names Alexandre E. Kopilovitch 2004-02-29 5:30 ` Error-names David Marceau 2 siblings, 1 reply; 25+ messages in thread From: Martin Dowie @ 2004-02-28 13:35 UTC (permalink / raw) > My problem now is that I also want to define return values for > exceptions like Constraint_Error. But I can't define something like: > > Constraint_Error : C_Integer := -3; You could change all the names round e.g. Error_Constraint Error_Routine_Not_Defined. etc. -- Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 13:35 ` Error-names Martin Dowie @ 2004-02-28 15:26 ` Martin Klaiber 2004-02-28 17:19 ` Error-names Marius Amado Alves 0 siblings, 1 reply; 25+ messages in thread From: Martin Klaiber @ 2004-02-28 15:26 UTC (permalink / raw) Martin Dowie <martin.dowie@btopenworld.com> wrote: >> My problem now is that I also want to define return values for >> exceptions like Constraint_Error. But I can't define something like: >> Constraint_Error : C_Integer := -3; > You could change all the names round e.g. > Error_Constraint > Error_Routine_Not_Defined. > etc. I was also thinking of that. But the last one could be misunderstood as: there is an error-routine not defined (IMHO). Perhaps I rename the 'Constraint'-part instead and call the constant 'Range_Error' or so. BTW: is there a way to handle all exceptions in one place? I have many functions (about 20 or more, they all set or get parameters) which all need this exception-handling. I was trying a solution like: function Handle_Exceptions return C_Integer is begin return 0; exception when Some_Exception => return Some_Exception_Error; when ... when ... when others => return General_Error; end Handle_Exceptions; function Set_Something return C_Integer is begin ... -- set the parameter return 0; exception when others => return Handle_Exceptions; raise; end Set_Something; and so on with all the other set- and get-functions. But I get a warning that 'raise' is unreachable code and when I try it out, it looks like the exception is really not re-raised. Thx, Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 15:26 ` Error-names Martin Klaiber @ 2004-02-28 17:19 ` Marius Amado Alves 2004-02-28 18:31 ` Error-names Martin Klaiber 0 siblings, 1 reply; 25+ messages in thread From: Marius Amado Alves @ 2004-02-28 17:19 UTC (permalink / raw) To: comp.lang.ada Martin, First, embrace long names. The standard C expression is (I think) "error code", so go on and just write Constraint_Error_Code, General_Error_Code, etc. Second, I'm not sure I understand your tentative code but maybe I understand what you want. You want to handle all exceptions in one place, the handling being returning the corresponding error code. Well, the place has to be in a function that contains all the calls that may raise the exceptions: function Main return Error_Code_Type is -- exception-raising calls here exception when E : others => return Error_Code_Of (E); end; Now you only have to implement Error_Code_Of. (Ain't top-down design great? ;-) The 'trick' you could be missing is the "E : others" construct above. E is the exception occurence. From it you can go to the exception name. See package Ada.Exceptions--or, better yet, section 11.4 of the ARM. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 17:19 ` Error-names Marius Amado Alves @ 2004-02-28 18:31 ` Martin Klaiber 2004-02-28 19:47 ` Error-names tmoran 2004-02-28 20:26 ` Error-names Jacob Sparre Andersen 0 siblings, 2 replies; 25+ messages in thread From: Martin Klaiber @ 2004-02-28 18:31 UTC (permalink / raw) Marius Amado Alves <amado.alves@netcabo.pt> wrote: > First, embrace long names. The standard C expression is (I think) "error > code", so go on and just write Constraint_Error_Code, General_Error_Code, etc. Hey, thanks, that sounds good. > Second, I'm not sure I understand your tentative code Well, in reality it's a library to calculate income tax, which is, of course written in Ada but shall get a C-Interface now. The 'problem' is that I have loads of procedures and functions to set and get the parameters (just counted, it's 35), but not all of them are valid for every year, etc. So I need return-values for the C-Interface, as C doesn't understand the Ada-exceptions. > but maybe I understand what you want. You want to handle all > exceptions in one place, the handling being returning the > corresponding error code. Yes, because I have about 5 or more exceptions which I want to convert into a return-value and everyone of the 35 functions needs this. I am not concerned about the writing but it's easy to make mistakes (later for instance, when new code is added) if so much code is just repeated. So, what I have now is like this: function Set_Parameter_A (A : A_Type) return C_Integer is begin ... -- set the parameter return 0; -- if the setting was ok. exception -- if the parameter is not defined for this year: when Not_Defined => return Not_Defined_Error; -- if the parameter is out of range which is also year-dependent: when Out_Of_Range => return Out_Of_Range_Error; -- if something else went wrong setting the parameter: when Constraint_Error => return Constraint_Error_Code; ... and so on. when others => return General_Error; end Set_Parameter_A; Well, and the same for Set_Parameter_B, and so on, 35 times :-( Ok, I could just copy and paste but I don't like the idea really. Well, in reality the functions have names like Set_ALTER1, Set_HINZUR or Set_RE4 but this should not be important here. The obscure names are the official names from the tax-laws. > Well, the place has to be in a function that contains all the calls that may > raise the exceptions: > function Main return Error_Code_Type is > -- exception-raising calls here > exception > when E : others => return Error_Code_Of (E); > end; > Now you only have to implement Error_Code_Of. > (Ain't top-down design great? ;-) > The 'trick' you could be missing is the "E : others" construct above. E is > the exception occurence. From it you can go to the exception name. See > package Ada.Exceptions--or, better yet, section 11.4 of the ARM. Well, if I understand it right, I still have to distinguish between the different exceptions before I call Error_Code_Of, is this right? Like this (assume I have 5 exceptions A to E): function Main return Error_Code_Type is -- exception-raising calls here exception when A : others => return Error_Code_Of (A); when B : others => return Error_Code_Of (B); when C : others => return Error_Code_Of (C); when D : others => return Error_Code_Of (D); when E : others => return Error_Code_Of (E); end; But now, how does, for instance, Set_Parameter_A does get the return value from Main? Calling function Set_Parameter_A... begin ... exception when others => return Main; raise; end Set... doesn't work, as I already mentioned. Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 18:31 ` Error-names Martin Klaiber @ 2004-02-28 19:47 ` tmoran 2004-02-28 20:29 ` Error-names Martin Klaiber 2004-02-29 19:03 ` Error-names Jeffrey Carter 2004-02-28 20:26 ` Error-names Jacob Sparre Andersen 1 sibling, 2 replies; 25+ messages in thread From: tmoran @ 2004-02-28 19:47 UTC (permalink / raw) >Well, if I understand it right, I still have to distinguish between >the different exceptions before I call Error_Code_Of, is this right? No. > > when E : others => return Error_Code_Of (E); works fine. subtype Exception_Codes is Interfaces.C.Int range -10 .. 1; Coded_Exception_List : constant array(Exception_Codes) := (Constraint_Error'Identity, Program_Error'Identity, Storage_Error'Identity, Tasking_Error'Identity, Ada.IO_Exceptions.Status_Error'Identity, Ada.IO_Exceptions.Mode_Error'Identity, Ada.IO_Exceptions.Name_Error'Identity, ... function Error_Code_Of(E : Ada.Exceptions.Exception_Occurrence) return Exception_Codes is use Ada.Exceptions; begin for i in Coded_Exception_List'range loop if Exception_Identity(E) = Coded_Exception_List(i) then return i; end if; end loop; raise; -- we have no code for this exception! re-raise it end Error_Code_Of; then function Set_Parameter_A... return Interfaces.C.Int is begin ... return ... -- return legitimate, non-exception, result exception when E : others => return Error_Code_Of(E); -- return exception code end Set... ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 19:47 ` Error-names tmoran @ 2004-02-28 20:29 ` Martin Klaiber 2004-02-29 19:03 ` Error-names Jeffrey Carter 1 sibling, 0 replies; 25+ messages in thread From: Martin Klaiber @ 2004-02-28 20:29 UTC (permalink / raw) tmoran@acm.org wrote: >>> when E : others => return Error_Code_Of (E); > works fine. [code] Oh yes, this is great. Thank's a lot! Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 19:47 ` Error-names tmoran 2004-02-28 20:29 ` Error-names Martin Klaiber @ 2004-02-29 19:03 ` Jeffrey Carter 2004-02-29 20:04 ` Error-names tmoran 2004-02-29 20:33 ` Error-names Martin Klaiber 1 sibling, 2 replies; 25+ messages in thread From: Jeffrey Carter @ 2004-02-29 19:03 UTC (permalink / raw) tmoran@acm.org wrote: > > subtype Exception_Codes is Interfaces.C.Int range -10 .. 1; > > Coded_Exception_List : constant array(Exception_Codes) > := (Constraint_Error'Identity, > Program_Error'Identity, > Storage_Error'Identity, > Tasking_Error'Identity, > Ada.IO_Exceptions.Status_Error'Identity, > Ada.IO_Exceptions.Mode_Error'Identity, > Ada.IO_Exceptions.Name_Error'Identity, > ... > > function Error_Code_Of(E : Ada.Exceptions.Exception_Occurrence) > return Exception_Codes is > use Ada.Exceptions; > begin > for i in Coded_Exception_List'range loop > if Exception_Identity(E) = Coded_Exception_List(i) then > return i; > end if; > end loop; > raise; -- we have no code for this exception! re-raise it > end Error_Code_Of; This is pretty much what I would have suggested if Moran hadn't beat me to it. However, I think you can't use "raise" here without an exception name, since we're not necessarily in an exception handler. You could use Ada.Exceptions.Raise_Exception (E), but I suspect what is really wanted, based on the OP's earlier messages, is to return General_Error_Code. -- Jeff Carter "No one is to stone anyone until I blow this whistle, do you understand? Even--and I want to make this absolutely clear--even if they do say, 'Jehova.'" Monty Python's Life of Brian 74 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 19:03 ` Error-names Jeffrey Carter @ 2004-02-29 20:04 ` tmoran 2004-02-29 23:24 ` Error-names Björn Persson 2004-02-29 20:33 ` Error-names Martin Klaiber 1 sibling, 1 reply; 25+ messages in thread From: tmoran @ 2004-02-29 20:04 UTC (permalink / raw) > > raise; -- we have no code for this exception! re-raise it > However, I think you can't use "raise" here without an exception > name, since we're not necessarily in an exception handler. You could use > Ada.Exceptions.Raise_Exception (E), Oops. Yes. > but I suspect what is really wanted, > based on the OP's earlier messages, is to return General_Error_Code. Agreed. And this was hasty: > > subtype Exception_Codes is Interfaces.C.Int range -10 .. 1; > > > > Coded_Exception_List : constant array(Exception_Codes) > > := (Constraint_Error'Identity, > > Program_Error'Identity, > > Storage_Error'Identity, it should have been subtype Exception_Codes is Interfaces.C.Int range -10 .. -1; Constraint_Error_Code : constant Exception_Codes := -10; Program_Error_Code : constant Exception_Codes := -9; Storage_Error_Code : constant Exception_Codes := -8; ... Coded_Exception_List : constant array(Exception_Codes) := (Constraint_Error_Code => Constraint_Error'Identity, Program_Error_Code => Program_Error'Identity, Storage_Error_Code => Storage_Error'Identity, ... so the compiler can confirm one, and only one, value for each error code. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 20:04 ` Error-names tmoran @ 2004-02-29 23:24 ` Björn Persson 2004-03-01 11:29 ` Error-names Martin Klaiber 0 siblings, 1 reply; 25+ messages in thread From: Björn Persson @ 2004-02-29 23:24 UTC (permalink / raw) Would this implementation be a bad idea? function Get_Error_Code (E : Ada.Exceptions.Exception_Occurrence) return C_Integer is begin Ada.Exceptions.Raise_Exception (E) exception when Program_Error => return Program_Error_Code; when Constraint_Error => return Constraint_Error_Code; ... when others => return Unexpected_Error_Code; end Get_Error_Code; -- Björn Persson jor ers @sv ge. b n_p son eri nu ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 23:24 ` Error-names Björn Persson @ 2004-03-01 11:29 ` Martin Klaiber 2004-03-01 12:48 ` Error-names Marius Amado Alves 0 siblings, 1 reply; 25+ messages in thread From: Martin Klaiber @ 2004-03-01 11:29 UTC (permalink / raw) Bj�rn Persson <spam-away@nowhere.nil> wrote: > function Get_Error_Code (E : Ada.Exceptions.Exception_Occurrence) > return C_Integer is > begin > Ada.Exceptions.Raise_Exception (E) > exception > when Program_Error => return Program_Error_Code; > when Constraint_Error => return Constraint_Error_Code; > ... > when others => return Unexpected_Error_Code; > end Get_Error_Code; Doesn't work here. Raise_Exception (E) causes the error: libopensteuer.adb:24:18: expected private type "Ada.Exceptions.Exception_Id" libopensteuer.adb:24:18: found private type "Ada.Exceptions.Exception_Occurrence" Sorry, I didn't look further how to fix it because I am a bit short of time. Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-03-01 11:29 ` Error-names Martin Klaiber @ 2004-03-01 12:48 ` Marius Amado Alves 2004-03-02 2:15 ` Error-names Jeffrey Carter 0 siblings, 1 reply; 25+ messages in thread From: Marius Amado Alves @ 2004-03-01 12:48 UTC (permalink / raw) To: Martin Klaiber, comp.lang.ada > > function Get_Error_Code (E : Ada.Exceptions.Exception_Occurrence) > > return C_Integer is > > begin > > Ada.Exceptions.Raise_Exception (E) > > exception > > when Program_Error => return Program_Error_Code; > > when Constraint_Error => return Constraint_Error_Code; > > ... > > when others => return Unexpected_Error_Code; > > end Get_Error_Code; > > Doesn't work here. Raise_Exception (E) causes the error: > > libopensteuer.adb:24:18: expected private type > "Ada.Exceptions.Exception_Id" libopensteuer.adb:24:18: found private type > "Ada.Exceptions.Exception_Occurrence" E'Identity or Exception_Identity (E) instead of just E in the call to Raise_Exception should solve the problem. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-03-01 12:48 ` Error-names Marius Amado Alves @ 2004-03-02 2:15 ` Jeffrey Carter 0 siblings, 0 replies; 25+ messages in thread From: Jeffrey Carter @ 2004-03-02 2:15 UTC (permalink / raw) Marius Amado Alves wrote: >>Doesn't work here. Raise_Exception (E) causes the error: >> >> libopensteuer.adb:24:18: expected private type >>"Ada.Exceptions.Exception_Id" libopensteuer.adb:24:18: found private type >>"Ada.Exceptions.Exception_Occurrence" > > > E'Identity or Exception_Identity (E) instead of just E in the call to > Raise_Exception should solve the problem. This is my fault. Moran was using identities, so I mentioned Raise_Exception. Of course you're going to have an occurence, so you should use Ada.Exceptions.Reraise_Occurrence. -- Jeff Carter "Your mother was a hamster and your father smelt of elderberries." Monty Python & the Holy Grail 06 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 19:03 ` Error-names Jeffrey Carter 2004-02-29 20:04 ` Error-names tmoran @ 2004-02-29 20:33 ` Martin Klaiber 2004-02-29 23:43 ` Error-names tmoran 1 sibling, 1 reply; 25+ messages in thread From: Martin Klaiber @ 2004-02-29 20:33 UTC (permalink / raw) Jeffrey Carter <spam@spam.com> wrote: > tmoran@acm.org wrote: >> subtype Exception_Codes is Interfaces.C.Int range -10 .. 1; >> Coded_Exception_List : constant array(Exception_Codes) >> := (Constraint_Error'Identity, >> Program_Error'Identity, >> Storage_Error'Identity, >> Tasking_Error'Identity, >> Ada.IO_Exceptions.Status_Error'Identity, >> Ada.IO_Exceptions.Mode_Error'Identity, >> Ada.IO_Exceptions.Name_Error'Identity, >> ... >> function Error_Code_Of(E : Ada.Exceptions.Exception_Occurrence) >> return Exception_Codes is >> use Ada.Exceptions; >> begin >> for i in Coded_Exception_List'range loop >> if Exception_Identity(E) = Coded_Exception_List(i) then >> return i; >> end if; >> end loop; >> raise; -- we have no code for this exception! re-raise it >> end Error_Code_Of; > This is pretty much what I would have suggested if Moran hadn't beat me > to it. However, I think you can't use "raise" here without an exception > name, since we're not necessarily in an exception handler. You could use > Ada.Exceptions.Raise_Exception (E), but I suspect what is really wanted, > based on the OP's earlier messages, is to return General_Error_Code. Yes, General_Error_Code shall be a fallback in case there is no special handler for a certain exception. I implemented it like this: function Get_Error_Code (E : Exception_Occurrence) return C_Integer is begin if Exception_Identity (E) = Program_Error'Identity then return Program_Error_Code; elsif Exception_Identity (E) = Constraint_Error'Identity then return Constraint_Error_Code; elsif ... ... else return General_Error_Code; end if; end Get_Error_Code; Not as elegant as Toms(?) code with the array but it works ok. It's a pity that I can't use "case" instead of "if". The compiler moans that Exception_Id is not a discrete type. Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 20:33 ` Error-names Martin Klaiber @ 2004-02-29 23:43 ` tmoran 2004-03-01 11:20 ` Error-names Martin Klaiber 0 siblings, 1 reply; 25+ messages in thread From: tmoran @ 2004-02-29 23:43 UTC (permalink / raw) > function Get_Error_Code (E : Exception_Occurrence) return C_Integer is > begin > if Exception_Identity (E) = Program_Error'Identity then > return Program_Error_Code; > elsif Exception_Identity (E) = Constraint_Error'Identity then > return Constraint_Error_Code; > elsif ... "Use the Force, Luke", or more specifically, Let the Ada compiler help you find and eliminate errors. It would not be hard to leave out, or have multiple uses of, an error code, as in: Constraint_Error_Code : constant Exception_Codes := -10; Program_Error_Code : constant Exception_Codes := -9; Storage_Error_Code : constant Exception_Codes := -9; Status_Error_Code : constant Exception_Codes := -7; My_Special_Error_Code : constant Exception_Codes := -5; ... Similarly, a new exception might be added, but someone forgets to add it to the if-elsif list. With the if-elsif style you can only hope that neither of those happens. But if you do Coded_Exception_List : constant array(Exception_Codes) of Ada.Exceptions.Exception_ID := (Constraint_Error_Code => Constraint_Error'Identity, Program_Error_Code => Program_Error'Identity, Storage_Error_Code => Storage_Error'Identity, IO_Status_Error_Code => Ada.IO_Exceptions.Status_Error'Identity, My_Special_Error_Code => My_Special_Exception'Identity, ... then the compiler will warn you if two of your error codes are the same, or if you've left any out in the Exception_Codes range. It also has the (possible) advantage that you can trivially translate a code back into an exception: Ada.Exceptions.Raise_Exception(Coded_Exception_List(Code), Message); ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 23:43 ` Error-names tmoran @ 2004-03-01 11:20 ` Martin Klaiber 2004-03-07 15:10 ` Error-names Björn Persson 2004-03-08 5:42 ` Error-names Dave Thompson 0 siblings, 2 replies; 25+ messages in thread From: Martin Klaiber @ 2004-03-01 11:20 UTC (permalink / raw) tmoran@acm.org wrote: > It would not be hard to leave out, or have multiple uses of, an error > code, as in: > Constraint_Error_Code : constant Exception_Codes := -10; > Program_Error_Code : constant Exception_Codes := -9; > Storage_Error_Code : constant Exception_Codes := -9; > Status_Error_Code : constant Exception_Codes := -7; > My_Special_Error_Code : constant Exception_Codes := -5; > ... > Similarly, a new exception might be added, but someone forgets to > add it to the if-elsif list. > With the if-elsif style you can only hope that neither of those happens. > But if you do > Coded_Exception_List : constant array(Exception_Codes) > of Ada.Exceptions.Exception_ID > := (Constraint_Error_Code => Constraint_Error'Identity, > Program_Error_Code => Program_Error'Identity, > Storage_Error_Code => Storage_Error'Identity, > IO_Status_Error_Code => Ada.IO_Exceptions.Status_Error'Identity, > My_Special_Error_Code => My_Special_Exception'Identity, > ... > then the compiler will warn you if two of your error codes are the > same, or if you've left any out in the Exception_Codes range. This is right but how can I export the constants then? At the moment I use in the spec-file: -- No error: No_Error_Code : constant C_Integer := 0; pragma export (C, No_Error_Code, "no_error_code"); -- Fallback: General_Error_Code : constant C_Integer := -1; pragma export (C, General_Error_Code, "general_error_code"); and so on. The reason is that I want the C-programmer to use the constants-names instead of the values, because I can't guarantee that the values will not change in the future. BTW: does someone know why these constants are not recognized by the C-program as constants? They are declared as constants and in the C header-file I put: /* error-codes */ extern const int no_error_code; extern const int general_error_code; ... But if I want to use it in a switch-command like that: int year; ... for (year = 2003; year <= 2005; ++year) { switch (set_year (year)) { case no_error_code : set_lzz (1); ... the compiler says: test_c.c:20: case label does not reduce to an integer constant Is my exporting wrong? Or is this a C-problem? When I use "case 0" instead of "case no_error_code" it works ok, but this is what I want to avoid. Thanks, Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-03-01 11:20 ` Error-names Martin Klaiber @ 2004-03-07 15:10 ` Björn Persson 2004-03-08 5:42 ` Error-names Dave Thompson 1 sibling, 0 replies; 25+ messages in thread From: Björn Persson @ 2004-03-07 15:10 UTC (permalink / raw) Martin Klaiber wrote: > BTW: does someone know why these constants are not recognized by the > C-program as constants? They are declared as constants and in the C > header-file I put: > > /* error-codes */ > > extern const int no_error_code; > extern const int general_error_code; > ... > > But if I want to use it in a switch-command like that: > > int year; > ... > for (year = 2003; year <= 2005; ++year) { > switch (set_year (year)) { > case no_error_code : > set_lzz (1); > ... > > the compiler says: > > test_c.c:20: case label does not reduce to an integer constant > > Is my exporting wrong? Or is this a C-problem? When I use "case 0" > instead of "case no_error_code" it works ok, but this is what I want > to avoid. As I understand it, "const" in C doesn't give you a constant. You get kind of a read-only variable. You can't change its value, but it's still treated as a variable and not allowed where a constant is required. Put another way, where the language requires a constant it actually requires a literal, not a named constant. I suppose this is why everyone uses preprocessor macros for constants, since they are translated to literals. Yet another reason to loathe C ... -- Björn Persson jor ers @sv ge. b n_p son eri nu ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-03-01 11:20 ` Error-names Martin Klaiber 2004-03-07 15:10 ` Error-names Björn Persson @ 2004-03-08 5:42 ` Dave Thompson 1 sibling, 0 replies; 25+ messages in thread From: Dave Thompson @ 2004-03-08 5:42 UTC (permalink / raw) On Mon, 1 Mar 2004 12:20:37 +0100, Martin Klaiber <martinkl@zedat.fu-berlin.de> wrote: <snip> > This is right but how can I export the constants then? At the moment > I use in the spec-file: > > -- No error: > No_Error_Code : constant C_Integer := 0; > pragma export (C, No_Error_Code, "no_error_code"); > > -- Fallback: > General_Error_Code : constant C_Integer := -1; > pragma export (C, General_Error_Code, "general_error_code"); > > and so on. The reason is that I want the C-programmer to use the > constants-names instead of the values, because I can't guarantee that > the values will not change in the future. > > BTW: does someone know why these constants are not recognized by the > C-program as constants? They are declared as constants and in the C > header-file I put: > > /* error-codes */ > > extern const int no_error_code; > extern const int general_error_code; > ... > > But if I want to use it in a switch-command like that: > > int year; > ... > for (year = 2003; year <= 2005; ++year) { > switch (set_year (year)) { > case no_error_code : > set_lzz (1); > ... > > the compiler says: > > test_c.c:20: case label does not reduce to an integer constant > 'const' in C is not what C calls a constant, it is a read-only variable (or at least a read-only lvalue = roughly a view). A 'constant', and a 'constant expression', in C is one determinable at compile time, even in the presence of separate compilation; in effect, it must be apparent from the source for one translation unit, that is, one source file plus the file(s) it #include's. This includes literals = 'C' /* characters are actually integers in C */, 123, 4.56, etc.; enum values = enum { foo = 3 } /* only int in C, long if needed in C++ */; expressions depending only on the above; and #define'd macros which after (pre-compile-time) expansion result in any of the above. It does not include any variable, even a const one, in C even an initialized const one; in C++ a const variable (!) of integer or enumeration type -- IF initialized (visibly to the compiler) by a constant expression -- is considered a constant and can be used in case labels, array bounds, etc. But you don't have that either. > Is my exporting wrong? Or is this a C-problem? When I use "case 0" > instead of "case no_error_code" it works ok, but this is what I want > to avoid. > This is a limitation of C, that case labels must be (separate) compile-time constants. Use an if/else chain; or export your constants as *source* #define's or enum's; or code-generate your C source instantiating the actual numbers -- which is effectively equivalent to the #define approach implemented "by hand". - David.Thompson1 at worldnet.att.net ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 18:31 ` Error-names Martin Klaiber 2004-02-28 19:47 ` Error-names tmoran @ 2004-02-28 20:26 ` Jacob Sparre Andersen 1 sibling, 0 replies; 25+ messages in thread From: Jacob Sparre Andersen @ 2004-02-28 20:26 UTC (permalink / raw) Martin Klaiber wrote: > Marius Amado Alves <amado.alves@netcabo.pt> wrote: > > function Main return Error_Code_Type is > > -- exception-raising calls here > > exception > > when E : others => return Error_Code_Of (E); > > end; > > > Now you only have to implement Error_Code_Of. > > > (Ain't top-down design great? ;-) > > > The 'trick' you could be missing is the "E : others" construct > > above. E is the exception occurence. From it you can go to the > > exception name. See package Ada.Exceptions--or, better yet, > > section 11.4 of the ARM. > > Well, if I understand it right, I still have to distinguish between > the different exceptions before I call Error_Code_Of, is this right? No. E is like a renaming of whatever exception actually was raised. > Like this (assume I have 5 exceptions A to E): > > function Main return Error_Code_Type is > -- exception-raising calls here > exception > when A : others => return Error_Code_Of (A); > when B : others => return Error_Code_Of (B); > when C : others => return Error_Code_Of (C); > when D : others => return Error_Code_Of (D); > when E : others => return Error_Code_Of (E); > end; No, that wouldn't work. Just: [...] exception when Raised_Exception : others => return Error_Code_Of (Raised_Exception); end; If the exception raised is A, then Ada.Exceptions.Exception_Name (Raised_Exception) will return the string "A" (or however it is that the compiler names the exception you call A. Read the suggested part of the reference manual. Jacob -- "We will be restoring normality as soon as we are sure what is normal anyway." ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 12:58 Error-names Martin Klaiber 2004-02-28 13:35 ` Error-names Martin Dowie @ 2004-02-28 18:29 ` Alexandre E. Kopilovitch 2004-02-29 5:30 ` Error-names David Marceau 2 siblings, 0 replies; 25+ messages in thread From: Alexandre E. Kopilovitch @ 2004-02-28 18:29 UTC (permalink / raw) To: comp.lang.ada Martin Klaiber wrote: > Is there an english word instead of 'error' I could use? Like 'fault' > for instance or 'mistake'? Probably you'll not find another generic term for that, but you always can use more specific names. These "fault" and "mistake" are just examples of such more specific terms - they are names of classes of errors. >Constraint_Fault, Constraint_Mistake. Hm, sounds strange to me. Certainly these aren't good conbinations. For constraints you probably should use another term: "violation", that is: Constraint_Violation Alexander Kopilovitch aek@vib.usr.pu.ru Saint-Petersburg Russia ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-28 12:58 Error-names Martin Klaiber 2004-02-28 13:35 ` Error-names Martin Dowie 2004-02-28 18:29 ` Error-names Alexandre E. Kopilovitch @ 2004-02-29 5:30 ` David Marceau 2004-02-29 12:17 ` Error-names Martin Klaiber 2 siblings, 1 reply; 25+ messages in thread From: David Marceau @ 2004-02-29 5:30 UTC (permalink / raw) Martin Klaiber wrote: > > Hi, > > this is not really a programming-problem (I hope), more a question > about english terms. > > I write a library with an interface to C. The Ada-exceptions shall > be turned into return-values for the C-functions. Like this: > > with Interfaces.C; > > package Something is > > -- Types: > type C_Integer is new Interfaces.C.int; > > -- Exceptions and errors: > General_Error : C_Integer := -1; > > Routine_Not_Defined : exception; > Routine_Not_Defined_Error : C_Integer := -2; > > and so on... > > package body Something is > > function Do_Something return C_Integer is > begin > ... > return 0; > exception > when Routine_Not_Defined => return Routine_Not_Defined_Error; > when others => return General_Error; > end Do_Something; > > end Something; > > My problem now is that I also want to define return values for > exceptions like Constraint_Error. But I can't define something like: > > Constraint_Error : C_Integer := -3; > > as Constraint_Error is the name for the exception. And I don't want to > use long names like: 'Routine_Not_Defined_Error_Constant' or similar. > I also don't want to rename the exceptions, as other Ada-Programs might > rely on them. > > Is there an english word instead of 'error' I could use? Like 'fault' > for instance or 'mistake'? > > Constraint_Fault, Constraint_Mistake. Hm, sounds strange to me. Would > it be alright though? > > Thanks a lot, > Martin I believe this is a case of C mentality/lifestyle being brought to Ada code. In my opinion this is bad Ada mentality/lifestyle The Ada idea from my understanding is to make it robust by separating all the different kinds of errors and dealing with each appropriate based on its context. The C style confuses and leaves you to wonder what the hell happened and what exactly was the root of the cause. The other thing about it is that because each case isn't handled separately the cleanup that one is supposed to handle for every different exception is not handled. SUGGESTION ----------- don't use when others all the time. make sure when others is used it is logged somewhere. don't return integers in exception handlers. it's ok to raise another more specific exception to a higher level. The special case ---------------- If you are writing a bridge that is controlled by C executable accessing an ada shared library then yes there may be a real reason to return constants for errors. Feel free to add other special cases if you want but I'm pretty sure this is the right direction to go instead of just porting a C mentality. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 5:30 ` Error-names David Marceau @ 2004-02-29 12:17 ` Martin Klaiber 2004-02-29 19:56 ` Error-names David Marceau 0 siblings, 1 reply; 25+ messages in thread From: Martin Klaiber @ 2004-02-29 12:17 UTC (permalink / raw) David Marceau <davidmarceau@sympatico.ca> wrote: > The Ada idea from my understanding is to make it robust by separating all the > different kinds of errors and dealing with each appropriate based on its > context. The C style confuses and leaves you to wonder what the hell happened > and what exactly was the root of the cause. I'd say, this depends on the elaboration of the return values. Just returning a value /= 0 for any error is quite poor indeed. But if one returns a specific value for each kind of error, the calling C-program should be as capable as an Ada-program finding out the cause of failure. > The other thing about it is that because each case isn't handled > separately the cleanup that one is supposed to handle for every > different exception is not handled. Well, perhaps this is a misunderstanding. The example in my previous post is just an example. In reality I distinguish between more exceptions. > SUGGESTION > ----------- > don't use when others all the time. I agree. General_Error is a fallback, as I must ensure that any exception is turned into a return-value, as the calling C-programm cannot deal with the Ada-exceptions. In other parts of the library, for instance in the part where I evaluate the tax-year, I don't use 'when others' to make sure that I really handle every year for every case. > make sure when others is used it is logged somewhere. Hm, sorry, I don't understand what you mean here. > don't return integers in exception handlers. I only do it for the functions called by the C-program. > it's ok to raise another more specific exception to a higher level. > The special case > ---------------- > If you are writing a bridge that is controlled by C executable accessing an ada > shared library then yes there may be a real reason to return constants for > errors. Yes, that's what I'm doing here. The library has two interfaces, one for Ada-programs and one for C-programs. The Ada-interface is doing no exception-handling at all. All exceptions are passed to the calling Ada-program. But for the C-interface I have to ensure that the calling program can handle errors and the library is not quitting execution by itself when an error occurs. As C can't deal with Ada-exceptions, I turn them into return-values. If there is a better way to do so, I'll happily use it. > Feel free to add other special cases if you want but I'm pretty sure this is the > right direction to go instead of just porting a C mentality. I don't see that I'm porting a C mentality. I am no expert, neither in Ada nor in C, although my C is worse ;-) But AFAIK return-values are the standard way to tell a C-program that a function failed. Correct me if I'm wrong. Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 12:17 ` Error-names Martin Klaiber @ 2004-02-29 19:56 ` David Marceau 2004-02-29 21:57 ` Error-names Martin Klaiber 2004-03-01 23:20 ` Error-names Randy Brukardt 0 siblings, 2 replies; 25+ messages in thread From: David Marceau @ 2004-02-29 19:56 UTC (permalink / raw) Martin Klaiber wrote: > > David Marceau <davidmarceau@sympatico.ca> wrote: > > > The Ada idea from my understanding is to make it robust by separating all the > > different kinds of errors and dealing with each appropriate based on its > > context. The C style confuses and leaves you to wonder what the hell happened > > and what exactly was the root of the cause. > > I'd say, this depends on the elaboration of the return values. Just > returning a value /= 0 for any error is quite poor indeed. But if one > returns a specific value for each kind of error, the calling C-program > should be as capable as an Ada-program finding out the cause of failure. > > > The other thing about it is that because each case isn't handled > > separately the cleanup that one is supposed to handle for every > > different exception is not handled. > > Well, perhaps this is a misunderstanding. The example in my previous > post is just an example. In reality I distinguish between more > exceptions. > > > SUGGESTION > > ----------- > > don't use when others all the time. > > I agree. General_Error is a fallback, as I must ensure that any > exception is turned into a return-value, as the calling C-programm > cannot deal with the Ada-exceptions. > > In other parts of the library, for instance in the part where I > evaluate the tax-year, I don't use 'when others' to make sure that I > really handle every year for every case. > > > make sure when others is used it is logged somewhere. > > Hm, sorry, I don't understand what you mean here. I just mean the reason you use "when others" in the first place is because it is an exception you never thought about when designing the component. You have to admit when this happens whatever happens in a "when others" you have to document and figure out in what context the situation occurred in order to go back and add more code and maybe a new exception type to raise :) The best way is to first catch it into a file in order to come back and read about it...hence logging the "when others" exception. I think you already understand this kind of thing but I voiced it out anyways just in case. A perfect application should not ever get into the part of the code inside "when others" at run-time. That said "when others" has to exist to catch a real exception and log the real exception to enable us programmers to analyze what the problem is later to be able to fix it ASAP. That's my opinion. Please correct me if I'm wrong. > > > don't return integers in exception handlers. > > I only do it for the functions called by the C-program. > > > it's ok to raise another more specific exception to a higher level. > > > The special case > > ---------------- > > If you are writing a bridge that is controlled by C executable accessing an ada > > shared library then yes there may be a real reason to return constants for > > errors. > > Yes, that's what I'm doing here. The library has two interfaces, one > for Ada-programs and one for C-programs. The Ada-interface is doing > no exception-handling at all. All exceptions are passed to the calling > Ada-program. Now your strategy does make sense. Just make sure all your Ada exceptions are handled in the ada shared lib. Ada Exceptions and C Exceptions don't seem to use the same default cleanup strategies so you have to be very careful. To protect your C executeable, make sure you have wrappers in a bridge/API on the ADA side that actually does the calling to the real Ada service API. In that manner, you have a better chance at catching and logging your exceptions in a textfile/database. > > But for the C-interface I have to ensure that the calling program can > handle errors and the library is not quitting execution by itself when > an error occurs. As C can't deal with Ada-exceptions, I turn them into > return-values. If there is a better way to do so, I'll happily use it. > > > Feel free to add other special cases if you want but I'm pretty sure this is the > > right direction to go instead of just porting a C mentality. > > I don't see that I'm porting a C mentality. I am no expert, neither in > Ada nor in C, although my C is worse ;-) But AFAIK return-values are > the standard way to tell a C-program that a function failed. Correct > me if I'm wrong. As you stated in a C program returning a constant value for the error is standard "C" practice. From what I understand, returning nothing and placing valuable information in an "in out" parameter is more Ada95. The valuable information I talking about is an object holding a structure of a bunch of structures. The advantage of this programming lifestyle which I learned from OLE(windows programming lifestyle oddly enough) is it permits the service API to attain a certain maturity quite quickly and focuses on limits change to services affecting only one object. The pattern of what I'm talking about in C is void somefunc( OLEORWINDOWSORJNIHANDLEOFSOMESORT, ObjectToWorkOn); i.e. setParmsForService1(ditto) callService1(ditto) It may seem longer but it's not. It may slow down the app a bit, but it makes the application much more maintainable than having to deal with something like: void someComplicatedObfuscatingServiceWrittenBySomeAssholeWizardNotWantingToShareHisKnowledge( SOMEHANDLEWHATEVER, OBJECT, parm1, p2, z3, o4(what the hell is o4), p65, qwer7, areYouStartingToUnderstandWhereImComingFrom8); What I just wrote is very common in vb/c/C++/perl/java land. Bad Code and inherited C style is what that is. Yes I've seen some bad ada code too. Now focus on what it should look like in Ada: procedure setParametersForServiceX ( OLEORWINDOWSORJNIHANDLEOFSOMESORT , ObjectToWorkOn , ObjectHoldingParametersToPassToObjectToWorkOn ); procedure callServiceX ( OLEORWINDOWSORJNIHANDLEOFSOMESORT , ObjectToWorkOn ); My variable names and declarations are not Ada standard or C standard but what's important is the placement of parameters and the number of parameters in the service calling pattern to facilitate long term maintenance. The rule of thumb is there should be no more than three parameters in setParametersForService and no more than two parameters in callService. There could be some other pattern services to write for errors and logging and stuff but the idea is reducing the number of parameters in each service makes the services much more maintainable in the long term. Throw me any service and I can justify that the thing doesn't have to be complicated and should follow the above pattern. Notice how I didn't show the type for these. That's up to you but in my opinion it usually is like a C++ reference where you can't change the actual address of the object but everything inside it is definitely up to you if you want it to muteable or not. I don't know if you'll notice but there's a bit of assembler programming influence in my source code format listing. I only have one or two and at max three things of code and maybe a following comment on each line. Also notice one line for the opening brace/parentheses and another line for closing brace/parentheses. Call me crazy but I think it is most legible this way. It also helps you do focus on one problem at a time for each line. I follow the same style for if statements and everything else. Sure it takes a bit more time but in the long run it's better in my humble opinion. I'd love to hear what others think about this. I'm all ears. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 19:56 ` Error-names David Marceau @ 2004-02-29 21:57 ` Martin Klaiber 2004-03-01 23:20 ` Error-names Randy Brukardt 1 sibling, 0 replies; 25+ messages in thread From: Martin Klaiber @ 2004-02-29 21:57 UTC (permalink / raw) David Marceau <davidmarceau@sympatico.ca> wrote: > Martin Klaiber wrote: >> David Marceau <davidmarceau@sympatico.ca> wrote: >>> make sure when others is used it is logged somewhere. >> Hm, sorry, I don't understand what you mean here. > I just mean the reason you use "when others" in the first place is > because it is an exception you never thought about when designing > the component. This is true and it shows the dilemma. When writing the code I don't know which exceptions a real Ada-implementation might provide. But I also must ensure all exceptions are handled to give the C-program a chance to avoid a crash. So I use "when others" at last. Is there a way to find out which exceptions an implementation provides? Ok, I have the types mentioned in the ARM but the implementation could add some more. > You have to admit when this happens whatever happens in a "when > others" you have to document and figure out in what context the > situation occurred in order to go back and add more code and maybe a > new exception type to raise :) That's right. Tracking down an error is more difficult then. > The best way is to first catch it into a file in order to come back and > read about it...hence logging the "when others" exception. I think you > already understand this kind of thing but I voiced it out anyways just > in case. A perfect application should not ever get into the part of > the code inside "when others" at run-time. That said "when others" has > to exist to catch a real exception and log the real exception to enable > us programmers to analyze what the problem is later to be able to fix > it ASAP. That's my opinion. Please correct me if I'm wrong. No, you're right. But I want to avoid to implement file-I/O to keep the lib as platform- and compiler-independent as possible. Perhaps I implement a function, which allows the calling C-program to recall the last error-message. This could be used for a bug-report then. > Ada Exceptions and C Exceptions don't seem to use the same default > cleanup strategies so you have to be very careful. What do you mean by C Exceptions? Can C handle exceptions? > As you stated in a C program returning a constant value for the error is > standard "C" practice. > From what I understand, returning nothing and placing valuable information in an > "in out" parameter is more Ada95. > The valuable information I talking about is an object holding a structure of a > bunch of structures. Ok, but complex types might give problems with the representation. I also wanted to use records/structs for the interface first, instead of the many set- and get-procedures/-functions. But people told me that a C-program compiled with a different compiler than the compiler used for the Ada-lib doesn't necessarily represent the types in the same way. So I only use the C-types "int" and "long" now. This makes it more simple and hopefully more robust. > Also notice one line for the opening brace/parentheses and another line for > closing brace/parentheses. Call me crazy but I think it is most legible this > way. It also helps you do focus on one problem at a time for each line. I > follow the same style for if statements and everything else. Sure it takes a > bit more time but in the long run it's better in my humble opinion. It think this is very individual preferences and cannot be answered generally. So I wouldn't puzzle myself with it. Preferences also change with time. I use more underscores now. Before I found the code without underscores more legible, now it's the other way round. Martin ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: Error-names. 2004-02-29 19:56 ` Error-names David Marceau 2004-02-29 21:57 ` Error-names Martin Klaiber @ 2004-03-01 23:20 ` Randy Brukardt 1 sibling, 0 replies; 25+ messages in thread From: Randy Brukardt @ 2004-03-01 23:20 UTC (permalink / raw) "David Marceau" <davidmarceau@sympatico.ca> wrote in message news:404243E5.376C42BB@sympatico.ca... ... > Now focus on what it should look like in Ada: > > procedure setParametersForServiceX > ( > OLEORWINDOWSORJNIHANDLEOFSOMESORT > , ObjectToWorkOn > , ObjectHoldingParametersToPassToObjectToWorkOn > ); > > procedure callServiceX > ( > OLEORWINDOWSORJNIHANDLEOFSOMESORT > , ObjectToWorkOn > ); > > My variable names and declarations are not Ada standard or C standard but what's > important is the placement of parameters and the number of parameters in the > service calling pattern to facilitate long term maintenance. The rule of thumb > is there should be no more than three parameters in setParametersForService and > no more than two parameters in callService. ... > I'd love to hear what others think about this. I'm all ears. In Ada 95, I don't think this is a great idea, because you lose the advantages of default parameters. We thought about this a lot in the context of Claw, and decided having separate parameters was better, because they could have appropriate defaults, and thus you rarely need to give them. Moreover, you can add parameters to a routine without changing any calls simply by giving appropriate defaults to new parameters. None of this is possible with records, because the aggregates need to be complete. So if you add a new item, you'll get errors on all of the calls, even if the new item is relatively unimportant. For instance, a Claw window create routine could look like: procedure Create (Window : in out Window_Type; Parent : in out Root_Window_Type'Class; Position : in Point_Type := Use_Default_Position; Size : in Size_Type := Use_Default_Size; Menu : in Menu_Type := No_Menu; Title : in String := ""; Show_System_Menu : in Boolean := True; Show_Close_Box : in Boolean := True; Allow_Resizing : in Boolean := True; ... ); A call could look like: Create (New_Window, My_Parent, Size => (100, 100)); While a call using a record would have to give all of the parameters (components). Yuck. Ada 200Y will fix this, as there is a way to initialize record components to defaults: (Size => (100, 100), others => <>); so your technique will work better in the future. But note that it still won't work well with indefinite parameters (like the Title parameter above). Randy. ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2004-03-08 5:42 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-02-28 12:58 Error-names Martin Klaiber 2004-02-28 13:35 ` Error-names Martin Dowie 2004-02-28 15:26 ` Error-names Martin Klaiber 2004-02-28 17:19 ` Error-names Marius Amado Alves 2004-02-28 18:31 ` Error-names Martin Klaiber 2004-02-28 19:47 ` Error-names tmoran 2004-02-28 20:29 ` Error-names Martin Klaiber 2004-02-29 19:03 ` Error-names Jeffrey Carter 2004-02-29 20:04 ` Error-names tmoran 2004-02-29 23:24 ` Error-names Björn Persson 2004-03-01 11:29 ` Error-names Martin Klaiber 2004-03-01 12:48 ` Error-names Marius Amado Alves 2004-03-02 2:15 ` Error-names Jeffrey Carter 2004-02-29 20:33 ` Error-names Martin Klaiber 2004-02-29 23:43 ` Error-names tmoran 2004-03-01 11:20 ` Error-names Martin Klaiber 2004-03-07 15:10 ` Error-names Björn Persson 2004-03-08 5:42 ` Error-names Dave Thompson 2004-02-28 20:26 ` Error-names Jacob Sparre Andersen 2004-02-28 18:29 ` Error-names Alexandre E. Kopilovitch 2004-02-29 5:30 ` Error-names David Marceau 2004-02-29 12:17 ` Error-names Martin Klaiber 2004-02-29 19:56 ` Error-names David Marceau 2004-02-29 21:57 ` Error-names Martin Klaiber 2004-03-01 23:20 ` Error-names Randy Brukardt
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox