diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-04 16:38:35 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-04 16:38:35 -0300 |
| commit | 435f587ed05e2c4d542e1db9ae9e4efbb7e02305 (patch) | |
| tree | 1b179bf836cfdaf8ed74df24c2d22cda8f07aaa9 | |
| parent | ae55f3eeada102f3fa8345173410feaf1db42cde (diff) | |
| download | lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.tar.gz lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.tar.bz2 lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.zip | |
(much) better handling of memory alloction errors
| -rw-r--r-- | lbuiltin.c | 8 | ||||
| -rw-r--r-- | lcode.c | 6 | ||||
| -rw-r--r-- | ldo.c | 94 | ||||
| -rw-r--r-- | lmem.c | 14 | ||||
| -rw-r--r-- | lstate.c | 39 | ||||
| -rw-r--r-- | lstring.c | 6 | ||||
| -rw-r--r-- | ltable.c | 10 | ||||
| -rw-r--r-- | ltests.c | 34 | ||||
| -rw-r--r-- | ltm.c | 6 | ||||
| -rw-r--r-- | lua.c | 8 |
10 files changed, 137 insertions, 88 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbuiltin.c,v 1.116 2000/06/12 13:52:05 roberto Exp roberto $ | 2 | ** $Id: lbuiltin.c,v 1.117 2000/06/30 14:35:17 roberto Exp roberto $ |
| 3 | ** Built-in functions | 3 | ** Built-in functions |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -365,8 +365,8 @@ void luaB_tostring (lua_State *L) { | |||
| 365 | sprintf(buff, "function: %p", clvalue(o)); | 365 | sprintf(buff, "function: %p", clvalue(o)); |
| 366 | break; | 366 | break; |
| 367 | case TAG_USERDATA: | 367 | case TAG_USERDATA: |
| 368 | sprintf(buff, "userdata: %p(%d)", tsvalue(o)->u.d.value, | 368 | sprintf(buff, "userdata(%d): %p", tsvalue(o)->u.d.tag, |
| 369 | tsvalue(o)->u.d.tag); | 369 | tsvalue(o)->u.d.value); |
| 370 | break; | 370 | break; |
| 371 | case TAG_NIL: | 371 | case TAG_NIL: |
| 372 | lua_pushstring(L, "nil"); | 372 | lua_pushstring(L, "nil"); |
| @@ -680,8 +680,6 @@ static const struct luaL_reg builtin_funcs[] = { | |||
| 680 | 680 | ||
| 681 | 681 | ||
| 682 | void luaB_predefine (lua_State *L) { | 682 | void luaB_predefine (lua_State *L) { |
| 683 | /* pre-register mem error messages, to avoid loop when error arises */ | ||
| 684 | luaS_newfixed(L, memEM); | ||
| 685 | luaL_openl(L, builtin_funcs); | 683 | luaL_openl(L, builtin_funcs); |
| 686 | #ifdef DEBUG | 684 | #ifdef DEBUG |
| 687 | luaB_opentests(L); /* internal test functions */ | 685 | luaB_opentests(L); /* internal test functions */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.40 2000/06/28 20:20:36 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.41 2000/06/30 14:35:17 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -620,8 +620,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
| 620 | } | 620 | } |
| 621 | if (fs->debug) { | 621 | if (fs->debug) { |
| 622 | LexState *ls = fs->ls; | 622 | LexState *ls = fs->ls; |
| 623 | luaX_checklimit(ls, ls->lastline, MAXARG_U, "lines in a chunk"); | 623 | luaM_growvector(fs->L, fs->f->lines, fs->pc, 1, int, |
| 624 | luaM_growvector(fs->L, fs->f->lines, fs->pc, 1, int, "??", MAXARG_U); | 624 | "code size overflow", MAX_INT); |
| 625 | fs->f->lines[fs->pc] = ls->lastline; | 625 | fs->f->lines[fs->pc] = ls->lastline; |
| 626 | } | 626 | } |
| 627 | /* put new instruction in code array */ | 627 | /* put new instruction in code array */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.80 2000/06/26 19:28:31 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.81 2000/06/28 20:20:36 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 | */ |
| @@ -237,17 +237,41 @@ static void message (lua_State *L, const char *s) { | |||
| 237 | } | 237 | } |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | |||
| 241 | void luaD_breakrun (lua_State *L, int errcode) { | ||
| 242 | if (L->errorJmp) { | ||
| 243 | L->errorJmp->status = errcode; | ||
| 244 | longjmp(L->errorJmp->b, 1); | ||
| 245 | } | ||
| 246 | else { | ||
| 247 | if (errcode != LUA_ERRMEM) | ||
| 248 | message(L, "unable to recover; exiting\n"); | ||
| 249 | exit(1); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 240 | /* | 253 | /* |
| 241 | ** Reports an error, and jumps up to the available recovery label | 254 | ** Reports an error, and jumps up to the available recovery label |
| 242 | */ | 255 | */ |
| 243 | void lua_error (lua_State *L, const char *s) { | 256 | void lua_error (lua_State *L, const char *s) { |
| 244 | if (s) message(L, s); | 257 | if (s) message(L, s); |
| 245 | if (L->errorJmp) | 258 | luaD_breakrun(L, LUA_ERRRUN); |
| 246 | longjmp(L->errorJmp->b, 1); | 259 | } |
| 247 | else { | 260 | |
| 248 | message(L, "unable to recover; exiting\n"); | 261 | |
| 249 | exit(1); | 262 | static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { |
| 250 | } | 263 | lj->base = L->Cstack.base; |
| 264 | lj->numCblocks = L->numCblocks; | ||
| 265 | lj->previous = L->errorJmp; | ||
| 266 | L->errorJmp = lj; | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | static void restore_longjmp (lua_State *L, struct lua_longjmp *lj) { | ||
| 271 | L->Cstack.num = 0; /* no results */ | ||
| 272 | L->top = L->Cstack.base = L->Cstack.lua2C = lj->base; | ||
| 273 | L->numCblocks = lj->numCblocks; | ||
| 274 | L->errorJmp = lj->previous; | ||
| 251 | } | 275 | } |
| 252 | 276 | ||
| 253 | 277 | ||
| @@ -257,58 +281,44 @@ void lua_error (lua_State *L, const char *s) { | |||
| 257 | */ | 281 | */ |
| 258 | int luaD_protectedrun (lua_State *L) { | 282 | int luaD_protectedrun (lua_State *L) { |
| 259 | struct lua_longjmp myErrorJmp; | 283 | struct lua_longjmp myErrorJmp; |
| 260 | StkId base = L->Cstack.base; | 284 | chain_longjmp(L, &myErrorJmp); |
| 261 | int numCblocks = L->numCblocks; | ||
| 262 | int status; | ||
| 263 | struct lua_longjmp *volatile oldErr = L->errorJmp; | ||
| 264 | L->errorJmp = &myErrorJmp; | ||
| 265 | if (setjmp(myErrorJmp.b) == 0) { | 285 | if (setjmp(myErrorJmp.b) == 0) { |
| 286 | StkId base = L->Cstack.base; | ||
| 266 | luaD_call(L, base, MULT_RET); | 287 | luaD_call(L, base, MULT_RET); |
| 267 | L->Cstack.lua2C = base; /* position of the new results */ | 288 | L->Cstack.lua2C = base; /* position of the new results */ |
| 268 | L->Cstack.num = L->top - base; | 289 | L->Cstack.num = L->top - base; |
| 269 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ | 290 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ |
| 270 | status = 0; | 291 | L->errorJmp = myErrorJmp.previous; |
| 292 | return 0; | ||
| 271 | } | 293 | } |
| 272 | else { /* an error occurred: restore the stack */ | 294 | else { /* an error occurred: restore the stack */ |
| 273 | L->Cstack.num = 0; /* no results */ | 295 | restore_longjmp(L, &myErrorJmp); |
| 274 | L->top = L->Cstack.base = L->Cstack.lua2C = base; | ||
| 275 | L->numCblocks = numCblocks; | ||
| 276 | restore_stack_limit(L); | 296 | restore_stack_limit(L); |
| 277 | status = 1; | 297 | return myErrorJmp.status; |
| 278 | } | 298 | } |
| 279 | L->errorJmp = oldErr; | ||
| 280 | return status; | ||
| 281 | } | 299 | } |
| 282 | 300 | ||
| 283 | 301 | ||
| 284 | /* | 302 | /* |
| 285 | ** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load | 303 | ** returns 0 = chunk loaded; >0 : error; -1 = no more chunks to load |
| 286 | */ | 304 | */ |
| 287 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 305 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
| 288 | struct lua_longjmp myErrorJmp; | 306 | struct lua_longjmp myErrorJmp; |
| 289 | StkId base = L->Cstack.base; | 307 | chain_longjmp(L, &myErrorJmp); |
| 290 | int numCblocks = L->numCblocks; | 308 | L->top = L->Cstack.base; /* clear C2Lua */ |
| 291 | int status; | ||
| 292 | Proto *volatile tf; | ||
| 293 | struct lua_longjmp *volatile oldErr = L->errorJmp; | ||
| 294 | L->errorJmp = &myErrorJmp; | ||
| 295 | L->top = base; /* clear C2Lua */ | ||
| 296 | if (setjmp(myErrorJmp.b) == 0) { | 309 | if (setjmp(myErrorJmp.b) == 0) { |
| 297 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); | 310 | Proto *tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); |
| 298 | status = 0; | 311 | L->errorJmp = myErrorJmp.previous; |
| 312 | if (tf == NULL) return -1; /* `natural' end */ | ||
| 313 | luaV_Lclosure(L, tf, 0); | ||
| 314 | return 0; | ||
| 299 | } | 315 | } |
| 300 | else { /* an error occurred: restore Cstack and top */ | 316 | else { /* an error occurred */ |
| 301 | L->Cstack.num = 0; /* no results */ | 317 | restore_longjmp(L, &myErrorJmp); |
| 302 | L->top = L->Cstack.base = L->Cstack.lua2C = base; | 318 | if (myErrorJmp.status == LUA_ERRRUN) |
| 303 | L->numCblocks = numCblocks; | 319 | myErrorJmp.status = LUA_ERRSYNTAX; |
| 304 | tf = NULL; | 320 | return myErrorJmp.status; /* error code */ |
| 305 | status = 1; | ||
| 306 | } | 321 | } |
| 307 | L->errorJmp = oldErr; | ||
| 308 | if (status) return 1; /* error code */ | ||
| 309 | if (tf == NULL) return 2; /* `natural' end */ | ||
| 310 | luaV_Lclosure(L, tf, 0); | ||
| 311 | return 0; | ||
| 312 | } | 322 | } |
| 313 | 323 | ||
| 314 | 324 | ||
| @@ -320,8 +330,8 @@ static int do_main (lua_State *L, ZIO *z, int bin) { | |||
| 320 | luaC_checkGC(L); | 330 | luaC_checkGC(L); |
| 321 | old_blocks = L->nblocks; | 331 | old_blocks = L->nblocks; |
| 322 | status = protectedparser(L, z, bin); | 332 | status = protectedparser(L, z, bin); |
| 323 | if (status == 1) return 1; /* error */ | 333 | if (status > 0) return status; /* error */ |
| 324 | else if (status == 2) return 0; /* `natural' end */ | 334 | else if (status < 0) return 0; /* `natural' end */ |
| 325 | else { | 335 | else { |
| 326 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); | 336 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); |
| 327 | L->GCthreshold += newelems2; | 337 | L->GCthreshold += newelems2; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lmem.c,v 1.33 2000/06/12 13:52:05 roberto Exp roberto $ | 2 | ** $Id: lmem.c,v 1.34 2000/06/26 19:28:31 roberto Exp roberto $ |
| 3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "lua.h" | 12 | #include "lua.h" |
| 13 | 13 | ||
| 14 | #include "ldo.h" | ||
| 14 | #include "lmem.h" | 15 | #include "lmem.h" |
| 15 | #include "lobject.h" | 16 | #include "lobject.h" |
| 16 | #include "lstate.h" | 17 | #include "lstate.h" |
| @@ -36,6 +37,7 @@ | |||
| 36 | 37 | ||
| 37 | 38 | ||
| 38 | #include <assert.h> | 39 | #include <assert.h> |
| 40 | #include <limits.h> | ||
| 39 | #include <string.h> | 41 | #include <string.h> |
| 40 | 42 | ||
| 41 | #undef realloc | 43 | #undef realloc |
| @@ -59,6 +61,7 @@ union L_U { double d; char *s; long l; }; | |||
| 59 | unsigned long memdebug_numblocks = 0; | 61 | unsigned long memdebug_numblocks = 0; |
| 60 | unsigned long memdebug_total = 0; | 62 | unsigned long memdebug_total = 0; |
| 61 | unsigned long memdebug_maxmem = 0; | 63 | unsigned long memdebug_maxmem = 0; |
| 64 | unsigned long memdebug_memlimit = LONG_MAX; | ||
| 62 | 65 | ||
| 63 | 66 | ||
| 64 | static void *checkblock (void *block) { | 67 | static void *checkblock (void *block) { |
| @@ -88,6 +91,8 @@ static void *debug_realloc (void *block, size_t size) { | |||
| 88 | freeblock(block); | 91 | freeblock(block); |
| 89 | return NULL; | 92 | return NULL; |
| 90 | } | 93 | } |
| 94 | else if (memdebug_total+size > memdebug_memlimit) | ||
| 95 | return NULL; /* to test memory allocation errors */ | ||
| 91 | else { | 96 | else { |
| 92 | size_t realsize = HEADER+size+MARKSIZE; | 97 | size_t realsize = HEADER+size+MARKSIZE; |
| 93 | char *newblock = (char *)(malloc)(realsize); /* alloc a new block */ | 98 | char *newblock = (char *)(malloc)(realsize); /* alloc a new block */ |
| @@ -139,8 +144,11 @@ void *luaM_realloc (lua_State *L, void *block, lint32 size) { | |||
| 139 | else if (size >= MAX_SIZET) | 144 | else if (size >= MAX_SIZET) |
| 140 | lua_error(L, "memory allocation error: block too big"); | 145 | lua_error(L, "memory allocation error: block too big"); |
| 141 | block = realloc(block, size); | 146 | block = realloc(block, size); |
| 142 | if (block == NULL) | 147 | if (block == NULL) { |
| 143 | lua_error(L, memEM); | 148 | if (L) |
| 149 | luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */ | ||
| 150 | else return NULL; /* error before creating state! */ | ||
| 151 | } | ||
| 144 | return block; | 152 | return block; |
| 145 | } | 153 | } |
| 146 | 154 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 1.28 2000/06/30 14:35:17 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.29 2000/06/30 19:17:08 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 | */ |
| @@ -28,8 +28,14 @@ lua_State *lua_state = NULL; | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | lua_State *lua_newstate (int stacksize, int put_builtin) { | 30 | lua_State *lua_newstate (int stacksize, int put_builtin) { |
| 31 | struct lua_longjmp myErrorJmp; | ||
| 31 | lua_State *L = luaM_new(NULL, lua_State); | 32 | lua_State *L = luaM_new(NULL, lua_State); |
| 32 | L->errorJmp = NULL; | 33 | if (L == NULL) return NULL; /* memory allocation error */ |
| 34 | L->stack = NULL; | ||
| 35 | L->strt.size = L->udt.size = 0; | ||
| 36 | L->strt.nuse = L->udt.nuse = 0; | ||
| 37 | L->strt.hash = NULL; | ||
| 38 | L->udt.hash = NULL; | ||
| 33 | L->Mbuffer = NULL; | 39 | L->Mbuffer = NULL; |
| 34 | L->Mbuffbase = 0; | 40 | L->Mbuffbase = 0; |
| 35 | L->Mbuffsize = 0; | 41 | L->Mbuffsize = 0; |
| @@ -40,6 +46,7 @@ lua_State *lua_newstate (int stacksize, int put_builtin) { | |||
| 40 | L->rootcl = NULL; | 46 | L->rootcl = NULL; |
| 41 | L->roottable = NULL; | 47 | L->roottable = NULL; |
| 42 | L->IMtable = NULL; | 48 | L->IMtable = NULL; |
| 49 | L->last_tag = -1; | ||
| 43 | L->refArray = NULL; | 50 | L->refArray = NULL; |
| 44 | L->refSize = 0; | 51 | L->refSize = 0; |
| 45 | L->refFree = NONEXT; | 52 | L->refFree = NONEXT; |
| @@ -49,16 +56,23 @@ lua_State *lua_newstate (int stacksize, int put_builtin) { | |||
| 49 | L->callhook = NULL; | 56 | L->callhook = NULL; |
| 50 | L->linehook = NULL; | 57 | L->linehook = NULL; |
| 51 | L->allowhooks = 1; | 58 | L->allowhooks = 1; |
| 52 | L->gt = luaH_new(L, 10); | 59 | L->errorJmp = &myErrorJmp; |
| 53 | if (stacksize == 0) stacksize = DEFAULT_STACK_SIZE; | 60 | if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */ |
| 54 | luaD_init(L, stacksize); | 61 | L->gt = luaH_new(L, 10); |
| 55 | luaS_init(L); | 62 | luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE : stacksize); |
| 56 | luaX_init(L); | 63 | luaS_init(L); |
| 57 | luaT_init(L); | 64 | luaX_init(L); |
| 58 | if (put_builtin) | 65 | luaT_init(L); |
| 59 | luaB_predefine(L); | 66 | if (put_builtin) |
| 60 | L->GCthreshold = L->nblocks*4; | 67 | luaB_predefine(L); |
| 61 | return L; | 68 | L->GCthreshold = L->nblocks*4; |
| 69 | L->errorJmp = NULL; | ||
| 70 | return L; | ||
| 71 | } | ||
| 72 | else { /* memory allocation error: free partial state */ | ||
| 73 | lua_close(L); | ||
| 74 | return NULL; | ||
| 75 | } | ||
| 62 | } | 76 | } |
| 63 | 77 | ||
| 64 | 78 | ||
| @@ -75,7 +89,6 @@ void lua_close (lua_State *L) { | |||
| 75 | luaM_free(L, L->Cblocks); | 89 | luaM_free(L, L->Cblocks); |
| 76 | LUA_ASSERT(L->numCblocks == 0, "Cblocks still open"); | 90 | LUA_ASSERT(L->numCblocks == 0, "Cblocks still open"); |
| 77 | LUA_ASSERT(L->nblocks == 0, "wrong count for nblocks"); | 91 | LUA_ASSERT(L->nblocks == 0, "wrong count for nblocks"); |
| 78 | LUA_ASSERT(L->Cstack.base == L->top, "C2Lua not empty"); | ||
| 79 | luaM_free(L, L); | 92 | luaM_free(L, L); |
| 80 | if (L == lua_state) { | 93 | if (L == lua_state) { |
| 81 | LUA_ASSERT(memdebug_numblocks == 0, "memory leak!"); | 94 | LUA_ASSERT(memdebug_numblocks == 0, "memory leak!"); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 1.39 2000/06/15 17:01:12 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.40 2000/06/30 14:35:17 roberto Exp $ |
| 3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -19,10 +19,10 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | void luaS_init (lua_State *L) { | 21 | void luaS_init (lua_State *L) { |
| 22 | L->strt.size = L->udt.size = 1; | ||
| 23 | L->strt.nuse = L->udt.nuse = 0; | ||
| 24 | L->strt.hash = luaM_newvector(L, 1, TString *); | 22 | L->strt.hash = luaM_newvector(L, 1, TString *); |
| 25 | L->udt.hash = luaM_newvector(L, 1, TString *); | 23 | L->udt.hash = luaM_newvector(L, 1, TString *); |
| 24 | L->strt.size = L->udt.size = 1; | ||
| 25 | L->strt.nuse = L->udt.nuse = 0; | ||
| 26 | L->strt.hash[0] = L->udt.hash[0] = NULL; | 26 | L->strt.hash[0] = L->udt.hash[0] = NULL; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 1.49 2000/06/28 17:03:56 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.50 2000/06/30 14:35:17 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -154,19 +154,22 @@ static void setnodevector (lua_State *L, Hash *t, lint32 size) { | |||
| 154 | ttype(&t->node[i].key) = ttype(&t->node[i].val) = TAG_NIL; | 154 | ttype(&t->node[i].key) = ttype(&t->node[i].val) = TAG_NIL; |
| 155 | t->node[i].next = NULL; | 155 | t->node[i].next = NULL; |
| 156 | } | 156 | } |
| 157 | L->nblocks += gcsize(L, size) - gcsize(L, t->size); | ||
| 157 | t->size = size; | 158 | t->size = size; |
| 158 | t->firstfree = &t->node[size-1]; /* first free position to be used */ | 159 | t->firstfree = &t->node[size-1]; /* first free position to be used */ |
| 159 | L->nblocks += gcsize(L, size); | ||
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | 162 | ||
| 163 | Hash *luaH_new (lua_State *L, int size) { | 163 | Hash *luaH_new (lua_State *L, int size) { |
| 164 | Hash *t = luaM_new(L, Hash); | 164 | Hash *t = luaM_new(L, Hash); |
| 165 | setnodevector(L, t, luaO_power2(size)); | ||
| 166 | t->htag = TagDefault; | 165 | t->htag = TagDefault; |
| 167 | t->next = L->roottable; | 166 | t->next = L->roottable; |
| 168 | L->roottable = t; | 167 | L->roottable = t; |
| 169 | t->marked = 0; | 168 | t->marked = 0; |
| 169 | t->size = 0; | ||
| 170 | L->nblocks += gcsize(L, 0); | ||
| 171 | t->node = NULL; | ||
| 172 | setnodevector(L, t, luaO_power2(size)); | ||
| 170 | return t; | 173 | return t; |
| 171 | } | 174 | } |
| 172 | 175 | ||
| @@ -204,7 +207,6 @@ static void rehash (lua_State *L, Hash *t) { | |||
| 204 | setnodevector(L, t, oldsize/2); | 207 | setnodevector(L, t, oldsize/2); |
| 205 | else | 208 | else |
| 206 | setnodevector(L, t, oldsize); | 209 | setnodevector(L, t, oldsize); |
| 207 | L->nblocks -= gcsize(L, oldsize); | ||
| 208 | for (i=0; i<oldsize; i++) { | 210 | for (i=0; i<oldsize; i++) { |
| 209 | Node *old = nold+i; | 211 | Node *old = nold+i; |
| 210 | if (ttype(&old->val) != TAG_NIL) | 212 | if (ttype(&old->val) != TAG_NIL) |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.28 2000/06/28 17:06:07 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.29 2000/06/30 19:17:08 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 | */ |
| @@ -169,9 +169,14 @@ static void get_limits (void) { | |||
| 169 | 169 | ||
| 170 | 170 | ||
| 171 | static void mem_query (void) { | 171 | static void mem_query (void) { |
| 172 | lua_pushnumber(memdebug_total); | 172 | lua_Object arg = lua_getparam(1); |
| 173 | lua_pushnumber(memdebug_numblocks); | 173 | if (arg == LUA_NOOBJECT) { |
| 174 | lua_pushnumber(memdebug_maxmem); | 174 | lua_pushnumber(memdebug_total); |
| 175 | lua_pushnumber(memdebug_numblocks); | ||
| 176 | lua_pushnumber(memdebug_maxmem); | ||
| 177 | } | ||
| 178 | else | ||
| 179 | memdebug_memlimit = luaL_check_int(1); | ||
| 175 | } | 180 | } |
| 176 | 181 | ||
| 177 | 182 | ||
| @@ -375,7 +380,10 @@ static void testC (void) { | |||
| 375 | else if EQ("newstate") { | 380 | else if EQ("newstate") { |
| 376 | int stacksize = getnum(&pc); | 381 | int stacksize = getnum(&pc); |
| 377 | lua_State *L1 = lua_newstate(stacksize, getnum(&pc)); | 382 | lua_State *L1 = lua_newstate(stacksize, getnum(&pc)); |
| 378 | lua_pushuserdata(L1); | 383 | if (L1) |
| 384 | lua_pushuserdata(L1); | ||
| 385 | else | ||
| 386 | lua_pushnil(); | ||
| 379 | } | 387 | } |
| 380 | else if EQ("closestate") { | 388 | else if EQ("closestate") { |
| 381 | (lua_close)((lua_State *)lua_getuserdata(reg[getreg(&pc)])); | 389 | (lua_close)((lua_State *)lua_getuserdata(reg[getreg(&pc)])); |
| @@ -385,14 +393,20 @@ static void testC (void) { | |||
| 385 | lua_Object str = reg[getreg(&pc)]; | 393 | lua_Object str = reg[getreg(&pc)]; |
| 386 | lua_State *L1; | 394 | lua_State *L1; |
| 387 | lua_Object temp; | 395 | lua_Object temp; |
| 388 | int i; | 396 | int status; |
| 389 | if (!lua_isuserdata(ol1) || !lua_isstring(str)) | 397 | if (!lua_isuserdata(ol1) || !lua_isstring(str)) |
| 390 | lua_error("bad arguments for `doremote'"); | 398 | lua_error("bad arguments for `doremote'"); |
| 391 | L1 = (lua_State *)lua_getuserdata(ol1); | 399 | L1 = (lua_State *)lua_getuserdata(ol1); |
| 392 | (lua_dostring)(L1, lua_getstring(str)); | 400 | status = (lua_dostring)(L1, lua_getstring(str)); |
| 393 | i = 1; | 401 | if (status != 0) { |
| 394 | while ((temp = (lua_getresult)(L1, i++)) != LUA_NOOBJECT) | 402 | lua_pushnil(); |
| 395 | lua_pushstring((lua_getstring)(L1, temp)); | 403 | lua_pushnumber(status); |
| 404 | } | ||
| 405 | else { | ||
| 406 | int i = 1; | ||
| 407 | while ((temp = (lua_getresult)(L1, i++)) != LUA_NOOBJECT) | ||
| 408 | lua_pushstring((lua_getstring)(L1, temp)); | ||
| 409 | } | ||
| 396 | } | 410 | } |
| 397 | #if LUA_DEPRECATETFUNCS | 411 | #if LUA_DEPRECATETFUNCS |
| 398 | else if EQ("rawsetglobal") { | 412 | else if EQ("rawsetglobal") { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.c,v 1.42 2000/06/08 17:48:31 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 1.43 2000/06/12 13:52:05 roberto Exp roberto $ |
| 3 | ** Tag methods | 3 | ** Tag methods |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -69,17 +69,17 @@ static void init_entry (lua_State *L, int tag) { | |||
| 69 | 69 | ||
| 70 | void luaT_init (lua_State *L) { | 70 | void luaT_init (lua_State *L) { |
| 71 | int t; | 71 | int t; |
| 72 | L->last_tag = NUM_TAGS-1; | ||
| 73 | luaM_growvector(L, L->IMtable, 0, NUM_TAGS, struct IM, "", MAX_INT); | 72 | luaM_growvector(L, L->IMtable, 0, NUM_TAGS, struct IM, "", MAX_INT); |
| 73 | L->last_tag = NUM_TAGS-1; | ||
| 74 | for (t=0; t<=L->last_tag; t++) | 74 | for (t=0; t<=L->last_tag; t++) |
| 75 | init_entry(L, t); | 75 | init_entry(L, t); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | 78 | ||
| 79 | int lua_newtag (lua_State *L) { | 79 | int lua_newtag (lua_State *L) { |
| 80 | ++L->last_tag; | ||
| 81 | luaM_growvector(L, L->IMtable, L->last_tag, 1, struct IM, | 80 | luaM_growvector(L, L->IMtable, L->last_tag, 1, struct IM, |
| 82 | "tag table overflow", MAX_INT); | 81 | "tag table overflow", MAX_INT); |
| 82 | L->last_tag++; | ||
| 83 | init_entry(L, L->last_tag); | 83 | init_entry(L, L->last_tag); |
| 84 | return L->last_tag; | 84 | return L->last_tag; |
| 85 | } | 85 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.c,v 1.41 2000/06/19 13:15:15 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.42 2000/06/30 19:17:08 roberto Exp roberto $ |
| 3 | ** Lua stand-alone interpreter | 3 | ** Lua stand-alone interpreter |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -62,6 +62,10 @@ static int ldo (int (*f)(lua_State *L, const char *), const char *name) { | |||
| 62 | handler h = lreset(); | 62 | handler h = lreset(); |
| 63 | res = f(lua_state, name); /* dostring | dofile */ | 63 | res = f(lua_state, name); /* dostring | dofile */ |
| 64 | signal(SIGINT, h); /* restore old action */ | 64 | signal(SIGINT, h); /* restore old action */ |
| 65 | if (res == LUA_ERRMEM) { | ||
| 66 | /* Lua gives no message in such case, so lua.c provides one */ | ||
| 67 | fprintf(stderr, "lua: memory allocation error\n"); | ||
| 68 | } | ||
| 65 | return res; | 69 | return res; |
| 66 | } | 70 | } |
| 67 | 71 | ||
| @@ -121,7 +125,7 @@ static void l_getargs (void) { | |||
| 121 | static void file_input (const char *argv) { | 125 | static void file_input (const char *argv) { |
| 122 | int result = ldo(lua_dofile, argv); | 126 | int result = ldo(lua_dofile, argv); |
| 123 | if (result) { | 127 | if (result) { |
| 124 | if (result == 2) { | 128 | if (result == LUA_ERRFILE) { |
| 125 | fprintf(stderr, "lua: cannot execute file "); | 129 | fprintf(stderr, "lua: cannot execute file "); |
| 126 | perror(argv); | 130 | perror(argv); |
| 127 | } | 131 | } |
