2
0
Эх сурвалжийг харах

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

Roberto Ierusalimschy 26 жил өмнө
parent
commit
4343420d4d
20 өөрчлөгдсөн 384 нэмэгдсэн , 443 устгасан
  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,