aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-08-05 14:36:24 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-08-05 14:36:24 -0300
commit4e23699aa647fd9dc04933bf5582217ca594c8ce (patch)
tree03d4f407c2f8974a62837a7d71f417c833aedd99
parent1c0ac3c0f53720c53dcfae13308b11b29dca38e4 (diff)
downloadlua-4e23699aa647fd9dc04933bf5582217ca594c8ce.tar.gz
lua-4e23699aa647fd9dc04933bf5582217ca594c8ce.tar.bz2
lua-4e23699aa647fd9dc04933bf5582217ca594c8ce.zip
new implementation for error handling
-rw-r--r--lauxlib.c15
-rw-r--r--ldblib.c21
-rw-r--r--ldo.c275
-rw-r--r--ldo.h11
-rw-r--r--lstate.c23
-rw-r--r--lstate.h31
-rw-r--r--luadebug.h3
-rw-r--r--lvm.c150
-rw-r--r--lvm.h9
9 files changed, 279 insertions, 259 deletions
diff --git a/lauxlib.c b/lauxlib.c
index d66250b3..01bcf9a1 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.77 2002/06/26 19:28:44 roberto Exp roberto $ 2** $Id: lauxlib.c,v 1.78 2002/07/01 19:23:58 roberto Exp $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -394,21 +394,20 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
394 394
395static void callalert (lua_State *L, int status) { 395static void callalert (lua_State *L, int status) {
396 if (status != 0) { 396 if (status != 0) {
397 int top;
398 if (status == LUA_ERRRUN)
399 lua_concat(L, 2); /* concat error message and traceback */
400 top = lua_gettop(L);
401 lua_getglobal(L, "_ALERT"); 397 lua_getglobal(L, "_ALERT");
402 lua_insert(L, -2); 398 lua_insert(L, -2);
403 lua_pcall(L, 1, 0); 399 lua_call(L, 1, 0);
404 lua_settop(L, top-1); 400 lua_pop(L, 1);
405 } 401 }
406} 402}
407 403
408 404
409static int aux_do (lua_State *L, int status) { 405static int aux_do (lua_State *L, int status) {
410 if (status == 0) /* parse OK? */ 406 if (status == 0) { /* parse OK? */
411 status = lua_pcall(L, 0, LUA_MULTRET); /* call main */ 407 status = lua_pcall(L, 0, LUA_MULTRET); /* call main */
408 if (status != 0)
409 lua_pcallreset(L);
410 }
412 callalert(L, status); 411 callalert(L, status);
413 return status; 412 return status;
414} 413}
diff --git a/ldblib.c b/ldblib.c
index 13e328d3..c86a12b4 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldblib.c,v 1.63 2002/07/08 20:22:08 roberto Exp roberto $ 2** $Id: ldblib.c,v 1.64 2002/07/17 16:25:13 roberto Exp roberto $
3** Interface from Lua to its debug API 3** Interface from Lua to its debug API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -194,15 +194,11 @@ static int debug (lua_State *L) {
194static int errorfb (lua_State *L) { 194static int errorfb (lua_State *L) {
195 int level = 1; /* skip level 0 (it's this function) */ 195 int level = 1; /* skip level 0 (it's this function) */
196 int firstpart = 1; /* still before eventual `...' */ 196 int firstpart = 1; /* still before eventual `...' */
197 int alllevels = 1;
198 const char *msg = lua_tostring(L, 1);
199 lua_Debug ar; 197 lua_Debug ar;
200 lua_settop(L, 0); 198 if (lua_gettop(L) == 0)
201 if (msg) { 199 lua_pushliteral(L, "");
202 alllevels = 0; 200 else if (!lua_isstring(L, 1)) return 1; /* no string message */
203 if (!strstr(msg, "stack traceback:\n")) 201 lua_pushliteral(L, "stack traceback:\n");
204 lua_pushliteral(L, "stack traceback:\n");
205 }
206 while (lua_getstack(L, level++, &ar)) { 202 while (lua_getstack(L, level++, &ar)) {
207 if (level > LEVELS1 && firstpart) { 203 if (level > LEVELS1 && firstpart) {
208 /* no more than `LEVELS2' more levels? */ 204 /* no more than `LEVELS2' more levels? */
@@ -217,7 +213,7 @@ static int errorfb (lua_State *L) {
217 continue; 213 continue;
218 } 214 }
219 lua_pushliteral(L, "\t"); 215 lua_pushliteral(L, "\t");
220 lua_getinfo(L, "Snlc", &ar); 216 lua_getinfo(L, "Snl", &ar);
221 lua_pushfstring(L, "%s:", ar.short_src); 217 lua_pushfstring(L, "%s:", ar.short_src);
222 if (ar.currentline > 0) 218 if (ar.currentline > 0)
223 lua_pushfstring(L, "%d:", ar.currentline); 219 lua_pushfstring(L, "%d:", ar.currentline);
@@ -240,7 +236,6 @@ static int errorfb (lua_State *L) {
240 } 236 }
241 lua_pushliteral(L, "\n"); 237 lua_pushliteral(L, "\n");
242 lua_concat(L, lua_gettop(L)); 238 lua_concat(L, lua_gettop(L));
243 if (!alllevels && ar.isprotected) break;
244 } 239 }
245 lua_concat(L, lua_gettop(L)); 240 lua_concat(L, lua_gettop(L));
246 return 1; 241 return 1;
@@ -261,9 +256,9 @@ static const luaL_reg dblib[] = {
261 256
262LUALIB_API int lua_dblibopen (lua_State *L) { 257LUALIB_API int lua_dblibopen (lua_State *L) {
263 luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0); 258 luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
264 lua_pushliteral(L, LUA_TRACEBACK); 259 lua_pushliteral(L, "_TRACEBACK");
265 lua_pushcfunction(L, errorfb); 260 lua_pushcfunction(L, errorfb);
266 lua_settable(L, LUA_REGISTRYINDEX); 261 lua_settable(L, LUA_GLOBALSINDEX);
267 return 0; 262 return 0;
268} 263}
269 264
diff --git a/ldo.c b/ldo.c
index 55f7958f..e6307b0c 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.187 2002/07/09 18:19:19 roberto Exp roberto $ 2** $Id: ldo.c,v 1.188 2002/07/16 14:26:56 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*/
@@ -29,40 +29,113 @@
29 29
30 30
31 31
32/*
33** {======================================================
34** Error-recovery functions (based on long jumps)
35** =======================================================
36*/
37
38
32/* chain list of long jump buffers */ 39/* chain list of long jump buffers */
33struct lua_longjmp { 40struct lua_longjmp {
34 struct lua_longjmp *previous; 41 struct lua_longjmp *previous;
35 CallInfo *ci; /* index of call info of active function that set protection */
36 StkId top; /* top stack when protection was set */
37 jmp_buf b; 42 jmp_buf b;
38 int allowhooks; /* `allowhook' state when protection was set */
39 volatile int status; /* error code */ 43 volatile int status; /* error code */
40 TObject *err; /* error messages (start of `ud') */
41}; 44};
42 45
43 46
44static void pusherrormsg (lua_State *L, int status, TObject *err) { 47static void seterrorobj (lua_State *L, int errcode) {
45 setobj(L->top++, &err[0]); 48 switch (errcode) {
46 if (status == LUA_ERRRUN) 49 case LUA_ERRMEM: {
47 setobj(L->top++, &err[1]); 50 setsvalue(L->top, luaS_new(L, MEMERRMSG));
51 break;
52 }
53 case LUA_ERRERR: {
54 setsvalue(L->top, luaS_new(L, "error in error handling"));
55 break;
56 }
57 case LUA_ERRSYNTAX:
58 case LUA_ERRRUN: {
59 return; /* error message already on top */
60 }
61 }
62 L->top++;
63}
64
65
66void luaD_throw (lua_State *L, int errcode) {
67 if (errcode == LUA_ERRRUN)
68 luaD_checkstack(L, LUA_MINSTACK); /* ensure stack space to handle error */
69 luaG_saveallpcs(L); /* C stack will disapear */
70 if (L->errorJmp) {
71 L->errorJmp->status = errcode;
72 longjmp(L->errorJmp->b, 1);
73 }
74 else {
75 G(L)->panic(L);
76 exit(EXIT_FAILURE);
77 }
78}
79
80
81int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
82 struct lua_longjmp lj;
83 lj.status = 0;
84 lj.previous = L->errorJmp; /* chain new error handler */
85 L->errorJmp = &lj;
86 if (setjmp(lj.b) == 0)
87 (*f)(L, ud);
88 L->errorJmp = lj.previous; /* restore old error handler */
89 return lj.status;
90}
91
92
93static void restore_stack_limit (lua_State *L) {
94 L->stack_last = L->stack+L->stacksize-1;
95 if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
96 int inuse = (L->ci - L->base_ci);
97 if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
98 luaD_reallocCI(L, LUA_MAXCALLS);
99 }
48} 100}
49 101
50 102
103void luaD_resetprotection (lua_State *L) {
104 Protection *p;
105 StkId err = L->top - 1; /* error msg. position (if there is one) */
106 lua_assert(L->number_toreset > 0);
107 p = &L->toreset[--L->number_toreset];
108 L->ci = restoreci(L, p->ci);
109 L->top = restorestack(L, p->top);
110 L->ci->top = L->top + LUA_MINSTACK;
111 setallowhook(L, p->allowhooks);
112 restore_stack_limit(L);
113 setobj(L->top++, err); /* copy error message to corrected top */
114}
115
116
117/*
118** invalidate all pc pointers from stack part that becomes inactive
119*/
120static void deactivateinfo (lua_State *L, CallInfo *p_ci) {
121 CallInfo *ci;
122 for (ci = L->ci; ci > p_ci; ci--)
123 ci->pc = NULL;
124}
125
126/* }====================================================== */
127
128
51static void correctstack (lua_State *L, TObject *oldstack) { 129static void correctstack (lua_State *L, TObject *oldstack) {
52 struct lua_longjmp *lj;
53 CallInfo *ci; 130 CallInfo *ci;
54 UpVal *up; 131 UpVal *up;
55 L->top = (L->top - oldstack) + L->stack; 132 L->top = (L->top - oldstack) + L->stack;
56 for (lj = L->errorJmp; lj != NULL; lj = lj->previous)
57 lj->top = (lj->top - oldstack) + L->stack;
58 for (up = L->openupval; up != NULL; up = up->next) 133 for (up = L->openupval; up != NULL; up = up->next)
59 up->v = (up->v - oldstack) + L->stack; 134 up->v = (up->v - oldstack) + L->stack;
60 for (ci = L->base_ci; ci <= L->ci; ci++) { 135 for (ci = L->base_ci; ci <= L->ci; ci++) {
61 ci->base = (ci->base - oldstack) + L->stack; 136 ci->base = (ci->base - oldstack) + L->stack;
62 ci->top = (ci->top - oldstack) + L->stack; 137 ci->top = (ci->top - oldstack) + L->stack;
63 if (isLua(ci) && /* is a Lua function... */ 138 if (ci->pc && ci->pc != &luaV_callingmark) /* function has a frame? */
64 !(isLua(ci-1) && /* and next is not a Lua function... */
65 ci->u.l.pc == (ci-1)->u.l.pc)) /* sharing the same C frame? */
66 *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ 139 *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
67 } 140 }
68} 141}
@@ -72,35 +145,17 @@ void luaD_reallocstack (lua_State *L, int newsize) {
72 TObject *oldstack = L->stack; 145 TObject *oldstack = L->stack;
73 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); 146 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
74 L->stacksize = newsize; 147 L->stacksize = newsize;
75 L->stack_last = L->stack+(newsize-EXTRA_STACK)-1; 148 L->stack_last = L->stack+newsize-1-EXTRA_STACK;
76 correctstack(L, oldstack); 149 correctstack(L, oldstack);
77} 150}
78 151
79 152
80static void correctCI (lua_State *L, CallInfo *oldci) {
81 struct lua_longjmp *lj;
82 for (lj = L->errorJmp; lj != NULL; lj = lj->previous) {
83 lj->ci = (lj->ci - oldci) + L->base_ci;
84 }
85}
86
87
88void luaD_reallocCI (lua_State *L, int newsize) { 153void luaD_reallocCI (lua_State *L, int newsize) {
89 CallInfo *oldci = L->base_ci; 154 CallInfo *oldci = L->base_ci;
90 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); 155 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
91 L->size_ci = newsize; 156 L->size_ci = newsize;
92 L->ci = (L->ci - oldci) + L->base_ci; 157 L->ci = (L->ci - oldci) + L->base_ci;
93 L->end_ci = L->base_ci + L->size_ci; 158 L->end_ci = L->base_ci + L->size_ci;
94 correctCI(L, oldci);
95}
96
97
98static void restore_stack_limit (lua_State *L) {
99 if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
100 int inuse = (L->ci - L->base_ci);
101 if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
102 luaD_reallocCI(L, LUA_MAXCALLS);
103 }
104} 159}
105 160
106 161
@@ -175,7 +230,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
175 const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); 230 const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
176 StkId p; 231 StkId p;
177 ptrdiff_t funcr = savestack(L, func); 232 ptrdiff_t funcr = savestack(L, func);
178 if (ttype(tm) != LUA_TFUNCTION) 233 if (!ttisfunction(tm))
179 luaG_typeerror(L, func, "call"); 234 luaG_typeerror(L, func, "call");
180 /* Open a hole inside the stack at `func' */ 235 /* Open a hole inside the stack at `func' */
181 for (p = L->top; p > func; p--) setobj(p, p-1); 236 for (p = L->top; p > func; p--) setobj(p, p-1);
@@ -189,7 +244,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
189StkId luaD_precall (lua_State *L, StkId func) { 244StkId luaD_precall (lua_State *L, StkId func) {
190 LClosure *cl; 245 LClosure *cl;
191 ptrdiff_t funcr = savestack(L, func); 246 ptrdiff_t funcr = savestack(L, func);
192 if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */ 247 if (!ttisfunction(func)) /* `func' is not a function? */
193 func = tryfuncTM(L, func); /* check the `function' tag method */ 248 func = tryfuncTM(L, func); /* check the `function' tag method */
194 if (L->ci + 1 == L->end_ci) luaD_growCI(L); 249 if (L->ci + 1 == L->end_ci) luaD_growCI(L);
195 cl = &clvalue(func)->l; 250 cl = &clvalue(func)->l;
@@ -202,7 +257,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
202 ci = ++L->ci; /* now `enter' new function */ 257 ci = ++L->ci; /* now `enter' new function */
203 ci->base = restorestack(L, funcr) + 1; 258 ci->base = restorestack(L, funcr) + 1;
204 ci->top = ci->base + p->maxstacksize; 259 ci->top = ci->base + p->maxstacksize;
205 ci->savedpc = p->code; /* starting point */ 260 ci->u.l.savedpc = p->code; /* starting point */
206 while (L->top < ci->top) 261 while (L->top < ci->top)
207 setnilvalue(L->top++); 262 setnilvalue(L->top++);
208 L->top = ci->top; 263 L->top = ci->top;
@@ -215,7 +270,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
215 ci = ++L->ci; /* now `enter' new function */ 270 ci = ++L->ci; /* now `enter' new function */
216 ci->base = restorestack(L, funcr) + 1; 271 ci->base = restorestack(L, funcr) + 1;
217 ci->top = L->top + LUA_MINSTACK; 272 ci->top = L->top + LUA_MINSTACK;
218 ci->savedpc = NULL; /* not a Lua function */ 273 ci->pc = NULL; /* not a Lua function */
219 if (L->hookmask & LUA_MASKCALL) { 274 if (L->hookmask & LUA_MASKCALL) {
220 luaD_callhook(L, LUA_HOOKCALL, -1); 275 luaD_callhook(L, LUA_HOOKCALL, -1);
221 ci = L->ci; /* previous call may realocate `ci' */ 276 ci = L->ci; /* previous call may realocate `ci' */
@@ -274,6 +329,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
274LUA_API void lua_cobegin (lua_State *L, int nargs) { 329LUA_API void lua_cobegin (lua_State *L, int nargs) {
275 lua_lock(L); 330 lua_lock(L);
276 luaD_precall(L, L->top - (nargs+1)); 331 luaD_precall(L, L->top - (nargs+1));
332 L->ci->pc = &luaV_callingmark; /* function is not active (yet) */
277 lua_unlock(L); 333 lua_unlock(L);
278} 334}
279 335
@@ -287,28 +343,24 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
287} 343}
288 344
289 345
290struct ResS {
291 TObject err[2];
292 int numres;
293};
294
295static void resume (lua_State *L, void *ud) { 346static void resume (lua_State *L, void *ud) {
296 StkId firstResult; 347 StkId firstResult;
297 CallInfo *ci = L->ci; 348 CallInfo *ci = L->ci;
298 if (!isLua(ci)) { /* not first time? */ 349 if (ci->pc == NULL) { /* not first time? */
299 /* finish interrupted execution of `OP_CALL' */ 350 /* finish interrupted execution of `OP_CALL' */
300 int nresults; 351 int nresults;
301 lua_assert(isLua(ci - 1)); 352 lua_assert((ci - 1)->pc == &luaV_callingmark);
302 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL); 353 lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
303 nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1; 354 GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
355 nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
304 luaD_poscall(L, nresults, L->top); /* complete it */ 356 luaD_poscall(L, nresults, L->top); /* complete it */
305 if (nresults >= 0) L->top = L->ci->top; 357 if (nresults >= 0) L->top = L->ci->top;
306 } 358 }
307 firstResult = luaV_execute(L); 359 firstResult = luaV_execute(L);
308 if (firstResult == NULL) /* yield? */ 360 if (firstResult == NULL) /* yield? */
309 cast(struct ResS *, ud)->numres = L->ci->u.c.yield_results; 361 *cast(int *, ud) = L->ci->u.c.yield_results;
310 else { /* return */ 362 else { /* return */
311 cast(struct ResS *, ud)->numres = L->top - firstResult; 363 *cast(int *, ud) = L->top - firstResult;
312 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ 364 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
313 } 365 }
314} 366}
@@ -316,7 +368,7 @@ static void resume (lua_State *L, void *ud) {
316 368
317LUA_API int lua_resume (lua_State *L, lua_State *co) { 369LUA_API int lua_resume (lua_State *L, lua_State *co) {
318 CallInfo *ci; 370 CallInfo *ci;
319 struct ResS ud; 371 int numres;
320 int status; 372 int status;
321 lua_lock(L); 373 lua_lock(L);
322 ci = co->ci; 374 ci = co->ci;
@@ -324,11 +376,13 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
324 luaG_runerror(L, "cannot resume dead thread"); 376 luaG_runerror(L, "cannot resume dead thread");
325 if (co->errorJmp != NULL) /* ?? */ 377 if (co->errorJmp != NULL) /* ?? */
326 luaG_runerror(L, "cannot resume active thread"); 378 luaG_runerror(L, "cannot resume active thread");
327 status = luaD_runprotected(co, resume, ud.err); 379 status = luaD_rawrunprotected(co, resume, &numres);
328 if (status == 0) 380 if (status == 0)
329 move_results(L, co->top - ud.numres, co->top); 381 move_results(L, co->top - numres, co->top);
330 else 382 else {
331 pusherrormsg(L, status, ud.err); 383 setobj(L->top++, co->top - 1); /* move error message to other stack */
384 co->ci = co->base_ci; /* `kill' thread */
385 }
332 lua_unlock(L); 386 lua_unlock(L);
333 return status; 387 return status;
334} 388}
@@ -338,9 +392,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
338 CallInfo *ci; 392 CallInfo *ci;
339 lua_lock(L); 393 lua_lock(L);
340 ci = L->ci; 394 ci = L->ci;
341 if (!isLua(ci-1)) 395 if ((ci-1)->pc == NULL)
342 luaG_runerror(L, "cannot yield a C function"); 396 luaG_runerror(L, "cannot yield a C function");
343 lua_assert(!isLua(ci)); 397 lua_assert(ci->pc == NULL); /* current function is not Lua */
344 ci->u.c.yield_results = nresults; 398 ci->u.c.yield_results = nresults;
345 lua_unlock(L); 399 lua_unlock(L);
346 return -1; 400 return -1;
@@ -351,7 +405,6 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
351** Execute a protected call. 405** Execute a protected call.
352*/ 406*/
353struct CallS { /* data to `f_call' */ 407struct CallS { /* data to `f_call' */
354 TObject err[2];
355 StkId func; 408 StkId func;
356 int nresults; 409 int nresults;
357}; 410};
@@ -359,6 +412,8 @@ struct CallS { /* data to `f_call' */
359 412
360static void f_call (lua_State *L, void *ud) { 413static void f_call (lua_State *L, void *ud) {
361 struct CallS *c = cast(struct CallS *, ud); 414 struct CallS *c = cast(struct CallS *, ud);
415 luaM_growvector(L, L->toreset, L->number_toreset, L->size_toreset,
416 Protection, MAX_INT, "");
362 luaD_call(L, c->func, c->nresults); 417 luaD_call(L, c->func, c->nresults);
363} 418}
364 419
@@ -366,13 +421,24 @@ static void f_call (lua_State *L, void *ud) {
366int luaD_pcall (lua_State *L, int nargs, int nresults) { 421int luaD_pcall (lua_State *L, int nargs, int nresults) {
367 struct CallS c; 422 struct CallS c;
368 int status; 423 int status;
424 int protectionlevel = L->number_toreset;
425 Protection protection;
426 protection.top = savestack(L, L->top);
427 protection.ci = saveci(L, L->ci);
428 protection.allowhooks = allowhook(L);
369 c.func = L->top - (nargs+1); /* function to be called */ 429 c.func = L->top - (nargs+1); /* function to be called */
370 c.nresults = nresults; 430 c.nresults = nresults;
371 status = luaD_runprotected(L, &f_call, c.err); 431 status = luaD_rawrunprotected(L, &f_call, &c);
372 if (status != 0) { /* an error occurred? */ 432 if (status != 0) { /* an error occurred? */
373 L->top -= nargs+1; /* remove parameters and func from the stack */ 433 /* remove parameters and func from the stack */
374 luaF_close(L, L->top); /* close eventual pending closures */ 434 protection.top = savestack(L, restorestack(L, protection.top) - (nargs+1));
375 pusherrormsg(L, status, c.err); 435 /* close eventual pending closures */
436 luaF_close(L, restorestack(L, protection.top));
437 L->ci->top = L->top + LUA_MINSTACK; /* extra space to handle error */
438 seterrorobj(L, status);
439 deactivateinfo(L, restoreci(L, protection.ci));
440 L->number_toreset = protectionlevel + 1;
441 L->toreset[L->number_toreset - 1] = protection;
376 } 442 }
377 return status; 443 return status;
378} 444}
@@ -382,7 +448,6 @@ int luaD_pcall (lua_State *L, int nargs, int nresults) {
382** Execute a protected parser. 448** Execute a protected parser.
383*/ 449*/
384struct SParser { /* data to `f_parser' */ 450struct SParser { /* data to `f_parser' */
385 TObject err[2];
386 ZIO *z; 451 ZIO *z;
387 int bin; 452 int bin;
388}; 453};
@@ -401,95 +466,25 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
401 struct SParser p; 466 struct SParser p;
402 lu_mem old_blocks; 467 lu_mem old_blocks;
403 int status; 468 int status;
469 ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
404 p.z = z; p.bin = bin; 470 p.z = z; p.bin = bin;
405 /* before parsing, give a (good) chance to GC */ 471 /* before parsing, give a (good) chance to GC */
406 if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold) 472 if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
407 luaC_collectgarbage(L); 473 luaC_collectgarbage(L);
408 old_blocks = G(L)->nblocks; 474 old_blocks = G(L)->nblocks;
409 status = luaD_runprotected(L, f_parser, p.err); 475 status = luaD_rawrunprotected(L, f_parser, &p);
410 if (status == 0) { 476 if (status == 0) {
411 /* add new memory to threshold (as it probably will stay) */ 477 /* add new memory to threshold (as it probably will stay) */
412 lua_assert(G(L)->nblocks >= old_blocks); 478 lua_assert(G(L)->nblocks >= old_blocks);
413 G(L)->GCthreshold += (G(L)->nblocks - old_blocks); 479 G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
414 } 480 }
415 else 481 else { /* error */
416 pusherrormsg(L, status, p.err); 482 StkId oldtop = restorestack(L, oldtopr);
417 return status; 483 seterrorobj(L, status);
418} 484 setobj(oldtop, L->top - 1); /* copy error message to old top */
419 485 L->top = oldtop+1;
420
421
422/*
423** {======================================================
424** Error-recovery functions (based on long jumps)
425** =======================================================
426*/
427
428static void seterrorobj (lua_State *L, int errcode, TObject *m) {
429 switch (errcode) {
430 case LUA_ERRMEM: {
431 if (G(L) != NULL && G(L)->GCthreshold > 0) /* state is OK? */
432 setsvalue(&m[0], luaS_new(L, MEMERRMSG));
433 break;
434 }
435 case LUA_ERRERR: {
436 setsvalue(&m[0], luaS_new(L, "error in error handling"));
437 break;
438 }
439 case LUA_ERRSYNTAX: { /* message is on stack top */
440 setobj(&m[0], L->top - 1);
441 break;
442 }
443 case LUA_ERRRUN: { /* traceback is on stack top */
444 setobj(&m[0], L->top - 2);
445 setobj(&m[1], L->top - 1);
446 break;
447 }
448 }
449}
450
451
452void luaD_throw (lua_State *L, int errcode) {
453 if (L->errorJmp) {
454 seterrorobj(L, errcode, L->errorJmp->err);
455 L->errorJmp->status = errcode;
456 longjmp(L->errorJmp->b, 1);
457 }
458 else {
459 G(L)->panic(L);
460 exit(EXIT_FAILURE);
461 }
462}
463
464
465int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
466 struct lua_longjmp lj;
467 lj.ci = L->ci;
468 lj.top = L->top;
469 lj.allowhooks = allowhook(L);
470 lj.status = 0;
471 lj.err = ud;
472 lj.previous = L->errorJmp; /* chain new error handler */
473 L->errorJmp = &lj;
474 if (setjmp(lj.b) == 0)
475 (*f)(L, ud);
476 else { /* an error occurred */
477 L->ci = lj.ci; /* restore the state */
478 L->top = lj.top;
479 setallowhook(L, lj.allowhooks);
480 restore_stack_limit(L);
481 } 486 }
482 L->errorJmp = lj.previous; /* restore old error handler */ 487 return status;
483 return lj.status;
484}
485
486
487int luaD_isprotected (lua_State *L, CallInfo *ci) {
488 struct lua_longjmp *l;
489 for (l = L->errorJmp; l; l = l->previous)
490 if (l->ci+1 == ci) return 1;
491 return 0;
492} 488}
493 489
494/* }====================================================== */
495 490
diff --git a/ldo.h b/ldo.h
index c18193d1..fdd889ed 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 1.47 2002/06/18 17:10:43 roberto Exp roberto $ 2** $Id: ldo.h,v 1.48 2002/07/08 18:21:33 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*/
@@ -27,10 +27,14 @@
27#define savestack(L,p) ((char *)(p) - (char *)L->stack) 27#define savestack(L,p) ((char *)(p) - (char *)L->stack)
28#define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) 28#define restorestack(L,n) ((TObject *)((char *)L->stack + (n)))
29 29
30#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
31#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
32
30 33
31/* type of protected functions, to be ran by `runprotected' */ 34/* type of protected functions, to be ran by `runprotected' */
32typedef void (*Pfunc) (lua_State *L, void *v); 35typedef void (*Pfunc) (lua_State *L, void *ud);
33 36
37void luaD_resetprotection (lua_State *L);
34int luaD_protectedparser (lua_State *L, ZIO *z, int bin); 38int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
35void luaD_callhook (lua_State *L, lua_Hookevent event, int line); 39void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
36StkId luaD_precall (lua_State *L, StkId func); 40StkId luaD_precall (lua_State *L, StkId func);
@@ -42,8 +46,7 @@ void luaD_reallocstack (lua_State *L, int newsize);
42void luaD_growstack (lua_State *L, int n); 46void luaD_growstack (lua_State *L, int n);
43 47
44void luaD_throw (lua_State *L, int errcode); 48void luaD_throw (lua_State *L, int errcode);
45int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud); 49int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
46int luaD_isprotected (lua_State *L, CallInfo *ci);
47 50
48 51
49#endif 52#endif
diff --git a/lstate.c b/lstate.c
index 1edb93f4..17d45f5f 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.98 2002/07/08 18:21:33 roberto Exp roberto $ 2** $Id: lstate.c,v 1.99 2002/07/16 14:26:56 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*/
@@ -35,17 +35,19 @@ static int default_panic (lua_State *L) {
35 35
36 36
37static void stack_init (lua_State *L, lua_State *OL) { 37static void stack_init (lua_State *L, lua_State *OL) {
38 L->stack = luaM_newvector(OL, BASIC_STACK_SIZE, TObject); 38 L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
39 L->stacksize = BASIC_STACK_SIZE; 39 L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
40 L->top = L->stack; 40 L->top = L->stack;
41 L->stack_last = L->stack+(BASIC_STACK_SIZE-EXTRA_STACK)-1; 41 L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
42 L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo); 42 L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
43 L->ci = L->base_ci; 43 L->ci = L->base_ci;
44 L->ci->savedpc = NULL; 44 L->ci->pc = NULL; /* not a Lua function */
45 L->ci->base = L->top; 45 L->ci->base = L->top;
46 L->ci->top = L->top + LUA_MINSTACK; 46 L->ci->top = L->top + LUA_MINSTACK;
47 L->size_ci = BASIC_CI_SIZE; 47 L->size_ci = BASIC_CI_SIZE;
48 L->end_ci = L->base_ci + L->size_ci; 48 L->end_ci = L->base_ci + L->size_ci;
49 L->toreset = luaM_newvector(OL, 2, Protection);
50 L->size_toreset = 2;
49} 51}
50 52
51 53
@@ -98,7 +100,12 @@ static void preinit_state (lua_State *L) {
98 resethookcount(L); 100 resethookcount(L);
99 L->openupval = NULL; 101 L->openupval = NULL;
100 L->size_ci = 0; 102 L->size_ci = 0;
101 L->base_ci = NULL; 103 L->base_ci = L->ci = NULL;
104 L->toreset = NULL;
105 L->size_toreset = L->number_toreset = 0;
106 setnilvalue(defaultmeta(L));
107 setnilvalue(gt(L));
108 setnilvalue(registry(L));
102} 109}
103 110
104 111
@@ -124,13 +131,12 @@ LUA_API lua_State *lua_newthread (lua_State *OL) {
124 131
125LUA_API lua_State *lua_open (void) { 132LUA_API lua_State *lua_open (void) {
126 lua_State *L; 133 lua_State *L;
127 TObject dummy[2];
128 L = luaM_new(NULL, lua_State); 134 L = luaM_new(NULL, lua_State);
129 if (L) { /* allocation OK? */ 135 if (L) { /* allocation OK? */
130 preinit_state(L); 136 preinit_state(L);
131 L->l_G = NULL; 137 L->l_G = NULL;
132 L->next = L->previous = L; 138 L->next = L->previous = L;
133 if (luaD_runprotected(L, f_luaopen, dummy) != 0) { 139 if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
134 /* memory allocation error: free partial state */ 140 /* memory allocation error: free partial state */
135 close_state(L); 141 close_state(L);
136 L = NULL; 142 L = NULL;
@@ -147,6 +153,7 @@ void luaE_closethread (lua_State *OL, lua_State *L) {
147 L->previous->next = L->next; 153 L->previous->next = L->next;
148 L->next->previous = L->previous; 154 L->next->previous = L->previous;
149 luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo); 155 luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
156 luaM_freearray(OL, L->toreset, L->size_toreset, Protection);
150 luaM_freearray(OL, L->stack, L->stacksize, TObject); 157 luaM_freearray(OL, L->stack, L->stacksize, TObject);
151 luaM_freelem(OL, L); 158 luaM_freelem(OL, L);
152} 159}
diff --git a/lstate.h b/lstate.h
index 5db528ff..a334921a 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.88 2002/07/08 20:22:08 roberto Exp roberto $ 2** $Id: lstate.h,v 1.89 2002/07/16 14:26:56 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*/
@@ -65,7 +65,7 @@ struct lua_longjmp; /* defined in ldo.c */
65#define registry(L) (L->globs + 2) 65#define registry(L) (L->globs + 2)
66 66
67 67
68/* space to handle TM calls and other temporary overflows */ 68/* extra stack space to handle TM calls and some other extras */
69#define EXTRA_STACK 5 69#define EXTRA_STACK 5
70 70
71 71
@@ -88,10 +88,10 @@ typedef struct stringtable {
88typedef struct CallInfo { 88typedef struct CallInfo {
89 StkId base; /* base for called function */ 89 StkId base; /* base for called function */
90 StkId top; /* top for this function */ 90 StkId top; /* top for this function */
91 const Instruction *savedpc; /* NULL means not a Lua function */ 91 const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
92 union { 92 union {
93 struct { /* for Lua functions */ 93 struct { /* for Lua functions */
94 const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ 94 const Instruction *savedpc;
95 StkId *pb; /* points to `base' variable in `luaV_execute' */ 95 StkId *pb; /* points to `base' variable in `luaV_execute' */
96 } l; 96 } l;
97 struct { /* for C functions */ 97 struct { /* for C functions */
@@ -101,7 +101,15 @@ typedef struct CallInfo {
101} CallInfo; 101} CallInfo;
102 102
103 103
104#define isLua(ci) ((ci)->savedpc != NULL) 104/*
105** informations about a `protection' (error recovery points)
106*/
107typedef struct Protection {
108 ptrdiff_t ci;
109 ptrdiff_t top;
110 int allowhooks;
111} Protection;
112
105 113
106#define ci_func(ci) (clvalue((ci)->base - 1)) 114#define ci_func(ci) (clvalue((ci)->base - 1))
107 115
@@ -133,22 +141,25 @@ typedef struct global_State {
133struct lua_State { 141struct lua_State {
134 LUA_USERSTATE 142 LUA_USERSTATE
135 StkId top; /* first free slot in the stack */ 143 StkId top; /* first free slot in the stack */
144 global_State *l_G;
136 CallInfo *ci; /* call info for current function */ 145 CallInfo *ci; /* call info for current function */
137 StkId stack_last; /* last free slot in the stack */ 146 StkId stack_last; /* last free slot in the stack */
138 StkId stack; /* stack base */ 147 StkId stack; /* stack base */
148 int stacksize;
139 CallInfo *end_ci; /* points after end of ci array*/ 149 CallInfo *end_ci; /* points after end of ci array*/
140 CallInfo *base_ci; /* array of CallInfo's */ 150 CallInfo *base_ci; /* array of CallInfo's */
141 global_State *l_G; 151 int size_ci; /* size of array `base_ci' */
142 int hookmask; 152 int hookmask;
143 ls_count hookcount; 153 ls_count hookcount;
144 lua_Hook hook; 154 lua_Hook hook;
145 TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
146 struct lua_longjmp *errorJmp; /* current error recover point */
147 UpVal *openupval; /* list of open upvalues in this stack */ 155 UpVal *openupval; /* list of open upvalues in this stack */
156 struct lua_longjmp *errorJmp; /* current error recover point */
157 Protection *toreset; /* array of pending pcall resets */
158 int number_toreset;
159 int size_toreset;
148 lua_State *next; /* circular double linked list of states */ 160 lua_State *next; /* circular double linked list of states */
149 lua_State *previous; 161 lua_State *previous;
150 int stacksize; 162 TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
151 int size_ci; /* size of array `base_ci' */
152}; 163};
153 164
154 165
diff --git a/luadebug.h b/luadebug.h
index 0f277727..4a37c640 100644
--- a/luadebug.h
+++ b/luadebug.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: luadebug.h,v 1.29 2002/07/08 18:21:33 roberto Exp roberto $ 2** $Id: luadebug.h,v 1.30 2002/07/08 20:22:08 roberto Exp $
3** Debugging API 3** Debugging API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -46,7 +46,6 @@ struct lua_Debug {
46 const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ 46 const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
47 const char *source; /* (S) */ 47 const char *source; /* (S) */
48 int currentline; /* (l) */ 48 int currentline; /* (l) */
49 int isprotected; /* (c) function was called in protected mode */
50 int nups; /* (u) number of upvalues */ 49 int nups; /* (u) number of upvalues */
51 int linedefined; /* (S) */ 50 int linedefined; /* (S) */
52 char short_src[LUA_IDSIZE]; /* (S) */ 51 char short_src[LUA_IDSIZE]; /* (S) */
diff --git a/lvm.c b/lvm.c
index d966a179..071b1d0f 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.247 2002/07/16 14:26:56 roberto Exp roberto $ 2** $Id: lvm.c,v 1.248 2002/07/17 16:25:13 roberto Exp $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -24,6 +24,9 @@
24#include "lvm.h" 24#include "lvm.h"
25 25
26 26
27Instruction const *luaV_callingmark = NULL;
28
29
27/* function to convert a lua_Number to a string */ 30/* function to convert a lua_Number to a string */
28#ifndef lua_number2str 31#ifndef lua_number2str
29#include <stdio.h> 32#include <stdio.h>
@@ -46,8 +49,8 @@ static void luaV_checkGC (lua_State *L, StkId top) {
46 49
47const TObject *luaV_tonumber (const TObject *obj, TObject *n) { 50const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
48 lua_Number num; 51 lua_Number num;
49 if (ttype(obj) == LUA_TNUMBER) return obj; 52 if (ttisnumber(obj)) return obj;
50 if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &num)) { 53 if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
51 setnvalue(n, num); 54 setnvalue(n, num);
52 return n; 55 return n;
53 } 56 }
@@ -57,7 +60,7 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
57 60
58 61
59int luaV_tostring (lua_State *L, TObject *obj) { 62int luaV_tostring (lua_State *L, TObject *obj) {
60 if (ttype(obj) != LUA_TNUMBER) 63 if (!ttisnumber(obj))
61 return 0; 64 return 0;
62 else { 65 else {
63 char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ 66 char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
@@ -80,16 +83,16 @@ static void traceexec (lua_State *L) {
80 if (mask & LUA_MASKLINE) { 83 if (mask & LUA_MASKLINE) {
81 CallInfo *ci = L->ci; 84 CallInfo *ci = L->ci;
82 Proto *p = ci_func(ci)->l.p; 85 Proto *p = ci_func(ci)->l.p;
83 int newline = getline(p, pcRel(*ci->u.l.pc, p)); 86 int newline = getline(p, pcRel(*ci->pc, p));
84 if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ 87 if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */
85 ci->savedpc = *ci->u.l.pc; /* initialize `savedpc' */ 88 ci->u.l.savedpc = *ci->pc; /* initialize `savedpc' */
86 /* calls linehook when enters a new line or jumps back (loop) */ 89 /* calls linehook when enters a new line or jumps back (loop) */
87 if (*ci->u.l.pc <= ci->savedpc || 90 if (*ci->pc <= ci->u.l.savedpc ||
88 newline != getline(p, pcRel(ci->savedpc, p))) { 91 newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
89 luaD_callhook(L, LUA_HOOKLINE, newline); 92 luaD_callhook(L, LUA_HOOKLINE, newline);
90 ci = L->ci; /* previous call may reallocate `ci' */ 93 ci = L->ci; /* previous call may reallocate `ci' */
91 } 94 }
92 ci->savedpc = *ci->u.l.pc; 95 ci->u.l.savedpc = *ci->pc;
93 } 96 }
94} 97}
95 98
@@ -123,7 +126,7 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
123 TObject *key, int loop) { 126 TObject *key, int loop) {
124 const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); 127 const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
125 if (tm == NULL) return &luaO_nilobject; /* no TM */ 128 if (tm == NULL) return &luaO_nilobject; /* no TM */
126 if (ttype(tm) == LUA_TFUNCTION) { 129 if (ttisfunction(tm)) {
127 callTMres(L, tm, t, key); 130 callTMres(L, tm, t, key);
128 return L->top; 131 return L->top;
129 } 132 }
@@ -133,9 +136,9 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
133static const TObject *luaV_getnotable (lua_State *L, const TObject *t, 136static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
134 TObject *key, int loop) { 137 TObject *key, int loop) {
135 const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE); 138 const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE);
136 if (ttype(tm) == LUA_TNIL) 139 if (ttisnil(tm))
137 luaG_typeerror(L, t, "index"); 140 luaG_typeerror(L, t, "index");
138 if (ttype(tm) == LUA_TFUNCTION) { 141 if (ttisfunction(tm)) {
139 callTMres(L, tm, t, key); 142 callTMres(L, tm, t, key);
140 return L->top; 143 return L->top;
141 } 144 }
@@ -152,10 +155,10 @@ const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
152 int loop) { 155 int loop) {
153 if (loop > MAXTAGLOOP) 156 if (loop > MAXTAGLOOP)
154 luaG_runerror(L, "loop in gettable"); 157 luaG_runerror(L, "loop in gettable");
155 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ 158 if (ttistable(t)) { /* `t' is a table? */
156 Table *h = hvalue(t); 159 Table *h = hvalue(t);
157 const TObject *v = luaH_get(h, key); /* do a primitive get */ 160 const TObject *v = luaH_get(h, key); /* do a primitive get */
158 if (ttype(v) != LUA_TNIL) return v; 161 if (!ttisnil(v)) return v;
159 else return luaV_index(L, t, key, loop+1); 162 else return luaV_index(L, t, key, loop+1);
160 } 163 }
161 else return luaV_getnotable(L, t, key, loop+1); 164 else return luaV_getnotable(L, t, key, loop+1);
@@ -169,19 +172,19 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
169 const TObject *tm; 172 const TObject *tm;
170 int loop = 0; 173 int loop = 0;
171 do { 174 do {
172 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ 175 if (ttistable(t)) { /* `t' is a table? */
173 Table *h = hvalue(t); 176 Table *h = hvalue(t);
174 TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ 177 TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
175 if (ttype(oldval) != LUA_TNIL || /* result is no nil? */ 178 if (!ttisnil(oldval) || /* result is no nil? */
176 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 179 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
177 setobj(oldval, val); 180 setobj(oldval, val);
178 return; 181 return;
179 } 182 }
180 /* else will try the tag method */ 183 /* else will try the tag method */
181 } 184 }
182 else if (ttype(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)) == LUA_TNIL) 185 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)))
183 luaG_typeerror(L, t, "index"); 186 luaG_typeerror(L, t, "index");
184 if (ttype(tm) == LUA_TFUNCTION) { 187 if (ttisfunction(tm)) {
185 callTM(L, tm, t, key, val); 188 callTM(L, tm, t, key, val);
186 return; 189 return;
187 } 190 }
@@ -195,9 +198,9 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
195 TObject *res, TMS event) { 198 TObject *res, TMS event) {
196 ptrdiff_t result = savestack(L, res); 199 ptrdiff_t result = savestack(L, res);
197 const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 200 const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
198 if (ttype(tm) == LUA_TNIL) 201 if (ttisnil(tm))
199 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 202 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
200 if (ttype(tm) != LUA_TFUNCTION) return 0; 203 if (!ttisfunction(tm)) return 0;
201 callTMres(L, tm, p1, p2); 204 callTMres(L, tm, p1, p2);
202 res = restorestack(L, result); /* previous call may change stack */ 205 res = restorestack(L, result); /* previous call may change stack */
203 setobj(res, L->top); 206 setobj(res, L->top);
@@ -230,9 +233,9 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
230int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { 233int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
231 if (ttype(l) != ttype(r)) 234 if (ttype(l) != ttype(r))
232 return luaG_ordererror(L, l, r); 235 return luaG_ordererror(L, l, r);
233 else if (ttype(l) == LUA_TNUMBER) 236 else if (ttisnumber(l))
234 return nvalue(l) < nvalue(r); 237 return nvalue(l) < nvalue(r);
235 else if (ttype(l) == LUA_TSTRING) 238 else if (ttisstring(l))
236 return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; 239 return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
237 else if (call_binTM(L, l, r, L->top, TM_LT)) 240 else if (call_binTM(L, l, r, L->top, TM_LT))
238 return !l_isfalse(L->top); 241 return !l_isfalse(L->top);
@@ -243,9 +246,9 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
243static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { 246static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
244 if (ttype(l) != ttype(r)) 247 if (ttype(l) != ttype(r))
245 return luaG_ordererror(L, l, r); 248 return luaG_ordererror(L, l, r);
246 else if (ttype(l) == LUA_TNUMBER) 249 else if (ttisnumber(l))
247 return nvalue(l) <= nvalue(r); 250 return nvalue(l) <= nvalue(r);
248 else if (ttype(l) == LUA_TSTRING) 251 else if (ttisstring(l))
249 return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; 252 return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
250 else if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */ 253 else if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */
251 return !l_isfalse(L->top); 254 return !l_isfalse(L->top);
@@ -330,7 +333,7 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
330 const TObject *f = luaH_getstr(hvalue(registry(L)), 333 const TObject *f = luaH_getstr(hvalue(registry(L)),
331 G(L)->tmname[TM_POW]); 334 G(L)->tmname[TM_POW]);
332 ptrdiff_t res = savestack(L, ra); 335 ptrdiff_t res = savestack(L, ra);
333 if (ttype(f) != LUA_TFUNCTION) 336 if (!ttisfunction(f))
334 luaG_runerror(L, "`pow' (for `^' operator) is not a function"); 337 luaG_runerror(L, "`pow' (for `^' operator) is not a function");
335 callTMres(L, f, b, c); 338 callTMres(L, f, b, c);
336 ra = restorestack(L, res); /* previous call may change stack */ 339 ra = restorestack(L, res); /* previous call may change stack */
@@ -370,9 +373,9 @@ StkId luaV_execute (lua_State *L) {
370 TObject *k; 373 TObject *k;
371 const Instruction *pc; 374 const Instruction *pc;
372 callentry: /* entry point when calling new functions */ 375 callentry: /* entry point when calling new functions */
373 L->ci->u.l.pc = &pc;
374 L->ci->u.l.pb = &base; 376 L->ci->u.l.pb = &base;
375 pc = L->ci->savedpc; 377 L->ci->pc = &pc;
378 pc = L->ci->u.l.savedpc;
376 if (L->hookmask & LUA_MASKCALL) 379 if (L->hookmask & LUA_MASKCALL)
377 luaD_callhook(L, LUA_HOOKCALL, -1); 380 luaD_callhook(L, LUA_HOOKCALL, -1);
378 retentry: /* entry point when returning to old functions */ 381 retentry: /* entry point when returning to old functions */
@@ -382,11 +385,10 @@ StkId luaV_execute (lua_State *L) {
382 /* main loop of interpreter */ 385 /* main loop of interpreter */
383 for (;;) { 386 for (;;) {
384 const Instruction i = *pc++; 387 const Instruction i = *pc++;
385 StkId ra; 388 const StkId ra = RA(i);
386 if (L->hookmask >= LUA_MASKLINE && 389 if (L->hookmask >= LUA_MASKLINE &&
387 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) 390 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
388 traceexec(L); 391 traceexec(L);
389 ra = RA(i);
390 lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); 392 lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
391 lua_assert(L->top == L->ci->top || 393 lua_assert(L->top == L->ci->top ||
392 GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || 394 GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
@@ -420,9 +422,9 @@ StkId luaV_execute (lua_State *L) {
420 case OP_GETGLOBAL: { 422 case OP_GETGLOBAL: {
421 StkId rb = KBx(i); 423 StkId rb = KBx(i);
422 const TObject *v; 424 const TObject *v;
423 lua_assert(ttype(rb) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE); 425 lua_assert(ttisstring(rb) && ttistable(&cl->g));
424 v = luaH_getstr(hvalue(&cl->g), tsvalue(rb)); 426 v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
425 if (ttype(v) != LUA_TNIL) { setobj(ra, v); } 427 if (!ttisnil(v)) { setobj(ra, v); }
426 else 428 else
427 setobj(RA(i), luaV_index(L, &cl->g, rb, 0)); 429 setobj(RA(i), luaV_index(L, &cl->g, rb, 0));
428 break; 430 break;
@@ -430,9 +432,9 @@ StkId luaV_execute (lua_State *L) {
430 case OP_GETTABLE: { 432 case OP_GETTABLE: {
431 StkId rb = RB(i); 433 StkId rb = RB(i);
432 TObject *rc = RKC(i); 434 TObject *rc = RKC(i);
433 if (ttype(rb) == LUA_TTABLE) { 435 if (ttistable(rb)) {
434 const TObject *v = luaH_get(hvalue(rb), rc); 436 const TObject *v = luaH_get(hvalue(rb), rc);
435 if (ttype(v) != LUA_TNIL) { setobj(ra, v); } 437 if (!ttisnil(v)) { setobj(ra, v); }
436 else 438 else
437 setobj(RA(i), luaV_index(L, rb, rc, 0)); 439 setobj(RA(i), luaV_index(L, rb, rc, 0));
438 } 440 }
@@ -441,7 +443,7 @@ StkId luaV_execute (lua_State *L) {
441 break; 443 break;
442 } 444 }
443 case OP_SETGLOBAL: { 445 case OP_SETGLOBAL: {
444 lua_assert(ttype(KBx(i)) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE); 446 lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
445 luaV_settable(L, &cl->g, KBx(i), ra); 447 luaV_settable(L, &cl->g, KBx(i), ra);
446 break; 448 break;
447 } 449 }
@@ -464,11 +466,11 @@ StkId luaV_execute (lua_State *L) {
464 case OP_SELF: { 466 case OP_SELF: {
465 StkId rb = RB(i); 467 StkId rb = RB(i);
466 TObject *rc = RKC(i); 468 TObject *rc = RKC(i);
467 runtime_check(L, ttype(rc) == LUA_TSTRING); 469 runtime_check(L, ttisstring(rc));
468 setobj(ra+1, rb); 470 setobj(ra+1, rb);
469 if (ttype(rb) == LUA_TTABLE) { 471 if (ttistable(rb)) {
470 const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc)); 472 const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
471 if (ttype(v) != LUA_TNIL) { setobj(ra, v); } 473 if (!ttisnil(v)) { setobj(ra, v); }
472 else 474 else
473 setobj(RA(i), luaV_index(L, rb, rc, 0)); 475 setobj(RA(i), luaV_index(L, rb, rc, 0));
474 } 476 }
@@ -479,7 +481,7 @@ StkId luaV_execute (lua_State *L) {
479 case OP_ADD: { 481 case OP_ADD: {
480 StkId rb = RB(i); 482 StkId rb = RB(i);
481 StkId rc = RKC(i); 483 StkId rc = RKC(i);
482 if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { 484 if (ttisnumber(rb) && ttisnumber(rc)) {
483 setnvalue(ra, nvalue(rb) + nvalue(rc)); 485 setnvalue(ra, nvalue(rb) + nvalue(rc));
484 } 486 }
485 else 487 else
@@ -489,7 +491,7 @@ StkId luaV_execute (lua_State *L) {
489 case OP_SUB: { 491 case OP_SUB: {
490 StkId rb = RB(i); 492 StkId rb = RB(i);
491 StkId rc = RKC(i); 493 StkId rc = RKC(i);
492 if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { 494 if (ttisnumber(rb) && ttisnumber(rc)) {
493 setnvalue(ra, nvalue(rb) - nvalue(rc)); 495 setnvalue(ra, nvalue(rb) - nvalue(rc));
494 } 496 }
495 else 497 else
@@ -499,7 +501,7 @@ StkId luaV_execute (lua_State *L) {
499 case OP_MUL: { 501 case OP_MUL: {
500 StkId rb = RB(i); 502 StkId rb = RB(i);
501 StkId rc = RKC(i); 503 StkId rc = RKC(i);
502 if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { 504 if (ttisnumber(rb) && ttisnumber(rc)) {
503 setnvalue(ra, nvalue(rb) * nvalue(rc)); 505 setnvalue(ra, nvalue(rb) * nvalue(rc));
504 } 506 }
505 else 507 else
@@ -509,7 +511,7 @@ StkId luaV_execute (lua_State *L) {
509 case OP_DIV: { 511 case OP_DIV: {
510 StkId rb = RB(i); 512 StkId rb = RB(i);
511 StkId rc = RKC(i); 513 StkId rc = RKC(i);
512 if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) { 514 if (ttisnumber(rb) && ttisnumber(rc)) {
513 setnvalue(ra, nvalue(rb) / nvalue(rc)); 515 setnvalue(ra, nvalue(rb) / nvalue(rc));
514 } 516 }
515 else 517 else
@@ -584,7 +586,8 @@ StkId luaV_execute (lua_State *L) {
584 } 586 }
585 break; 587 break;
586 } 588 }
587 case OP_CALL: { 589 case OP_CALL:
590 case OP_TAILCALL: {
588 StkId firstResult; 591 StkId firstResult;
589 int b = GETARG_B(i); 592 int b = GETARG_B(i);
590 int nresults; 593 int nresults;
@@ -593,46 +596,47 @@ StkId luaV_execute (lua_State *L) {
593 firstResult = luaD_precall(L, ra); 596 firstResult = luaD_precall(L, ra);
594 if (firstResult) { 597 if (firstResult) {
595 if (firstResult > L->top) { /* yield? */ 598 if (firstResult > L->top) { /* yield? */
596 (L->ci-1)->savedpc = pc; 599 (L->ci - 1)->u.l.savedpc = pc;
600 (L->ci - 1)->pc = &luaV_callingmark;
597 return NULL; 601 return NULL;
598 } 602 }
599 /* it was a C function (`precall' called it); adjust results */ 603 /* it was a C function (`precall' called it); adjust results */
600 luaD_poscall(L, nresults, firstResult); 604 luaD_poscall(L, nresults, firstResult);
601 if (nresults >= 0) L->top = L->ci->top; 605 if (nresults >= 0) L->top = L->ci->top;
602 } 606 }
603 else { /* it is a Lua function: `call' it */ 607 else { /* it is a Lua function */
604 (L->ci-1)->savedpc = pc; 608 if (GET_OPCODE(i) == OP_CALL) { /* regular call? */
609 (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */
610 (L->ci-1)->pc = &luaV_callingmark; /* function is calling */
611 }
612 else { /* tail call: put new frame in place of previous one */
613 int aux;
614 StkId ra1 = RA(i); /* `luaD_precall' may change the stack */
615 if (L->openupval) luaF_close(L, base);
616 for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */
617 setobj(base+aux-1, ra1+aux);
618 (L->ci - 1)->top = L->top = base+aux; /* correct top */
619 (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
620 L->ci--; /* remove previous frame */
621 }
605 goto callentry; 622 goto callentry;
606 } 623 }
607 break; 624 break;
608 } 625 }
609 case OP_TAILCALL: {
610 int b = GETARG_B(i);
611 if (L->openupval) luaF_close(L, base);
612 if (b != 0) L->top = ra+b; /* else previous instruction set top */
613 luaD_poscall(L, LUA_MULTRET, ra); /* move down function and args. */
614 ra = luaD_precall(L, base-1);
615 if (ra == NULL) goto callentry; /* it is a Lua function */
616 else if (ra > L->top) return NULL; /* yield??? */
617 else goto ret;
618 }
619 case OP_RETURN: { 626 case OP_RETURN: {
620 int b; 627 CallInfo *ci = L->ci - 1;
621 if (L->openupval) luaF_close(L, base); 628 int b = GETARG_B(i);
622 b = GETARG_B(i);
623 if (b != 0) L->top = ra+b-1; 629 if (b != 0) L->top = ra+b-1;
624 lua_assert(L->ci->u.l.pc == &pc); 630 lua_assert(L->ci->pc == &pc);
625 } 631 if (L->openupval) luaF_close(L, base);
626 ret: {
627 CallInfo *ci;
628 ci = L->ci - 1;
629 /* previous function was running `here'? */ 632 /* previous function was running `here'? */
630 if (!isLua(ci) || ci->u.l.pc != &pc) 633 if (ci->pc != &luaV_callingmark)
631 return ra; /* no: return */ 634 return ra; /* no: return */
632 else { /* yes: continue its execution */ 635 else { /* yes: continue its execution (go through) */
633 int nresults; 636 int nresults;
634 lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); 637 lua_assert(ttisfunction(ci->base-1));
635 pc = ci->savedpc; 638 ci->pc = &pc; /* function is active again */
639 pc = ci->u.l.savedpc;
636 lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); 640 lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL);
637 nresults = GETARG_C(*(pc-1)) - 1; 641 nresults = GETARG_C(*(pc-1)) - 1;
638 luaD_poscall(L, nresults, ra); 642 luaD_poscall(L, nresults, ra);
@@ -644,7 +648,7 @@ StkId luaV_execute (lua_State *L) {
644 lua_Number step, index, limit; 648 lua_Number step, index, limit;
645 const TObject *plimit = ra+1; 649 const TObject *plimit = ra+1;
646 const TObject *pstep = ra+2; 650 const TObject *pstep = ra+2;
647 if (ttype(ra) != LUA_TNUMBER) 651 if (!ttisnumber(ra))
648 luaG_runerror(L, "`for' initial value must be a number"); 652 luaG_runerror(L, "`for' initial value must be a number");
649 if (!tonumber(plimit, ra+1)) 653 if (!tonumber(plimit, ra+1))
650 luaG_runerror(L, "`for' limit must be a number"); 654 luaG_runerror(L, "`for' limit must be a number");
@@ -666,12 +670,12 @@ StkId luaV_execute (lua_State *L) {
666 L->top = ra+5; 670 L->top = ra+5;
667 luaD_call(L, ra+2, GETARG_C(i) + 1); 671 luaD_call(L, ra+2, GETARG_C(i) + 1);
668 L->top = L->ci->top; 672 L->top = L->ci->top;
669 if (ttype(ra+2) == LUA_TNIL) pc++; /* skip jump (break loop) */ 673 if (ttisnil(ra+2)) pc++; /* skip jump (break loop) */
670 else dojump(pc, GETARG_sBx(*pc) + 1); /* else jump back */ 674 else dojump(pc, GETARG_sBx(*pc) + 1); /* else jump back */
671 break; 675 break;
672 } 676 }
673 case OP_TFORPREP: { /* for compatibility only */ 677 case OP_TFORPREP: { /* for compatibility only */
674 if (ttype(ra) == LUA_TTABLE) { 678 if (ttistable(ra)) {
675 setobj(ra+1, ra); 679 setobj(ra+1, ra);
676 setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next"))); 680 setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
677 } 681 }
@@ -683,7 +687,7 @@ StkId luaV_execute (lua_State *L) {
683 int bc; 687 int bc;
684 int n; 688 int n;
685 Table *h; 689 Table *h;
686 runtime_check(L, ttype(ra) == LUA_TTABLE); 690 runtime_check(L, ttistable(ra));
687 h = hvalue(ra); 691 h = hvalue(ra);
688 bc = GETARG_Bx(i); 692 bc = GETARG_Bx(i);
689 if (GET_OPCODE(i) == OP_SETLIST) 693 if (GET_OPCODE(i) == OP_SETLIST)
diff --git a/lvm.h b/lvm.h
index 6b462e09..c1b2c312 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 1.43 2002/06/24 13:08:45 roberto Exp roberto $ 2** $Id: lvm.h,v 1.44 2002/07/05 18:27:39 roberto Exp $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -22,6 +22,13 @@
22 (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) 22 (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
23 23
24 24
25/*
26** dummy addrees, to mark Lua functions calling other Lua functions (and
27** therefore without a valid `pc'
28*/
29extern Instruction const *luaV_callingmark;
30
31
25int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); 32int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
26int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); 33int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
27const TObject *luaV_tonumber (const TObject *obj, TObject *n); 34const TObject *luaV_tonumber (const TObject *obj, TObject *n);