diff --git a/lapi.c b/lapi.c index 92a841d1..1f63dbc5 100644 --- a/lapi.c +++ b/lapi.c @@ -1,11 +1,10 @@ /* -** $Id: lapi.c,v 1.49 1999/09/20 14:57:29 roberto Exp roberto $ +** $Id: lapi.c,v 1.50 1999/09/21 16:10:13 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ -#include #include #include "lapi.h" @@ -15,6 +14,7 @@ #include "lgc.h" #include "lmem.h" #include "lobject.h" +#include "lref.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" @@ -387,14 +387,14 @@ void lua_settag (int tag) { TaggedString *luaA_nextvar (TaggedString *g) { if (g == NULL) - g = (TaggedString *)L->rootglobal.next; /* first variable */ + g = L->rootglobal; /* first variable */ else { /* check whether name is in global var list */ - luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected"); - g = (TaggedString *)g->head.next; /* get next */ + luaL_arg_check(g != g->next, 1, "variable name expected"); + g = g->next; /* get next */ } while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */ - g = (TaggedString *)g->head.next; + g = g->next; if (g) { ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g; incr_top; @@ -574,12 +574,18 @@ static int checkfunc (TObject *o) { const char *lua_getobjname (lua_Object o, const char **name) { /* try to find a name for given function */ + TaggedString *g; set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */ - if ((*name = luaS_travsymbol(checkfunc)) != NULL) - return "global"; - else if ((*name = luaT_travtagmethods(checkfunc)) != NULL) + for (g=L->rootglobal; g; g=g->next) { + if (checkfunc(&g->u.s.globalval)) { + *name = g->str; + return "global"; + } + } + /* not found: try tag methods */ + if ((*name = luaT_travtagmethods(checkfunc)) != NULL) return "tag-method"; - else return ""; + else return ""; /* not found at all */ } /* }====================================================== */ @@ -615,7 +621,7 @@ void lua_endblock (void) { int lua_ref (int lock) { int ref; checkCparams(1); - ref = luaC_ref(L->stack.top-1, lock); + ref = luaR_ref(L->stack.top-1, lock); L->stack.top--; return ref; } @@ -623,7 +629,7 @@ int lua_ref (int lock) { lua_Object lua_getref (int ref) { - const TObject *o = luaC_getref(ref); + const TObject *o = luaR_getref(ref); return (o ? put_luaObject(o) : LUA_NOOBJECT); } diff --git a/lbuiltin.c b/lbuiltin.c index 74e8c6d0..b4bdcfd3 100644 --- a/lbuiltin.c +++ b/lbuiltin.c @@ -1,5 +1,5 @@ /* -** $Id: lbuiltin.c,v 1.62 1999/09/08 20:45:18 roberto Exp roberto $ +** $Id: lbuiltin.c,v 1.63 1999/09/20 14:57:29 roberto Exp roberto $ ** Built-in functions ** See Copyright Notice in lua.h */ @@ -222,9 +222,15 @@ static void luaB_rawsettable (void) { } static void luaB_settagmethod (void) { + int tag = luaL_check_int(1); + const char *event = luaL_check_string(2); lua_Object nf = luaL_nonnullarg(3); +#ifndef LUA_COMPAT_GC + if (strcmp(event, "gc") == 0 && tag != LUA_T_NIL) + lua_error("cannot set this tag method from Lua"); +#endif lua_pushobject(nf); - lua_pushobject(lua_settagmethod(luaL_check_int(1), luaL_check_string(2))); + lua_pushobject(lua_settagmethod(tag, event)); } static void luaB_gettagmethod (void) { @@ -437,12 +443,11 @@ static void luaB_foreach (void) { static void luaB_foreachvar (void) { - GCnode *g; + TaggedString *s; TObject f; /* see comment in 'foreachi' */ f = *luaA_Address(luaL_functionarg(1)); luaD_checkstack(4); /* for extra var name, f, var name, and globalval */ - for (g = L->rootglobal.next; g; g = g->next) { - TaggedString *s = (TaggedString *)g; + for (s = L->rootglobal; s; s = s->next) { if (s->u.s.globalval.ttype != LUA_T_NIL) { pushtagstring(s); /* keep (extra) s on stack to avoid GC */ *(L->stack.top++) = f; @@ -451,10 +456,10 @@ static void luaB_foreachvar (void) { luaD_calln(2, 1); if (ttype(L->stack.top-1) != LUA_T_NIL) { L->stack.top--; - *(L->stack.top-1) = *L->stack.top; /* remove extra s */ + *(L->stack.top-1) = *L->stack.top; /* remove extra `s' */ return; } - L->stack.top-=2; /* remove result and extra s */ + L->stack.top-=2; /* remove result and extra `s' */ } } } @@ -602,20 +607,42 @@ static void mem_query (void) { static void query_strings (void) { - lua_pushnumber(L->string_root[luaL_check_int(1)].nuse); + int h = luaL_check_int(1) - 1; + int s = luaL_opt_int(2, 0) - 1; + if (s==-1) { + if (h < NUM_HASHS) { + lua_pushnumber(L->string_root[h].nuse); + lua_pushnumber(L->string_root[h].size); + } + } + else { + TaggedString *ts = L->string_root[h].hash[s]; + if (ts == NULL) lua_pushstring(""); + else if (ts == &luaS_EMPTY) lua_pushstring(""); + else if (ts->constindex == -1) lua_pushstring(""); + else lua_pushstring(ts->str); + } } -static void countlist (void) { - const char *s = luaL_check_string(1); - GCnode *l = (s[0]=='t') ? L->roottable.next : (s[0]=='c') ? L->rootcl.next : - (s[0]=='p') ? L->rootproto.next : L->rootglobal.next; - int i=0; - while (l) { - i++; - l = l->next; +static void extra_services (void) { + const char *service = luaL_check_string(1); + switch (*service) { + case 'U': /* create a userdata with a given value/tag */ + lua_pushusertag((void *)luaL_check_int(2), luaL_check_int(3)); + break; + + case 'u': /* return the value of a userdata */ + lua_pushnumber((int)lua_getuserdata(lua_getparam(2))); + break; + + case 't': /* set `gc' tag method */ + lua_pushobject(lua_getparam(3)); + lua_settagmethod(luaL_check_int(2), "gc"); + break; + + default: luaL_arg_check(0, 1, "invalid service"); } - lua_pushnumber(i); } @@ -679,9 +706,9 @@ static void testC (void) { static const struct luaL_reg builtin_funcs[] = { #ifdef DEBUG + {"extra", extra_services}, {"testC", testC}, {"totalmem", mem_query}, - {"count", countlist}, {"querystr", query_strings}, #endif {"_ALERT", luaB_alert}, diff --git a/ldo.c b/ldo.c index da9207e4..e6125e36 100644 --- a/ldo.c +++ b/ldo.c @@ -1,18 +1,16 @@ /* -** $Id: ldo.c,v 1.46 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: ldo.c,v 1.47 1999/09/06 15:24:46 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ #include -#include #include #include #include "lauxlib.h" #include "ldo.h" -#include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" @@ -219,17 +217,6 @@ void luaD_calln (int nArgs, int nResults) { } -/* -** Traverse all objects on L->stack.stack -*/ -void luaD_travstack (int (*fn)(TObject *)) { - StkId i; - for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) - fn(L->stack.stack+i); -} - - - static void message (const char *s) { const TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval); if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || diff --git a/ldo.h b/ldo.h index a4dac9a5..5deb5005 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.6 1999/06/22 20:37:23 roberto Exp roberto $ +** $Id: ldo.h,v 1.7 1999/08/16 20:52:00 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -39,7 +39,6 @@ void luaD_calln (int nArgs, int nResults); void luaD_callTM (const TObject *f, int nParams, int nResults); int luaD_protectedrun (void); void luaD_gcIM (const TObject *o); -void luaD_travstack (int (*fn)(TObject *)); void luaD_checkstack (int n); diff --git a/lfunc.c b/lfunc.c index 32fefb29..ea8a9a42 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.10 1999/03/04 21:17:26 roberto Exp roberto $ +** $Id: lfunc.c,v 1.11 1999/08/16 20:52:00 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -18,7 +18,9 @@ Closure *luaF_newclosure (int nelems) { Closure *c = (Closure *)luaM_malloc(sizeof(Closure)+nelems*sizeof(TObject)); - luaO_insertlist(&(L->rootcl), (GCnode *)c); + c->next = L->rootcl; + L->rootcl = c; + c->marked = 0; L->nblocks += gcsizeclosure(c); c->nelems = nelems; return c; @@ -33,14 +35,16 @@ TProtoFunc *luaF_newproto (void) { f->consts = NULL; f->nconsts = 0; f->locvars = NULL; - luaO_insertlist(&(L->rootproto), (GCnode *)f); + f->next = L->rootproto; + L->rootproto = f; + f->marked = 0; L->nblocks += gcsizeproto(f); return f; } - -static void freefunc (TProtoFunc *f) { +void luaF_freeproto (TProtoFunc *f) { + L->nblocks -= gcsizeproto(f); luaM_free(f->code); luaM_free(f->locvars); luaM_free(f->consts); @@ -48,23 +52,9 @@ static void freefunc (TProtoFunc *f) { } -void luaF_freeproto (TProtoFunc *l) { - while (l) { - TProtoFunc *next = (TProtoFunc *)l->head.next; - L->nblocks -= gcsizeproto(l); - freefunc(l); - l = next; - } -} - - -void luaF_freeclosure (Closure *l) { - while (l) { - Closure *next = (Closure *)l->head.next; - L->nblocks -= gcsizeclosure(l); - luaM_free(l); - l = next; - } +void luaF_freeclosure (Closure *c) { + L->nblocks -= gcsizeclosure(c); + luaM_free(c); } diff --git a/lfunc.h b/lfunc.h index 718a76c6..f4109dc1 100644 --- a/lfunc.h +++ b/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 1.5 1997/12/15 16:17:20 roberto Exp roberto $ +** $Id: lfunc.h,v 1.6 1999/08/16 20:52:00 roberto Exp roberto $ ** Lua Function structures ** See Copyright Notice in lua.h */ @@ -14,8 +14,8 @@ TProtoFunc *luaF_newproto (void); Closure *luaF_newclosure (int nelems); -void luaF_freeproto (TProtoFunc *l); -void luaF_freeclosure (Closure *l); +void luaF_freeproto (TProtoFunc *f); +void luaF_freeclosure (Closure *c); const char *luaF_getlocalname (TProtoFunc *func, int local_number, int line); diff --git a/lgc.c b/lgc.c index a710ec4f..e78f0fdb 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.25 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: lgc.c,v 1.26 1999/09/27 18:00:25 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -8,8 +8,8 @@ #include "ldo.h" #include "lfunc.h" #include "lgc.h" -#include "lmem.h" #include "lobject.h" +#include "lref.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" @@ -21,138 +21,15 @@ static int markobject (TObject *o); - -/* -** ======================================================= -** REF mechanism -** ======================================================= -*/ - - -int luaC_ref (const TObject *o, int lock) { - int ref; - if (ttype(o) == LUA_T_NIL) - ref = LUA_REFNIL; - else { - for (ref=0; refrefSize; ref++) - if (L->refArray[ref].status == FREE) - break; - if (ref == L->refSize) { /* no more empty spaces? */ - luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); - L->refSize++; - } - L->refArray[ref].o = *o; - L->refArray[ref].status = lock ? LOCK : HOLD; - } - return ref; -} - - -void lua_unref (int ref) { - if (ref >= 0 && ref < L->refSize) - L->refArray[ref].status = FREE; -} - - -const TObject *luaC_getref (int ref) { - if (ref == LUA_REFNIL) - return &luaO_nilobject; - if (ref >= 0 && ref < L->refSize && - (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD)) - return &L->refArray[ref].o; - else - return NULL; -} - - -static void travlock (void) { - int i; - for (i=0; irefSize; i++) - if (L->refArray[i].status == LOCK) - markobject(&L->refArray[i].o); -} - - -static int ismarked (const TObject *o) { - /* valid only for locked objects */ - switch (o->ttype) { - case LUA_T_STRING: case LUA_T_USERDATA: - return o->value.ts->head.marked; - case LUA_T_ARRAY: - return o->value.a->head.marked; - case LUA_T_CLOSURE: - return o->value.cl->head.marked; - case LUA_T_PROTO: - return o->value.tf->head.marked; -#ifdef DEBUG - case LUA_T_LINE: case LUA_T_CLMARK: - case LUA_T_CMARK: case LUA_T_PMARK: - LUA_INTERNALERROR("invalid type"); -#endif - default: /* nil, number or cproto */ - return 1; - } -} +/* mark a string; marks bigger than 1 cannot be changed */ +#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} -static void invalidaterefs (void) { - int i; - for (i=0; irefSize; i++) - if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) - L->refArray[i].status = COLLECTED; -} - - - -void luaC_hashcallIM (Hash *l) { - TObject t; - ttype(&t) = LUA_T_ARRAY; - for (; l; l=(Hash *)l->head.next) { - avalue(&t) = l; - luaD_gcIM(&t); - } -} - - -void luaC_strcallIM (TaggedString *l) { - TObject o; - ttype(&o) = LUA_T_USERDATA; - for (; l; l=(TaggedString *)l->head.next) - if (l->constindex == -1) { /* is userdata? */ - tsvalue(&o) = l; - luaD_gcIM(&o); - } -} - - - -static GCnode *listcollect (GCnode *l) { - GCnode *frees = NULL; - while (l) { - GCnode *next = l->next; - l->marked = 0; - while (next && !next->marked) { - l->next = next->next; - next->next = frees; - frees = next; - next = l->next; - } - l = next; - } - return frees; -} - - -/* -** mark a string; marks bigger than 1 cannot be changed. -*/ -#define strmark(s) {if ((s)->head.marked == 0) (s)->head.marked = 1;} - static void protomark (TProtoFunc *f) { - if (!f->head.marked) { + if (!f->marked) { int i; - f->head.marked = 1; + f->marked = 1; strmark(f->source); for (i=f->nconsts-1; i>=0; i--) markobject(&f->consts[i]); @@ -161,9 +38,9 @@ static void protomark (TProtoFunc *f) { static void closuremark (Closure *f) { - if (!f->head.marked) { + if (!f->marked) { int i; - f->head.marked = 1; + f->marked = 1; for (i=f->nelems; i>=0; i--) markobject(&f->consts[i]); } @@ -171,9 +48,9 @@ static void closuremark (Closure *f) { static void hashmark (Hash *h) { - if (!h->head.marked) { + if (!h->marked) { int i; - h->head.marked = 1; + h->marked = 1; for (i=nhash(h)-1; i>=0; i--) { Node *n = node(h,i); if (ttype(ref(n)) != LUA_T_NIL) { @@ -187,7 +64,7 @@ static void hashmark (Hash *h) { static void globalmark (void) { TaggedString *g; - for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){ + for (g=L->rootglobal; g; g=g->next) { LUA_ASSERT(g->constindex >= 0, "userdata in global list"); if (g->u.s.globalval.ttype != LUA_T_NIL) { markobject(&g->u.s.globalval); @@ -197,6 +74,21 @@ static void globalmark (void) { } +static void travstack (void) { + StkId i; + for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) + markobject(L->stack.stack+i); +} + + +static void travlock (void) { + int i; + for (i=0; irefSize; i++) + if (L->refArray[i].status == LOCK) + markobject(&L->refArray[i].o); +} + + static int markobject (TObject *o) { switch (ttype(o)) { case LUA_T_USERDATA: case LUA_T_STRING: @@ -217,36 +109,138 @@ static int markobject (TObject *o) { } +static void collectproto (void) { + TProtoFunc **p = &L->rootproto; + TProtoFunc *next; + while ((next = *p) != NULL) { + if (next->marked) { + next->marked = 0; + p = &next->next; + } + else { + *p = next->next; + luaF_freeproto(next); + } + } +} + + +static void collectclosure (void) { + Closure **p = &L->rootcl; + Closure *next; + while ((next = *p) != NULL) { + if (next->marked) { + next->marked = 0; + p = &next->next; + } + else { + *p = next->next; + luaF_freeclosure(next); + } + } +} + + +static void collecttable (void) { + Hash **p = &L->roottable; + Hash *next; + while ((next = *p) != NULL) { + if (next->marked) { + next->marked = 0; + p = &next->next; + } + else { + *p = next->next; + luaH_free(next); + } + } +} + + +static void clear_global_list (void) { + TaggedString **p = &L->rootglobal; + TaggedString *next; + while ((next = *p) != NULL) { + if (next->marked) p = &next->next; + else *p = next->next; + } +} + + +/* +** collect all elements with `marked' < `limit'. +** with limit=1, that means all unmarked elements; +** with limit=MAX_INT, that means all elements (but EMPTY). +*/ +static void collectstring (int limit) { + TObject o; /* to call userdata 'gc' tag method */ + int i; + ttype(&o) = LUA_T_USERDATA; + clear_global_list(); + for (i=0; istring_root[i]; + int j; + for (j=0; jsize; j++) { + TaggedString *t = tb->hash[j]; + if (t == NULL) continue; + if (t->marked < limit) { + if (t->constindex == -1) { /* is userdata? */ + tsvalue(&o) = t; + luaD_gcIM(&o); + } + luaS_free(t); + tb->hash[j] = &luaS_EMPTY; + } + else if (t->marked == 1) + t->marked = 0; + } + } +} + + +#ifdef LUA_COMPAT_GC +static void tableTM (void) { + Hash *p; + TObject o; + ttype(&o) = LUA_T_ARRAY; + for (p = L->roottable; p; p = p->next) { + if (!p->marked) { + avalue(&o) = p; + luaD_gcIM(&o); + } + } +} +#else +#define tableTM() /* do nothing */ +#endif + + static void markall (void) { - luaD_travstack(markobject); /* mark stack objects */ + travstack(); /* mark stack objects */ globalmark(); /* mark global variable values and names */ travlock(); /* mark locked objects */ - luaT_travtagmethods(markobject); /* mark fallbacks */ + luaT_travtagmethods(markobject); /* mark tag methods */ +} + + +void luaC_collect (int all) { + L->GCthreshold *= 4; /* to avoid GC during GC */ + tableTM(); /* call TM for tables (if LUA_COMPAT_GC) */ + collecttable(); + collectstring(all?MAX_INT:1); + collectproto(); + collectclosure(); + luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ } long lua_collectgarbage (long limit) { unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ - Hash *freetable; - TaggedString *freestr; - TProtoFunc *freefunc; - Closure *freeclos; markall(); - invalidaterefs(); - freestr = luaS_collector(); - freetable = (Hash *)listcollect(&(L->roottable)); - freefunc = (TProtoFunc *)listcollect(&(L->rootproto)); - freeclos = (Closure *)listcollect(&(L->rootcl)); - L->GCthreshold *= 4; /* to avoid GC during GC */ - luaC_hashcallIM(freetable); /* GC tag methods for tables */ - luaC_strcallIM(freestr); /* GC tag methods for userdata */ - luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ - luaH_free(freetable); - luaS_free(freestr); - luaF_freeproto(freefunc); - luaF_freeclosure(freeclos); - recovered = recovered-L->nblocks; + luaR_invalidaterefs(); + luaC_collect(0); + recovered = recovered - L->nblocks; L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; return recovered; } diff --git a/lgc.h b/lgc.h index 8bd7b3b1..4f086da3 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 1.4 1997/12/01 20:31:25 roberto Exp roberto $ +** $Id: lgc.h,v 1.5 1999/08/16 20:52:00 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -12,10 +12,7 @@ void luaC_checkGC (void); -const TObject *luaC_getref (int ref); -int luaC_ref (const TObject *o, int lock); -void luaC_hashcallIM (Hash *l); -void luaC_strcallIM (TaggedString *l); +void luaC_collect (int all); #endif diff --git a/llex.c b/llex.c index 09891b61..54213e9c 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.38 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: llex.c,v 1.39 1999/09/06 13:55:09 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ void luaX_init (void) { int i; for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { TaggedString *ts = luaS_new(reserved[i]); - ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ + ts->marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ } } @@ -426,8 +426,8 @@ int luaX_lex (LexState *LS) { } while (isalnum(LS->current) || LS->current == '_'); save('\0'); ts = luaS_new(L->Mbuffer+L->Mbuffbase); - if (ts->head.marked >= FIRST_RESERVED) - return ts->head.marked; /* reserved word */ + if (ts->marked >= FIRST_RESERVED) + return ts->marked; /* reserved word */ LS->seminfo.ts = ts; return NAME; } diff --git a/lobject.c b/lobject.c index 926c8c6c..2c87b7d0 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 1.22 1999/09/06 20:19:22 roberto Exp roberto $ +** $Id: lobject.c,v 1.23 1999/09/08 20:45:18 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -55,13 +55,6 @@ int luaO_equalval (const TObject *t1, const TObject *t2) { } -void luaO_insertlist (GCnode *root, GCnode *node) { - node->next = root->next; - root->next = node; - node->marked = 0; -} - - #ifdef OLD_ANSI void luaO_memup (void *dest, void *src, int size) { while (size--) diff --git a/lobject.h b/lobject.h index 2e69ebf5..99239909 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.29 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: lobject.h,v 1.30 1999/09/06 20:34:18 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -85,21 +85,13 @@ typedef struct TObject { -/* -** generic header for garbage collector lists -*/ -typedef struct GCnode { - struct GCnode *next; - int marked; -} GCnode; - - /* ** String headers for string table */ typedef struct TaggedString { - GCnode head; + struct TaggedString *next; + int marked; unsigned long hash; int constindex; /* hint to reuse constants (= -1 if this is a userdata) */ union { @@ -122,7 +114,8 @@ typedef struct TaggedString { ** Function Prototypes */ typedef struct TProtoFunc { - GCnode head; + struct TProtoFunc *next; + int marked; struct TObject *consts; int nconsts; Byte *code; /* ends with opcode ENDCODE */ @@ -157,7 +150,8 @@ typedef struct LocVar { ** Closures */ typedef struct Closure { - GCnode head; + struct Closure *next; + int marked; int nelems; /* not included the first one (always the prototype) */ TObject consts[1]; /* at least one for prototype */ } Closure; @@ -170,7 +164,8 @@ typedef struct node { } Node; typedef struct Hash { - GCnode head; + struct Hash *next; + int marked; Node *node; int nhash; int nuse; @@ -189,7 +184,6 @@ extern const TObject luaO_nilobject; : luaO_equalval(t1,t2)) int luaO_equalval (const TObject *t1, const TObject *t2); int luaO_redimension (int oldsize); -void luaO_insertlist (GCnode *root, GCnode *node); int luaO_str2d (const char *s, real *result); #ifdef OLD_ANSI diff --git a/lstate.c b/lstate.c index e5ad27bd..c8f3d65b 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.12 1999/05/11 20:08:20 roberto Exp roberto $ +** $Id: lstate.c,v 1.13 1999/08/16 20:52:00 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -7,13 +7,11 @@ #include "lbuiltin.h" #include "ldo.h" -#include "lfunc.h" #include "lgc.h" #include "llex.h" #include "lmem.h" #include "lstate.h" #include "lstring.h" -#include "ltable.h" #include "ltm.h" @@ -36,14 +34,10 @@ void lua_open (void) { L->debug = 0; L->callhook = NULL; L->linehook = NULL; - L->rootproto.next = NULL; - L->rootproto.marked = 0; - L->rootcl.next = NULL; - L->rootcl.marked = 0; - L->rootglobal.next = NULL; - L->rootglobal.marked = 0; - L->roottable.next = NULL; - L->roottable.marked = 0; + L->rootproto = NULL; + L->rootcl = NULL; + L->rootglobal = NULL; + L->roottable = NULL; L->IMtable = NULL; L->refArray = NULL; L->refSize = 0; @@ -58,21 +52,14 @@ void lua_open (void) { void lua_close (void) { - TaggedString *alludata = luaS_collectudata(); - L->GCthreshold = MAX_INT; /* to avoid GC during GC */ - luaC_hashcallIM((Hash *)L->roottable.next); /* GC t.methods for tables */ - luaC_strcallIM(alludata); /* GC tag methods for userdata */ - luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ - luaH_free((Hash *)L->roottable.next); - luaF_freeproto((TProtoFunc *)L->rootproto.next); - luaF_freeclosure((Closure *)L->rootcl.next); - luaS_free(alludata); + luaC_collect(1); /* collect all elements */ luaS_freeall(); luaM_free(L->stack.stack); luaM_free(L->IMtable); luaM_free(L->refArray); luaM_free(L->Mbuffer); luaM_free(L->Cblocks); + LUA_ASSERT(L->nblocks == 0, "wrong count for nblocks"); luaM_free(L); L = NULL; #ifdef DEBUG diff --git a/lstate.h b/lstate.h index 2690a1f9..0af3cc31 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.18 1999/05/11 14:19:32 roberto Exp roberto $ +** $Id: lstate.h,v 1.19 1999/05/11 20:08:20 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -73,10 +73,10 @@ struct lua_State { lua_CHFunction callhook; lua_LHFunction linehook; /* global state */ - GCnode rootproto; /* list of all prototypes */ - GCnode rootcl; /* list of all closures */ - GCnode roottable; /* list of all tables */ - GCnode rootglobal; /* list of strings with global values */ + TProtoFunc *rootproto; /* list of all prototypes */ + Closure *rootcl; /* list of all closures */ + Hash *roottable; /* list of all tables */ + TaggedString *rootglobal; /* list of strings with global values */ stringtable *string_root; /* array of hash tables for strings and udata */ struct IM *IMtable; /* table for tag methods */ int last_tag; /* last used tag in IMtable */ diff --git a/lstring.c b/lstring.c index 13a123e3..633fbcd4 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 1.20 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: lstring.c,v 1.21 1999/09/28 12:27:06 roberto Exp roberto $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -14,17 +14,13 @@ #include "lua.h" -#define NUM_HASHSTR 31 -#define NUM_HASHUDATA 31 -#define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) - #define gcsizestring(l) (1+(l/64)) /* "weight" for a string with length 'l' */ -static TaggedString EMPTY = {{NULL, 2}, 0L, 0, - {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; +TaggedString luaS_EMPTY = {NULL, MAX_INT, 0L, 0, + {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; @@ -49,6 +45,16 @@ void luaS_init (void) { } +void luaS_freeall (void) { + int i; + for (i=0; istring_root[i].hash != init_hash) + luaM_free(L->string_root[i].hash); + } + luaM_free(L->string_root); +} + + static unsigned long hash_s (const char *s, long l) { unsigned long h = 0; /* seed */ while (l--) @@ -57,12 +63,12 @@ static unsigned long hash_s (const char *s, long l) { } -static int newsize (stringtable *tb) { +static int newsize (const stringtable *tb) { int realuse = 0; int i; /* count how many entries are really in use */ for (i=0; isize; i++) { - if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) + if (tb->hash[i] != NULL && tb->hash[i] != &luaS_EMPTY) realuse++; } return luaO_redimension(realuse*2); @@ -78,7 +84,7 @@ static void grow (stringtable *tb) { /* rehash */ tb->nuse = 0; for (i=0; isize; i++) { - if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) { + if (tb->hash[i] != NULL && tb->hash[i] != &luaS_EMPTY) { unsigned long h = tb->hash[i]->hash; int h1 = h%ns; while (newhash[h1]) { @@ -103,8 +109,8 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) { ts->u.s.len = l; ts->constindex = 0; L->nblocks += gcsizestring(l); - ts->head.marked = 0; - ts->head.next = (GCnode *)ts; /* signal it is in no list */ + ts->marked = 0; + ts->next = ts; /* signal it is in no list */ ts->hash = h; return ts; } @@ -115,8 +121,8 @@ static TaggedString *newone_u (void *buff, int tag, unsigned long h) { ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; ts->constindex = -1; /* tag -> this is a userdata */ L->nblocks++; - ts->head.marked = 0; - ts->head.next = (GCnode *)ts; /* signal it is in no list */ + ts->marked = 0; + ts->next = ts; /* signal it is in no list */ ts->hash = h; return ts; } @@ -144,7 +150,7 @@ static TaggedString *insert_s (const char *str, long l, stringtable *tb) { int j = -1; /* last empty place found (or -1) */ int h1 = h%size; while ((ts = tb->hash[h1]) != NULL) { - if (ts == &EMPTY) + if (ts == &luaS_EMPTY) j = h1; else if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) return ts; @@ -168,7 +174,7 @@ static TaggedString *insert_u (void *buff, int tag, stringtable *tb) { int j = -1; int h1 = h%size; while ((ts = tb->hash[h1]) != NULL) { - if (ts == &EMPTY) + if (ts == &luaS_EMPTY) j = h1; else if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v) return ts; @@ -200,115 +206,29 @@ TaggedString *luaS_new (const char *str) { TaggedString *luaS_newfixedstring (const char *str) { TaggedString *ts = luaS_new(str); - if (ts->head.marked == 0) - ts->head.marked = 2; /* avoid GC */ + if (ts->marked == 0) ts->marked = 2; /* avoid GC */ return ts; } -void luaS_free (TaggedString *l) { - while (l) { - TaggedString *next = (TaggedString *)l->head.next; - L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len); - luaM_free(l); - l = next; - } -} - - -/* -** Garbage collection functions. -*/ - -static void remove_from_list (GCnode *l) { - while (l) { - GCnode *next = l->next; - while (next && !next->marked) - next = l->next = next->next; - l = next; - } -} - - -TaggedString *luaS_collector (void) { - TaggedString *frees = NULL; - int i; - remove_from_list(&(L->rootglobal)); - for (i=0; istring_root[i]; - int j; - for (j=0; jsize; j++) { - TaggedString *t = tb->hash[j]; - if (t == NULL) continue; - if (t->head.marked == 1) - t->head.marked = 0; - else if (!t->head.marked) { - t->head.next = (GCnode *)frees; - frees = t; - tb->hash[j] = &EMPTY; - } - } - } - return frees; -} - - -TaggedString *luaS_collectudata (void) { - TaggedString *frees = NULL; - int i; - L->rootglobal.next = NULL; /* empty list of globals */ - for (i=NUM_HASHSTR; istring_root[i]; - int j; - for (j=0; jsize; j++) { - TaggedString *t = tb->hash[j]; - if (t == NULL || t == &EMPTY) - continue; - LUA_ASSERT(t->constindex == -1, "must be userdata"); - t->head.next = (GCnode *)frees; - frees = t; - tb->hash[j] = &EMPTY; - } - } - return frees; -} - - -void luaS_freeall (void) { - int i; - for (i=0; istring_root[i]; - int j; - for (j=0; jsize; j++) { - TaggedString *t = tb->hash[j]; - if (t != &EMPTY) luaM_free(t); - } - if (tb->hash != init_hash) luaM_free(tb->hash); - } - luaM_free(L->string_root); +void luaS_free (TaggedString *t) { + L->nblocks -= (t->constindex == -1) ? 1 : gcsizestring(t->u.s.len); + luaM_free(t); } -void luaS_rawsetglobal (TaggedString *ts, TObject *newval) { +void luaS_rawsetglobal (TaggedString *ts, const TObject *newval) { ts->u.s.globalval = *newval; - if (ts->head.next == (GCnode *)ts) { /* is not in list? */ - ts->head.next = L->rootglobal.next; - L->rootglobal.next = (GCnode *)ts; + if (ts->next == ts) { /* is not in list? */ + ts->next = L->rootglobal; + L->rootglobal = ts; } } -const char *luaS_travsymbol (int (*fn)(TObject *)) { - TaggedString *g; - for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) - if (fn(&g->u.s.globalval)) - return g->str; - return NULL; -} - - int luaS_globaldefined (const char *name) { TaggedString *ts = luaS_new(name); return ts->u.s.globalval.ttype != LUA_T_NIL; } + diff --git a/lstring.h b/lstring.h index 0680cf6d..7fc50810 100644 --- a/lstring.h +++ b/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.7 1998/03/06 16:54:42 roberto Exp roberto $ +** $Id: lstring.h,v 1.8 1999/08/16 20:52:00 roberto Exp roberto $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -11,18 +11,22 @@ #include "lobject.h" +#define NUM_HASHSTR 31 +#define NUM_HASHUDATA 31 +#define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) + + +extern TaggedString luaS_EMPTY; + void luaS_init (void); TaggedString *luaS_createudata (void *udata, int tag); -TaggedString *luaS_collector (void); -void luaS_free (TaggedString *l); +void luaS_freeall (void); +void luaS_free (TaggedString *ts); TaggedString *luaS_newlstr (const char *str, long l); TaggedString *luaS_new (const char *str); TaggedString *luaS_newfixedstring (const char *str); -void luaS_rawsetglobal (TaggedString *ts, TObject *newval); -const char *luaS_travsymbol (int (*fn)(TObject *)); +void luaS_rawsetglobal (TaggedString *ts, const TObject *newval); int luaS_globaldefined (const char *name); -TaggedString *luaS_collectudata (void); -void luaS_freeall (void); #endif diff --git a/ltable.c b/ltable.c index fbded6cf..3070ea90 100644 --- a/ltable.c +++ b/ltable.c @@ -1,10 +1,9 @@ /* -** $Id: ltable.c,v 1.23 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: ltable.c,v 1.24 1999/09/22 14:38:45 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ -#include #include "lauxlib.h" #include "lmem.h" @@ -69,17 +68,6 @@ Node *luaH_present (const Hash *t, const TObject *key) { } -void luaH_free (Hash *frees) { - while (frees) { - Hash *next = (Hash *)frees->head.next; - L->nblocks -= gcsize(frees->nhash); - luaM_free(nodevector(frees)); - luaM_free(frees); - frees = next; - } -} - - static Node *hashnodecreate (int nhash) { Node *const v = luaM_newvector(nhash, Node); int i; @@ -96,12 +84,21 @@ Hash *luaH_new (int nhash) { nhash(t) = nhash; nuse(t) = 0; t->htag = TagDefault; - luaO_insertlist(&(L->roottable), (GCnode *)t); + t->next = L->roottable; + L->roottable = t; + t->marked = 0; L->nblocks += gcsize(nhash); return t; } +void luaH_free (Hash *t) { + L->nblocks -= gcsize(t->nhash); + luaM_free(nodevector(t)); + luaM_free(t); +} + + static int newsize (Hash *t) { Node *const v = t->node; const int size = nhash(t); diff --git a/ltable.h b/ltable.h index 6c8bbe40..034acbab 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 1.11 1999/02/23 14:57:28 roberto Exp roberto $ +** $Id: ltable.h,v 1.12 1999/08/16 20:52:00 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -19,7 +19,7 @@ #define luaH_move(t,from,to) (luaH_setint(t, to, luaH_getint(t, from))) Hash *luaH_new (int nhash); -void luaH_free (Hash *frees); +void luaH_free (Hash *t); Node *luaH_present (const Hash *t, const TObject *key); void luaH_set (Hash *t, const TObject *ref, const TObject *val); int luaH_pos (const Hash *t, const TObject *r); diff --git a/ltm.c b/ltm.c index f5da877f..37ef9fef 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 1.26 1999/08/16 20:52:00 roberto Exp roberto $ +** $Id: ltm.c,v 1.27 1999/09/20 14:57:29 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -39,13 +39,17 @@ static const char luaT_validevents[NUM_TAGS][IM_N] = { {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */ {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */ {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */ -{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */ +{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_ARRAY */ {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_PROTO */ {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CPROTO */ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */ }; int luaT_validevent (int t, int e) { /* ORDER LUA_T */ +#ifdef LUA_COMPAT_GC + if (t == LUA_T_ARRAY && e == IM_GC) + return 1; /* old versions allowed gc tag method for tables */ +#endif return (t < LUA_T_NIL) ? 1 : luaT_validevents[-t][e]; } diff --git a/makefile b/makefile index 7dc366d7..c76108ae 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ # -## $Id: makefile,v 1.19 1999/02/24 21:31:03 roberto Exp roberto $ +## $Id: makefile,v 1.20 1999/08/17 20:21:52 roberto Exp roberto $ ## Makefile ## See Copyright Notice in lua.h # @@ -15,20 +15,19 @@ # facilities (e.g. strerror, locale.h, memmove). SunOS does not comply; # so, add "-DOLD_ANSI" on SunOS # -# define LUA_COMPAT2_5 if yous system does need to be compatible with -# version 2.5 (or older) -# # define LUA_NUM_TYPE if you need numbers to be different from double # (for instance, -DLUA_NUM_TYPE=float) # +# define LUA_COMPAT_GC if you need garbage-collect tag methods for tables +# (only for compatibility with previous versions) CONFIG = -DPOPEN -D_POSIX_SOURCE -#CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG +#CONFIG = -DOLD_ANSI -DDEBUG -DLUA_COMPAT_GC # Compilation parameters CC = gcc -CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-declarations -Wnested-externs +CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-declarations -Wnested-externs -Werror CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2 @@ -53,6 +52,7 @@ LUAOBJS = \ lmem.o \ lobject.o \ lparser.o \ + lref.o \ lstate.o \ lstring.o \ ltable.o \ @@ -99,7 +99,7 @@ clear : lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h \ - luadebug.h lfunc.h lgc.h lmem.h lstring.h ltable.h ltm.h lvm.h + luadebug.h lfunc.h lgc.h lmem.h lref.h lstring.h ltable.h ltm.h lvm.h lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \ luadebug.h @@ -107,11 +107,11 @@ lbuiltin.o: lbuiltin.c lapi.h lua.h lobject.h lauxlib.h lbuiltin.h \ ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \ lundump.h lzio.h lvm.h ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h -ldo.o: ldo.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ +ldo.o: ldo.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h lgc.h \ lmem.h lparser.h lzio.h lstring.h ltm.h lundump.h lvm.h lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \ - lmem.h lstring.h ltable.h ltm.h + lref.h lstring.h ltable.h ltm.h linit.o: linit.c lua.h lualib.h liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h 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 \ lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h luadebug.h lobject.o: lobject.c lobject.h lua.h -lparser.o: lparser.c lauxlib.h lua.h ldo.h lobject.h lstate.h \ - luadebug.h lfunc.h llex.h lzio.h lmem.h lopcodes.h lparser.h \ - lstring.h +lparser.o: lparser.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h \ + llex.h lzio.h lmem.h lopcodes.h lparser.h lstring.h +lref.o: lref.c lmem.h lref.h lobject.h lua.h lstate.h luadebug.h lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h \ - luadebug.h lfunc.h lgc.h llex.h lzio.h lmem.h lstring.h ltable.h \ - ltm.h + luadebug.h lgc.h llex.h lzio.h lmem.h lstring.h ltm.h lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h luadebug.h \ lstring.h 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 \ ltm.h lua.o: lua.c lua.h luadebug.h lualib.h lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ - lstring.h lundump.h lzio.h + lopcodes.h lstring.h lundump.h lzio.h lvm.o: lvm.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h \ - lfunc.h lgc.h lmem.h lopcodes.h lstring.h ltable.h ltm.h lvm.h + lfunc.h lgc.h lopcodes.h lstring.h ltable.h ltm.h lvm.h lzio.o: lzio.c lzio.h diff --git a/manual.tex b/manual.tex index e8c3b6a5..ba9af4ff 100644 --- a/manual.tex +++ b/manual.tex @@ -1,4 +1,4 @@ -% $Id: manual.tex,v 1.32 1999/05/11 20:46:28 roberto Exp roberto $ +% $Id: manual.tex,v 1.33 1999/05/27 20:21:03 roberto Exp roberto $ \documentclass[11pt]{article} \usepackage{fullpage,bnf} @@ -41,7 +41,7 @@ Waldemar Celes \tecgraf\ --- Computer Science Department --- PUC-Rio } -\date{{\small \tt\$Date: 1999/05/11 20:46:28 $ $}} +\date{{\small \tt\$Date: 1999/05/27 20:21:03 $ $}} \maketitle @@ -1273,7 +1273,8 @@ is terminated, returning an error condition. The only argument to \verb|_ERRORMESSAGE| is a string describing the error. -The default definition for this function calls \verb|_ALERT|, +The default definition for +this function calls \verb|_ALERT|, \Deffunc{_ALERT} which prints the message to \verb|stderr| \see{alert}. The standard I/O library redefines \verb|_ERRORMESSAGE|, and uses the debug facilities \see{debugI} @@ -1835,6 +1836,8 @@ void lua_unref (int ref); The function \verb|lua_ref| creates a reference to the object that is on the top of the stack, and returns this reference. +For a \nil{} object, the reference is always -1; +otherwise, it is a non-negative integer. If \verb|lock| is true, the object is \emph{locked}: this means the object will not be garbage collected. Note that an unlocked reference may be garbage collected. @@ -2503,26 +2506,32 @@ The following combinations are allowed in describing a character class: \item[\T{\%s}] --- represents all space characters. \item[\T{\%u}] --- represents all upper case letters. \item[\T{\%w}] --- represents all alphanumeric characters. -\item[\T{\%x}] --- represents all hexa-decimal digits. +\item[\T{\%x}] --- represents all hexadecimal digits. \item[\T{\%z}] --- represents the character with representation 0. \item[\T{\%\M{x}}] (where \M{x} is any non alphanumeric character) --- represents the character \M{x}. This is the standard way to escape the magic characters \verb|()%.[]*-?|. It is strongly recommended that any control character (even the non magic), when used to represent itself in a pattern, should be preceded by a \verb|%|. + \item[\T{[char-set]}] --- Represents the class which is the union of all characters in char-set. -To include a \verb|]| in char-set, it must be the first character. A range of characters may be specified by separating the end characters of the range with a \verb|-|. -If \verb|-| appears as the first or last character of char-set, -then it represents itself. All classes \verb|%|\emph{x} described above can also be used as components in a char-set. All other characters in char-set represent themselves. -E.g., assuming an \emph{ascii} character set, -\verb|[%dA-Fa-f]| specifies the hexa-decimal digits. +E.g., \verb|[%w_]| (or \verb|[_%w]|) +represents all alphanumeric characters plus the underscore, +\verb|[0-7]| represents the octal digits, +and \verb|[0-7%l%-]| represents the octal digits plus +the lower case letters plus the \verb|-| character. + +The interaction between ranges and classes is not defined. +Therefore, patterns like \verb|[%a-z]| or \verb|[a-%%]| +have no meaning. + \item[\T{[\^{ }char-set]}] --- represents the complement of char-set, where char-set is interpreted as above. @@ -3187,6 +3196,8 @@ accepting commands from standard input until an \verb|EOF|. Each line entered is immediately executed. \item[\T{-q}] same as \T{-i}, but without a prompt (quiet mode). \item[\T{-}] executes \verb|stdin| as a file. +\item[\T{--}] stops the execution of arguments; +all arguments after it are simply passed to the Lua script. \item[\T{var=value}] sets global \verb|var| with string \verb|"value"|. \item[\T{filename}] executes file \verb|filename| as a Lua chunk. \end{description} @@ -3203,6 +3214,37 @@ will first interact with the user until an \verb|EOF|, then will set \verb|a| to \verb|"test"|, and finally will run the file \verb|prog.lua|. +All arguments from the command line are passed to the Lua program in +a table called \verb|arg|. +If the command line has the \verb|--| argument, +this argument is at index 0; +the arguments after it get indices 1, 2, \ldots; +and the arguments before it get negative indices. +The field \verb|n| gets the index of the last argument, +and the field \verb|nn| gets the index of the first argument +(always a negative number). +For instance: +\begin{verbatim} +$ lua -e "foreach(arg, print)" -- a b +-1 foreach(arg, print) +-2 -e +-3 lua +0 -- +1 a +2 b +nn -3 +n 2 +\end{verbatim} +If the command line has no \verb|--| argument, +all arguments have negative indices, with the last one at position -1. +As a general rule, if you want to traverse all the +arguments after the \verb|--|, you loop from 1 to \verb|arg.n| +(you can use the \verb|foreachi| function, for instance). +If you want to traverse all arguments, +you loop from \verb|arg.nn| until \verb|arg.n|. +In any case, you may call \verb|exit| at the end of a script, +to stop Lua from running the other arguments. + When in interactive mode, a multi-line statement can be written finishing intermediate lines with a backslash (\verb|\|). @@ -3216,6 +3258,7 @@ In Unix systems, Lua scripts can be made into executable programs by using the \verb|#!| form, as in \verb|#!/usr/local/bin/lua|. + \section*{Acknowledgments} The authors would like to thank CENPES/PETROBRAS which,