On 31-Jan-2001, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
> 
> 
> I have not read the whole of this log yet.  But the following caught my
> eye, and I have to address dres' reservations:
> 
> An error stack is about as close as you can come to having exceptions in
> C.  Here's how it works.  (This example uses macros, please pardon the
> sin)
> 
> 
> typedef enum { BadDog=23, ...} ErrType;
> 
> ErrType pop_error(void);
> void push_error(ErrType);
> 
> void some_low_func (..) 
> {
>    if(something bad) { THROW (BadDog);  }
> }
> 
> void some_user_func(..)
> {
>    TRY {
>      some_low_func();
>    }
>    CATCH {
>       case BadDog:
>           printf ("Bad Dog! Sit in the corner!!!\n");
>           break;
>    }
> }

Exceptions also involve more complicated control transfer.  Consider:

/* this is the same as your function */
void some_low_func (..) 
{
        if(something bad) { THROW (BadDog);  }
}

/* a new function in the middle */
void some_mid_func (..) 
{
        ...
        some_low_func();
        ...
        (other code, possibly throwing different exceptions)
        ...
}

void some_user_func(..)
{
     TRY {
        some_mid_func();
     }
     CATCH {
        case BadDog:
            printf ("Bad Dog! Sit in the corner!!!\n");
            break;
     }
}

You have to transfer control from the exception in some_low_func through
some_mid_func into some_user_func.  some_mid_func might do arbitrary
amounts of computation after calling some_low_func, so you can't rely on
it to return to some_user_func to trigger the exception catch clauses
without writing explicit code to do this, or putting a TRY/CATCH in
every function.

You actually need to use setjmp/longjmp to get this to work like
C++/Java exceptions.  `return' is not flexible enough to implement
exceptions in this manner.

> and the 'magic macros' that make this work:
> 
> #define THROW(ERR)  { push_error(ERR); return; }
> #define TRY  /* no-op */
> #define CATCH {ErrType e;  while (e=pop_error()) { switch (e) { 

This is still pseudocode, but something like:

/* try: add a new jump_buf to the stack */

#define TRY 
        {
                push_new_jump_buf_onto_error_stack();
                if (setjmp(error_stack.jump_buf) == 0) {

/* catch: must directly follow a try, removes the jump_buf from the stack
if the try succeeds, otherwise it provides the else case to setjmp,
which handles any errors that get to here. */

#define CATCH
                        pop_jump_buf_from_error_stack();        
                } else {
                        pop_jump_buf_from_error_stack();        
                        ErrType current_exception;
                        while (current_exception = pop_error()) { 
                                switch (e) { 

/* endcatch just closes off the braces, and if the catch didn't handle the
error then it re-throws it. */

#define ENDCATCH
                                default:
                                        RETHROW();
                                }
                        }
                }
        }


/* throw: just puts the error on the error stack and then goes to the
topmost jump buf. */

#define THROW(ERR)  
        { 
                push_error(ERR); 
                longjmp(error_stack.env, 1);
        }

/* rethrow: throws the current exception again */
#define RETHROW
        {       
                throw(current_exception)
        }

I haven't tested this (but I can if you want to use it).

> I've got some parens matching problems here, and its a little
> oversimplified, but its hopefully obvious now that C++/Java exceptions
> are nothing more than an error stack with some syntatic sugar.
> 
> So dres: you said you wished for C exceptions? 

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     [EMAIL PROTECTED]        # 
http://www.cs.mu.oz.au/~trd #

_______________________________________________
gnucash-devel mailing list
[EMAIL PROTECTED]
http://www.gnumatic.com/cgi-bin/mailman/listinfo/gnucash-devel

Reply via email to