comp.lang.ada
 help / color / mirror / Atom feed
* 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 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 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 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 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 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-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 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: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 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 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 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 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-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-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

* 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-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

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