diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-10-04 15:51:04 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-10-04 15:51:04 -0200 |
| commit | 4343420d4d559a7d4cdacdbc1fd61552dcf59f04 (patch) | |
| tree | 57e0bdd41e2f3a4ab70d3150022569751e3d02ad | |
| parent | 1f7103e05d01a6a4c300a73bcfc8d9b17b2c20a4 (diff) | |
| download | lua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.tar.gz lua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.tar.bz2 lua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.zip | |
simplified version of `gc' tag method (only for userdata now).
| -rw-r--r-- | lapi.c | 30 | ||||
| -rw-r--r-- | lbuiltin.c | 63 | ||||
| -rw-r--r-- | ldo.c | 15 | ||||
| -rw-r--r-- | ldo.h | 3 | ||||
| -rw-r--r-- | lfunc.c | 34 | ||||
| -rw-r--r-- | lfunc.h | 6 | ||||
| -rw-r--r-- | lgc.c | 302 | ||||
| -rw-r--r-- | lgc.h | 7 | ||||
| -rw-r--r-- | llex.c | 8 | ||||
| -rw-r--r-- | lobject.c | 9 | ||||
| -rw-r--r-- | lobject.h | 24 | ||||
| -rw-r--r-- | lstate.c | 27 | ||||
| -rw-r--r-- | lstate.h | 10 | ||||
| -rw-r--r-- | lstring.c | 142 | ||||
| -rw-r--r-- | lstring.h | 18 | ||||
| -rw-r--r-- | ltable.c | 25 | ||||
| -rw-r--r-- | ltable.h | 4 | ||||
| -rw-r--r-- | ltm.c | 8 | ||||
| -rw-r--r-- | makefile | 31 | ||||
| -rw-r--r-- | manual.tex | 61 |
20 files changed, 384 insertions, 443 deletions
| @@ -1,11 +1,10 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 1.49 1999/09/20 14:57:29 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.50 1999/09/21 16:10:13 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | #include <stdlib.h> | ||
| 9 | #include <string.h> | 8 | #include <string.h> |
| 10 | 9 | ||
| 11 | #include "lapi.h" | 10 | #include "lapi.h" |
| @@ -15,6 +14,7 @@ | |||
| 15 | #include "lgc.h" | 14 | #include "lgc.h" |
| 16 | #include "lmem.h" | 15 | #include "lmem.h" |
| 17 | #include "lobject.h" | 16 | #include "lobject.h" |
| 17 | #include "lref.h" | ||
| 18 | #include "lstate.h" | 18 | #include "lstate.h" |
| 19 | #include "lstring.h" | 19 | #include "lstring.h" |
| 20 | #include "ltable.h" | 20 | #include "ltable.h" |
| @@ -387,14 +387,14 @@ void lua_settag (int tag) { | |||
| 387 | 387 | ||
| 388 | TaggedString *luaA_nextvar (TaggedString *g) { | 388 | TaggedString *luaA_nextvar (TaggedString *g) { |
| 389 | if (g == NULL) | 389 | if (g == NULL) |
| 390 | g = (TaggedString *)L->rootglobal.next; /* first variable */ | 390 | g = L->rootglobal; /* first variable */ |
| 391 | else { | 391 | else { |
| 392 | /* check whether name is in global var list */ | 392 | /* check whether name is in global var list */ |
| 393 | luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected"); | 393 | luaL_arg_check(g != g->next, 1, "variable name expected"); |
| 394 | g = (TaggedString *)g->head.next; /* get next */ | 394 | g = g->next; /* get next */ |
| 395 | } | 395 | } |
| 396 | while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ | 396 | while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ |
| 397 | g = (TaggedString *)g->head.next; | 397 | g = g->next; |
| 398 | if (g) { | 398 | if (g) { |
| 399 | ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g; | 399 | ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g; |
| 400 | incr_top; | 400 | incr_top; |
| @@ -574,12 +574,18 @@ static int checkfunc (TObject *o) { | |||
| 574 | 574 | ||
| 575 | const char *lua_getobjname (lua_Object o, const char **name) { | 575 | const char *lua_getobjname (lua_Object o, const char **name) { |
| 576 | /* try to find a name for given function */ | 576 | /* try to find a name for given function */ |
| 577 | TaggedString *g; | ||
| 577 | set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */ | 578 | set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */ |
| 578 | if ((*name = luaS_travsymbol(checkfunc)) != NULL) | 579 | for (g=L->rootglobal; g; g=g->next) { |
| 579 | return "global"; | 580 | if (checkfunc(&g->u.s.globalval)) { |
| 580 | else if ((*name = luaT_travtagmethods(checkfunc)) != NULL) | 581 | *name = g->str; |
| 582 | return "global"; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | /* not found: try tag methods */ | ||
| 586 | if ((*name = luaT_travtagmethods(checkfunc)) != NULL) | ||
| 581 | return "tag-method"; | 587 | return "tag-method"; |
| 582 | else return ""; | 588 | else return ""; /* not found at all */ |
| 583 | } | 589 | } |
| 584 | 590 | ||
| 585 | /* }====================================================== */ | 591 | /* }====================================================== */ |
| @@ -615,7 +621,7 @@ void lua_endblock (void) { | |||
| 615 | int lua_ref (int lock) { | 621 | int lua_ref (int lock) { |
| 616 | int ref; | 622 | int ref; |
| 617 | checkCparams(1); | 623 | checkCparams(1); |
| 618 | ref = luaC_ref(L->stack.top-1, lock); | 624 | ref = luaR_ref(L->stack.top-1, lock); |
| 619 | L->stack.top--; | 625 | L->stack.top--; |
| 620 | return ref; | 626 | return ref; |
| 621 | } | 627 | } |
| @@ -623,7 +629,7 @@ int lua_ref (int lock) { | |||
| 623 | 629 | ||
| 624 | 630 | ||
| 625 | lua_Object lua_getref (int ref) { | 631 | lua_Object lua_getref (int ref) { |
| 626 | const TObject *o = luaC_getref(ref); | 632 | const TObject *o = luaR_getref(ref); |
| 627 | return (o ? put_luaObject(o) : LUA_NOOBJECT); | 633 | return (o ? put_luaObject(o) : LUA_NOOBJECT); |
| 628 | } | 634 | } |
| 629 | 635 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbuiltin.c,v 1.62 1999/09/08 20:45:18 roberto Exp roberto $ | 2 | ** $Id: lbuiltin.c,v 1.63 1999/09/20 14:57:29 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 | */ |
| @@ -222,9 +222,15 @@ static void luaB_rawsettable (void) { | |||
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static void luaB_settagmethod (void) { | 224 | static void luaB_settagmethod (void) { |
| 225 | int tag = luaL_check_int(1); | ||
| 226 | const char *event = luaL_check_string(2); | ||
| 225 | lua_Object nf = luaL_nonnullarg(3); | 227 | lua_Object nf = luaL_nonnullarg(3); |
| 228 | #ifndef LUA_COMPAT_GC | ||
| 229 | if (strcmp(event, "gc") == 0 && tag != LUA_T_NIL) | ||
| 230 | lua_error("cannot set this tag method from Lua"); | ||
| 231 | #endif | ||
| 226 | lua_pushobject(nf); | 232 | lua_pushobject(nf); |
| 227 | lua_pushobject(lua_settagmethod(luaL_check_int(1), luaL_check_string(2))); | 233 | lua_pushobject(lua_settagmethod(tag, event)); |
| 228 | } | 234 | } |
| 229 | 235 | ||
| 230 | static void luaB_gettagmethod (void) { | 236 | static void luaB_gettagmethod (void) { |
| @@ -437,12 +443,11 @@ static void luaB_foreach (void) { | |||
| 437 | 443 | ||
| 438 | 444 | ||
| 439 | static void luaB_foreachvar (void) { | 445 | static void luaB_foreachvar (void) { |
| 440 | GCnode *g; | 446 | TaggedString *s; |
| 441 | TObject f; /* see comment in 'foreachi' */ | 447 | TObject f; /* see comment in 'foreachi' */ |
| 442 | f = *luaA_Address(luaL_functionarg(1)); | 448 | f = *luaA_Address(luaL_functionarg(1)); |
| 443 | luaD_checkstack(4); /* for extra var name, f, var name, and globalval */ | 449 | luaD_checkstack(4); /* for extra var name, f, var name, and globalval */ |
| 444 | for (g = L->rootglobal.next; g; g = g->next) { | 450 | for (s = L->rootglobal; s; s = s->next) { |
| 445 | TaggedString *s = (TaggedString *)g; | ||
| 446 | if (s->u.s.globalval.ttype != LUA_T_NIL) { | 451 | if (s->u.s.globalval.ttype != LUA_T_NIL) { |
| 447 | pushtagstring(s); /* keep (extra) s on stack to avoid GC */ | 452 | pushtagstring(s); /* keep (extra) s on stack to avoid GC */ |
| 448 | *(L->stack.top++) = f; | 453 | *(L->stack.top++) = f; |
| @@ -451,10 +456,10 @@ static void luaB_foreachvar (void) { | |||
| 451 | luaD_calln(2, 1); | 456 | luaD_calln(2, 1); |
| 452 | if (ttype(L->stack.top-1) != LUA_T_NIL) { | 457 | if (ttype(L->stack.top-1) != LUA_T_NIL) { |
| 453 | L->stack.top--; | 458 | L->stack.top--; |
| 454 | *(L->stack.top-1) = *L->stack.top; /* remove extra s */ | 459 | *(L->stack.top-1) = *L->stack.top; /* remove extra `s' */ |
| 455 | return; | 460 | return; |
| 456 | } | 461 | } |
| 457 | L->stack.top-=2; /* remove result and extra s */ | 462 | L->stack.top-=2; /* remove result and extra `s' */ |
| 458 | } | 463 | } |
| 459 | } | 464 | } |
| 460 | } | 465 | } |
| @@ -602,20 +607,42 @@ static void mem_query (void) { | |||
| 602 | 607 | ||
| 603 | 608 | ||
| 604 | static void query_strings (void) { | 609 | static void query_strings (void) { |
| 605 | lua_pushnumber(L->string_root[luaL_check_int(1)].nuse); | 610 | int h = luaL_check_int(1) - 1; |
| 611 | int s = luaL_opt_int(2, 0) - 1; | ||
| 612 | if (s==-1) { | ||
| 613 | if (h < NUM_HASHS) { | ||
| 614 | lua_pushnumber(L->string_root[h].nuse); | ||
| 615 | lua_pushnumber(L->string_root[h].size); | ||
| 616 | } | ||
| 617 | } | ||
| 618 | else { | ||
| 619 | TaggedString *ts = L->string_root[h].hash[s]; | ||
| 620 | if (ts == NULL) lua_pushstring("<NIL>"); | ||
| 621 | else if (ts == &luaS_EMPTY) lua_pushstring("<EMPTY>"); | ||
| 622 | else if (ts->constindex == -1) lua_pushstring("<USERDATA>"); | ||
| 623 | else lua_pushstring(ts->str); | ||
| 624 | } | ||
| 606 | } | 625 | } |
| 607 | 626 | ||
| 608 | 627 | ||
| 609 | static void countlist (void) { | 628 | static void extra_services (void) { |
| 610 | const char *s = luaL_check_string(1); | 629 | const char *service = luaL_check_string(1); |
| 611 | GCnode *l = (s[0]=='t') ? L->roottable.next : (s[0]=='c') ? L->rootcl.next : | 630 | switch (*service) { |
| 612 | (s[0]=='p') ? L->rootproto.next : L->rootglobal.next; | 631 | case 'U': /* create a userdata with a given value/tag */ |
| 613 | int i=0; | 632 | lua_pushusertag((void *)luaL_check_int(2), luaL_check_int(3)); |
| 614 | while (l) { | 633 | break; |
| 615 | i++; | 634 | |
| 616 | l = l->next; | 635 | case 'u': /* return the value of a userdata */ |
| 636 | lua_pushnumber((int)lua_getuserdata(lua_getparam(2))); | ||
| 637 | break; | ||
| 638 | |||
| 639 | case 't': /* set `gc' tag method */ | ||
| 640 | lua_pushobject(lua_getparam(3)); | ||
| 641 | lua_settagmethod(luaL_check_int(2), "gc"); | ||
| 642 | break; | ||
| 643 | |||
| 644 | default: luaL_arg_check(0, 1, "invalid service"); | ||
| 617 | } | 645 | } |
| 618 | lua_pushnumber(i); | ||
| 619 | } | 646 | } |
| 620 | 647 | ||
| 621 | 648 | ||
| @@ -679,9 +706,9 @@ static void testC (void) { | |||
| 679 | 706 | ||
| 680 | static const struct luaL_reg builtin_funcs[] = { | 707 | static const struct luaL_reg builtin_funcs[] = { |
| 681 | #ifdef DEBUG | 708 | #ifdef DEBUG |
| 709 | {"extra", extra_services}, | ||
| 682 | {"testC", testC}, | 710 | {"testC", testC}, |
| 683 | {"totalmem", mem_query}, | 711 | {"totalmem", mem_query}, |
| 684 | {"count", countlist}, | ||
| 685 | {"querystr", query_strings}, | 712 | {"querystr", query_strings}, |
| 686 | #endif | 713 | #endif |
| 687 | {"_ALERT", luaB_alert}, | 714 | {"_ALERT", luaB_alert}, |
| @@ -1,18 +1,16 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.46 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.47 1999/09/06 15:24:46 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 | */ |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | #include <setjmp.h> | 8 | #include <setjmp.h> |
| 9 | #include <stdio.h> | ||
| 10 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 11 | #include <string.h> | 10 | #include <string.h> |
| 12 | 11 | ||
| 13 | #include "lauxlib.h" | 12 | #include "lauxlib.h" |
| 14 | #include "ldo.h" | 13 | #include "ldo.h" |
| 15 | #include "lfunc.h" | ||
| 16 | #include "lgc.h" | 14 | #include "lgc.h" |
| 17 | #include "lmem.h" | 15 | #include "lmem.h" |
| 18 | #include "lobject.h" | 16 | #include "lobject.h" |
| @@ -219,17 +217,6 @@ void luaD_calln (int nArgs, int nResults) { | |||
| 219 | } | 217 | } |
| 220 | 218 | ||
| 221 | 219 | ||
| 222 | /* | ||
| 223 | ** Traverse all objects on L->stack.stack | ||
| 224 | */ | ||
| 225 | void luaD_travstack (int (*fn)(TObject *)) { | ||
| 226 | StkId i; | ||
| 227 | for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) | ||
| 228 | fn(L->stack.stack+i); | ||
| 229 | } | ||
| 230 | |||
| 231 | |||
| 232 | |||
| 233 | static void message (const char *s) { | 220 | static void message (const char *s) { |
| 234 | const TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval); | 221 | const TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval); |
| 235 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || | 222 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 1.6 1999/06/22 20:37:23 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 1.7 1999/08/16 20:52:00 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 | */ |
| @@ -39,7 +39,6 @@ void luaD_calln (int nArgs, int nResults); | |||
| 39 | void luaD_callTM (const TObject *f, int nParams, int nResults); | 39 | void luaD_callTM (const TObject *f, int nParams, int nResults); |
| 40 | int luaD_protectedrun (void); | 40 | int luaD_protectedrun (void); |
| 41 | void luaD_gcIM (const TObject *o); | 41 | void luaD_gcIM (const TObject *o); |
| 42 | void luaD_travstack (int (*fn)(TObject *)); | ||
| 43 | void luaD_checkstack (int n); | 42 | void luaD_checkstack (int n); |
| 44 | 43 | ||
| 45 | 44 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 1.10 1999/03/04 21:17:26 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.11 1999/08/16 20:52:00 roberto Exp roberto $ |
| 3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -18,7 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | Closure *luaF_newclosure (int nelems) { | 19 | Closure *luaF_newclosure (int nelems) { |
| 20 | Closure *c = (Closure *)luaM_malloc(sizeof(Closure)+nelems*sizeof(TObject)); | 20 | Closure *c = (Closure *)luaM_malloc(sizeof(Closure)+nelems*sizeof(TObject)); |
| 21 | luaO_insertlist(&(L->rootcl), (GCnode *)c); | 21 | c->next = L->rootcl; |
| 22 | L->rootcl = c; | ||
| 23 | c->marked = 0; | ||
| 22 | L->nblocks += gcsizeclosure(c); | 24 | L->nblocks += gcsizeclosure(c); |
| 23 | c->nelems = nelems; | 25 | c->nelems = nelems; |
| 24 | return c; | 26 | return c; |
| @@ -33,14 +35,16 @@ TProtoFunc *luaF_newproto (void) { | |||
| 33 | f->consts = NULL; | 35 | f->consts = NULL; |
| 34 | f->nconsts = 0; | 36 | f->nconsts = 0; |
| 35 | f->locvars = NULL; | 37 | f->locvars = NULL; |
| 36 | luaO_insertlist(&(L->rootproto), (GCnode *)f); | 38 | f->next = L->rootproto; |
| 39 | L->rootproto = f; | ||
| 40 | f->marked = 0; | ||
| 37 | L->nblocks += gcsizeproto(f); | 41 | L->nblocks += gcsizeproto(f); |
| 38 | return f; | 42 | return f; |
| 39 | } | 43 | } |
| 40 | 44 | ||
| 41 | 45 | ||
| 42 | 46 | void luaF_freeproto (TProtoFunc *f) { | |
| 43 | static void freefunc (TProtoFunc *f) { | 47 | L->nblocks -= gcsizeproto(f); |
| 44 | luaM_free(f->code); | 48 | luaM_free(f->code); |
| 45 | luaM_free(f->locvars); | 49 | luaM_free(f->locvars); |
| 46 | luaM_free(f->consts); | 50 | luaM_free(f->consts); |
| @@ -48,23 +52,9 @@ static void freefunc (TProtoFunc *f) { | |||
| 48 | } | 52 | } |
| 49 | 53 | ||
| 50 | 54 | ||
| 51 | void luaF_freeproto (TProtoFunc *l) { | 55 | void luaF_freeclosure (Closure *c) { |
| 52 | while (l) { | 56 | L->nblocks -= gcsizeclosure(c); |
| 53 | TProtoFunc *next = (TProtoFunc *)l->head.next; | 57 | luaM_free(c); |
| 54 | L->nblocks -= gcsizeproto(l); | ||
| 55 | freefunc(l); | ||
| 56 | l = next; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | |||
| 61 | void luaF_freeclosure (Closure *l) { | ||
| 62 | while (l) { | ||
| 63 | Closure *next = (Closure *)l->head.next; | ||
| 64 | L->nblocks -= gcsizeclosure(l); | ||
| 65 | luaM_free(l); | ||
| 66 | l = next; | ||
| 67 | } | ||
| 68 | } | 58 | } |
| 69 | 59 | ||
| 70 | 60 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.h,v 1.5 1997/12/15 16:17:20 roberto Exp roberto $ | 2 | ** $Id: lfunc.h,v 1.6 1999/08/16 20:52:00 roberto Exp roberto $ |
| 3 | ** Lua Function structures | 3 | ** Lua Function structures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -14,8 +14,8 @@ | |||
| 14 | 14 | ||
| 15 | TProtoFunc *luaF_newproto (void); | 15 | TProtoFunc *luaF_newproto (void); |
| 16 | Closure *luaF_newclosure (int nelems); | 16 | Closure *luaF_newclosure (int nelems); |
| 17 | void luaF_freeproto (TProtoFunc *l); | 17 | void luaF_freeproto (TProtoFunc *f); |
| 18 | void luaF_freeclosure (Closure *l); | 18 | void luaF_freeclosure (Closure *c); |
| 19 | 19 | ||
| 20 | const char *luaF_getlocalname (TProtoFunc *func, int local_number, int line); | 20 | const char *luaF_getlocalname (TProtoFunc *func, int local_number, int line); |
| 21 | 21 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.25 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.26 1999/09/27 18:00:25 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -8,8 +8,8 @@ | |||
| 8 | #include "ldo.h" | 8 | #include "ldo.h" |
| 9 | #include "lfunc.h" | 9 | #include "lfunc.h" |
| 10 | #include "lgc.h" | 10 | #include "lgc.h" |
| 11 | #include "lmem.h" | ||
| 12 | #include "lobject.h" | 11 | #include "lobject.h" |
| 12 | #include "lref.h" | ||
| 13 | #include "lstate.h" | 13 | #include "lstate.h" |
| 14 | #include "lstring.h" | 14 | #include "lstring.h" |
| 15 | #include "ltable.h" | 15 | #include "ltable.h" |
| @@ -21,138 +21,15 @@ | |||
| 21 | static int markobject (TObject *o); | 21 | static int markobject (TObject *o); |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | /* mark a string; marks bigger than 1 cannot be changed */ | |
| 25 | /* | 25 | #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} |
| 26 | ** ======================================================= | ||
| 27 | ** REF mechanism | ||
| 28 | ** ======================================================= | ||
| 29 | */ | ||
| 30 | |||
| 31 | |||
| 32 | int luaC_ref (const TObject *o, int lock) { | ||
| 33 | int ref; | ||
| 34 | if (ttype(o) == LUA_T_NIL) | ||
| 35 | ref = LUA_REFNIL; | ||
| 36 | else { | ||
| 37 | for (ref=0; ref<L->refSize; ref++) | ||
| 38 | if (L->refArray[ref].status == FREE) | ||
| 39 | break; | ||
| 40 | if (ref == L->refSize) { /* no more empty spaces? */ | ||
| 41 | luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); | ||
| 42 | L->refSize++; | ||
| 43 | } | ||
| 44 | L->refArray[ref].o = *o; | ||
| 45 | L->refArray[ref].status = lock ? LOCK : HOLD; | ||
| 46 | } | ||
| 47 | return ref; | ||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 51 | void lua_unref (int ref) { | ||
| 52 | if (ref >= 0 && ref < L->refSize) | ||
| 53 | L->refArray[ref].status = FREE; | ||
| 54 | } | ||
| 55 | |||
| 56 | |||
| 57 | const TObject *luaC_getref (int ref) { | ||
| 58 | if (ref == LUA_REFNIL) | ||
| 59 | return &luaO_nilobject; | ||
| 60 | if (ref >= 0 && ref < L->refSize && | ||
| 61 | (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD)) | ||
| 62 | return &L->refArray[ref].o; | ||
| 63 | else | ||
| 64 | return NULL; | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | static void travlock (void) { | ||
| 69 | int i; | ||
| 70 | for (i=0; i<L->refSize; i++) | ||
| 71 | if (L->refArray[i].status == LOCK) | ||
| 72 | markobject(&L->refArray[i].o); | ||
| 73 | } | ||
| 74 | |||
| 75 | |||
| 76 | static int ismarked (const TObject *o) { | ||
| 77 | /* valid only for locked objects */ | ||
| 78 | switch (o->ttype) { | ||
| 79 | case LUA_T_STRING: case LUA_T_USERDATA: | ||
| 80 | return o->value.ts->head.marked; | ||
| 81 | case LUA_T_ARRAY: | ||
| 82 | return o->value.a->head.marked; | ||
| 83 | case LUA_T_CLOSURE: | ||
| 84 | return o->value.cl->head.marked; | ||
| 85 | case LUA_T_PROTO: | ||
| 86 | return o->value.tf->head.marked; | ||
| 87 | #ifdef DEBUG | ||
| 88 | case LUA_T_LINE: case LUA_T_CLMARK: | ||
| 89 | case LUA_T_CMARK: case LUA_T_PMARK: | ||
| 90 | LUA_INTERNALERROR("invalid type"); | ||
| 91 | #endif | ||
| 92 | default: /* nil, number or cproto */ | ||
| 93 | return 1; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | 26 | ||
| 97 | 27 | ||
| 98 | static void invalidaterefs (void) { | ||
| 99 | int i; | ||
| 100 | for (i=0; i<L->refSize; i++) | ||
| 101 | if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) | ||
| 102 | L->refArray[i].status = COLLECTED; | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | |||
| 107 | void luaC_hashcallIM (Hash *l) { | ||
| 108 | TObject t; | ||
| 109 | ttype(&t) = LUA_T_ARRAY; | ||
| 110 | for (; l; l=(Hash *)l->head.next) { | ||
| 111 | avalue(&t) = l; | ||
| 112 | luaD_gcIM(&t); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | void luaC_strcallIM (TaggedString *l) { | ||
| 118 | TObject o; | ||
| 119 | ttype(&o) = LUA_T_USERDATA; | ||
| 120 | for (; l; l=(TaggedString *)l->head.next) | ||
| 121 | if (l->constindex == -1) { /* is userdata? */ | ||
| 122 | tsvalue(&o) = l; | ||
| 123 | luaD_gcIM(&o); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | |||
| 129 | static GCnode *listcollect (GCnode *l) { | ||
| 130 | GCnode *frees = NULL; | ||
| 131 | while (l) { | ||
| 132 | GCnode *next = l->next; | ||
| 133 | l->marked = 0; | ||
| 134 | while (next && !next->marked) { | ||
| 135 | l->next = next->next; | ||
| 136 | next->next = frees; | ||
| 137 | frees = next; | ||
| 138 | next = l->next; | ||
| 139 | } | ||
| 140 | l = next; | ||
| 141 | } | ||
| 142 | return frees; | ||
| 143 | } | ||
| 144 | |||
| 145 | |||
| 146 | /* | ||
| 147 | ** mark a string; marks bigger than 1 cannot be changed. | ||
| 148 | */ | ||
| 149 | #define strmark(s) {if ((s)->head.marked == 0) (s)->head.marked = 1;} | ||
| 150 | |||
| 151 | 28 | ||
| 152 | static void protomark (TProtoFunc *f) { | 29 | static void protomark (TProtoFunc *f) { |
| 153 | if (!f->head.marked) { | 30 | if (!f->marked) { |
| 154 | int i; | 31 | int i; |
| 155 | f->head.marked = 1; | 32 | f->marked = 1; |
| 156 | strmark(f->source); | 33 | strmark(f->source); |
| 157 | for (i=f->nconsts-1; i>=0; i--) | 34 | for (i=f->nconsts-1; i>=0; i--) |
| 158 | markobject(&f->consts[i]); | 35 | markobject(&f->consts[i]); |
| @@ -161,9 +38,9 @@ static void protomark (TProtoFunc *f) { | |||
| 161 | 38 | ||
| 162 | 39 | ||
| 163 | static void closuremark (Closure *f) { | 40 | static void closuremark (Closure *f) { |
| 164 | if (!f->head.marked) { | 41 | if (!f->marked) { |
| 165 | int i; | 42 | int i; |
| 166 | f->head.marked = 1; | 43 | f->marked = 1; |
| 167 | for (i=f->nelems; i>=0; i--) | 44 | for (i=f->nelems; i>=0; i--) |
| 168 | markobject(&f->consts[i]); | 45 | markobject(&f->consts[i]); |
| 169 | } | 46 | } |
| @@ -171,9 +48,9 @@ static void closuremark (Closure *f) { | |||
| 171 | 48 | ||
| 172 | 49 | ||
| 173 | static void hashmark (Hash *h) { | 50 | static void hashmark (Hash *h) { |
| 174 | if (!h->head.marked) { | 51 | if (!h->marked) { |
| 175 | int i; | 52 | int i; |
| 176 | h->head.marked = 1; | 53 | h->marked = 1; |
| 177 | for (i=nhash(h)-1; i>=0; i--) { | 54 | for (i=nhash(h)-1; i>=0; i--) { |
| 178 | Node *n = node(h,i); | 55 | Node *n = node(h,i); |
| 179 | if (ttype(ref(n)) != LUA_T_NIL) { | 56 | if (ttype(ref(n)) != LUA_T_NIL) { |
| @@ -187,7 +64,7 @@ static void hashmark (Hash *h) { | |||
| 187 | 64 | ||
| 188 | static void globalmark (void) { | 65 | static void globalmark (void) { |
| 189 | TaggedString *g; | 66 | TaggedString *g; |
| 190 | for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){ | 67 | for (g=L->rootglobal; g; g=g->next) { |
| 191 | LUA_ASSERT(g->constindex >= 0, "userdata in global list"); | 68 | LUA_ASSERT(g->constindex >= 0, "userdata in global list"); |
| 192 | if (g->u.s.globalval.ttype != LUA_T_NIL) { | 69 | if (g->u.s.globalval.ttype != LUA_T_NIL) { |
| 193 | markobject(&g->u.s.globalval); | 70 | markobject(&g->u.s.globalval); |
| @@ -197,6 +74,21 @@ static void globalmark (void) { | |||
| 197 | } | 74 | } |
| 198 | 75 | ||
| 199 | 76 | ||
| 77 | static void travstack (void) { | ||
| 78 | StkId i; | ||
| 79 | for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) | ||
| 80 | markobject(L->stack.stack+i); | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | static void travlock (void) { | ||
| 85 | int i; | ||
| 86 | for (i=0; i<L->refSize; i++) | ||
| 87 | if (L->refArray[i].status == LOCK) | ||
| 88 | markobject(&L->refArray[i].o); | ||
| 89 | } | ||
| 90 | |||
| 91 | |||
| 200 | static int markobject (TObject *o) { | 92 | static int markobject (TObject *o) { |
| 201 | switch (ttype(o)) { | 93 | switch (ttype(o)) { |
| 202 | case LUA_T_USERDATA: case LUA_T_STRING: | 94 | case LUA_T_USERDATA: case LUA_T_STRING: |
| @@ -217,36 +109,138 @@ static int markobject (TObject *o) { | |||
| 217 | } | 109 | } |
| 218 | 110 | ||
| 219 | 111 | ||
| 112 | static void collectproto (void) { | ||
| 113 | TProtoFunc **p = &L->rootproto; | ||
| 114 | TProtoFunc *next; | ||
| 115 | while ((next = *p) != NULL) { | ||
| 116 | if (next->marked) { | ||
| 117 | next->marked = 0; | ||
| 118 | p = &next->next; | ||
| 119 | } | ||
| 120 | else { | ||
| 121 | *p = next->next; | ||
| 122 | luaF_freeproto(next); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | static void collectclosure (void) { | ||
| 129 | Closure **p = &L->rootcl; | ||
| 130 | Closure *next; | ||
| 131 | while ((next = *p) != NULL) { | ||
| 132 | if (next->marked) { | ||
| 133 | next->marked = 0; | ||
| 134 | p = &next->next; | ||
| 135 | } | ||
| 136 | else { | ||
| 137 | *p = next->next; | ||
| 138 | luaF_freeclosure(next); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | |||
| 144 | static void collecttable (void) { | ||
| 145 | Hash **p = &L->roottable; | ||
| 146 | Hash *next; | ||
| 147 | while ((next = *p) != NULL) { | ||
| 148 | if (next->marked) { | ||
| 149 | next->marked = 0; | ||
| 150 | p = &next->next; | ||
| 151 | } | ||
| 152 | else { | ||
| 153 | *p = next->next; | ||
| 154 | luaH_free(next); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | |||
| 160 | static void clear_global_list (void) { | ||
| 161 | TaggedString **p = &L->rootglobal; | ||
| 162 | TaggedString *next; | ||
| 163 | while ((next = *p) != NULL) { | ||
| 164 | if (next->marked) p = &next->next; | ||
| 165 | else *p = next->next; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | |||
| 170 | /* | ||
| 171 | ** collect all elements with `marked' < `limit'. | ||
| 172 | ** with limit=1, that means all unmarked elements; | ||
| 173 | ** with limit=MAX_INT, that means all elements (but EMPTY). | ||
| 174 | */ | ||
| 175 | static void collectstring (int limit) { | ||
| 176 | TObject o; /* to call userdata 'gc' tag method */ | ||
| 177 | int i; | ||
| 178 | ttype(&o) = LUA_T_USERDATA; | ||
| 179 | clear_global_list(); | ||
| 180 | for (i=0; i<NUM_HASHS; i++) { | ||
| 181 | stringtable *tb = &L->string_root[i]; | ||
| 182 | int j; | ||
| 183 | for (j=0; j<tb->size; j++) { | ||
| 184 | TaggedString *t = tb->hash[j]; | ||
| 185 | if (t == NULL) continue; | ||
| 186 | if (t->marked < limit) { | ||
| 187 | if (t->constindex == -1) { /* is userdata? */ | ||
| 188 | tsvalue(&o) = t; | ||
| 189 | luaD_gcIM(&o); | ||
| 190 | } | ||
| 191 | luaS_free(t); | ||
| 192 | tb->hash[j] = &luaS_EMPTY; | ||
| 193 | } | ||
| 194 | else if (t->marked == 1) | ||
| 195 | t->marked = 0; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | #ifdef LUA_COMPAT_GC | ||
| 202 | static void tableTM (void) { | ||
| 203 | Hash *p; | ||
| 204 | TObject o; | ||
| 205 | ttype(&o) = LUA_T_ARRAY; | ||
| 206 | for (p = L->roottable; p; p = p->next) { | ||
| 207 | if (!p->marked) { | ||
| 208 | avalue(&o) = p; | ||
| 209 | luaD_gcIM(&o); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | #else | ||
| 214 | #define tableTM() /* do nothing */ | ||
| 215 | #endif | ||
| 216 | |||
| 217 | |||
| 220 | 218 | ||
| 221 | static void markall (void) { | 219 | static void markall (void) { |
| 222 | luaD_travstack(markobject); /* mark stack objects */ | 220 | travstack(); /* mark stack objects */ |
| 223 | globalmark(); /* mark global variable values and names */ | 221 | globalmark(); /* mark global variable values and names */ |
| 224 | travlock(); /* mark locked objects */ | 222 | travlock(); /* mark locked objects */ |
| 225 | luaT_travtagmethods(markobject); /* mark fallbacks */ | 223 | luaT_travtagmethods(markobject); /* mark tag methods */ |
| 224 | } | ||
| 225 | |||
| 226 | |||
| 227 | void luaC_collect (int all) { | ||
| 228 | L->GCthreshold *= 4; /* to avoid GC during GC */ | ||
| 229 | tableTM(); /* call TM for tables (if LUA_COMPAT_GC) */ | ||
| 230 | collecttable(); | ||
| 231 | collectstring(all?MAX_INT:1); | ||
| 232 | collectproto(); | ||
| 233 | collectclosure(); | ||
| 234 | luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ | ||
| 226 | } | 235 | } |
| 227 | 236 | ||
| 228 | 237 | ||
| 229 | long lua_collectgarbage (long limit) { | 238 | long lua_collectgarbage (long limit) { |
| 230 | unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ | 239 | unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ |
| 231 | Hash *freetable; | ||
| 232 | TaggedString *freestr; | ||
| 233 | TProtoFunc *freefunc; | ||
| 234 | Closure *freeclos; | ||
| 235 | markall(); | 240 | markall(); |
| 236 | invalidaterefs(); | 241 | luaR_invalidaterefs(); |
| 237 | freestr = luaS_collector(); | 242 | luaC_collect(0); |
| 238 | freetable = (Hash *)listcollect(&(L->roottable)); | 243 | recovered = recovered - L->nblocks; |
| 239 | freefunc = (TProtoFunc *)listcollect(&(L->rootproto)); | ||
| 240 | freeclos = (Closure *)listcollect(&(L->rootcl)); | ||
| 241 | L->GCthreshold *= 4; /* to avoid GC during GC */ | ||
| 242 | luaC_hashcallIM(freetable); /* GC tag methods for tables */ | ||
| 243 | luaC_strcallIM(freestr); /* GC tag methods for userdata */ | ||
| 244 | luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ | ||
| 245 | luaH_free(freetable); | ||
| 246 | luaS_free(freestr); | ||
| 247 | luaF_freeproto(freefunc); | ||
| 248 | luaF_freeclosure(freeclos); | ||
| 249 | recovered = recovered-L->nblocks; | ||
| 250 | L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; | 244 | L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; |
| 251 | return recovered; | 245 | return recovered; |
| 252 | } | 246 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 1.4 1997/12/01 20:31:25 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 1.5 1999/08/16 20:52:00 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -12,10 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | void luaC_checkGC (void); | 14 | void luaC_checkGC (void); |
| 15 | const TObject *luaC_getref (int ref); | 15 | void luaC_collect (int all); |
| 16 | int luaC_ref (const TObject *o, int lock); | ||
| 17 | void luaC_hashcallIM (Hash *l); | ||
| 18 | void luaC_strcallIM (TaggedString *l); | ||
| 19 | 16 | ||
| 20 | 17 | ||
| 21 | #endif | 18 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llex.c,v 1.38 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 1.39 1999/09/06 13:55:09 roberto Exp roberto $ |
| 3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -37,7 +37,7 @@ void luaX_init (void) { | |||
| 37 | int i; | 37 | int i; |
| 38 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { | 38 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { |
| 39 | TaggedString *ts = luaS_new(reserved[i]); | 39 | TaggedString *ts = luaS_new(reserved[i]); |
| 40 | ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ | 40 | ts->marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ |
| 41 | } | 41 | } |
| 42 | } | 42 | } |
| 43 | 43 | ||
| @@ -426,8 +426,8 @@ int luaX_lex (LexState *LS) { | |||
| 426 | } while (isalnum(LS->current) || LS->current == '_'); | 426 | } while (isalnum(LS->current) || LS->current == '_'); |
| 427 | save('\0'); | 427 | save('\0'); |
| 428 | ts = luaS_new(L->Mbuffer+L->Mbuffbase); | 428 | ts = luaS_new(L->Mbuffer+L->Mbuffbase); |
| 429 | if (ts->head.marked >= FIRST_RESERVED) | 429 | if (ts->marked >= FIRST_RESERVED) |
| 430 | return ts->head.marked; /* reserved word */ | 430 | return ts->marked; /* reserved word */ |
| 431 | LS->seminfo.ts = ts; | 431 | LS->seminfo.ts = ts; |
| 432 | return NAME; | 432 | return NAME; |
| 433 | } | 433 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.c,v 1.22 1999/09/06 20:19:22 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 1.23 1999/09/08 20:45:18 roberto Exp roberto $ |
| 3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -55,13 +55,6 @@ int luaO_equalval (const TObject *t1, const TObject *t2) { | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | void luaO_insertlist (GCnode *root, GCnode *node) { | ||
| 59 | node->next = root->next; | ||
| 60 | root->next = node; | ||
| 61 | node->marked = 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | |||
| 65 | #ifdef OLD_ANSI | 58 | #ifdef OLD_ANSI |
| 66 | void luaO_memup (void *dest, void *src, int size) { | 59 | void luaO_memup (void *dest, void *src, int size) { |
| 67 | while (size--) | 60 | while (size--) |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 1.29 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 1.30 1999/09/06 20:34:18 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -86,20 +86,12 @@ typedef struct TObject { | |||
| 86 | 86 | ||
| 87 | 87 | ||
| 88 | /* | 88 | /* |
| 89 | ** generic header for garbage collector lists | ||
| 90 | */ | ||
| 91 | typedef struct GCnode { | ||
| 92 | struct GCnode *next; | ||
| 93 | int marked; | ||
| 94 | } GCnode; | ||
| 95 | |||
| 96 | |||
| 97 | /* | ||
| 98 | ** String headers for string table | 89 | ** String headers for string table |
| 99 | */ | 90 | */ |
| 100 | 91 | ||
| 101 | typedef struct TaggedString { | 92 | typedef struct TaggedString { |
| 102 | GCnode head; | 93 | struct TaggedString *next; |
| 94 | int marked; | ||
| 103 | unsigned long hash; | 95 | unsigned long hash; |
| 104 | int constindex; /* hint to reuse constants (= -1 if this is a userdata) */ | 96 | int constindex; /* hint to reuse constants (= -1 if this is a userdata) */ |
| 105 | union { | 97 | union { |
| @@ -122,7 +114,8 @@ typedef struct TaggedString { | |||
| 122 | ** Function Prototypes | 114 | ** Function Prototypes |
| 123 | */ | 115 | */ |
| 124 | typedef struct TProtoFunc { | 116 | typedef struct TProtoFunc { |
| 125 | GCnode head; | 117 | struct TProtoFunc *next; |
| 118 | int marked; | ||
| 126 | struct TObject *consts; | 119 | struct TObject *consts; |
| 127 | int nconsts; | 120 | int nconsts; |
| 128 | Byte *code; /* ends with opcode ENDCODE */ | 121 | Byte *code; /* ends with opcode ENDCODE */ |
| @@ -157,7 +150,8 @@ typedef struct LocVar { | |||
| 157 | ** Closures | 150 | ** Closures |
| 158 | */ | 151 | */ |
| 159 | typedef struct Closure { | 152 | typedef struct Closure { |
| 160 | GCnode head; | 153 | struct Closure *next; |
| 154 | int marked; | ||
| 161 | int nelems; /* not included the first one (always the prototype) */ | 155 | int nelems; /* not included the first one (always the prototype) */ |
| 162 | TObject consts[1]; /* at least one for prototype */ | 156 | TObject consts[1]; /* at least one for prototype */ |
| 163 | } Closure; | 157 | } Closure; |
| @@ -170,7 +164,8 @@ typedef struct node { | |||
| 170 | } Node; | 164 | } Node; |
| 171 | 165 | ||
| 172 | typedef struct Hash { | 166 | typedef struct Hash { |
| 173 | GCnode head; | 167 | struct Hash *next; |
| 168 | int marked; | ||
| 174 | Node *node; | 169 | Node *node; |
| 175 | int nhash; | 170 | int nhash; |
| 176 | int nuse; | 171 | int nuse; |
| @@ -189,7 +184,6 @@ extern const TObject luaO_nilobject; | |||
| 189 | : luaO_equalval(t1,t2)) | 184 | : luaO_equalval(t1,t2)) |
| 190 | int luaO_equalval (const TObject *t1, const TObject *t2); | 185 | int luaO_equalval (const TObject *t1, const TObject *t2); |
| 191 | int luaO_redimension (int oldsize); | 186 | int luaO_redimension (int oldsize); |
| 192 | void luaO_insertlist (GCnode *root, GCnode *node); | ||
| 193 | int luaO_str2d (const char *s, real *result); | 187 | int luaO_str2d (const char *s, real *result); |
| 194 | 188 | ||
| 195 | #ifdef OLD_ANSI | 189 | #ifdef OLD_ANSI |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 1.12 1999/05/11 20:08:20 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.13 1999/08/16 20:52:00 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,13 +7,11 @@ | |||
| 7 | 7 | ||
| 8 | #include "lbuiltin.h" | 8 | #include "lbuiltin.h" |
| 9 | #include "ldo.h" | 9 | #include "ldo.h" |
| 10 | #include "lfunc.h" | ||
| 11 | #include "lgc.h" | 10 | #include "lgc.h" |
| 12 | #include "llex.h" | 11 | #include "llex.h" |
| 13 | #include "lmem.h" | 12 | #include "lmem.h" |
| 14 | #include "lstate.h" | 13 | #include "lstate.h" |
| 15 | #include "lstring.h" | 14 | #include "lstring.h" |
| 16 | #include "ltable.h" | ||
| 17 | #include "ltm.h" | 15 | #include "ltm.h" |
| 18 | 16 | ||
| 19 | 17 | ||
| @@ -36,14 +34,10 @@ void lua_open (void) { | |||
| 36 | L->debug = 0; | 34 | L->debug = 0; |
| 37 | L->callhook = NULL; | 35 | L->callhook = NULL; |
| 38 | L->linehook = NULL; | 36 | L->linehook = NULL; |
| 39 | L->rootproto.next = NULL; | 37 | L->rootproto = NULL; |
| 40 | L->rootproto.marked = 0; | 38 | L->rootcl = NULL; |
| 41 | L->rootcl.next = NULL; | 39 | L->rootglobal = NULL; |
| 42 | L->rootcl.marked = 0; | 40 | L->roottable = NULL; |
| 43 | L->rootglobal.next = NULL; | ||
| 44 | L->rootglobal.marked = 0; | ||
| 45 | L->roottable.next = NULL; | ||
| 46 | L->roottable.marked = 0; | ||
| 47 | L->IMtable = NULL; | 41 | L->IMtable = NULL; |
| 48 | L->refArray = NULL; | 42 | L->refArray = NULL; |
| 49 | L->refSize = 0; | 43 | L->refSize = 0; |
| @@ -58,21 +52,14 @@ void lua_open (void) { | |||
| 58 | 52 | ||
| 59 | 53 | ||
| 60 | void lua_close (void) { | 54 | void lua_close (void) { |
| 61 | TaggedString *alludata = luaS_collectudata(); | 55 | luaC_collect(1); /* collect all elements */ |
| 62 | L->GCthreshold = MAX_INT; /* to avoid GC during GC */ | ||
| 63 | luaC_hashcallIM((Hash *)L->roottable.next); /* GC t.methods for tables */ | ||
| 64 | luaC_strcallIM(alludata); /* GC tag methods for userdata */ | ||
| 65 | luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ | ||
| 66 | luaH_free((Hash *)L->roottable.next); | ||
| 67 | luaF_freeproto((TProtoFunc *)L->rootproto.next); | ||
| 68 | luaF_freeclosure((Closure *)L->rootcl.next); | ||
| 69 | luaS_free(alludata); | ||
| 70 | luaS_freeall(); | 56 | luaS_freeall(); |
| 71 | luaM_free(L->stack.stack); | 57 | luaM_free(L->stack.stack); |
| 72 | luaM_free(L->IMtable); | 58 | luaM_free(L->IMtable); |
| 73 | luaM_free(L->refArray); | 59 | luaM_free(L->refArray); |
| 74 | luaM_free(L->Mbuffer); | 60 | luaM_free(L->Mbuffer); |
| 75 | luaM_free(L->Cblocks); | 61 | luaM_free(L->Cblocks); |
| 62 | LUA_ASSERT(L->nblocks == 0, "wrong count for nblocks"); | ||
| 76 | luaM_free(L); | 63 | luaM_free(L); |
| 77 | L = NULL; | 64 | L = NULL; |
| 78 | #ifdef DEBUG | 65 | #ifdef DEBUG |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.18 1999/05/11 14:19:32 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.19 1999/05/11 20:08:20 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 | */ |
| @@ -73,10 +73,10 @@ struct lua_State { | |||
| 73 | lua_CHFunction callhook; | 73 | lua_CHFunction callhook; |
| 74 | lua_LHFunction linehook; | 74 | lua_LHFunction linehook; |
| 75 | /* global state */ | 75 | /* global state */ |
| 76 | GCnode rootproto; /* list of all prototypes */ | 76 | TProtoFunc *rootproto; /* list of all prototypes */ |
| 77 | GCnode rootcl; /* list of all closures */ | 77 | Closure *rootcl; /* list of all closures */ |
| 78 | GCnode roottable; /* list of all tables */ | 78 | Hash *roottable; /* list of all tables */ |
| 79 | GCnode rootglobal; /* list of strings with global values */ | 79 | TaggedString *rootglobal; /* list of strings with global values */ |
| 80 | stringtable *string_root; /* array of hash tables for strings and udata */ | 80 | stringtable *string_root; /* array of hash tables for strings and udata */ |
| 81 | struct IM *IMtable; /* table for tag methods */ | 81 | struct IM *IMtable; /* table for tag methods */ |
| 82 | int last_tag; /* last used tag in IMtable */ | 82 | int last_tag; /* last used tag in IMtable */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 1.20 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.21 1999/09/28 12:27:06 roberto Exp roberto $ |
| 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 | */ |
| @@ -14,17 +14,13 @@ | |||
| 14 | #include "lua.h" | 14 | #include "lua.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | #define NUM_HASHSTR 31 | ||
| 18 | #define NUM_HASHUDATA 31 | ||
| 19 | #define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) | ||
| 20 | |||
| 21 | 17 | ||
| 22 | #define gcsizestring(l) (1+(l/64)) /* "weight" for a string with length 'l' */ | 18 | #define gcsizestring(l) (1+(l/64)) /* "weight" for a string with length 'l' */ |
| 23 | 19 | ||
| 24 | 20 | ||
| 25 | 21 | ||
| 26 | static TaggedString EMPTY = {{NULL, 2}, 0L, 0, | 22 | TaggedString luaS_EMPTY = {NULL, MAX_INT, 0L, 0, |
| 27 | {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; | 23 | {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; |
| 28 | 24 | ||
| 29 | 25 | ||
| 30 | 26 | ||
| @@ -49,6 +45,16 @@ void luaS_init (void) { | |||
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | 47 | ||
| 48 | void luaS_freeall (void) { | ||
| 49 | int i; | ||
| 50 | for (i=0; i<NUM_HASHS; i++) { | ||
| 51 | if (L->string_root[i].hash != init_hash) | ||
| 52 | luaM_free(L->string_root[i].hash); | ||
| 53 | } | ||
| 54 | luaM_free(L->string_root); | ||
| 55 | } | ||
| 56 | |||
| 57 | |||
| 52 | static unsigned long hash_s (const char *s, long l) { | 58 | static unsigned long hash_s (const char *s, long l) { |
| 53 | unsigned long h = 0; /* seed */ | 59 | unsigned long h = 0; /* seed */ |
| 54 | while (l--) | 60 | while (l--) |
| @@ -57,12 +63,12 @@ static unsigned long hash_s (const char *s, long l) { | |||
| 57 | } | 63 | } |
| 58 | 64 | ||
| 59 | 65 | ||
| 60 | static int newsize (stringtable *tb) { | 66 | static int newsize (const stringtable *tb) { |
| 61 | int realuse = 0; | 67 | int realuse = 0; |
| 62 | int i; | 68 | int i; |
| 63 | /* count how many entries are really in use */ | 69 | /* count how many entries are really in use */ |
| 64 | for (i=0; i<tb->size; i++) { | 70 | for (i=0; i<tb->size; i++) { |
| 65 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) | 71 | if (tb->hash[i] != NULL && tb->hash[i] != &luaS_EMPTY) |
| 66 | realuse++; | 72 | realuse++; |
| 67 | } | 73 | } |
| 68 | return luaO_redimension(realuse*2); | 74 | return luaO_redimension(realuse*2); |
| @@ -78,7 +84,7 @@ static void grow (stringtable *tb) { | |||
| 78 | /* rehash */ | 84 | /* rehash */ |
| 79 | tb->nuse = 0; | 85 | tb->nuse = 0; |
| 80 | for (i=0; i<tb->size; i++) { | 86 | for (i=0; i<tb->size; i++) { |
| 81 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) { | 87 | if (tb->hash[i] != NULL && tb->hash[i] != &luaS_EMPTY) { |
| 82 | unsigned long h = tb->hash[i]->hash; | 88 | unsigned long h = tb->hash[i]->hash; |
| 83 | int h1 = h%ns; | 89 | int h1 = h%ns; |
| 84 | while (newhash[h1]) { | 90 | while (newhash[h1]) { |
| @@ -103,8 +109,8 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) { | |||
| 103 | ts->u.s.len = l; | 109 | ts->u.s.len = l; |
| 104 | ts->constindex = 0; | 110 | ts->constindex = 0; |
| 105 | L->nblocks += gcsizestring(l); | 111 | L->nblocks += gcsizestring(l); |
| 106 | ts->head.marked = 0; | 112 | ts->marked = 0; |
| 107 | ts->head.next = (GCnode *)ts; /* signal it is in no list */ | 113 | ts->next = ts; /* signal it is in no list */ |
| 108 | ts->hash = h; | 114 | ts->hash = h; |
| 109 | return ts; | 115 | return ts; |
| 110 | } | 116 | } |
| @@ -115,8 +121,8 @@ static TaggedString *newone_u (void *buff, int tag, unsigned long h) { | |||
| 115 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | 121 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; |
| 116 | ts->constindex = -1; /* tag -> this is a userdata */ | 122 | ts->constindex = -1; /* tag -> this is a userdata */ |
| 117 | L->nblocks++; | 123 | L->nblocks++; |
| 118 | ts->head.marked = 0; | 124 | ts->marked = 0; |
| 119 | ts->head.next = (GCnode *)ts; /* signal it is in no list */ | 125 | ts->next = ts; /* signal it is in no list */ |
| 120 | ts->hash = h; | 126 | ts->hash = h; |
| 121 | return ts; | 127 | return ts; |
| 122 | } | 128 | } |
| @@ -144,7 +150,7 @@ static TaggedString *insert_s (const char *str, long l, stringtable *tb) { | |||
| 144 | int j = -1; /* last empty place found (or -1) */ | 150 | int j = -1; /* last empty place found (or -1) */ |
| 145 | int h1 = h%size; | 151 | int h1 = h%size; |
| 146 | while ((ts = tb->hash[h1]) != NULL) { | 152 | while ((ts = tb->hash[h1]) != NULL) { |
| 147 | if (ts == &EMPTY) | 153 | if (ts == &luaS_EMPTY) |
| 148 | j = h1; | 154 | j = h1; |
| 149 | else if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) | 155 | else if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) |
| 150 | return ts; | 156 | return ts; |
| @@ -168,7 +174,7 @@ static TaggedString *insert_u (void *buff, int tag, stringtable *tb) { | |||
| 168 | int j = -1; | 174 | int j = -1; |
| 169 | int h1 = h%size; | 175 | int h1 = h%size; |
| 170 | while ((ts = tb->hash[h1]) != NULL) { | 176 | while ((ts = tb->hash[h1]) != NULL) { |
| 171 | if (ts == &EMPTY) | 177 | if (ts == &luaS_EMPTY) |
| 172 | j = h1; | 178 | j = h1; |
| 173 | else if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v) | 179 | else if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v) |
| 174 | return ts; | 180 | return ts; |
| @@ -200,115 +206,29 @@ TaggedString *luaS_new (const char *str) { | |||
| 200 | 206 | ||
| 201 | TaggedString *luaS_newfixedstring (const char *str) { | 207 | TaggedString *luaS_newfixedstring (const char *str) { |
| 202 | TaggedString *ts = luaS_new(str); | 208 | TaggedString *ts = luaS_new(str); |
| 203 | if (ts->head.marked == 0) | 209 | if (ts->marked == 0) ts->marked = 2; /* avoid GC */ |
| 204 | ts->head.marked = 2; /* avoid GC */ | ||
| 205 | return ts; | 210 | return ts; |
| 206 | } | 211 | } |
| 207 | 212 | ||
| 208 | 213 | ||
| 209 | void luaS_free (TaggedString *l) { | 214 | void luaS_free (TaggedString *t) { |
| 210 | while (l) { | 215 | L->nblocks -= (t->constindex == -1) ? 1 : gcsizestring(t->u.s.len); |
| 211 | TaggedString *next = (TaggedString *)l->head.next; | 216 | luaM_free(t); |
| 212 | L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len); | ||
| 213 | luaM_free(l); | ||
| 214 | l = next; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | |||
| 219 | /* | ||
| 220 | ** Garbage collection functions. | ||
| 221 | */ | ||
| 222 | |||
| 223 | static void remove_from_list (GCnode *l) { | ||
| 224 | while (l) { | ||
| 225 | GCnode *next = l->next; | ||
| 226 | while (next && !next->marked) | ||
| 227 | next = l->next = next->next; | ||
| 228 | l = next; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | |||
| 233 | TaggedString *luaS_collector (void) { | ||
| 234 | TaggedString *frees = NULL; | ||
| 235 | int i; | ||
| 236 | remove_from_list(&(L->rootglobal)); | ||
| 237 | for (i=0; i<NUM_HASHS; i++) { | ||
| 238 | stringtable *tb = &L->string_root[i]; | ||
| 239 | int j; | ||
| 240 | for (j=0; j<tb->size; j++) { | ||
| 241 | TaggedString *t = tb->hash[j]; | ||
| 242 | if (t == NULL) continue; | ||
| 243 | if (t->head.marked == 1) | ||
| 244 | t->head.marked = 0; | ||
| 245 | else if (!t->head.marked) { | ||
| 246 | t->head.next = (GCnode *)frees; | ||
| 247 | frees = t; | ||
| 248 | tb->hash[j] = &EMPTY; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | } | ||
| 252 | return frees; | ||
| 253 | } | ||
| 254 | |||
| 255 | |||
| 256 | TaggedString *luaS_collectudata (void) { | ||
| 257 | TaggedString *frees = NULL; | ||
| 258 | int i; | ||
| 259 | L->rootglobal.next = NULL; /* empty list of globals */ | ||
| 260 | for (i=NUM_HASHSTR; i<NUM_HASHS; i++) { | ||
| 261 | stringtable *tb = &L->string_root[i]; | ||
| 262 | int j; | ||
| 263 | for (j=0; j<tb->size; j++) { | ||
| 264 | TaggedString *t = tb->hash[j]; | ||
| 265 | if (t == NULL || t == &EMPTY) | ||
| 266 | continue; | ||
| 267 | LUA_ASSERT(t->constindex == -1, "must be userdata"); | ||
| 268 | t->head.next = (GCnode *)frees; | ||
| 269 | frees = t; | ||
| 270 | tb->hash[j] = &EMPTY; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | return frees; | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 277 | void luaS_freeall (void) { | ||
| 278 | int i; | ||
| 279 | for (i=0; i<NUM_HASHS; i++) { | ||
| 280 | stringtable *tb = &L->string_root[i]; | ||
| 281 | int j; | ||
| 282 | for (j=0; j<tb->size; j++) { | ||
| 283 | TaggedString *t = tb->hash[j]; | ||
| 284 | if (t != &EMPTY) luaM_free(t); | ||
| 285 | } | ||
| 286 | if (tb->hash != init_hash) luaM_free(tb->hash); | ||
| 287 | } | ||
| 288 | luaM_free(L->string_root); | ||
| 289 | } | 217 | } |
| 290 | 218 | ||
| 291 | 219 | ||
| 292 | void luaS_rawsetglobal (TaggedString *ts, TObject *newval) { | 220 | void luaS_rawsetglobal (TaggedString *ts, const TObject *newval) { |
| 293 | ts->u.s.globalval = *newval; | 221 | ts->u.s.globalval = *newval; |
| 294 | if (ts->head.next == (GCnode *)ts) { /* is not in list? */ | 222 | if (ts->next == ts) { /* is not in list? */ |
| 295 | ts->head.next = L->rootglobal.next; | 223 | ts->next = L->rootglobal; |
| 296 | L->rootglobal.next = (GCnode *)ts; | 224 | L->rootglobal = ts; |
| 297 | } | 225 | } |
| 298 | } | 226 | } |
| 299 | 227 | ||
| 300 | 228 | ||
| 301 | const char *luaS_travsymbol (int (*fn)(TObject *)) { | ||
| 302 | TaggedString *g; | ||
| 303 | for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) | ||
| 304 | if (fn(&g->u.s.globalval)) | ||
| 305 | return g->str; | ||
| 306 | return NULL; | ||
| 307 | } | ||
| 308 | |||
| 309 | |||
| 310 | int luaS_globaldefined (const char *name) { | 229 | int luaS_globaldefined (const char *name) { |
| 311 | TaggedString *ts = luaS_new(name); | 230 | TaggedString *ts = luaS_new(name); |
| 312 | return ts->u.s.globalval.ttype != LUA_T_NIL; | 231 | return ts->u.s.globalval.ttype != LUA_T_NIL; |
| 313 | } | 232 | } |
| 314 | 233 | ||
| 234 | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.h,v 1.7 1998/03/06 16:54:42 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.8 1999/08/16 20:52:00 roberto Exp roberto $ |
| 3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,18 +11,22 @@ | |||
| 11 | #include "lobject.h" | 11 | #include "lobject.h" |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #define NUM_HASHSTR 31 | ||
| 15 | #define NUM_HASHUDATA 31 | ||
| 16 | #define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) | ||
| 17 | |||
| 18 | |||
| 19 | extern TaggedString luaS_EMPTY; | ||
| 20 | |||
| 14 | void luaS_init (void); | 21 | void luaS_init (void); |
| 15 | TaggedString *luaS_createudata (void *udata, int tag); | 22 | TaggedString *luaS_createudata (void *udata, int tag); |
| 16 | TaggedString *luaS_collector (void); | 23 | void luaS_freeall (void); |
| 17 | void luaS_free (TaggedString *l); | 24 | void luaS_free (TaggedString *ts); |
| 18 | TaggedString *luaS_newlstr (const char *str, long l); | 25 | TaggedString *luaS_newlstr (const char *str, long l); |
| 19 | TaggedString *luaS_new (const char *str); | 26 | TaggedString *luaS_new (const char *str); |
| 20 | TaggedString *luaS_newfixedstring (const char *str); | 27 | TaggedString *luaS_newfixedstring (const char *str); |
| 21 | void luaS_rawsetglobal (TaggedString *ts, TObject *newval); | 28 | void luaS_rawsetglobal (TaggedString *ts, const TObject *newval); |
| 22 | const char *luaS_travsymbol (int (*fn)(TObject *)); | ||
| 23 | int luaS_globaldefined (const char *name); | 29 | int luaS_globaldefined (const char *name); |
| 24 | TaggedString *luaS_collectudata (void); | ||
| 25 | void luaS_freeall (void); | ||
| 26 | 30 | ||
| 27 | 31 | ||
| 28 | #endif | 32 | #endif |
| @@ -1,10 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 1.23 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.24 1999/09/22 14:38:45 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 | */ |
| 6 | 6 | ||
| 7 | #include <stdlib.h> | ||
| 8 | 7 | ||
| 9 | #include "lauxlib.h" | 8 | #include "lauxlib.h" |
| 10 | #include "lmem.h" | 9 | #include "lmem.h" |
| @@ -69,17 +68,6 @@ Node *luaH_present (const Hash *t, const TObject *key) { | |||
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | 70 | ||
| 72 | void luaH_free (Hash *frees) { | ||
| 73 | while (frees) { | ||
| 74 | Hash *next = (Hash *)frees->head.next; | ||
| 75 | L->nblocks -= gcsize(frees->nhash); | ||
| 76 | luaM_free(nodevector(frees)); | ||
| 77 | luaM_free(frees); | ||
| 78 | frees = next; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 83 | static Node *hashnodecreate (int nhash) { | 71 | static Node *hashnodecreate (int nhash) { |
| 84 | Node *const v = luaM_newvector(nhash, Node); | 72 | Node *const v = luaM_newvector(nhash, Node); |
| 85 | int i; | 73 | int i; |
| @@ -96,12 +84,21 @@ Hash *luaH_new (int nhash) { | |||
| 96 | nhash(t) = nhash; | 84 | nhash(t) = nhash; |
| 97 | nuse(t) = 0; | 85 | nuse(t) = 0; |
| 98 | t->htag = TagDefault; | 86 | t->htag = TagDefault; |
| 99 | luaO_insertlist(&(L->roottable), (GCnode *)t); | 87 | t->next = L->roottable; |
| 88 | L->roottable = t; | ||
| 89 | t->marked = 0; | ||
| 100 | L->nblocks += gcsize(nhash); | 90 | L->nblocks += gcsize(nhash); |
| 101 | return t; | 91 | return t; |
| 102 | } | 92 | } |
| 103 | 93 | ||
| 104 | 94 | ||
| 95 | void luaH_free (Hash *t) { | ||
| 96 | L->nblocks -= gcsize(t->nhash); | ||
| 97 | luaM_free(nodevector(t)); | ||
| 98 | luaM_free(t); | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 105 | static int newsize (Hash *t) { | 102 | static int newsize (Hash *t) { |
| 106 | Node *const v = t->node; | 103 | Node *const v = t->node; |
| 107 | const int size = nhash(t); | 104 | const int size = nhash(t); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.h,v 1.11 1999/02/23 14:57:28 roberto Exp roberto $ | 2 | ** $Id: ltable.h,v 1.12 1999/08/16 20:52:00 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 | */ |
| @@ -19,7 +19,7 @@ | |||
| 19 | #define luaH_move(t,from,to) (luaH_setint(t, to, luaH_getint(t, from))) | 19 | #define luaH_move(t,from,to) (luaH_setint(t, to, luaH_getint(t, from))) |
| 20 | 20 | ||
| 21 | Hash *luaH_new (int nhash); | 21 | Hash *luaH_new (int nhash); |
| 22 | void luaH_free (Hash *frees); | 22 | void luaH_free (Hash *t); |
| 23 | Node *luaH_present (const Hash *t, const TObject *key); | 23 | Node *luaH_present (const Hash *t, const TObject *key); |
| 24 | void luaH_set (Hash *t, const TObject *ref, const TObject *val); | 24 | void luaH_set (Hash *t, const TObject *ref, const TObject *val); |
| 25 | int luaH_pos (const Hash *t, const TObject *r); | 25 | int luaH_pos (const Hash *t, const TObject *r); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.c,v 1.26 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 1.27 1999/09/20 14:57:29 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 | */ |
| @@ -39,13 +39,17 @@ static const char luaT_validevents[NUM_TAGS][IM_N] = { | |||
| 39 | {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */ | 39 | {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */ |
| 40 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */ | 40 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */ |
| 41 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */ | 41 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */ |
| 42 | {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */ | 42 | {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_ARRAY */ |
| 43 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_PROTO */ | 43 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_PROTO */ |
| 44 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CPROTO */ | 44 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CPROTO */ |
| 45 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */ | 45 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */ |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | int luaT_validevent (int t, int e) { /* ORDER LUA_T */ | 48 | int luaT_validevent (int t, int e) { /* ORDER LUA_T */ |
| 49 | #ifdef LUA_COMPAT_GC | ||
| 50 | if (t == LUA_T_ARRAY && e == IM_GC) | ||
| 51 | return 1; /* old versions allowed gc tag method for tables */ | ||
| 52 | #endif | ||
| 49 | return (t < LUA_T_NIL) ? 1 : luaT_validevents[-t][e]; | 53 | return (t < LUA_T_NIL) ? 1 : luaT_validevents[-t][e]; |
| 50 | } | 54 | } |
| 51 | 55 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | # | 1 | # |
| 2 | ## $Id: makefile,v 1.19 1999/02/24 21:31:03 roberto Exp roberto $ | 2 | ## $Id: makefile,v 1.20 1999/08/17 20:21:52 roberto Exp roberto $ |
| 3 | ## Makefile | 3 | ## Makefile |
| 4 | ## See Copyright Notice in lua.h | 4 | ## See Copyright Notice in lua.h |
| 5 | # | 5 | # |
| @@ -15,20 +15,19 @@ | |||
| 15 | # facilities (e.g. strerror, locale.h, memmove). SunOS does not comply; | 15 | # facilities (e.g. strerror, locale.h, memmove). SunOS does not comply; |
| 16 | # so, add "-DOLD_ANSI" on SunOS | 16 | # so, add "-DOLD_ANSI" on SunOS |
| 17 | # | 17 | # |
| 18 | # define LUA_COMPAT2_5 if yous system does need to be compatible with | ||
| 19 | # version 2.5 (or older) | ||
| 20 | # | ||
| 21 | # define LUA_NUM_TYPE if you need numbers to be different from double | 18 | # define LUA_NUM_TYPE if you need numbers to be different from double |
| 22 | # (for instance, -DLUA_NUM_TYPE=float) | 19 | # (for instance, -DLUA_NUM_TYPE=float) |
| 23 | # | 20 | # |
| 21 | # define LUA_COMPAT_GC if you need garbage-collect tag methods for tables | ||
| 22 | # (only for compatibility with previous versions) | ||
| 24 | 23 | ||
| 25 | CONFIG = -DPOPEN -D_POSIX_SOURCE | 24 | CONFIG = -DPOPEN -D_POSIX_SOURCE |
| 26 | #CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG | 25 | #CONFIG = -DOLD_ANSI -DDEBUG -DLUA_COMPAT_GC |
| 27 | 26 | ||
| 28 | 27 | ||
| 29 | # Compilation parameters | 28 | # Compilation parameters |
| 30 | CC = gcc | 29 | CC = gcc |
| 31 | CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-declarations -Wnested-externs | 30 | CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-declarations -Wnested-externs -Werror |
| 32 | CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 | 31 | CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 |
| 33 | 32 | ||
| 34 | 33 | ||
| @@ -53,6 +52,7 @@ LUAOBJS = \ | |||
| 53 | lmem.o \ | 52 | lmem.o \ |
| 54 | lobject.o \ | 53 | lobject.o \ |
| 55 | lparser.o \ | 54 | lparser.o \ |
| 55 | lref.o \ | ||
| 56 | lstate.o \ | 56 | lstate.o \ |
| 57 | lstring.o \ | 57 | lstring.o \ |
| 58 | ltable.o \ | 58 | ltable.o \ |
| @@ -99,7 +99,7 @@ clear : | |||
| 99 | 99 | ||
| 100 | 100 | ||
| 101 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h \ | 101 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h \ |
| 102 | luadebug.h lfunc.h lgc.h lmem.h lstring.h ltable.h ltm.h lvm.h | 102 | luadebug.h lfunc.h lgc.h lmem.h lref.h lstring.h ltable.h ltm.h lvm.h |
| 103 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h | 103 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h |
| 104 | lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \ | 104 | lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \ |
| 105 | luadebug.h | 105 | luadebug.h |
| @@ -107,11 +107,11 @@ lbuiltin.o: lbuiltin.c lapi.h lua.h lobject.h lauxlib.h lbuiltin.h \ | |||
| 107 | ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \ | 107 | ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \ |
| 108 | lundump.h lzio.h lvm.h | 108 | lundump.h lzio.h lvm.h |
| 109 | ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h | 109 | ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h |
| 110 | ldo.o: ldo.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ | 110 | ldo.o: ldo.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h lgc.h \ |
| 111 | lmem.h lparser.h lzio.h lstring.h ltm.h lundump.h lvm.h | 111 | lmem.h lparser.h lzio.h lstring.h ltm.h lundump.h lvm.h |
| 112 | lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h | 112 | lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h |
| 113 | lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ | 113 | lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ |
| 114 | lmem.h lstring.h ltable.h ltm.h | 114 | lref.h lstring.h ltable.h ltm.h |
| 115 | linit.o: linit.c lua.h lualib.h | 115 | linit.o: linit.c lua.h lualib.h |
| 116 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h | 116 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h |
| 117 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ | 117 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ |
| @@ -119,12 +119,11 @@ llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ | |||
| 119 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h | 119 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h |
| 120 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h luadebug.h | 120 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h luadebug.h |
| 121 | lobject.o: lobject.c lobject.h lua.h | 121 | lobject.o: lobject.c lobject.h lua.h |
| 122 | lparser.o: lparser.c lauxlib.h lua.h ldo.h lobject.h lstate.h \ | 122 | lparser.o: lparser.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h \ |
| 123 | luadebug.h lfunc.h llex.h lzio.h lmem.h lopcodes.h lparser.h \ | 123 | llex.h lzio.h lmem.h lopcodes.h lparser.h lstring.h |
| 124 | lstring.h | 124 | lref.o: lref.c lmem.h lref.h lobject.h lua.h lstate.h luadebug.h |
| 125 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h \ | 125 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h \ |
| 126 | luadebug.h lfunc.h lgc.h llex.h lzio.h lmem.h lstring.h ltable.h \ | 126 | luadebug.h lgc.h llex.h lzio.h lmem.h lstring.h ltm.h |
| 127 | ltm.h | ||
| 128 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h luadebug.h \ | 127 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h luadebug.h \ |
| 129 | lstring.h | 128 | lstring.h |
| 130 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h | 129 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h |
| @@ -134,7 +133,7 @@ ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h luadebug.h \ | |||
| 134 | ltm.h | 133 | ltm.h |
| 135 | lua.o: lua.c lua.h luadebug.h lualib.h | 134 | lua.o: lua.c lua.h luadebug.h lualib.h |
| 136 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ | 135 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ |
| 137 | lstring.h lundump.h lzio.h | 136 | lopcodes.h lstring.h lundump.h lzio.h |
| 138 | lvm.o: lvm.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h \ | 137 | lvm.o: lvm.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h \ |
| 139 | lfunc.h lgc.h lmem.h lopcodes.h lstring.h ltable.h ltm.h lvm.h | 138 | lfunc.h lgc.h lopcodes.h lstring.h ltable.h ltm.h lvm.h |
| 140 | lzio.o: lzio.c lzio.h | 139 | lzio.o: lzio.c lzio.h |
| @@ -1,4 +1,4 @@ | |||
| 1 | % $Id: manual.tex,v 1.32 1999/05/11 20:46:28 roberto Exp roberto $ | 1 | % $Id: manual.tex,v 1.33 1999/05/27 20:21:03 roberto Exp roberto $ |
| 2 | 2 | ||
| 3 | \documentclass[11pt]{article} | 3 | \documentclass[11pt]{article} |
| 4 | \usepackage{fullpage,bnf} | 4 | \usepackage{fullpage,bnf} |
| @@ -41,7 +41,7 @@ Waldemar Celes | |||
| 41 | \tecgraf\ --- Computer Science Department --- PUC-Rio | 41 | \tecgraf\ --- Computer Science Department --- PUC-Rio |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | \date{{\small \tt\$Date: 1999/05/11 20:46:28 $ $}} | 44 | \date{{\small \tt\$Date: 1999/05/27 20:21:03 $ $}} |
| 45 | 45 | ||
| 46 | \maketitle | 46 | \maketitle |
| 47 | 47 | ||
| @@ -1273,7 +1273,8 @@ is terminated, returning an error condition. | |||
| 1273 | 1273 | ||
| 1274 | The only argument to \verb|_ERRORMESSAGE| is a string | 1274 | The only argument to \verb|_ERRORMESSAGE| is a string |
| 1275 | describing the error. | 1275 | describing the error. |
| 1276 | The default definition for this function calls \verb|_ALERT|, | 1276 | The default definition for |
| 1277 | this function calls \verb|_ALERT|, \Deffunc{_ALERT} | ||
| 1277 | which prints the message to \verb|stderr| \see{alert}. | 1278 | which prints the message to \verb|stderr| \see{alert}. |
| 1278 | The standard I/O library redefines \verb|_ERRORMESSAGE|, | 1279 | The standard I/O library redefines \verb|_ERRORMESSAGE|, |
| 1279 | and uses the debug facilities \see{debugI} | 1280 | and uses the debug facilities \see{debugI} |
| @@ -1835,6 +1836,8 @@ void lua_unref (int ref); | |||
| 1835 | The function \verb|lua_ref| creates a reference | 1836 | The function \verb|lua_ref| creates a reference |
| 1836 | to the object that is on the top of the stack, | 1837 | to the object that is on the top of the stack, |
| 1837 | and returns this reference. | 1838 | and returns this reference. |
| 1839 | For a \nil{} object, the reference is always -1; | ||
| 1840 | otherwise, it is a non-negative integer. | ||
| 1838 | If \verb|lock| is true, the object is \emph{locked}: | 1841 | If \verb|lock| is true, the object is \emph{locked}: |
| 1839 | this means the object will not be garbage collected. | 1842 | this means the object will not be garbage collected. |
| 1840 | Note that an unlocked reference may be garbage collected. | 1843 | Note that an unlocked reference may be garbage collected. |
| @@ -2503,26 +2506,32 @@ The following combinations are allowed in describing a character class: | |||
| 2503 | \item[\T{\%s}] --- represents all space characters. | 2506 | \item[\T{\%s}] --- represents all space characters. |
| 2504 | \item[\T{\%u}] --- represents all upper case letters. | 2507 | \item[\T{\%u}] --- represents all upper case letters. |
| 2505 | \item[\T{\%w}] --- represents all alphanumeric characters. | 2508 | \item[\T{\%w}] --- represents all alphanumeric characters. |
| 2506 | \item[\T{\%x}] --- represents all hexa-decimal digits. | 2509 | \item[\T{\%x}] --- represents all hexadecimal digits. |
| 2507 | \item[\T{\%z}] --- represents the character with representation 0. | 2510 | \item[\T{\%z}] --- represents the character with representation 0. |
| 2508 | \item[\T{\%\M{x}}] (where \M{x} is any non alphanumeric character) --- | 2511 | \item[\T{\%\M{x}}] (where \M{x} is any non alphanumeric character) --- |
| 2509 | represents the character \M{x}. | 2512 | represents the character \M{x}. |
| 2510 | This is the standard way to escape the magic characters \verb|()%.[]*-?|. | 2513 | This is the standard way to escape the magic characters \verb|()%.[]*-?|. |
| 2511 | It is strongly recommended that any control character (even the non magic), | 2514 | It is strongly recommended that any control character (even the non magic), |
| 2512 | when used to represent itself in a pattern, should be preceded by a \verb|%|. | 2515 | when used to represent itself in a pattern, should be preceded by a \verb|%|. |
| 2516 | |||
| 2513 | \item[\T{[char-set]}] --- | 2517 | \item[\T{[char-set]}] --- |
| 2514 | Represents the class which is the union of all | 2518 | Represents the class which is the union of all |
| 2515 | characters in char-set. | 2519 | characters in char-set. |
| 2516 | To include a \verb|]| in char-set, it must be the first character. | ||
| 2517 | A range of characters may be specified by | 2520 | A range of characters may be specified by |
| 2518 | separating the end characters of the range with a \verb|-|. | 2521 | separating the end characters of the range with a \verb|-|. |
| 2519 | If \verb|-| appears as the first or last character of char-set, | ||
| 2520 | then it represents itself. | ||
| 2521 | All classes \verb|%|\emph{x} described above can also be used as | 2522 | All classes \verb|%|\emph{x} described above can also be used as |
| 2522 | components in a char-set. | 2523 | components in a char-set. |
| 2523 | All other characters in char-set represent themselves. | 2524 | All other characters in char-set represent themselves. |
| 2524 | E.g., assuming an \emph{ascii} character set, | 2525 | E.g., \verb|[%w_]| (or \verb|[_%w]|) |
| 2525 | \verb|[%dA-Fa-f]| specifies the hexa-decimal digits. | 2526 | represents all alphanumeric characters plus the underscore, |
| 2527 | \verb|[0-7]| represents the octal digits, | ||
| 2528 | and \verb|[0-7%l%-]| represents the octal digits plus | ||
| 2529 | the lower case letters plus the \verb|-| character. | ||
| 2530 | |||
| 2531 | The interaction between ranges and classes is not defined. | ||
| 2532 | Therefore, patterns like \verb|[%a-z]| or \verb|[a-%%]| | ||
| 2533 | have no meaning. | ||
| 2534 | |||
| 2526 | \item[\T{[\^{ }char-set]}] --- | 2535 | \item[\T{[\^{ }char-set]}] --- |
| 2527 | represents the complement of char-set, | 2536 | represents the complement of char-set, |
| 2528 | where char-set is interpreted as above. | 2537 | where char-set is interpreted as above. |
| @@ -3187,6 +3196,8 @@ accepting commands from standard input until an \verb|EOF|. | |||
| 3187 | Each line entered is immediately executed. | 3196 | Each line entered is immediately executed. |
| 3188 | \item[\T{-q}] same as \T{-i}, but without a prompt (quiet mode). | 3197 | \item[\T{-q}] same as \T{-i}, but without a prompt (quiet mode). |
| 3189 | \item[\T{-}] executes \verb|stdin| as a file. | 3198 | \item[\T{-}] executes \verb|stdin| as a file. |
| 3199 | \item[\T{--}] stops the execution of arguments; | ||
| 3200 | all arguments after it are simply passed to the Lua script. | ||
| 3190 | \item[\T{var=value}] sets global \verb|var| with string \verb|"value"|. | 3201 | \item[\T{var=value}] sets global \verb|var| with string \verb|"value"|. |
| 3191 | \item[\T{filename}] executes file \verb|filename| as a Lua chunk. | 3202 | \item[\T{filename}] executes file \verb|filename| as a Lua chunk. |
| 3192 | \end{description} | 3203 | \end{description} |
| @@ -3203,6 +3214,37 @@ will first interact with the user until an \verb|EOF|, | |||
| 3203 | then will set \verb|a| to \verb|"test"|, | 3214 | then will set \verb|a| to \verb|"test"|, |
| 3204 | and finally will run the file \verb|prog.lua|. | 3215 | and finally will run the file \verb|prog.lua|. |
| 3205 | 3216 | ||
| 3217 | All arguments from the command line are passed to the Lua program in | ||
| 3218 | a table called \verb|arg|. | ||
| 3219 | If the command line has the \verb|--| argument, | ||
| 3220 | this argument is at index 0; | ||
| 3221 | the arguments after it get indices 1, 2, \ldots; | ||
| 3222 | and the arguments before it get negative indices. | ||
| 3223 | The field \verb|n| gets the index of the last argument, | ||
| 3224 | and the field \verb|nn| gets the index of the first argument | ||
| 3225 | (always a negative number). | ||
| 3226 | For instance: | ||
| 3227 | \begin{verbatim} | ||
| 3228 | $ lua -e "foreach(arg, print)" -- a b | ||
| 3229 | -1 foreach(arg, print) | ||
| 3230 | -2 -e | ||
| 3231 | -3 lua | ||
| 3232 | 0 -- | ||
| 3233 | 1 a | ||
| 3234 | 2 b | ||
| 3235 | nn -3 | ||
| 3236 | n 2 | ||
| 3237 | \end{verbatim} | ||
| 3238 | If the command line has no \verb|--| argument, | ||
| 3239 | all arguments have negative indices, with the last one at position -1. | ||
| 3240 | As a general rule, if you want to traverse all the | ||
| 3241 | arguments after the \verb|--|, you loop from 1 to \verb|arg.n| | ||
| 3242 | (you can use the \verb|foreachi| function, for instance). | ||
| 3243 | If you want to traverse all arguments, | ||
| 3244 | you loop from \verb|arg.nn| until \verb|arg.n|. | ||
| 3245 | In any case, you may call \verb|exit| at the end of a script, | ||
| 3246 | to stop Lua from running the other arguments. | ||
| 3247 | |||
| 3206 | When in interactive mode, | 3248 | When in interactive mode, |
| 3207 | a multi-line statement can be written finishing intermediate | 3249 | a multi-line statement can be written finishing intermediate |
| 3208 | lines with a backslash (\verb|\|). | 3250 | lines with a backslash (\verb|\|). |
| @@ -3216,6 +3258,7 @@ In Unix systems, Lua scripts can be made into executable programs | |||
| 3216 | by using the \verb|#!| form, | 3258 | by using the \verb|#!| form, |
| 3217 | as in \verb|#!/usr/local/bin/lua|. | 3259 | as in \verb|#!/usr/local/bin/lua|. |
| 3218 | 3260 | ||
| 3261 | |||
| 3219 | \section*{Acknowledgments} | 3262 | \section*{Acknowledgments} |
| 3220 | 3263 | ||
| 3221 | The authors would like to thank CENPES/PETROBRAS which, | 3264 | The authors would like to thank CENPES/PETROBRAS which, |
