aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c168
1 files changed, 104 insertions, 64 deletions
diff --git a/ldo.c b/ldo.c
index 9d981468..8f49b595 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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
202static 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
213void 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*/
228void lua_error (lua_State *L, const char *s) { 205struct 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 210static void f_call (lua_State *L, void *ud) {
234static 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
242static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) { 216int 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*/
252int lua_call (lua_State *L, int nargs, int nresults) { 231struct 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); 236static 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
267static int protectedparser (lua_State *L, ZIO *z, int bin) { 243static 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 */
322struct lua_longjmp {
323 jmp_buf b;
324 struct lua_longjmp *previous;
325 volatile int status; /* error code */
326};
327
328
329static 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*/
343void lua_error (lua_State *L, const char *s) {
344 if (s) message(L, s);
345 luaD_breakrun(L, LUA_ERRRUN);
346}
347
348
349void 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
362int 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