Browse Source

simplified version of `gc' tag method (only for userdata now).

Roberto Ierusalimschy 26 years ago
parent
commit
4343420d4d
20 changed files with 384 additions and 443 deletions
  1. 18 12
      lapi.c
  2. 45 18
      lbuiltin.c
  3. 1 14
      ldo.c
  4. 1 2
      ldo.h
  5. 12 22
      lfunc.c
  6. 3 3
      lfunc.h
  7. 148 154
      lgc.c
  8. 2 5
      lgc.h
  9. 4 4
      llex.c
  10. 1 8
      lobject.c
  11. 9 15
      lobject.h
  12. 7 20
      lstate.c
  13. 5 5
      lstate.h
  14. 31 111
      lstring.c
  15. 11 7
      lstring.h
  16. 11 14
      ltable.c
  17. 2 2
      ltable.h
  18. 6 2
      ltm.c
  19. 15 16
      makefile
  20. 52 9
      manual.tex

+ 18 - 12
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 <stdlib.h>
 #include <string.h>
 
 #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);
 }
 

+ 45 - 18
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("<NIL>");
+    else if (ts == &luaS_EMPTY) lua_pushstring("<EMPTY>");
+    else if (ts->constindex == -1) lua_pushstring("<USERDATA>");
+    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},

+ 1 - 14
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 <setjmp.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #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 ||

+ 1 - 2
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);
 
 

+ 12 - 22
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);
 }
 
 

+ 3 - 3
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);
 

+ 148 - 154
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; ref<L->refSize; 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; i<L->refSize; 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; i<L->refSize; 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; i<L->refSize; 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; i<NUM_HASHS; i++) {
+    stringtable *tb = &L->string_root[i];
+    int j;
+    for (j=0; j<tb->size; 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;
 }

+ 2 - 5
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

+ 4 - 4
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;
         }

+ 1 - 8
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--)

+ 9 - 15
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

+ 7 - 20
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

+ 5 - 5
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 */

+ 31 - 111
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; i<NUM_HASHS; i++) {
+    if (L->string_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; i<tb->size; 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; i<tb->size; 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; i<NUM_HASHS; i++) {
-    stringtable *tb = &L->string_root[i];
-    int j;
-    for (j=0; j<tb->size; 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; i<NUM_HASHS; i++) {
-    stringtable *tb = &L->string_root[i];
-    int j;
-    for (j=0; j<tb->size; 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; i<NUM_HASHS; i++) {
-    stringtable *tb = &L->string_root[i];
-    int j;
-    for (j=0; j<tb->size; 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;
 }
 
+

+ 11 - 7
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

+ 11 - 14
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 <stdlib.h>
 
 #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);

+ 2 - 2
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);

+ 6 - 2
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];
 }
 

+ 15 - 16
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

+ 52 - 9
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,