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