aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-09-25 13:22:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-09-25 13:22:42 -0300
commit13635f7de7c51b26c447ce444a2c045cba83fe7c (patch)
treeb9461626b368e8ca1161b01e2771447898fdecd8
parentd8a442206d2845e1749cc36dd59208428ef1d117 (diff)
downloadlua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.gz
lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.bz2
lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.zip
new version of protected execution
-rw-r--r--ldo.c168
-rw-r--r--ldo.h6
-rw-r--r--lstate.c49
-rw-r--r--lstate.h14
-rw-r--r--ltests.c12
5 files changed, 149 insertions, 100 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
diff --git a/ldo.h b/ldo.h
index becbf417..da52e496 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $ 2** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 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*/
@@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra);
24void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); 24void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
25void luaD_call (lua_State *L, StkId func, int nResults); 25void luaD_call (lua_State *L, StkId func, int nResults);
26void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); 26void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
27void luaD_breakrun (lua_State *L, int errcode);
28void luaD_checkstack (lua_State *L, int n); 27void luaD_checkstack (lua_State *L, int n);
29 28
29void luaD_breakrun (lua_State *L, int errcode);
30int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud);
31
30 32
31#endif 33#endif
diff --git a/lstate.c b/lstate.c
index d315e976..71671785 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $ 2** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -20,7 +20,7 @@
20 20
21 21
22#ifdef DEBUG 22#ifdef DEBUG
23extern lua_State *lua_state; 23static lua_State *lua_state = NULL;
24void luaB_opentests (lua_State *L); 24void luaB_opentests (lua_State *L);
25#endif 25#endif
26 26
@@ -38,8 +38,29 @@ static int errormessage (lua_State *L) {
38} 38}
39 39
40 40
41/*
42** open parts that may cause memory-allocation errors
43*/
44static void f_luaopen (lua_State *L, void *ud) {
45 int stacksize = *(int *)ud;
46 if (stacksize == 0)
47 stacksize = DEFAULT_STACK_SIZE;
48 else
49 stacksize += LUA_MINSTACK;
50 L->gt = luaH_new(L, 10);
51 luaD_init(L, stacksize);
52 luaS_init(L);
53 luaX_init(L);
54 luaT_init(L);
55 lua_register(L, LUA_ERRORMESSAGE, errormessage);
56#ifdef DEBUG
57 luaB_opentests(L);
58 if (lua_state == NULL) lua_state = L; /* keep first state to be opened */
59#endif
60}
61
62
41lua_State *lua_open (int stacksize) { 63lua_State *lua_open (int stacksize) {
42 struct lua_longjmp myErrorJmp;
43 lua_State *L = luaM_new(NULL, lua_State); 64 lua_State *L = luaM_new(NULL, lua_State);
44 if (L == NULL) return NULL; /* memory allocation error */ 65 if (L == NULL) return NULL; /* memory allocation error */
45 L->stack = NULL; 66 L->stack = NULL;
@@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) {
62 L->callhook = NULL; 83 L->callhook = NULL;
63 L->linehook = NULL; 84 L->linehook = NULL;
64 L->allowhooks = 1; 85 L->allowhooks = 1;
65 L->errorJmp = &myErrorJmp; 86 L->errorJmp = NULL;
66 if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */ 87 if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) {
67 L->gt = luaH_new(L, 10); 88 /* memory allocation error: free partial state */
68 luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE :
69 stacksize+LUA_MINSTACK);
70 luaS_init(L);
71 luaX_init(L);
72 luaT_init(L);
73 lua_register(L, LUA_ERRORMESSAGE, errormessage);
74#ifdef DEBUG
75 luaB_opentests(L);
76#endif
77 L->GCthreshold = L->nblocks*4;
78 L->errorJmp = NULL;
79 return L;
80 }
81 else { /* memory allocation error: free partial state */
82 lua_close(L); 89 lua_close(L);
83 return NULL; 90 return NULL;
84 } 91 }
92 L->GCthreshold = L->nblocks*4;
93 return L;
85} 94}
86 95
87 96
diff --git a/lstate.h b/lstate.h
index 66ae964d..8d54e932 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $ 2** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -7,8 +7,6 @@
7#ifndef lstate_h 7#ifndef lstate_h
8#define lstate_h 8#define lstate_h
9 9
10#include <setjmp.h>
11
12#include "lobject.h" 10#include "lobject.h"
13#include "lua.h" 11#include "lua.h"
14#include "luadebug.h" 12#include "luadebug.h"
@@ -33,15 +31,7 @@ struct Ref {
33}; 31};
34 32
35 33
36/* 34struct lua_longjmp; /* defined in ldo.c */
37** chain list of long jumps
38*/
39struct lua_longjmp {
40 jmp_buf b;
41 struct lua_longjmp *previous;
42 volatile int status; /* error code */
43 StkId base;
44};
45 35
46 36
47typedef struct stringtable { 37typedef struct stringtable {
diff --git a/ltests.c b/ltests.c
index fe0ed439..85bfaad8 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $ 2** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -422,11 +422,19 @@ static int testC (lua_State *L) {
422 else if EQ("concat") { 422 else if EQ("concat") {
423 lua_concat(L, getnum); 423 lua_concat(L, getnum);
424 } 424 }
425 else if EQ("call") { 425 else if EQ("rawcall") {
426 int narg = getnum; 426 int narg = getnum;
427 int nres = getnum; 427 int nres = getnum;
428 lua_rawcall(L, narg, nres); 428 lua_rawcall(L, narg, nres);
429 } 429 }
430 else if EQ("call") {
431 int narg = getnum;
432 int nres = getnum;
433 lua_call(L, narg, nres);
434 }
435 else if EQ("dostring") {
436 lua_dostring(L, luaL_check_string(L, getnum));
437 }
430 else if EQ("type") { 438 else if EQ("type") {
431 lua_pushstring(L, lua_type(L, getnum)); 439 lua_pushstring(L, lua_type(L, getnum));
432 } 440 }