Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Nov 1999 18:10:18 -0800 (PST)
From:      Archie Cobbs <archie@whistle.com>
To:        freebsd-java@freebsd.org
Subject:   try { } catch { } finally { } in C!
Message-ID:  <199911040210.SAA82085@bubba.whistle.com>

next in thread | raw e-mail | index | archive | help
Did you know that try { } catch { } finally { } is possible from C?
Well, GNU C anyway..

Example (using the header file included below):

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>

    #include <assert.h>
    #include <setjmp.h>
    #include "trycatch.h"

    int
    func()
    {
      int r = (int)random() % 32;

      if (r > 16) {
	printf("func() throwing %d\n", 7);
	THROW(7);
      }
      printf("func() returning %d\n", r);
      return r;
    }

    int
    main()
    {
      int r = 123;

      srandom(time(NULL));

      TRY {
	int y;

	printf("main() try #1\n");
	printf("main() calling func()\n");
	y = func();
	printf("func() returned %d\n", r);
	y = (int)random() % 32;
	if (y > 20) {
	  printf("main() throwing %d\n", -y);
	  THROW(-y);
	}
	printf("main() end of try part\n");
	printf("main() RETURN()'ing %d\n", r);
	RETURN(r);
      } CATCH(int, x) {
	printf("main() start of catch, x=%d\n", x);
      } FINALLY {
	printf("main() start of finally, r=%d\n", r);
      } ENDTRY;

      printf("main() returning\n");
      return(0);
    }


-Archie

___________________________________________________________________________
Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com


/* This is a per-thread global variable */
jmp_buf _tryJmpBuf;

/* This precedes the TRY block */
#define TRY	{							\
		    __label__ _finallyLabel;				\
		    volatile jmp_buf _tryJmpBufSave;			\
		    void *_finallyReturn = NULL;			\
		    int _thrownValue;					\
									\
		    memcpy((void *)&_tryJmpBufSave,			\
			_tryJmpBuf, sizeof(jmp_buf));			\
		    if ((_thrownValue = setjmp(_tryJmpBuf)) == 0)

/* This precedes the CATCH block */
#define CATCH(type, var)						\
		    else {						\
			type var = (type) _thrownValue;			\
									\
			memcpy(&_tryJmpBuf, (void *)&_tryJmpBufSave,	\
			    sizeof(jmp_buf));				\
			if ((_thrownValue = setjmp(_tryJmpBuf)) == 0) {

/* Use this instead of CATCH() when you don't want to catch anything */
#define NOCATCH()   {							\
			if (0) {

/* This precedes the FINALLY block */
#define FINALLY		} else {					\
			    memcpy(&_tryJmpBuf, (void *)&_tryJmpBufSave,\
				sizeof(jmp_buf));			\
		    	}						\
		    }							\
		(void)&&_finallyLabel;	/* avoid gcc warning */		\
		_finallyLabel:

/* This is requried after the FINALLY block */
#define ENDTRY	    if (_thrownValue != 0)				\
			THROW(_thrownValue);				\
		    if (_finallyReturn != NULL)				\
			goto *_finallyReturn;				\
		}

/* Throw an exception 't' which must be castable to type int */
#define THROW(t)    do {						\
			int value = (int) t;				\
			assert(value != 0);				\
			longjmp(_tryJmpBuf, value);			\
		    } while (0)

/* For use only within TRY or CATCH blocks (not FINALLY) */
#define RETURN(x...) do {						\
			__label__ _returnLabel;				\
			_finallyReturn = &&_returnLabel;		\
			goto _finallyLabel;				\
		    _returnLabel:					\
			return x;					\
		    } while (0)



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-java" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199911040210.SAA82085>