diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 168 |
1 files changed, 104 insertions, 64 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
199 | } | 199 | } |
200 | 200 | ||
201 | 201 | ||
202 | static void message (lua_State *L, const char *s) { | ||
203 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
204 | if (*luaO_typename(em) == 'f') { | ||
205 | *L->top = *em; | ||
206 | incr_top; | ||
207 | lua_pushstring(L, s); | ||
208 | luaD_call(L, L->top-2, 0); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | |||
213 | void luaD_breakrun (lua_State *L, int errcode) { | ||
214 | if (L->errorJmp) { | ||
215 | L->errorJmp->status = errcode; | ||
216 | longjmp(L->errorJmp->b, 1); | ||
217 | } | ||
218 | else { | ||
219 | if (errcode != LUA_ERRMEM) | ||
220 | message(L, "unable to recover; exiting\n"); | ||
221 | exit(EXIT_FAILURE); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /* | 202 | /* |
226 | ** Reports an error, and jumps up to the available recovery label | 203 | ** Execute a protected call. |
227 | */ | 204 | */ |
228 | void lua_error (lua_State *L, const char *s) { | 205 | struct CallS { /* data to `f_call' */ |
229 | if (s) message(L, s); | 206 | StkId func; |
230 | luaD_breakrun(L, LUA_ERRRUN); | 207 | int nresults; |
231 | } | 208 | }; |
232 | 209 | ||
233 | 210 | static void f_call (lua_State *L, void *ud) { | |
234 | static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { | 211 | struct CallS *c = (struct CallS *)ud; |
235 | lj->status = 0; | 212 | luaD_call(L, c->func, c->nresults); |
236 | lj->base = L->Cbase; | ||
237 | lj->previous = L->errorJmp; | ||
238 | L->errorJmp = lj; | ||
239 | } | 213 | } |
240 | 214 | ||
241 | 215 | ||
242 | static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) { | 216 | int lua_call (lua_State *L, int nargs, int nresults) { |
243 | L->Cbase = lj->base; | 217 | StkId func = L->top - (nargs+1); /* function to be called */ |
244 | L->errorJmp = lj->previous; | 218 | struct CallS c; |
245 | return lj->status; | 219 | int status; |
220 | c.func = func; c.nresults = nresults; | ||
221 | status = luaD_runprotected(L, f_call, &c); | ||
222 | if (status != 0) /* an error occurred? */ | ||
223 | L->top = func; /* remove parameters from the stack */ | ||
224 | return status; | ||
246 | } | 225 | } |
247 | 226 | ||
248 | 227 | ||
249 | /* | 228 | /* |
250 | ** Execute a protected call. | 229 | ** Execute a protected parser. |
251 | */ | 230 | */ |
252 | int lua_call (lua_State *L, int nargs, int nresults) { | 231 | struct ParserS { /* data to `f_parser' */ |
253 | StkId func = L->top - (nargs+1); /* function to be called */ | 232 | ZIO *z; |
254 | struct lua_longjmp myErrorJmp; | 233 | int bin; |
255 | chain_longjmp(L, &myErrorJmp); | 234 | }; |
256 | if (setjmp(myErrorJmp.b) == 0) { | 235 | |
257 | luaD_call(L, func, nresults); | 236 | static void f_parser (lua_State *L, void *ud) { |
258 | } | 237 | struct ParserS *p = (struct ParserS *)ud; |
259 | else { /* an error occurred: restore the state */ | 238 | Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); |
260 | L->top = func; /* remove garbage from the stack */ | 239 | luaV_Lclosure(L, tf, 0); |
261 | restore_stack_limit(L); | ||
262 | } | ||
263 | return restore_longjmp(L, &myErrorJmp); | ||
264 | } | 240 | } |
265 | 241 | ||
266 | 242 | ||
267 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 243 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
268 | struct lua_longjmp myErrorJmp; | 244 | struct ParserS p; |
269 | unsigned long old_blocks; | 245 | unsigned long old_blocks; |
246 | int status; | ||
247 | p.z = z; p.bin = bin; | ||
270 | luaC_checkGC(L); | 248 | luaC_checkGC(L); |
271 | old_blocks = L->nblocks; | 249 | old_blocks = L->nblocks; |
272 | chain_longjmp(L, &myErrorJmp); | 250 | status = luaD_runprotected(L, f_parser, &p); |
273 | if (setjmp(myErrorJmp.b) == 0) { | 251 | if (status == LUA_ERRRUN) /* an error occurred: correct error code */ |
274 | Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z); | 252 | status = LUA_ERRSYNTAX; |
275 | luaV_Lclosure(L, tf, 0); | ||
276 | } | ||
277 | else { /* an error occurred: correct error code */ | ||
278 | if (myErrorJmp.status == LUA_ERRRUN) | ||
279 | myErrorJmp.status = LUA_ERRSYNTAX; | ||
280 | } | ||
281 | /* add new memory to threshould (as it probably will stay) */ | 253 | /* add new memory to threshould (as it probably will stay) */ |
282 | L->GCthreshold += (L->nblocks - old_blocks); | 254 | L->GCthreshold += (L->nblocks - old_blocks); |
283 | return restore_longjmp(L, &myErrorJmp); /* error code */ | 255 | return status; |
284 | } | 256 | } |
285 | 257 | ||
286 | 258 | ||
@@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) { | |||
339 | return lua_dobuffer(L, str, strlen(str), str); | 311 | return lua_dobuffer(L, str, strlen(str), str); |
340 | } | 312 | } |
341 | 313 | ||
314 | |||
315 | /* | ||
316 | ** {====================================================== | ||
317 | ** Error-recover functions (based on long jumps) | ||
318 | ** ======================================================= | ||
319 | */ | ||
320 | |||
321 | /* chain list of long jump buffers */ | ||
322 | struct lua_longjmp { | ||
323 | jmp_buf b; | ||
324 | struct lua_longjmp *previous; | ||
325 | volatile int status; /* error code */ | ||
326 | }; | ||
327 | |||
328 | |||
329 | static void message (lua_State *L, const char *s) { | ||
330 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
331 | if (*luaO_typename(em) == 'f') { | ||
332 | *L->top = *em; | ||
333 | incr_top; | ||
334 | lua_pushstring(L, s); | ||
335 | luaD_call(L, L->top-2, 0); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | ** Reports an error, and jumps up to the available recovery label | ||
342 | */ | ||
343 | void lua_error (lua_State *L, const char *s) { | ||
344 | if (s) message(L, s); | ||
345 | luaD_breakrun(L, LUA_ERRRUN); | ||
346 | } | ||
347 | |||
348 | |||
349 | void luaD_breakrun (lua_State *L, int errcode) { | ||
350 | if (L->errorJmp) { | ||
351 | L->errorJmp->status = errcode; | ||
352 | longjmp(L->errorJmp->b, 1); | ||
353 | } | ||
354 | else { | ||
355 | if (errcode != LUA_ERRMEM) | ||
356 | message(L, "unable to recover; exiting\n"); | ||
357 | exit(EXIT_FAILURE); | ||
358 | } | ||
359 | } | ||
360 | |||
361 | |||
362 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | ||
363 | StkId oldCbase = L->Cbase; | ||
364 | StkId oldtop = L->top; | ||
365 | struct lua_longjmp lj; | ||
366 | lj.status = 0; | ||
367 | lj.previous = L->errorJmp; /* chain new error handler */ | ||
368 | L->errorJmp = &lj; | ||
369 | if (setjmp(lj.b) == 0) | ||
370 | (*f)(L, ud); | ||
371 | else { /* an error occurred: restore the state */ | ||
372 | L->Cbase = oldCbase; | ||
373 | L->top = oldtop; | ||
374 | restore_stack_limit(L); | ||
375 | } | ||
376 | L->errorJmp = lj.previous; /* restore old error handler */ | ||
377 | return lj.status; | ||
378 | } | ||
379 | |||
380 | /* }====================================================== */ | ||
381 | |||