File: Exception.c

package info (click to toggle)
oo2c64 1.5.0-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 8,904 kB
  • ctags: 5,775
  • sloc: ansic: 97,209; sh: 473; makefile: 344; perl: 57; lisp: 21
file content (240 lines) | stat: -rw-r--r-- 7,248 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*      $Id: Exception.c,v 1.10 1999/10/03 11:46:36 ooc-devel Exp $    */
/*  Provides facilities to raise and handle exceptions.
    Copyright (C) 1997, 1998, 1999  Michael van Acken

    This module is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public License
    as published by the Free Software Foundation; either version 2 of
    the License, or (at your option) any later version.

    This module is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with OOC. If not, write to the Free Software Foundation,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stddef.h>
#include <setjmp.h>
#include <string.h>

#include "__oo2c.h"
#include "__mini_gc.h"
#include "__config.h"

/* --- begin #include "Exception.d" */
#include "Exception.h"

/* local definitions */
Exception__Source Exception__halt;
Exception__Source Exception__assert;
Exception__Source Exception__signal;
Exception__Source Exception__runtime;

/* function prototypes */

/* module and type descriptors */
static const struct {
  int length;
  void* pad;
  const char name[10];
} _n0 = {10, NULL, {"Exception"}};
static struct _MD Exception_md = {
  NULL, 
  &Kernel__ModuleDesc_td.td, 
  {
    NULL, 
    (const unsigned char*)_n0.name, 
    -1, 
    NULL
  }
};

static const struct {
  int length;
  void* pad;
  const char name[20];
} _n1 = {20, NULL, {"SourceDesc"}};
static const struct {
  int length;
  void* pad;
  _Type btypes[1];
} Exception__SourceDesc_tdb = {
  1, 
  NULL, 
  {
    &Exception__SourceDesc_td.td
  }
};
static const struct {
  int length;
  void* pad;
  const void* tbprocs[1];
} _tb0 = {0, NULL, {
  NULL
}};
struct _TD Exception__SourceDesc_td = {
  NULL,
  &Types__TypeDesc_td.td,
  {
    Exception__SourceDesc_tdb.btypes,
    _tb0.tbprocs,
    (const unsigned char*)_n1.name,
    &Exception_md.md,
    0, 
    '0', '1',
    sizeof(Exception__SourceDesc),
    NULL
  }
};

/* local strings */

/* --- end #include "Exception.d" */


/* boolean variable to distinguish between normal and exception execution 
   state; the program starts in the state of normal execution, of course */
static int is_exception = 0;

/* current top of context stack; NULL means the stack is empty, the default
   exception handler should be used */
static _ExecutionContext top_context = NULL;

/* this variable is used to pass the exception source to the reactivation
   of PUSHCONTEXT: */
void* _Exception__source = NULL;

/* exception source associated with exceptions raised by this module */
static Exception__Source eexcept;
#define NORMAL_EXECUTION 1
#define EXCEPTIONAL_EXECUTION 2
#define STACK_EMPTY 3
#define INVALID_RAISE 4

/* the following variables describe together with _Exception__source the raised
   exception if the program is in the exceptional execution state: */
#define MESSAGE_LENGTH 128
static _ExecutionContext _Exception__context = NULL;
static LONGINT _Exception__number = 0;
static CHAR _Exception__message[MESSAGE_LENGTH];


#define STR_PARAM(text) (CHAR*)text,sizeof(text)


static _ModId _mid;

void _push_Exception__context(_ExecutionContext c) {
  c->next = top_context;
  top_context = c;
}

void Exception__POPCONTEXT(void) {
  if(top_context) {     /* stack isn't empty */
    if(is_exception) {
      /* pass exception along to next higher exception handler; since we are
         in an exception, RAISE will reactivate the second stack element */
      Exception__RAISE(_Exception__source, _Exception__number, 
                      _Exception__message,
                      strlen((char*)_Exception__message));
    } else {                    /* just pop top of stack */
      top_context = top_context->next;
    }
  } else {
    Exception__RAISE(eexcept, STACK_EMPTY,
                    STR_PARAM("[Exception] POPCONTEXT called while stack is empty"));
  }
}

void Exception__RETRY(void) {
  _exception_pos = 0;           /* clear file position */
  if(is_exception) {
    longjmp(*(jmp_buf*)_Exception__context->jmpbuf, -1);
  } else {
    Exception__RAISE(eexcept, NORMAL_EXECUTION, 
                    STR_PARAM("[Exception] RETRY called in normal execution state"));
  }
}

void Exception__ACKNOWLEDGE(void) {
  _exception_pos = 0;           /* clear file position */
  if(is_exception) {
    is_exception = 0;
  } else {
    Exception__RAISE(eexcept, NORMAL_EXECUTION, 
                    STR_PARAM("[Exception] ACKNOWLEDGE called in normal execution state"));
  }
}

void Exception__AllocateSource(Exception__Source *newSource) {
  NEW_REC(*newSource, Exception__SourceDesc);
}

void Exception__RAISE(Exception__Source source, LONGINT number, 
                     const CHAR* message__ref, LONGINT message_0d) {
  if (!source) {
    Exception__RAISE(eexcept, INVALID_RAISE, 
                    STR_PARAM("[Exception] First parameter of RAISE is NIL"));
  }
    
  if(is_exception) {
    /* if an exception was raised while handling an exception, pop the topmost
       context that caused the second exception and reactivate the context 
       below it to deal with the new exception */
    top_context = top_context->next;
  } else {
    is_exception = 1;
  }
  /* store information describing the current exception in global variables */
  _Exception__source = source;
  _Exception__number = number;
  _Exception__context = top_context;
  _string_copy(_Exception__message, message__ref, MESSAGE_LENGTH);
  if (_Exception__context) {
    /* reactivate topmost context */
    longjmp(*(jmp_buf*)_Exception__context->jmpbuf, 1);
  } else {
    /* oops, stack is empty; use default exception handler from __oo2c.c --
       it'll write a nice message and abort */
    _default_exception_handler(source, number, message__ref);
  }
}

LONGINT Exception__CurrentNumber(Exception__Source source) {
  if(is_exception) {
    return _Exception__number;
  } else {
    Exception__RAISE(eexcept, NORMAL_EXECUTION, 
                    STR_PARAM("[Exception] CurrentNumber called in normal execution state"));
    return 0;  /* never reached */
  }
}

void Exception__GetMessage(CHAR* text, LONGINT text_0d) {
  if(is_exception) {
    _string_copy(text, _Exception__message, text_0d);
  } else {
    Exception__RAISE(eexcept, NORMAL_EXECUTION, 
                    STR_PARAM("[Exception] GetMessage called in normal execution state"));
  }
}

BOOLEAN Exception__IsExceptionalExecution(void) {
  return (BOOLEAN)(is_exception != 0);
}

void Exception_init(void) {
  _mid = _register_module(&Exception_md.md, &Exception__SourceDesc_td.td);
  Exception__AllocateSource(&eexcept);
  Exception__AllocateSource(&Exception__halt);
  Exception__AllocateSource(&Exception__assert);
  Exception__AllocateSource(&Exception__runtime);
  Exception__AllocateSource(&Exception__signal);
  _exception_halt = Exception__halt;
  _exception_assert = Exception__assert;
  _exception_raise = (void (*) (void*, LONGINT, const CHAR*, LONGINT)) Exception__RAISE;
}