

/*************************************************************************/
/* Package name  : Except.                                               */
/* Version       : 1.0                                                   */
/* Completed     : April 1993.                                           */
/* Released      : 29 September 1993.                                    */
/* First created : This package was first created in April 1993.         */
/* Summary       : This package provides Ada-like exceptions for C.      */
/* Components    : except.fw  - FunnelWeb source file.                   */
/*                 except.h   - Exported header file.                    */
/*                 except.c   - Implementation file.                     */
/*                 ex_test.c  - C test program.                          */
/* Requires      : style.h, as.h, as.c.                                  */
/* Author        : Ross N. Williams (ross@guest.adelaide.edu.au)         */
/*                 Rocksoft^tm Pty Ltd                                   */
/*                 16 Lerwick Avenue, Hazelwood Park 5066, Australia.    */
/* FTP Archive   : This file can be found in                             */
/*                 "ftp.adelaide.edu.au/pub/funnelweb/examples/"         */
/* Disclaimer    : This program is distributed WITHOUT ANY WARRANTY;     */
/*                 without even the implied warranty of MERCHANTABILITY  */
/*                 or FITNESS FOR A PARTICULAR PURPOSE.                  */
/* Copyright     : Copyright (C) Ross Williams 1993.                     */
/*                 However, permission is granted for anyone to copy,    */
/*                 modify, and distribute this work for any purpose,     */
/*                 commercial or non-commercial, so long as this notice  */
/*                 is included verbatim, and so long as all              */
/*                 modifications are recorded in the change log below.   */
/* Changes       : Please log any changes to this software either in the */
/*                 originating FunnelWeb source file, or, if you must,   */
/*                 in the C source files produced from the FunnelWeb     */
/*                 file.                                                 */
/* --<Start of Change Log>--                                             */
/* ??-Apr-93: RNW: Created this package.                                 */
/* 29-Sep-93: RNW: Released this package.                                */
/* --<End of Change Log>--                                               */
/*************************************************************************/

#ifndef _EX_DONE
#define _EX_DONE 1

#include "style.h"
#include <setjmp.h>


typedef string p_ex_t;
#define EX_EXCEPT(NAME)      extern const p_ex_t NAME
#define EX_EXPORT(NAME,DESC)        const p_ex_t NAME = DESC
#define EX_LOCAL(NAME,DESC)  static const p_ex_t NAME = DESC



#define _EX_FAST FALSE
/* Set _EX_FAST to TRUE to turn on inlining and turn off checking. */


#define _EX_THRD FALSE
/* To configure this package to work under a multi-threaded environment, */
/* set _EX_THRD to TRUE and modify the k_var calls later on in the file. */


typedef struct _ex_cxt_
  {
#if !_EX_FAST
   ulong _ex_mag1;  /* Header magic number. */
#endif
   jmp_buf          _ex_jmbf;  /* Exception block context.          */
   struct _ex_cxt_ *_ex_prev;  /* Pointer to previous stack record. */
#if !_EX_FAST
   ulong _ex_mag2;  /* Trailer magic number. */
#endif
  } _ex_cx_t;

#define _EX_MAG1 0xFB8A5D30
#define _EX_MAG2 0x09F2E7A2


#if !_EX_THRD
extern _ex_cx_t *_ex_curr;
extern p_ex_t    _ex_id;
extern ptrint    _ex_info;
#endif


#if !_EX_THRD
/* Non-threaded system macros simply point to variables. */
#define _EX_CURR _ex_curr
#define  EX_ID   ((p_ex_t) _ex_id)
#define _EX_ID   _ex_id
#define  EX_INFO _ex_info
#else
/* Threaded system macros translate to kernel calls.          */
/* To make this package work in a multi-threaded environment, */
/* set _EX_THRD to TRUE and modify these definitions.         */
/* Note: The kernel should initialize _EX_CURR to NULL.       */
#define _EX_CURR           (* ((_ex_cx_t *) k_var(51)))
#define  EX_ID   ((p_ex_t) (* ((p_ex_t   *) k_var(52))))
#define _EX_ID             (* ((p_ex_t   *) k_var(52)))
#define  EX_INFO           (* ((ptrint   *) k_var(53)))
#endif



#if _EX_FAST
#define EX_RAISE(P_EX) {_EX_ID = (P_EX); longjmp(_EX_CURR->_ex_jmbf,NON_ZERO);}
#else
#define EX_RAISE(P_EX) {_exrai(P_EX);}
#endif


#if _EX_FAST
#define EX_BEGIN    \
{_ex_cx_t _ex_cxlc;              \
 _ex_cxlc._ex_prev = _EX_CURR;   \
 _EX_CURR          = &_ex_cxlc;  \
 if (!setjmp(_ex_cxlc._ex_jmbf)) { 
#define EX_FORGET      ;EX_POP} else {EX_POP; if (FALSE) {
#define EX_WHEN(P_EX)  } else if ((P_EX) == (EX_ID)) {
#define EX_OTHERS      } else if (TRUE) {
#define EX_END         } else longjmp(_EX_CURR->_ex_jmbf,NON_ZERO); }}
#define EX_POP         {_EX_CURR = _EX_CURR->_ex_prev;}
#else
#define EX_BEGIN    \
{_ex_cx_t _ex_cxlc;              \
 _ex_cxlc._ex_mag1 = _EX_MAG1;   \
 _ex_cxlc._ex_mag2 = _EX_MAG2;   \
 _ex_cxlc._ex_prev = _EX_CURR;   \
 _EX_CURR          = &_ex_cxlc;  \
 if (!setjmp(_ex_cxlc._ex_jmbf)) { 
#define EX_FORGET      ;EX_POP} else {EX_POP; if (FALSE) {
#define EX_WHEN(P_EX)  } else if ((P_EX) == (EX_ID)) {
#define EX_OTHERS      } else if (TRUE) {
#define EX_END         } else _exrai(EX_ID); }}
#define EX_POP         {_expop(&_ex_cxlc);}
#endif

EXPORT string ex_str P_((p_ex_t));

EXPORT void _exrai P_((p_ex_t));
EXPORT void _expop P_((_ex_cx_t *));

#endif

