mirror of https://github.com/rusefi/lua.git
simplified version of `gc' tag method (only for userdata now).
This commit is contained in:
parent
1f7103e05d
commit
4343420d4d
30
lapi.c
30
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);
|
||||
}
|
||||
|
||||
|
|
63
lbuiltin.c
63
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},
|
||||
|
|
15
ldo.c
15
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 ||
|
||||
|
|
3
ldo.h
3
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);
|
||||
|
||||
|
||||
|
|
34
lfunc.c
34
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
6
lfunc.h
6
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);
|
||||
|
||||
|
|
302
lgc.c
302
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);
|
||||
|
||||
|
||||
/* mark a string; marks bigger than 1 cannot be changed */
|
||||
#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;}
|
||||
|
||||
/*
|
||||
** =======================================================
|
||||
** 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
7
lgc.h
7
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
|
||||
|
|
8
llex.c
8
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,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--)
|
||||
|
|
24
lobject.h
24
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
|
||||
|
|
27
lstate.c
27
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
|
||||
|
|
10
lstate.h
10
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 */
|
||||
|
|
142
lstring.c
142
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;
|
||||
}
|
||||
void luaS_free (TaggedString *t) {
|
||||
L->nblocks -= (t->constindex == -1) ? 1 : gcsizestring(t->u.s.len);
|
||||
luaM_free(t);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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_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;
|
||||
}
|
||||
|
||||
|
||||
|
|
18
lstring.h
18
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
|
||||
|
|
25
ltable.c
25
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);
|
||||
|
|
4
ltable.h
4
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);
|
||||
|
|
8
ltm.c
8
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];
|
||||
}
|
||||
|
||||
|
|
31
makefile
31
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
|
||||
|
|
61
manual.tex
61
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,
|
||||
|
|
Loading…
Reference in New Issue