|
|
1 # define INCLUDE_FILE_IO
2 # include "dgd.h"
3 # include "str.h"
4 # include "array.h"
5 # include "object.h"
6 # include "interpret.h"
7 # include "comm.h"
8
9 typedef struct _context_ {
10 jmp_buf env; /* error context */
11 frame *f; /* frame context */
12 unsigned short offset; /* sp offset */
13 rlinfo *rlim; /* rlimits info */
14 ec_ftn handler; /* error handler */
15 struct _context_ *next; /* next in linked list */
16 } context;
17
18 static context firstcontext; /* bottom context */
19 static context *econtext; /* current error context */
20 static context *atomicec; /* first context beyond atomic */
21 static string *errstr; /* current error string */
22
23 /*
24 * NAME: errcontext->clear()
25 * DESCRIPTION: clear the error context string
26 */
27 void ec_clear()
28 {
29 if (errstr != (string *) NULL) {
30 str_del(errstr);
31 errstr = (string *) NULL;
32 }
33 }
34
35 /*
36 * NAME: errcontext->_push_()
37 * DESCRIPTION: push and return the current errorcontext
38 */
39 jmp_buf *_ec_push_(handler)
40 ec_ftn handler;
41 {
42 register context *e;
43
44 if (econtext == (context *) NULL) {
45 e = &firstcontext;
46 } else {
47 e = ALLOC(context, 1);
48 }
49 e->f = cframe;
50 e->offset = cframe->fp - cframe->sp;
51 e->rlim = cframe->rlim;
52
53 e->handler = handler;
54 e->next = econtext;
55 econtext = e;
56 return &e->env;
57 }
58
59 /*
60 * NAME: errcontext->pop()
61 * DESCRIPTION: pop the current errorcontext
62 */
63 void ec_pop()
64 {
65 register context *e;
66
67 e = econtext;
68 # ifdef DEBUG
69 if (e == (context *) NULL) {
70 fatal("pop empty error stack");
71 }
72 # endif
73 econtext = e->next;
74 if (e != &firstcontext) {
75 FREE(e);
76 } else {
77 ec_clear();
78 }
79 }
80
81 /*
82 * NAME: errorcontext->handler()
83 * DESCRIPTION: dummy handler for previously handled error
84 */
85 static void ec_handler(f, depth)
86 frame *f;
87 Int depth;
88 {
89 }
90
91 /*
92 * NAME: errorstr()
93 * DESCRIPTION: return the current error string
94 */
95 string *errorstr()
96 {
97 return errstr;
98 }
99
100 /*
101 * NAME: serror()
102 * DESCRIPTION: cause an error, with a string argument
103 */
104 void serror(str)
105 string *str;
106 {
107 jmp_buf env;
108 register context *e;
109 int offset;
110 ec_ftn handler;
111
112 if (str != (string *) NULL) {
113 if (errstr != (string *) NULL) {
114 str_del(errstr);
115 }
116 str_ref(errstr = str);
117 # ifdef DEBUG
118 } else if (errstr == (string *) NULL) {
119 fatal("no error string");
120 # endif
121 }
122
123 e = econtext;
124 offset = e->offset;
125 memcpy(&env, &e->env, sizeof(jmp_buf));
126
127 if (atomicec == (context *) NULL || atomicec == e) {
128 do {
129 if (cframe->level != e->f->level) {
130 if (atomicec == (context *) NULL) {
131 i_atomic_error(cframe, e->f->level);
132 if (e != econtext) {
133 atomicec = e;
134 break; /* handle rollback later */
135 }
136 }
137
138 cframe = i_restore(cframe, e->f->level);
139 atomicec = (context *) NULL;
140 }
141
142 if (e->handler != (ec_ftn) NULL) {
143 handler = e->handler;
144 e->handler = (ec_ftn) ec_handler;
145 (*handler)(cframe, e->f->depth);
146 break;
147 }
148 e = e->next;
149 } while (e != (context *) NULL);
150 }
151
152 if (cframe->rlim != econtext->rlim) {
153 i_set_rlimits(cframe, econtext->rlim);
154 }
155 cframe = i_set_sp(cframe, econtext->f->fp - offset);
156 cframe->rlim = econtext->rlim;
157 ec_pop();
158 longjmp(env, 1);
159 }
160
161 /*
162 * NAME: error()
163 * DESCRIPTION: cause an error
164 */
165 void error(format, arg1, arg2, arg3, arg4, arg5, arg6)
166 char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
167 {
168 char ebuf[4 * STRINGSZ];
169
170 if (format != (char *) NULL) {
171 sprintf(ebuf, format, arg1, arg2, arg3, arg4, arg5, arg6);
172 serror(str_new(ebuf, (long) strlen(ebuf)));
173 } else {
174 serror((string *) NULL);
175 }
176 }
177
178 /*
179 * NAME: fatal()
180 * DESCRIPTION: a fatal error has been encountered; terminate the program and
181 * dump a core if possible
182 */
183 void fatal(format, arg1, arg2, arg3, arg4, arg5, arg6)
184 char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
185 {
186 static short count;
187 char ebuf1[STRINGSZ], ebuf2[STRINGSZ];
188
189 if (count++ == 0) {
190 sprintf(ebuf1, format, arg1, arg2, arg3, arg4, arg5, arg6);
191 sprintf(ebuf2, "Fatal error: %s\012", ebuf1); /* LF */
192
193 P_message(ebuf2); /* show message */
194
195 comm_finish();
196 }
197 abort();
198 }
199
200 /*
201 * NAME: message()
202 * DESCRIPTION: issue a message on stderr
203 */
204 void message(format, arg1, arg2, arg3, arg4, arg5, arg6)
205 char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
206 {
207 char ebuf[4 * STRINGSZ];
208
209 if (format == (char *) NULL) {
210 # ifdef DEBUG
211 if (errstr == (string *) NULL) {
212 fatal("no error string");
213 }
214 # endif
215 if (errstr->len <= sizeof(ebuf) - 2) {
216 sprintf(ebuf, "%s\012", errstr->text);
217 } else {
218 strcpy(ebuf, "[too long error string]\012");
219 }
220 } else {
221 sprintf(ebuf, format, arg1, arg2, arg3, arg4, arg5, arg6);
222 }
223 P_message(ebuf); /* show message */
224 }
225
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.