Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: Notesfiles $Revision: 1.6.2.16 $; site ada-uts.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!ada-uts!richw
From: richw@ada-uts.UUCP
Newsgroups: net.lang.c
Subject: Exception Handling?  Impossible!
Message-ID: <10200002@ada-uts.UUCP>
Date: Mon, 12-Aug-85 15:03:00 EDT
Article-I.D.: ada-uts.10200002
Posted: Mon Aug 12 15:03:00 1985
Date-Received: Sun, 18-Aug-85 01:41:47 EDT
Lines: 121
Nf-ID: #N:ada-uts:10200002:000:3256
Nf-From: ada-uts!richw    Aug 12 15:03:00 1985


EXCEPTION HANDLING ??!?

The following includes "files" of macros and a simple modification
of the "exit" routine which allows one to do pseudo-exception-handling
in C.  An example of their use is provided in the "test.c" file.

There are problems with these macros (and the modified "exit"),
I admit.  The purpose of this note is to get feedback on possible
solutions to some of the problems.  I'd also like INTELLIGENT comments
about what's going on (please refrain from verborrhea like "How
could you name the macro 'except_when'?!  Name it 'if_exception'!" ).

Problems I can see right off:

1) The raise macro must still use a return statement (which is why
   I've provided raise_return, for those cases where garbage results
   are inappropriate).

2) Arbitrary statements may be executed between the call to the procedure
   that raised an exception and the handler.

3) Unhandled exceptions come to the attention of the user only when
   another "raise" is attempted or when the program terminates.

4) The raise macro includes a return statement since most exceptions
   (at least in programs that I write) are used to signal alternate
   termination conditions of a procedure.  This implies that "local"
   exceptions can't be raised (e.g. to jump out of nested loops).

5) An "exception" is simply a string.  It's "declaration" requires (?)
   some redundancy (i.e. the variable name and the string literal will
   usually look the same).


-- Rich Wagner

------------------------- test.c -------------------------------

#include "exceptions.h"
#include 

Exception overflow = "Overflow";

raiser(b)
int b;
{
	fprintf(stderr, "Raiser called with %d\n", b);
	if (b) raise(overflow);
	fprintf(stderr, "Leaving raiser\n\n");
}

main()
{
	raiser(0);
	    except_when(overflow)
		    fprintf(stderr, "Caught when it wasn't raised\n");
	    end_except;
	raiser(1);
	    except_when(overflow)
		    fprintf(stderr, "Caught\n");
	    end_except;
	raiser(0);
	raiser(1);
	raiser(1);
	fprintf(stderr, "Last line of main\n");
}

------------------------ test output ----------------------------

Raiser called with 0
Leaving raiser

Raiser called with 1
Caught
Raiser called with 0
Leaving raiser

Raiser called with 1
Raiser called with 1
Unhandled exception: Overflow

------------------------ exceptions.h ---------------------------

extern int _xxraised;
extern char *_xxexc;

#define raise(e) { if (_xxraised) exit(1);\
                   _xxexc = e; _xxraised = 1; return; }
#define raise_return(e,r) { if (_xxraised) exit(1);\
                            _xxexc = e; _xxraised = 1 ; return r; }

#define except_when(e) if (_xxraised) {\
			      if (_xxexc == (e)) { _xxraised = 0;

#define when(e) } else if (_xxexc == (e)) { _xxraised = 0;

#define end_except } else exit(1); }

typedef char *Exception;

------------------------ exceptions.c -----------------------------


#include 

int _xxraised = 0;
char *_xxexc;

exit(status)
int status;
{
	if (_xxraised) {
		fprintf(stderr, "Unhandled exception: %s\n", _xxexc);
                _xxexit(status ? status : 1);
        }
	_xxexit(status);

        /*  _xxexit is the old "exit" we all know and love, */
        /*  just renamed.                                   */
}