Compare commits

..

30 Commits

Author SHA1 Message Date
Roberto Ierusalimschy
16024861bd new format for numbers in precompiled code (as strings) 1999-07-08 09:43:23 -03:00
Roberto Ierusalimschy
3f43aaa23f new RedHat defines PI :-( 1999-07-07 14:54:08 -03:00
Roberto Ierusalimschy
3b4c831ca9 some systems do not reset signal handlers when a signal happens 1999-07-02 15:22:38 -03:00
Roberto Ierusalimschy
3fdab3981b no more automatic setlocale. 1999-06-24 16:42:02 -03:00
Roberto Ierusalimschy
88b65da4d7 simplifications. 1999-06-23 10:48:39 -03:00
Roberto Ierusalimschy
521b38532a better interfaces for luaD_calln (x luaD_call) 1999-06-22 17:37:23 -03:00
Roberto Ierusalimschy
36b6fe8d17 better treatment for arbitrary limits 1999-06-17 14:04:03 -03:00
Roberto Ierusalimschy
d4dce57f5c cannot assign to unlimited variables, because it causes overflow in
the number of returns of a function.
1999-06-16 10:35:01 -03:00
Roberto Ierusalimschy
5c19ed2a13 bigger limit for number of local variables and upvalues 1999-06-16 10:22:04 -03:00
Roberto Ierusalimschy
5caf7f4a33 tremove erases its previous last element (to avoid locking potential
garbagge).
1999-05-27 17:21:03 -03:00
Roberto Ierusalimschy
3b533ea7c7 foreach, foreachi, foreachvar points to function in stack when stack
can be reallocated.
1999-05-24 14:53:49 -03:00
Roberto Ierusalimschy
995775e1cb tighter control on the stack when debugging 1999-05-24 14:53:03 -03:00
Roberto Ierusalimschy
abfc885079 when debugging, move and erase old blocks to realloc. 1999-05-24 14:51:05 -03:00
Roberto Ierusalimschy
613b60c156 detail 1999-05-21 16:54:06 -03:00
Roberto Ierusalimschy
cdd0fe9946 some C compilers cannot initialize a local struct 1999-05-21 16:41:49 -03:00
Roberto Ierusalimschy
bc8619342a better control of stack size (only for DEBUG). 1999-05-21 14:23:15 -03:00
Roberto Ierusalimschy
48326500d0 longer marks when controling memory leaks 1999-05-20 17:43:06 -03:00
Roberto Ierusalimschy
c8d219798a lhf 1999-05-17 11:12:01 -03:00
Roberto Ierusalimschy
34695d4f4a details (message text) 1999-05-14 09:24:20 -03:00
Roberto Ierusalimschy
924bbe020b bigger limits 1999-05-14 09:24:04 -03:00
Roberto Ierusalimschy
3aa500b524 new pattern item '+' 1999-05-11 17:46:28 -03:00
Roberto Ierusalimschy
f1861ee210 no more beta 1999-05-11 17:29:19 -03:00
Roberto Ierusalimschy
705eae9fe4 there is no need for a size for Cblocks 1999-05-11 17:08:20 -03:00
Roberto Ierusalimschy
6eb1399a1c array Cblocks should grow dynamically 1999-05-11 11:19:32 -03:00
Roberto Ierusalimschy
c390f73e3b block must always have a power-of-2 size (even at the limit) 1999-05-11 11:18:40 -03:00
Roberto Ierusalimschy
73308c7605 warnings by clinio 1999-05-10 10:54:01 -03:00
Roberto Ierusalimschy
288fa05602 opcodes with LONGARG do not use byte variants. 1999-05-06 11:41:41 -03:00
Roberto Ierusalimschy
7808ea3a5f new implementation for '*' in patterns + new option '+' 1999-05-05 16:23:11 -03:00
Roberto Ierusalimschy
732741b62f cannot use (i=i+1) 1999-05-05 16:21:57 -03:00
Roberto Ierusalimschy
cc0f635ef7 '$' at end of pattern was matching regular '$', too. 1999-04-30 11:12:05 -03:00
24 changed files with 579 additions and 472 deletions

31
bugs
View File

@@ -4,6 +4,7 @@ Tue Dec 2 10:45:48 EDT 1997
>> started only in the 2nd line of a function.
--- Version 3.1 alpha
** lua.c
@@ -13,7 +14,7 @@ Thu Jan 15 14:34:58 EDT 1998
** lbuiltin.c / lobject.h
Thu Jan 15 14:34:58 EDT 1998
>> MAX_WORD may be bigger than MAX_INT
(by lhf)
** llex.c
Mon Jan 19 18:17:18 EDT 1998
@@ -42,6 +43,7 @@ Mon May 18 19:20:00 EST 1998
>> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
--- Version 3.1
** liolib.c / lauxlib.c
@@ -52,11 +54,13 @@ of view) when functions have upvalues.
** lstrlib.c
Tue Nov 10 17:29:36 EDT 1998
>> gsub/strfind do not check whether captures are properly finished.
(by roberto/tomas)
** lbuiltin.c
Fri Dec 18 11:22:55 EDT 1998
>> "tonumber" goes crazy with negative numbers in other bases (not 10),
because "strtol" returns long, not unsigned long.
(by Visual C++)
** lstrlib.c
Mon Jan 4 10:41:40 EDT 1999
@@ -70,8 +74,31 @@ lua_isnumber can modify it.
** lstrlib.c
Thu Feb 4 17:08:50 EDT 1999
>> format "%s" may break limit of "sprintf" on some machines.
(by Marcelo Sales)
** lzio.c
Thu Mar 4 11:49:37 EST 1999
>> file stream cannot call fread after EOF.
(by lhf)
--- Version 3.2 (beta)
** lstrlib.c
Fri Apr 30 11:10:20 EST 1999
>> '$' at end of pattern was matching regular '$', too.
(by anna; since 2.5)
** lbuiltin.c
Fri May 21 17:15:11 EST 1999
>> foreach, foreachi, foreachvar points to function in stack when stack
can be reallocated.
(by tomas; since 3.2 beta)
** lparser.c
Wed Jun 16 10:32:46 EST 1999
>> cannot assign to unlimited variables, because it causes overflow in
the number of returns of a function.
(since 3.1)

59
lapi.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 1.41 1999/03/04 21:17:26 roberto Exp roberto $
** $Id: lapi.c,v 1.46 1999/06/17 17:04:03 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -131,7 +131,7 @@ int lua_callfunction (lua_Object function)
else {
luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
set_normalized(L->stack.stack+L->Cstack.base, Address(function));
return luaD_protectedrun(MULT_RET);
return luaD_protectedrun();
}
}
@@ -167,15 +167,12 @@ lua_Object lua_gettable (void)
}
lua_Object lua_rawgettable (void)
{
lua_Object lua_rawgettable (void) {
checkCparams(2);
if (ttype(L->stack.top-2) != LUA_T_ARRAY)
lua_error("indexed expression not a table in rawgettable");
else {
*(L->stack.top-2) = *luaH_get(avalue(L->stack.top-2), L->stack.top-1);
--L->stack.top;
}
*(L->stack.top-2) = *luaH_get(avalue(L->stack.top-2), L->stack.top-1);
--L->stack.top;
return put_luaObjectonTop();
}
@@ -368,14 +365,11 @@ void luaA_pushobject (TObject *o)
incr_top;
}
void lua_pushobject (lua_Object o)
{
void lua_pushobject (lua_Object o) {
if (o == LUA_NOOBJECT)
lua_error("API error - attempt to push a NOOBJECT");
else {
set_normalized(L->stack.top, Address(o));
incr_top;
}
set_normalized(L->stack.top, Address(o));
incr_top;
}
@@ -596,7 +590,7 @@ int lua_setlocal (lua_Function func, int local_number)
void lua_funcinfo (lua_Object func, char **source, int *linedefined) {
if (!lua_isfunction(func))
lua_error("API - `funcinfo' called with a non-function value");
lua_error("API error - `funcinfo' called with a non-function value");
else {
TObject *f = luaA_protovalue(Address(func));
if (normalized_type(f) == LUA_T_PROTO) {
@@ -637,16 +631,19 @@ char *lua_getobjname (lua_Object o, char **name)
*/
void lua_beginblock (void)
{
if (L->numCblocks >= MAX_C_BLOCKS)
lua_error("too many nested blocks");
#ifndef MAX_C_BLOCKS
#define MAX_C_BLOCKS 1000 /* arbitrary limit */
#endif
void lua_beginblock (void) {
luaM_growvector(L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
"too many nested blocks", MAX_C_BLOCKS);
L->Cblocks[L->numCblocks] = L->Cstack;
L->numCblocks++;
}
void lua_endblock (void)
{
void lua_endblock (void) {
--L->numCblocks;
L->Cstack = L->Cblocks[L->numCblocks];
luaD_adjusttop(L->Cstack.base);
@@ -654,8 +651,7 @@ void lua_endblock (void)
int lua_ref (int lock)
{
int lua_ref (int lock) {
int ref;
checkCparams(1);
ref = luaC_ref(L->stack.top-1, lock);
@@ -665,8 +661,7 @@ int lua_ref (int lock)
lua_Object lua_getref (int ref)
{
lua_Object lua_getref (int ref) {
TObject *o = luaC_getref(ref);
return (o ? put_luaObject(o) : LUA_NOOBJECT);
}
@@ -680,17 +675,15 @@ lua_Object lua_getref (int ref)
** API: set a function as a fallback
*/
static void do_unprotectedrun (lua_CFunction f, int nParams, int nResults)
{
StkId base = (L->stack.top-L->stack.stack)-nParams;
static void do_unprotectedrun (lua_CFunction f, int nParams, int nResults) {
luaD_openstack(nParams);
L->stack.stack[base].ttype = LUA_T_CPROTO;
L->stack.stack[base].value.f = f;
luaD_call(base+1, nResults);
(L->stack.top-nParams)->ttype = LUA_T_CPROTO;
(L->stack.top-nParams)->value.f = f;
luaD_calln(nParams, nResults);
}
lua_Object lua_setfallback (char *name, lua_CFunction fallback)
{
lua_Object lua_setfallback (char *name, lua_CFunction fallback) {
lua_pushstring(name);
lua_pushcfunction(fallback);
do_unprotectedrun(luaT_setfallback, 2, 1);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lbuiltin.c,v 1.55 1999/03/01 20:22:16 roberto Exp roberto $
** $Id: lbuiltin.c,v 1.58 1999/05/27 20:21:03 roberto Exp roberto $
** Built-in functions
** See Copyright Notice in lua.h
*/
@@ -111,7 +111,10 @@ static void error_message (void) {
** model but changing "fputs" to put the strings at a proper place
** (a console window or a log file, for instance).
*/
#define MAXPRINT 40
#ifndef MAXPRINT
#define MAXPRINT 40 /* arbitrary limit */
#endif
static void luaB_print (void) {
lua_Object args[MAXPRINT];
lua_Object obj;
@@ -389,12 +392,16 @@ static void luaB_assert (void) {
static void luaB_foreachi (void) {
Hash *t = gethash(1);
TObject *f = luaA_Address(luaL_functionarg(2));
int i;
int n = (int)getnarg(t);
TObject f;
/* 'f' cannot be a pointer to TObject, because it is on the stack, and the
stack may be reallocated by the call. Moreover, some C compilers do not
initialize structs, so we must do the assignment after the declaration */
f = *luaA_Address(luaL_functionarg(2));
luaD_checkstack(3); /* for f, ref, and val */
for (i=1; i<=n; i++) {
*(L->stack.top++) = *f;
*(L->stack.top++) = f;
ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i;
*(L->stack.top++) = *luaH_getint(t, i);
luaD_calln(2, 1);
@@ -407,13 +414,14 @@ static void luaB_foreachi (void) {
static void luaB_foreach (void) {
Hash *a = gethash(1);
TObject *f = luaA_Address(luaL_functionarg(2));
int i;
TObject f; /* see comment in 'foreachi' */
f = *luaA_Address(luaL_functionarg(2));
luaD_checkstack(3); /* for f, ref, and val */
for (i=0; i<a->nhash; i++) {
Node *nd = &(a->node[i]);
if (ttype(val(nd)) != LUA_T_NIL) {
*(L->stack.top++) = *f;
*(L->stack.top++) = f;
*(L->stack.top++) = *ref(nd);
*(L->stack.top++) = *val(nd);
luaD_calln(2, 1);
@@ -426,14 +434,15 @@ static void luaB_foreach (void) {
static void luaB_foreachvar (void) {
TObject *f = luaA_Address(luaL_functionarg(1));
GCnode *g;
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;
if (s->u.s.globalval.ttype != LUA_T_NIL) {
pushtagstring(s); /* keep (extra) s on stack to avoid GC */
*(L->stack.top++) = *f;
*(L->stack.top++) = f;
pushtagstring(s);
*(L->stack.top++) = s->u.s.globalval;
luaD_calln(2, 1);
@@ -464,10 +473,10 @@ static void luaB_tinsert (void) {
v = luaL_nonnullarg(2);
pos = n+1;
}
luaV_setn(a, n+1); /* increment field "n" */
luaV_setn(a, n+1); /* a.n = n+1 */
for ( ;n>=pos; n--)
luaH_move(a, n, n+1);
luaH_setint(a, pos, luaA_Address(v));
luaH_move(a, n, n+1); /* a[n+1] = a[n] */
luaH_setint(a, pos, luaA_Address(v)); /* a[pos] = v */
}
@@ -476,10 +485,11 @@ static void luaB_tremove (void) {
int n = (int)getnarg(a);
int pos = luaL_opt_int(2, n);
if (n <= 0) return; /* table is "empty" */
luaA_pushobject(luaH_getint(a, pos)); /* push result */
luaV_setn(a, n-1); /* decrement field "n" */
luaA_pushobject(luaH_getint(a, pos)); /* result = a[pos] */
for ( ;pos<n; pos++)
luaH_move(a, pos+1, pos);
luaH_move(a, pos+1, pos); /* a[pos] = a[pos+1] */
luaV_setn(a, n-1); /* a.n = n-1 */
luaH_setint(a, n, &luaO_nilobject); /* a[n] = nil */
}
@@ -494,10 +504,10 @@ static void swap (Hash *a, int i, int j) {
luaH_setint(a, j, &temp);
}
static int sort_comp (TObject *f, TObject *a, TObject *b) {
static int sort_comp (lua_Object f, TObject *a, TObject *b) {
/* notice: the caller (auxsort) must check stack space */
if (f) {
*(L->stack.top) = *f;
if (f != LUA_NOOBJECT) {
*(L->stack.top) = *luaA_Address(f);
*(L->stack.top+1) = *a;
*(L->stack.top+2) = *b;
L->stack.top += 3;
@@ -512,7 +522,7 @@ static int sort_comp (TObject *f, TObject *a, TObject *b) {
return ttype(--(L->stack.top)) != LUA_T_NIL;
}
static void auxsort (Hash *a, int l, int u, TObject *f) {
static void auxsort (Hash *a, int l, int u, lua_Object f) {
while (l < u) { /* for tail recursion */
TObject *P;
int i, j;
@@ -560,10 +570,10 @@ static void luaB_sort (void) {
Hash *a = gethash(1);
int n = (int)getnarg(a);
lua_Object func = lua_getparam(2);
TObject *f = luaA_Address(func);
luaL_arg_check(!f || lua_isfunction(func), 2, "function expected");
luaL_arg_check(func == LUA_NOOBJECT || lua_isfunction(func), 2,
"function expected");
luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */
auxsort(a, 1, n, f);
auxsort(a, 1, n, func);
lua_pushobject(t);
}

106
ldo.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 1.40 1999/03/10 14:23:07 roberto Exp roberto $
** $Id: ldo.c,v 1.44 1999/06/17 17:04:03 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -29,7 +29,7 @@
#ifndef STACK_LIMIT
#define STACK_LIMIT 6000
#define STACK_LIMIT 6000 /* arbitrary limit */
#endif
@@ -37,6 +37,12 @@
#define STACK_UNIT 128
#ifdef DEBUG
#undef STACK_UNIT
#define STACK_UNIT 2
#endif
void luaD_init (void) {
L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
L->stack.top = L->stack.stack;
@@ -80,16 +86,14 @@ void luaD_adjusttop (StkId newtop) {
/*
** Open a hole below "nelems" from the L->stack.top.
*/
void luaD_openstack (int nelems)
{
void luaD_openstack (int nelems) {
luaO_memup(L->stack.top-nelems+1, L->stack.top-nelems,
nelems*sizeof(TObject));
incr_top;
}
void luaD_lineHook (int line)
{
void luaD_lineHook (int line) {
struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0;
@@ -99,8 +103,7 @@ void luaD_lineHook (int line)
}
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn)
{
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn) {
struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0;
@@ -123,28 +126,26 @@ void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn)
** Cstack.num is the number of arguments; Cstack.lua2C points to the
** first argument. Returns an index to the first result from C.
*/
static StkId callC (lua_CFunction f, StkId base)
{
struct C_Lua_Stack *CS = &L->Cstack;
struct C_Lua_Stack oldCLS = *CS;
static StkId callC (lua_CFunction f, StkId base) {
struct C_Lua_Stack *cls = &L->Cstack;
struct C_Lua_Stack oldCLS = *cls;
StkId firstResult;
int numarg = (L->stack.top-L->stack.stack) - base;
CS->num = numarg;
CS->lua2C = base;
CS->base = base+numarg; /* == top-stack */
cls->num = numarg;
cls->lua2C = base;
cls->base = base+numarg; /* == top-stack */
if (L->callhook)
luaD_callHook(base, NULL, 0);
(*f)(); /* do the actual call */
if (L->callhook) /* func may have changed callhook */
luaD_callHook(base, NULL, 1);
firstResult = CS->base;
*CS = oldCLS;
firstResult = cls->base;
*cls = oldCLS;
return firstResult;
}
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base)
{
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base) {
TObject *pbase;
int nup = cl->nelems; /* number of upvalues */
luaD_checkstack(nup);
@@ -166,15 +167,17 @@ void luaD_callTM (TObject *f, int nParams, int nResults) {
/*
** Call a function (C or Lua). The parameters must be on the L->stack.stack,
** between [L->stack.stack+base,L->stack.top). The function to be called is at L->stack.stack+base-1.
** When returns, the results are on the L->stack.stack, between [L->stack.stack+base-1,L->stack.top).
** Call a function (C or Lua). The parameters must be on the stack,
** between [top-nArgs,top). The function to be called is right below the
** arguments.
** When returns, the results are on the stack, between [top-nArgs-1,top).
** The number of results is nResults, unless nResults=MULT_RET.
*/
void luaD_call (StkId base, int nResults)
{
void luaD_calln (int nArgs, int nResults) {
struct Stack *S = &L->stack; /* to optimize */
StkId base = (S->top-S->stack)-nArgs;
TObject *func = S->stack+base-1;
StkId firstResult;
TObject *func = L->stack.stack+base-1;
int i;
switch (ttype(func)) {
case LUA_T_CPROTO:
@@ -199,24 +202,20 @@ void luaD_call (StkId base, int nResults)
TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
if (ttype(im) == LUA_T_NIL)
lua_error("call expression not a function");
luaD_callTM(im, (L->stack.top-L->stack.stack)-(base-1), nResults);
luaD_callTM(im, (S->top-S->stack)-(base-1), nResults);
return;
}
}
/* adjust the number of results */
if (nResults != MULT_RET)
if (nResults == MULT_RET)
nResults = (S->top-S->stack)-firstResult;
else
luaD_adjusttop(firstResult+nResults);
/* move results to base-1 (to erase parameters and function) */
base--;
nResults = L->stack.top - (L->stack.stack+firstResult); /* actual number of results */
for (i=0; i<nResults; i++)
*(L->stack.stack+base+i) = *(L->stack.stack+firstResult+i);
L->stack.top -= firstResult-base;
}
void luaD_calln (int nArgs, int nResults) {
luaD_call((L->stack.top-L->stack.stack)-nArgs, nResults);
*(S->stack+base+i) = *(S->stack+firstResult+i);
S->top -= firstResult-base;
}
@@ -249,39 +248,30 @@ static void message (char *s) {
void lua_error (char *s) {
if (s) message(s);
if (L->errorJmp)
longjmp(*((jmp_buf *)L->errorJmp), 1);
longjmp(L->errorJmp->b, 1);
else {
message("exit(1). Unable to recover.\n");
exit(1);
}
}
/*
** Call the function at L->Cstack.base, and incorporate results on
** the Lua2C structure.
*/
static void do_callinc (int nResults)
{
StkId base = L->Cstack.base;
luaD_call(base+1, nResults);
L->Cstack.lua2C = base; /* position of the new results */
L->Cstack.num = (L->stack.top-L->stack.stack) - base; /* number of results */
L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */
}
/*
** Execute a protected call. Assumes that function is at L->Cstack.base and
** parameters are on top of it. Leave nResults on the stack.
*/
int luaD_protectedrun (int nResults) {
int luaD_protectedrun (void) {
volatile struct C_Lua_Stack oldCLS = L->Cstack;
jmp_buf myErrorJmp;
struct lua_longjmp myErrorJmp;
volatile int status;
jmp_buf *volatile oldErr = L->errorJmp;
struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp) == 0) {
do_callinc(nResults);
if (setjmp(myErrorJmp.b) == 0) {
StkId base = L->Cstack.base;
luaD_calln((L->stack.top-L->stack.stack)-base-1, MULT_RET);
L->Cstack.lua2C = base; /* position of the new results */
L->Cstack.num = (L->stack.top-L->stack.stack) - base;
L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */
status = 0;
}
else { /* an error occurred: restore L->Cstack and L->stack.top */
@@ -299,12 +289,12 @@ int luaD_protectedrun (int nResults) {
*/
static int protectedparser (ZIO *z, int bin) {
volatile struct C_Lua_Stack oldCLS = L->Cstack;
jmp_buf myErrorJmp;
struct lua_longjmp myErrorJmp;
volatile int status;
TProtoFunc *volatile tf;
jmp_buf *volatile oldErr = L->errorJmp;
struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp) == 0) {
if (setjmp(myErrorJmp.b) == 0) {
tf = bin ? luaU_undump1(z) : luaY_parser(z);
status = 0;
}
@@ -336,7 +326,7 @@ static int do_main (ZIO *z, int bin) {
else {
unsigned long newelems2 = 2*(L->nblocks-old_blocks);
L->GCthreshold += newelems2;
status = luaD_protectedrun(MULT_RET);
status = luaD_protectedrun();
L->GCthreshold -= newelems2;
}
} while (bin && status == 0);

5
ldo.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 1.4 1997/12/15 16:17:20 roberto Exp roberto $
** $Id: ldo.h,v 1.5 1998/07/12 16:14:34 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -35,10 +35,9 @@ void luaD_adjusttop (StkId newtop);
void luaD_openstack (int nelems);
void luaD_lineHook (int line);
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn);
void luaD_call (StkId base, int nResults);
void luaD_calln (int nArgs, int nResults);
void luaD_callTM (TObject *f, int nParams, int nResults);
int luaD_protectedrun (int nResults);
int luaD_protectedrun (void);
void luaD_gcIM (TObject *o);
void luaD_travstack (int (*fn)(TObject *));
void luaD_checkstack (int n);

View File

@@ -1,5 +1,5 @@
/*
** $Id: liolib.c,v 1.37 1999/04/05 19:47:05 roberto Exp roberto $
** $Id: liolib.c,v 1.40 1999/05/14 12:24:04 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -157,9 +157,13 @@ static void setfile (FILE *f, char *name, int tag) {
static void setreturn (FILE *f, char *name) {
int tag = gettag();
setfile(f, name, tag);
lua_pushusertag(f, tag);
if (f == NULL)
pushresult(0);
else {
int tag = gettag();
setfile(f, name, tag);
lua_pushusertag(f, tag);
}
}
@@ -175,10 +179,6 @@ static void io_readfrom (void) {
else {
char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
if (current == NULL) {
pushresult(0);
return;
}
}
setreturn(current, FINPUT);
}
@@ -196,21 +196,14 @@ static void io_writeto (void) {
else {
char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w");
if (current == NULL) {
pushresult(0);
return;
}
}
setreturn(current, FOUTPUT);
}
static void io_appendto (void) {
FILE *fp = fopen(luaL_check_string(FIRSTARG), "a");
if (fp != NULL)
setreturn(fp, FOUTPUT);
else
pushresult(0);
FILE *current = fopen(luaL_check_string(FIRSTARG), "a");
setreturn(current, FOUTPUT);
}
@@ -244,23 +237,25 @@ static int read_pattern (FILE *f, char *p) {
p++;
continue;
default: {
char *ep; /* get what is next */
char *ep = luaI_classend(p); /* get what is next */
int m; /* match result */
if (c == NEED_OTHER) c = getc(f);
if (c != EOF)
m = luaI_singlematch(c, p, &ep);
else {
luaI_singlematch(0, p, &ep); /* to set "ep" */
m = 0; /* EOF matches no pattern */
}
m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
if (m) {
if (!inskip) luaL_addchar(c);
c = NEED_OTHER;
}
switch (*ep) {
case '*': /* repetition */
if (!m) p = ep+1; /* else stay in (repeat) the same item */
continue;
case '+': /* repetition (1 or more) */
if (!m) goto break_while; /* pattern fails? */
/* else go through */
case '*': /* repetition (0 or more) */
while (m) { /* reads the same item until it fails */
c = getc(f);
m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
if (m && !inskip) luaL_addchar(c);
}
/* go through to continue reading the pattern */
case '?': /* optional */
p = ep+1; /* continues reading the pattern */
continue;
@@ -336,7 +331,7 @@ static void io_read (void) {
success = 1; /* always success */
break;
case 4: /* word */
success = read_pattern(f, "{%s*}%S%S*");
success = read_pattern(f, "{%s*}%S+");
break;
default:
success = read_pattern(f, p);
@@ -475,7 +470,7 @@ static void io_debug (void) {
#define MAXMESSAGE (MESSAGESIZE*10)
#define MAXSRC 40
#define MAXSRC 60
static void errorfb (void) {
@@ -492,7 +487,7 @@ static void errorfb (void) {
lua_funcinfo(func, &chunkname, &linedefined);
luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk));
if (level == 2) strcat(buff, "Active Stack:\n");
strcat(buff, "\t");
strcat(buff, " ");
if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) {
strcat(buff, "...\n");
break; /* buffer is full */
@@ -506,11 +501,11 @@ static void errorfb (void) {
break;
default: {
if (linedefined == 0)
sprintf(buff+strlen(buff), "main of %.50s", buffchunk);
sprintf(buff+strlen(buff), "main of %.70s", buffchunk);
else if (linedefined < 0)
sprintf(buff+strlen(buff), "%.50s", buffchunk);
sprintf(buff+strlen(buff), "%.70s", buffchunk);
else
sprintf(buff+strlen(buff), "function <%d:%.50s>",
sprintf(buff+strlen(buff), "function <%d:%.70s>",
linedefined, buffchunk);
chunkname = NULL;
}
@@ -518,7 +513,7 @@ static void errorfb (void) {
if ((currentline = lua_currentline(func)) > 0)
sprintf(buff+strlen(buff), " at line %d", currentline);
if (chunkname)
sprintf(buff+strlen(buff), " [%.50s]", buffchunk);
sprintf(buff+strlen(buff), " [%.70s]", buffchunk);
strcat(buff, "\n");
}
func = lua_rawgetglobal("_ALERT");

27
llex.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 1.33 1999/03/11 18:59:19 roberto Exp roberto $
** $Id: llex.c,v 1.35 1999/05/14 12:24:04 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -41,14 +41,14 @@ void luaX_init (void) {
}
#define MAXSRC 40
#define MAXSRC 80
void luaX_syntaxerror (LexState *ls, char *s, char *token) {
char buff[MAXSRC];
luaL_chunkid(buff, zname(ls->lex_z), sizeof(buff));
if (token[0] == '\0')
token = "<eof>";
luaL_verror("%.100s;\n last token read: `%.50s' at line %d in %.50s",
luaL_verror("%.100s;\n last token read: `%.50s' at line %d in %.80s",
s, token, ls->linenumber, buff);
}
@@ -70,7 +70,7 @@ void luaX_token2str (int token, char *s) {
static void luaX_invalidchar (LexState *ls, int c) {
char buff[10];
char buff[8];
sprintf(buff, "0x%02X", c);
luaX_syntaxerror(ls, "invalid control char", buff);
}
@@ -106,17 +106,17 @@ void luaX_setinput (LexState *LS, ZIO *z)
** =======================================================
*/
#define PRAGMASIZE 20
#ifndef PRAGMASIZE
#define PRAGMASIZE 80 /* arbitrary limit */
#endif
static void skipspace (LexState *LS)
{
static void skipspace (LexState *LS) {
while (LS->current == ' ' || LS->current == '\t' || LS->current == '\r')
next(LS);
}
static int checkcond (LexState *LS, char *buff)
{
static int checkcond (LexState *LS, char *buff) {
static char *opts[] = {"nil", "1", NULL};
int i = luaL_findstring(buff, opts);
if (i >= 0) return i;
@@ -129,8 +129,7 @@ static int checkcond (LexState *LS, char *buff)
}
static void readname (LexState *LS, char *buff)
{
static void readname (LexState *LS, char *buff) {
int i = 0;
skipspace(LS);
while (isalnum(LS->current) || LS->current == '_') {
@@ -148,8 +147,7 @@ static void readname (LexState *LS, char *buff)
static void inclinenumber (LexState *LS);
static void ifskip (LexState *LS)
{
static void ifskip (LexState *LS) {
while (LS->ifstate[LS->iflevel].skip) {
if (LS->current == '\n')
inclinenumber(LS);
@@ -160,8 +158,7 @@ static void ifskip (LexState *LS)
}
static void inclinenumber (LexState *LS)
{
static void inclinenumber (LexState *LS) {
static char *pragmas [] =
{"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
next(LS); /* skip '\n' */

6
llex.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.h,v 1.10 1998/07/24 18:02:38 roberto Exp roberto $
** $Id: llex.h,v 1.11 1999/02/25 19:13:56 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -25,7 +25,9 @@ enum RESERVED {
NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS};
#define MAX_IFS 5
#ifndef MAX_IFS
#define MAX_IFS 5 /* arbitrary limit */
#endif
/* "ifstate" keeps the state of each nested $if the lexical is dealing with. */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lmathlib.c,v 1.15 1999/01/04 12:41:12 roberto Exp roberto $
** $Id: lmathlib.c,v 1.16 1999/02/19 17:33:35 roberto Exp roberto $
** Lua standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -13,6 +13,7 @@
#include "lualib.h"
#undef PI
#define PI (3.14159265358979323846)
#define RADIANS_PER_DEGREE (PI/180.0)

95
lmem.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lmem.c,v 1.13 1999/02/26 15:50:10 roberto Exp roberto $
** $Id: lmem.c,v 1.16 1999/05/20 20:43:06 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -22,12 +22,10 @@
#endif
#define MINSIZE 16 /* minimum size for "growing" vectors */
#define MINSIZE 8 /* minimum size for "growing" vectors */
#ifndef DEBUG
static unsigned long power2 (unsigned long n) {
unsigned long p = MINSIZE;
@@ -39,20 +37,17 @@ static unsigned long power2 (unsigned long n) {
void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
char *errormsg, unsigned long limit) {
unsigned long newn = nelems+inc;
if (newn >= limit) lua_error(errormsg);
if ((newn ^ nelems) <= nelems || /* still the same power of 2 limit? */
(nelems > 0 && newn < MINSIZE)) /* or block already is MINSIZE? */
return block; /* do not need to reallocate */
else { /* it crossed a power of 2 boundary; grow to next power */
if (newn >= limit)
lua_error(errormsg);
newn = power2(newn);
if (newn > limit)
newn = limit;
return luaM_realloc(block, newn*size);
}
else /* it crossed a power of 2 boundary; grow to next power */
return luaM_realloc(block, power2(newn)*size);
}
#ifndef DEBUG
/*
** generic allocation routine.
*/
@@ -78,57 +73,67 @@ void *luaM_realloc (void *block, unsigned long size) {
#include <string.h>
void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
char *errormsg, unsigned long limit) {
unsigned long newn = nelems+inc;
if (newn >= limit)
lua_error(errormsg);
return luaM_realloc(block, newn*size);
}
#define HEADER (sizeof(double))
#define MARKSIZE 16
#define MARK 55
#define blocksize(b) ((unsigned long *)((char *)(b) - HEADER))
unsigned long numblocks = 0;
unsigned long totalmem = 0;
static void *checkblock (void *block) {
unsigned long *b = (unsigned long *)((char *)block - HEADER);
unsigned long size = *b;
LUA_ASSERT(*(((char *)b)+size+HEADER) == MARK,
"corrupted block");
numblocks--;
totalmem -= size;
return b;
if (block == NULL)
return NULL;
else {
unsigned long *b = blocksize(block);
unsigned long size = *b;
int i;
for (i=0;i<MARKSIZE;i++)
LUA_ASSERT(*(((char *)b)+HEADER+size+i) == MARK+i, "corrupted block");
numblocks--;
totalmem -= size;
return b;
}
}
static void freeblock (void *block) {
if (block)
memset(block, -1, *blocksize(block)); /* erase block */
free(checkblock(block));
}
void *luaM_realloc (void *block, unsigned long size) {
unsigned long realsize = HEADER+size+1;
unsigned long realsize = HEADER+size+MARKSIZE;
if (realsize != (size_t)realsize)
lua_error("memory allocation error: block too big");
if (size == 0) {
if (block) {
unsigned long *b = (unsigned long *)((char *)block - HEADER);
memset(block, -1, *b); /* erase block */
block = checkblock(block);
}
free(block);
freeblock(block);
return NULL;
}
if (block)
block = checkblock(block);
block = (unsigned long *)realloc(block, realsize);
if (block == NULL)
lua_error(memEM);
totalmem += size;
numblocks++;
*(unsigned long *)block = size;
*(((char *)block)+size+HEADER) = MARK;
return (unsigned long *)((char *)block+HEADER);
else {
char *newblock = malloc(realsize);
int i;
if (block) {
unsigned long oldsize = *blocksize(block);
if (oldsize > size) oldsize = size;
memcpy(newblock+HEADER, block, oldsize);
freeblock(block); /* erase (and check) old copy */
}
if (newblock == NULL)
lua_error(memEM);
totalmem += size;
numblocks++;
*(unsigned long *)newblock = size;
for (i=0;i<MARKSIZE;i++)
*(newblock+HEADER+size+i) = MARK+i;
return newblock+HEADER;
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lopcodes.h,v 1.31 1999/03/05 21:16:07 roberto Exp roberto $
** $Id: lopcodes.h,v 1.32 1999/03/10 14:09:45 roberto Exp roberto $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -113,7 +113,7 @@ CHECKSTACK /* b (assert #temporaries == b; only for internal debuging!) */
#define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */
#define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) */
#define ZEROVARARG 64
#define ZEROVARARG 128
/* maximum value of an arg of 3 bytes; must fit in an "int" */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 1.30 1999/03/23 19:58:37 roberto Exp roberto $
** $Id: lparser.c,v 1.36 1999/06/16 13:35:01 roberto Exp roberto $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -22,35 +22,48 @@
#include "lzio.h"
/* for limit numbers in error messages */
#define MES_LIM(x) "(limit=" x ")"
/* size of a "normal" jump instruction: OpCode + 1 byte */
#define JMPSIZE 2
/* maximum number of local variables */
#define MAXLOCALS 32
#define SMAXLOCALS "32"
#ifndef MAXLOCALS
#define MAXLOCALS 200 /* arbitrary limit (<256) */
#endif
/* maximum number of upvalues */
#define MAXUPVALUES 16
#define SMAXUPVALUES "16"
#ifndef MAXUPVALUES
#define MAXUPVALUES 32 /* arbitrary limit (<256) */
#endif
/* maximum number of variables in the left side of an assignment */
#ifndef MAXVARSLH
#define MAXVARSLH 100 /* arbitrary limit (<255) */
#endif
/* maximum number of parameters in a function */
#ifndef MAXPARAMS
#define MAXPARAMS 100 /* arbitrary limit (<ZEROVARARG) */
#endif
/*
** Variable descriptor:
** must include a "exp" option because LL(1) cannot distinguish
** must include an "exp" option because LL(1) cannot distinguish
** between variables, upvalues and function calls on first sight.
** VGLOBAL: info is constant index of global name
** VLOCAL: info is stack index
** VDOT: info is constant index of index name
** VEXP: info is pc index of "nparam" of function call (or 0 if exp is closed)
*/
typedef enum {VGLOBAL, VLOCAL, VDOT, VINDEXED, VEXP} varkind;
typedef enum {
VGLOBAL, /* info is constant index of global name */
VLOCAL, /* info is stack index */
VDOT, /* info is constant index of index name */
VINDEXED, /* no info (table and index are on the stack) */
VEXP /* info is pc index of "nparam" of a call (or 0 if exp is closed) */
} varkind;
typedef struct {
typedef struct vardesc {
varkind k;
int info;
} vardesc;
@@ -62,7 +75,7 @@ typedef struct {
** and, if last expression is open (a function call),
** where is its pc index of "nparam"
*/
typedef struct {
typedef struct listdesc {
int n;
int pc; /* 0 if last expression is closed */
} listdesc;
@@ -74,7 +87,7 @@ typedef struct {
** it is a list constructor (k = 0) or a record constructor (k = 1)
** or empty (k = ';' or '}')
*/
typedef struct {
typedef struct constdesc {
int n;
int k;
} constdesc;
@@ -129,6 +142,15 @@ static void var_or_func_tail (LexState *ls, vardesc *v);
static void checklimit (LexState *ls, int val, int limit, char *msg) {
if (val > limit) {
char buff[100];
sprintf(buff, "too many %s (limit=%d)", msg, limit);
luaX_error(ls, buff);
}
}
static void check_pc (FuncState *fs, int n) {
luaM_growvector(fs->f->code, fs->pc, n, Byte, codeEM, MAX_INT);
}
@@ -159,24 +181,25 @@ static void code_oparg_at (LexState *ls, int pc, OpCode op,
code[pc] = (Byte)op;
code[pc+1] = (Byte)arg;
}
else if (arg <= MAX_WORD) {
else if (arg > MAX_ARG)
luaX_error(ls, "code too long");
else { /* MAX_BYTE < arg < MAX_ARG */
if (arg > MAX_WORD) {
code[pc] = (Byte)LONGARG;
code[pc+1] = (Byte)(arg>>16);
pc += 2;
}
code[pc] = (Byte)(op-1); /* opcode for word argument */
code[pc+1] = (Byte)(arg>>8);
code[pc+1] = (Byte)((arg&0xFFFF)>>8);
code[pc+2] = (Byte)(arg&0xFF);
}
else if (arg <= MAX_ARG) {
code[pc] = (Byte)LONGARG;
code[pc+1] = (Byte)(arg>>16);
code_oparg_at(ls, pc+2, op, arg&0xFFFF, 0);
}
else luaX_error(ls, "code too long");
}
static int codesize (int arg) {
if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */
else if (arg <= MAX_WORD) return 3; /* opcode + 1 word */
else return 2+codesize(arg&0xFFFF); /* LONGARG + 1 byte + original opcode */
else if (arg <= MAX_WORD) return 3; /* opcode + 1 word (2 bytes) */
else return 5; /* LONGARG + 1 byte + opcode + 1 word (2 bytes) */
}
@@ -302,8 +325,7 @@ static void luaI_unregisterlocalvar (FuncState *fs, int line) {
static void store_localvar (LexState *ls, TaggedString *name, int n) {
FuncState *fs = ls->fs;
if (fs->nlocalvar+n >= MAXLOCALS)
luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS));
checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables");
fs->localvar[fs->nlocalvar+n] = name;
luaI_registerlocalvar(fs, name, ls->linenumber);
}
@@ -361,9 +383,8 @@ static int indexupvalue (LexState *ls, TaggedString *n) {
return i;
}
/* new one */
if (++(fs->nupvalues) > MAXUPVALUES)
luaX_error(ls, "too many upvalues in a single function "
MES_LIM(SMAXUPVALUES));
++(fs->nupvalues);
checklimit(ls, fs->nupvalues, MAXUPVALUES, "upvalues");
fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */
return i;
}
@@ -431,6 +452,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
static void code_args (LexState *ls, int nparams, int dots) {
FuncState *fs = ls->fs;
fs->nlocalvar += nparams; /* "self" may already be there */
checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters");
nparams = fs->nlocalvar;
if (!dots) {
fs->f->code[1] = (Byte)nparams; /* fill-in arg information */
@@ -529,7 +551,8 @@ static void func_onstack (LexState *ls, FuncState *func) {
else {
for (i=0; i<func->nupvalues; i++)
lua_pushvar(ls, &func->upvalues[i]);
code_oparg(ls, CLOSURE, c, -func->nupvalues+1);
deltastack(ls, 1); /* CLOSURE puts one extra element (before poping) */
code_oparg(ls, CLOSURE, c, -func->nupvalues);
code_byte(fs, (Byte)func->nupvalues);
}
}
@@ -908,9 +931,9 @@ static int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6};
static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP,
LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP};
#define MAXOPS 20 /* op's stack size */
#define MAXOPS 20 /* op's stack size (arbitrary limit) */
typedef struct {
typedef struct stack_op {
int ops[MAXOPS];
int top;
} stack_op;
@@ -1217,6 +1240,7 @@ static void decinit (LexState *ls, listdesc *d) {
static int assignment (LexState *ls, vardesc *v, int nvars) {
int left = 0;
checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment");
unloaddot(ls, v);
if (ls->token == ',') { /* assignment -> ',' NAME assignment */
vardesc nv;

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 1.9 1999/02/25 15:17:01 roberto Exp roberto $
** $Id: lstate.c,v 1.11 1999/05/11 14:19:32 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -32,6 +32,7 @@ void lua_open (void)
L->Mbuffbase = 0;
L->Mbuffsize = 0;
L->Mbuffnext = 0;
L->Cblocks = NULL;
L->numCblocks = 0;
L->debug = 0;
L->callhook = NULL;
@@ -73,6 +74,7 @@ void lua_close (void)
luaM_free(L->IMtable);
luaM_free(L->refArray);
luaM_free(L->Mbuffer);
luaM_free(L->Cblocks);
luaM_free(L);
L = NULL;
#ifdef DEBUG

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 1.15 1999/02/25 15:17:01 roberto Exp roberto $
** $Id: lstate.h,v 1.18 1999/05/11 14:19:32 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -14,13 +14,21 @@
#include "luadebug.h"
#define MAX_C_BLOCKS 10
#define GARBAGE_BLOCK 150
typedef int StkId; /* index to stack elements */
/*
** "jmp_buf" may be an array, so it is better to make sure it has an
** address (and not that it *is* an address...)
*/
struct lua_longjmp {
jmp_buf b;
};
struct Stack {
TObject *top;
TObject *stack;
@@ -35,7 +43,7 @@ struct C_Lua_Stack {
};
typedef struct {
typedef struct stringtable {
int size;
int nuse; /* number of elements (including EMPTYs) */
TaggedString **hash;
@@ -54,12 +62,12 @@ struct lua_State {
/* thread-specific state */
struct Stack stack; /* Lua stack */
struct C_Lua_Stack Cstack; /* C2lua struct */
jmp_buf *errorJmp; /* current error recover point */
struct lua_longjmp *errorJmp; /* current error recover point */
char *Mbuffer; /* global buffer */
int Mbuffbase; /* current first position of Mbuffer */
int Mbuffsize; /* size of Mbuffer */
int Mbuffnext; /* next position to fill in Mbuffer */
struct C_Lua_Stack Cblocks[MAX_C_BLOCKS];
struct C_Lua_Stack *Cblocks;
int numCblocks; /* number of nested Cblocks */
int debug;
lua_CHFunction callhook;

253
lstrlib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.27 1999/02/25 19:13:56 roberto Exp roberto $
** $Id: lstrlib.c,v 1.31 1999/05/14 12:24:04 roberto Exp roberto $
** Standard library for strings and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -117,7 +117,10 @@ static void str_char (void) {
** =======================================================
*/
#define MAX_CAPT 9
#ifndef MAX_CAPT
#define MAX_CAPT 32 /* arbitrary limit */
#endif
struct Capture {
char *src_end; /* end ('\0') of source string */
@@ -130,7 +133,7 @@ struct Capture {
#define ESC '%'
#define SPECIALS "^$*?.([%-"
#define SPECIALS "^$*+?.([%-"
static void push_captures (struct Capture *cap) {
@@ -160,8 +163,21 @@ static int capture_to_close (struct Capture *cap) {
}
static char *bracket_end (char *p) {
return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']');
char *luaI_classend (char *p) {
switch (*p++) {
case ESC:
if (*p == '\0')
luaL_verror("incorrect pattern (ends with `%c')", ESC);
return p+1;
case '[':
if (*p == '^') p++;
if (*p == ']') p++;
p = strchr(p, ']');
if (!p) lua_error("incorrect pattern (missing `]')");
return p+1;
default:
return p;
}
}
@@ -184,48 +200,55 @@ static int matchclass (int c, int cl) {
}
int luaI_singlematch (int c, char *p, char **ep) {
static int matchbracketclass (int c, char *p, char *end) {
int sig = 1;
if (*(p+1) == '^') {
sig = 0;
p++; /* skip the '^' */
}
while (++p < end) {
if (*p == ESC) {
p++;
if ((p < end) && matchclass(c, (unsigned char)*p))
return sig;
}
else if ((*(p+1) == '-') && (p+2 < end)) {
p+=2;
if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p)
return sig;
}
else if ((unsigned char)*p == c) return sig;
}
return !sig;
}
int luaI_singlematch (int c, char *p, char *ep) {
switch (*p) {
case '.': /* matches any char */
*ep = p+1;
return 1;
case '\0': /* end of pattern; matches nothing */
*ep = p;
return 0;
case ESC:
if (*(++p) == '\0')
luaL_verror("incorrect pattern (ends with `%c')", ESC);
*ep = p+1;
return matchclass(c, (unsigned char)*p);
case '[': {
char *end = bracket_end(p+1);
int sig = *(p+1) == '^' ? (p++, 0) : 1;
if (end == NULL) lua_error("incorrect pattern (missing `]')");
*ep = end+1;
while (++p < end) {
if (*p == ESC) {
if (((p+1) < end) && matchclass(c, (unsigned char)*++p))
return sig;
}
else if ((*(p+1) == '-') && (p+2 < end)) {
p+=2;
if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p)
return sig;
}
else if ((unsigned char)*p == c) return sig;
}
return !sig;
}
return matchclass(c, (unsigned char)*(p+1));
case '[':
return matchbracketclass(c, p, ep-1);
default:
*ep = p+1;
return ((unsigned char)*p == c);
}
}
static char *matchbalance (char *s, int b, int e, struct Capture *cap) {
if (*s != b) return NULL;
static char *match (char *s, char *p, struct Capture *cap);
static char *matchbalance (char *s, char *p, struct Capture *cap) {
if (*p == 0 || *(p+1) == 0)
lua_error("unbalanced pattern");
if (*s != *p) return NULL;
else {
int b = *p;
int e = *(p+1);
int cont = 1;
while (++s < cap->src_end) {
if (*s == e) {
@@ -238,87 +261,109 @@ static char *matchbalance (char *s, int b, int e, struct Capture *cap) {
}
static char *matchitem (char *s, char *p, struct Capture *cap, char **ep) {
if (*p == ESC) {
p++;
if (isdigit((unsigned char)*p)) { /* capture */
int l = check_cap(*p, cap);
int len = cap->capture[l].len;
*ep = p+1;
if (cap->src_end-s >= len && memcmp(cap->capture[l].init, s, len) == 0)
return s+len;
else return NULL;
}
else if (*p == 'b') { /* balanced string */
p++;
if (*p == 0 || *(p+1) == 0)
lua_error("unbalanced pattern");
*ep = p+2;
return matchbalance(s, *p, *(p+1), cap);
}
else p--; /* and go through */
static char *max_expand (char *s, char *p, char *ep, struct Capture *cap) {
int i = 0; /* counts maximum expand for item */
while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep))
i++;
/* keeps trying to match mith the maximum repetitions */
while (i>=0) {
char *res = match((s+i), ep+1, cap);
if (res) return res;
i--; /* else didn't match; reduce 1 repetition to try again */
}
/* "luaI_singlematch" sets "ep" (so must be called even at the end of "s" */
return (luaI_singlematch((unsigned char)*s, p, ep) && s<cap->src_end) ?
s+1 : NULL;
return NULL;
}
static char *min_expand (char *s, char *p, char *ep, struct Capture *cap) {
for (;;) {
char *res = match(s, ep+1, cap);
if (res != NULL)
return res;
else if (s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep))
s++; /* try with one more repetition */
else return NULL;
}
}
static char *start_capt (char *s, char *p, struct Capture *cap) {
char *res;
int level = cap->level;
if (level >= MAX_CAPT) lua_error("too many captures");
cap->capture[level].init = s;
cap->capture[level].len = -1;
cap->level = level+1;
if ((res=match(s, p+1, cap)) == NULL) /* match failed? */
cap->level--; /* undo capture */
return res;
}
static char *end_capt (char *s, char *p, struct Capture *cap) {
int l = capture_to_close(cap);
char *res;
cap->capture[l].len = s - cap->capture[l].init; /* close capture */
if ((res = match(s, p+1, cap)) == NULL) /* match failed? */
cap->capture[l].len = -1; /* undo capture */
return res;
}
static char *match_capture (char *s, int level, struct Capture *cap) {
int l = check_cap(level, cap);
int len = cap->capture[l].len;
if (cap->src_end-s >= len &&
memcmp(cap->capture[l].init, s, len) == 0)
return s+len;
else return NULL;
}
static char *match (char *s, char *p, struct Capture *cap) {
init: /* using goto's to optimize tail recursion */
switch (*p) {
case '(': { /* start capture */
char *res;
if (cap->level >= MAX_CAPT) lua_error("too many captures");
cap->capture[cap->level].init = s;
cap->capture[cap->level].len = -1;
cap->level++;
if ((res=match(s, p+1, cap)) == NULL) /* match failed? */
cap->level--; /* undo capture */
return res;
}
case ')': { /* end capture */
int l = capture_to_close(cap);
char *res;
cap->capture[l].len = s - cap->capture[l].init; /* close capture */
if ((res = match(s, p+1, cap)) == NULL) /* match failed? */
cap->capture[l].len = -1; /* undo capture */
return res;
}
case '\0': case '$': /* (possibly) end of pattern */
if (*p == 0 || (*(p+1) == 0 && s == cap->src_end))
return s;
/* else go through */
default: { /* it is a pattern item */
char *ep; /* will point to what is next */
char *s1 = matchitem(s, p, cap, &ep);
case '(': /* start capture */
return start_capt(s, p, cap);
case ')': /* end capture */
return end_capt(s, p, cap);
case ESC: /* may be %[0-9] or %b */
if (isdigit((unsigned char)(*(p+1)))) { /* capture? */
s = match_capture(s, *(p+1), cap);
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(p+2, s, cap) */
}
else if (*(p+1) == 'b') { /* balanced string? */
s = matchbalance(s, p+2, cap);
if (s == NULL) return NULL;
p+=4; goto init; /* else return match(p+4, s, cap); */
}
else goto dflt; /* case default */
case '\0': /* end of pattern */
return s; /* match succeeded */
case '$':
if (*(p+1) == '\0') /* is the '$' the last char in pattern? */
return (s == cap->src_end) ? s : NULL; /* check end of string */
else goto dflt;
default: dflt: { /* it is a pattern item */
char *ep = luaI_classend(p); /* points to what is next */
int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep);
switch (*ep) {
case '*': { /* repetition */
char *res;
if (s1 && s1>s && ((res=match(s1, p, cap)) != NULL))
return res;
p=ep+1; goto init; /* else return match(s, ep+1, cap); */
}
case '?': { /* optional */
char *res;
if (s1 && ((res=match(s1, ep+1, cap)) != NULL))
if (m && ((res=match(s+1, ep+1, cap)) != NULL))
return res;
p=ep+1; goto init; /* else return match(s, ep+1, cap); */
}
case '-': { /* repetition */
char *res;
if ((res = match(s, ep+1, cap)) != NULL)
return res;
else if (s1 && s1>s) {
s = s1;
goto init; /* return match(s1, p, cap); */
}
else
return NULL;
}
case '*': /* 0 or more repetitions */
return max_expand(s, p, ep, cap);
case '+': /* 1 or more repetitions */
return (m ? max_expand(s+1, p, ep, cap) : NULL);
case '-': /* 0 or more repetitions (minimum) */
return min_expand(s, p, ep, cap);
default:
if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, cap); */
else return NULL;
if (!m) return NULL;
s++; p=ep; goto init; /* else return match(s+1, ep, cap); */
}
}
}
@@ -457,7 +502,7 @@ static void luaI_addquoted (int arg) {
}
/* maximum size of each format specification (such as '%-099.99d') */
#define MAX_FORMAT 20
#define MAX_FORMAT 20 /* arbitrary limit */
static void str_format (void) {
int arg = 1;

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.c,v 1.20 1999/01/25 17:41:19 roberto Exp roberto $
** $Id: ltable.c,v 1.21 1999/02/23 14:57:28 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -140,7 +140,8 @@ void luaH_set (Hash *t, TObject *ref, TObject *val) {
if (ttype(ref(n)) != LUA_T_NIL)
*val(n) = *val;
else {
TObject buff = *val; /* rehash may invalidate this address */
TObject buff;
buff = *val; /* rehash may invalidate this address */
if ((long)nuse(t)*3L > (long)nhash(t)*2L) {
rehash(t);
n = luaH_present(t, ref);

5
ltm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 1.23 1999/02/25 19:13:56 roberto Exp roberto $
** $Id: ltm.c,v 1.24 1999/02/26 15:48:55 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -129,7 +129,7 @@ TObject *luaT_gettagmethod (int t, char *event) {
void luaT_settagmethod (int t, char *event, TObject *func) {
TObject temp = *func;
TObject temp;
int e = luaI_checkevent(event, luaT_eventname);
checktag(t);
if (!luaT_validevent(t, e))
@@ -137,6 +137,7 @@ void luaT_settagmethod (int t, char *event, TObject *func) {
luaT_eventname[e], luaO_typenames[-t],
(t == LUA_T_ARRAY || t == LUA_T_USERDATA) ? " with default tag"
: "");
temp = *func;
*func = *luaT_getim(t,e);
*luaT_getim(t, e) = temp;
}

11
lua.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.18 1999/01/26 11:50:58 roberto Exp roberto $
** $Id: lua.c,v 1.20 1999/06/24 19:42:02 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -15,12 +15,6 @@
#include "lualib.h"
#ifndef OLD_ANSI
#include <locale.h>
#else
#define setlocale(a,b) 0
#endif
#ifdef _POSIX_SOURCE
#include <unistd.h>
#else
@@ -51,6 +45,8 @@ static void lstop (void) {
static void laction (int i) {
signal(SIGINT, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
old_linehook = lua_setlinehook((lua_LHFunction)lstop);
old_callhook = lua_setcallhook((lua_CHFunction)lstop);
}
@@ -131,7 +127,6 @@ int main (int argc, char *argv[])
int i;
lua_open();
lua_pushstring("> "); lua_setglobal("_PROMPT");
setlocale(LC_ALL, "");
lua_userinit();
if (argc < 2) { /* no arguments? */
if (isatty(0)) {

4
lua.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.30 1999/02/25 19:13:56 roberto Exp roberto $
** $Id: lua.h,v 1.31 1999/04/15 12:33:19 roberto Exp roberto $
** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua@tecgraf.puc-rio.br
@@ -11,7 +11,7 @@
#ifndef lua_h
#define lua_h
#define LUA_VERSION "Lua 3.2 (beta)"
#define LUA_VERSION "Lua 3.2"
#define LUA_COPYRIGHT "Copyright (C) 1994-1999 TeCGraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"

View File

@@ -1,5 +1,5 @@
/*
** $Id: lualib.h,v 1.4 1998/06/19 16:14:09 roberto Exp roberto $
** $Id: lualib.h,v 1.5 1999/01/08 16:47:44 roberto Exp roberto $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
@@ -29,7 +29,8 @@ void lua_userinit (void);
/* Auxiliary functions (private) */
int luaI_singlematch (int c, char *p, char **ep);
char *luaI_classend (char *p);
int luaI_singlematch (int c, char *p, char *ep);
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lundump.c,v 1.18 1999/04/09 03:10:40 lhf Exp lhf $
** $Id: lundump.c,v 1.21 1999/07/02 19:34:26 lhf Exp $
** load bytecodes from files
** See Copyright Notice in lua.h
*/
@@ -15,12 +15,6 @@
#define LoadBlock(b,size,Z) ezread(Z,b,size)
#if LUAC_NATIVE
#define doLoadNumber(x,Z) LoadBlock(&x,sizeof(x),Z)
#else
#define doLoadNumber(x,Z) x=LoadNumber(Z)
#endif
static void unexpectedEOZ (ZIO* Z)
{
luaL_verror("unexpected end of file in %s",zname(Z));
@@ -53,16 +47,33 @@ static unsigned long LoadLong (ZIO* Z)
return (hi<<16)|lo;
}
static real LoadNumber (ZIO* Z)
/*
* convert number from text
*/
double luaU_str2d (char* b, char* where)
{
char b[256];
int size=ezgetc(Z);
LoadBlock(b,size,Z);
b[size]=0;
if (b[0]=='-')
return -luaO_str2d(b+1);
int negative=(b[0]=='-');
double x=luaO_str2d(b+negative);
if (x<0) luaL_verror("cannot convert number '%s' in %s",b,where);
return negative ? -x : x;
}
static real LoadNumber (ZIO* Z, int native)
{
real x;
if (native)
{
LoadBlock(&x,sizeof(x),Z);
return x;
}
else
return luaO_str2d(b);
{
char b[256];
int size=ezgetc(Z);
LoadBlock(b,size,Z);
b[size]=0;
return luaU_str2d(b,zname(Z));
}
}
static int LoadInt (ZIO* Z, char* message)
@@ -112,9 +123,9 @@ static void LoadLocals (TProtoFunc* tf, ZIO* Z)
tf->locvars[i].varname=NULL;
}
static TProtoFunc* LoadFunction (ZIO* Z);
static TProtoFunc* LoadFunction (ZIO* Z, int native);
static void LoadConstants (TProtoFunc* tf, ZIO* Z)
static void LoadConstants (TProtoFunc* tf, ZIO* Z, int native)
{
int i,n=LoadInt(Z,"too many constants (%ld) in %s");
tf->nconsts=n;
@@ -127,13 +138,13 @@ static void LoadConstants (TProtoFunc* tf, ZIO* Z)
switch (ttype(o))
{
case LUA_T_NUMBER:
doLoadNumber(nvalue(o),Z);
nvalue(o)=LoadNumber(Z,native);
break;
case LUA_T_STRING:
tsvalue(o)=LoadTString(Z);
break;
case LUA_T_PROTO:
tfvalue(o)=LoadFunction(Z);
tfvalue(o)=LoadFunction(Z,native);
break;
case LUA_T_NIL:
break;
@@ -144,7 +155,7 @@ static void LoadConstants (TProtoFunc* tf, ZIO* Z)
}
}
static TProtoFunc* LoadFunction (ZIO* Z)
static TProtoFunc* LoadFunction (ZIO* Z, int native)
{
TProtoFunc* tf=luaF_newproto();
tf->lineDefined=LoadInt(Z,"lineDefined too large (%ld) in %s");
@@ -152,7 +163,7 @@ static TProtoFunc* LoadFunction (ZIO* Z)
if (tf->source==NULL) tf->source=luaS_new(zname(Z));
tf->code=LoadCode(Z);
LoadLocals(tf,Z);
LoadConstants(tf,Z);
LoadConstants(tf,Z,native);
return tf;
}
@@ -164,9 +175,10 @@ static void LoadSignature (ZIO* Z)
if (*s!=0) luaL_verror("bad signature in %s",zname(Z));
}
static void LoadHeader (ZIO* Z)
static int LoadHeader (ZIO* Z)
{
int version,sizeofR;
int native;
LoadSignature(Z);
version=ezgetc(Z);
if (version>VERSION)
@@ -177,36 +189,29 @@ static void LoadHeader (ZIO* Z)
luaL_verror(
"%s too old: version=0x%02x; expected at least 0x%02x",
zname(Z),version,VERSION0);
sizeofR=ezgetc(Z); /* test number representation */
#if LUAC_NATIVE
if (sizeofR==0)
luaL_verror("cannot read numbers in %s: "
"support for decimal format not enabled",
zname(Z));
if (sizeofR!=sizeof(real))
luaL_verror("unknown number size in %s: read %d; expected %d",
zname(Z),sizeofR,sizeof(real));
else
sizeofR=ezgetc(Z);
native=(sizeofR!=0);
if (native) /* test number representation */
{
real f=-TEST_NUMBER,tf=TEST_NUMBER;
doLoadNumber(f,Z);
if (f!=tf)
luaL_verror("unknown number representation in %s: "
"read " NUMBER_FMT "; expected " NUMBER_FMT,
zname(Z),f,tf);
if (sizeofR!=sizeof(real))
luaL_verror("unknown number size in %s: read %d; expected %d",
zname(Z),sizeofR,sizeof(real));
else
{
real tf=TEST_NUMBER;
real f=LoadNumber(Z,native);
if ((long)f!=(long)tf)
luaL_verror("unknown number format in %s: "
"read " NUMBER_FMT "; expected " NUMBER_FMT,
zname(Z),f,tf);
}
}
#else
if (sizeofR!=0)
luaL_verror("cannot read numbers in %s: "
"support for native format not enabled",
zname(Z));
#endif
return native;
}
static TProtoFunc* LoadChunk (ZIO* Z)
{
LoadHeader(Z);
return LoadFunction(Z);
return LoadFunction(Z,LoadHeader(Z));
}
/*

View File

@@ -1,5 +1,5 @@
/*
** $Id: lundump.h,v 1.13 1999/03/29 16:16:18 lhf Exp lhf $
** $Id: lundump.h,v 1.15 1999/07/02 19:34:26 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -13,6 +13,8 @@
TProtoFunc* luaU_undump1 (ZIO* Z); /* load one chunk */
void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf);
/* handle cases that cannot happen */
double luaU_str2d (char* b, char* where);
/* convert number from text */
/* definitions for headers of binary files */
#define VERSION 0x32 /* last format change was in 3.2 */
@@ -30,19 +32,8 @@ void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf);
#define NUMBER_FMT "%.16g" /* LUA_NUMBER */
#endif
/* LUA_NUMBER
* by default, numbers are stored in precompiled chunks as decimal strings.
* this is completely portable and fast enough for most applications.
* if you want to use this default, do nothing.
* if you want additional speed at the expense of portability, move the line
* below out of this comment.
#define LUAC_NATIVE
*/
#ifdef LUAC_NATIVE
/* a multiple of PI for testing number representation */
/* a multiple of PI for testing native format */
/* multiplying by 1E8 gives non-trivial integer values */
#define TEST_NUMBER 3.14159265358979323846E8
#endif
#endif

23
lvm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 1.54 1999/03/10 14:09:45 roberto Exp roberto $
** $Id: lvm.c,v 1.57 1999/05/21 19:41:49 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -214,7 +214,8 @@ void luaV_setglobal (TaggedString *ts) {
else {
/* WARNING: caller must assure stack space */
struct Stack *S = &L->stack;
TObject newvalue = *(S->top-1);
TObject newvalue;
newvalue = *(S->top-1);
ttype(S->top-1) = LUA_T_STRING;
tsvalue(S->top-1) = ts;
*S->top++ = *oldvalue;
@@ -341,11 +342,11 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
goto ret;
case CALL: aux = *pc++;
luaD_call((S->top-S->stack)-(*pc++), aux);
luaD_calln(*pc++, aux);
break;
case TAILCALL: aux = *pc++;
luaD_call((S->top-S->stack)-(*pc++), MULT_RET);
luaD_calln(*pc++, MULT_RET);
base += aux;
goto ret;
@@ -403,7 +404,8 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
case PUSHSELFW: aux += highbyte(*pc++);
case PUSHSELF: aux += *pc++; {
TObject receiver = *(S->top-1);
TObject receiver;
receiver = *(S->top-1);
*S->top++ = consts[aux];
luaV_gettable();
*S->top++ = receiver;
@@ -439,17 +441,17 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
case SETLISTW: aux += highbyte(*pc++);
case SETLIST: aux += *pc++; {
int n = *(pc++);
TObject *arr = S->top-n-1;
Hash *arr = avalue(S->top-n-1);
aux *= LFIELDS_PER_FLUSH;
for (; n; n--)
luaH_setint(avalue(arr), n+aux, --S->top);
luaH_setint(arr, n+aux, --S->top);
break;
}
case SETMAP: aux = *pc++; {
TObject *arr = S->top-(2*aux)-3;
Hash *arr = avalue(S->top-(2*aux)-3);
do {
luaH_set(avalue(arr), S->top-2, S->top-1);
luaH_set(arr, S->top-2, S->top-1);
S->top-=2;
} while (aux--);
break;
@@ -620,7 +622,8 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
goto switchentry; /* do not reset "aux" */
case CHECKSTACK: aux = *pc++;
LUA_ASSERT((S->top-S->stack)-base == aux, "wrong stack size");
LUA_ASSERT((S->top-S->stack)-base == aux && S->last >= S->top,
"wrong stack size");
break;
}

View File

@@ -1,4 +1,4 @@
% $Id: manual.tex,v 1.29 1999/04/07 16:40:04 roberto Exp roberto $
% $Id: manual.tex,v 1.32 1999/05/11 20:46:28 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/04/07 16:40:04 $ $}}
\date{{\small \tt\$Date: 1999/05/11 20:46:28 $ $}}
\maketitle
@@ -1719,9 +1719,9 @@ equivalent to the Lua code:
lua_pushnumber(4); /* 3rd argument */
lua_callfunction(lua_getglobal("f")); /* call Lua function */
lua_pushobject(lua_getresult(1)); /* push first result of the call */
lua_setglobal("a"); /* sets global variable 'a' */
lua_pushobject(lua_getresult(2)); /* push second result of the call */
lua_setglobal("b"); /* sets global variable 'b' */
lua_setglobal("a"); /* set global variable 'a' */
lua_pushobject(lua_getresult(2)); /* push second result of the call */
lua_setglobal("b"); /* set global variable 'b' */
\end{verbatim}
Some special Lua functions have exclusive interfaces.
@@ -2152,10 +2152,11 @@ This function could be defined in Lua:
\begin{verbatim}
function getn (t)
if type(t.n) == 'number' then return t.n end
local i = nil
local max = 0
while (i=next(t, i)) do
local i = next(t, nil)
while i do
if type(i) == 'number' and i>max then max=i end
i = next(t, i)
end
return max
end
@@ -2198,10 +2199,11 @@ as the final value of \verb|foreachi|.
This function could be defined in Lua:
\begin{verbatim}
function foreachi (t, f)
local i, n = 0, getn(t)
while (i=i+1)<=n do
local i, n = 1, getn(t)
while i <= n do
local res = f(i, t[i])
if res then return res end
i = i+1
end
end
\end{verbatim}
@@ -2279,11 +2281,12 @@ except that the table accesses are all raw (that is, without tag methods):
pos = pos or n
local value = t[pos]
if n<=0 then return end
t.n = n-1
while pos < n do
t[pos] = t[pos+1]
pos = pos+1
end
t[n] = nil
t.n = n-1
return value
end
\end{verbatim}
@@ -2457,27 +2460,27 @@ For instance, when \verb|n| is 1 only the first occurrence of
Here are some examples:
\begin{verbatim}
x = gsub("hello world", "(%w%w*)", "%1 %1")
x = gsub("hello world", "(%w+)", "%1 %1")
--> x="hello hello world world"
x = gsub("hello world", "(%w%w*)", "%1 %1", 1)
x = gsub("hello world", "(%w+)", "%1 %1", 1)
--> x="hello hello world"
x = gsub("hello world from Lua", "(%w%w*)%s*(%w%w*)", "%2 %1")
x = gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
--> x="world hello Lua from"
x = gsub("home = $HOME, user = $USER", "$(%w%w*)", getenv)
x = gsub("home = $HOME, user = $USER", "%$(%w+)", getenv)
--> x="home = /home/roberto, user = roberto" (for instance)
x = gsub("4+5 = $return 4+5$", "$(.-)%$", dostring)
x = gsub("4+5 = $return 4+5$", "%$(.-)%$", dostring)
--> x="4+5 = 9"
local t = {name="lua", version="3.1"}
x = gsub("$name - $version", "$(%w%w*)", function (v) return %t[v] end)
--> x="lua - 3.1"
local t = {name="lua", version="3.2"}
x = gsub("$name - $version", "%$(%w+)", function (v) return %t[v] end)
--> x="lua - 3.2"
t = {n=0}
gsub("first second word", "(%w%w*)", function (w) tinsert(%t, w) end)
gsub("first second word", "(%w+)", function (w) tinsert(%t, w) end)
--> t={"first", "second", "word"; n=3}
\end{verbatim}
@@ -2489,7 +2492,7 @@ a \Def{character class} is used to represent a set of characters.
The following combinations are allowed in describing a character class:
\begin{description}
\item[\emph{x}] (where \emph{x} is any character not in the list
\verb|()%.[]*-?|)
\verb|^$()%.[]*+-?|)
--- represents the character \emph{x} itself.
\item[\T{.}] --- (a dot) represents all characters.
\item[\T{\%a}] --- represents all letters.
@@ -2505,6 +2508,8 @@ The following combinations are allowed in describing a character class:
\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.
@@ -2531,7 +2536,7 @@ In particular, the class \verb|[a-z]| may not be equivalent to \verb|%l|.
The second form should be preferred for more portable programs.
\paragraph{Pattern Item:}
a \Def{pattern item} may be:
a \Def{pattern item} may be
\begin{itemize}
\item
a single character class,
@@ -2539,12 +2544,16 @@ which matches any single character in the class;
\item
a single character class followed by \verb|*|,
which matches 0 or more repetitions of characters in the class.
These repetition items will always match the longest possible sequence.
These repetition items will always match the longest possible sequence;
\item
a single character class followed by \verb|+|,
which matches 1 or more repetitions of characters in the class.
These repetition items will always match the longest possible sequence;
\item
a single character class followed by \verb|-|,
which also matches 0 or more repetitions of characters in the class.
Unlike \verb|*|,
these repetition items will always match the shortest possible sequence.
these repetition items will always match the shortest possible sequence;
\item
a single character class followed by \verb|?|,
which matches 0 or 1 occurrence of a character in the class;
@@ -2802,7 +2811,7 @@ it uses a default pattern that reads the next line
A \Def{read pattern} is a sequence of read pattern items.
An item may be a single character class
or a character class followed by \verb|?| or by \verb|*|.
or a character class followed by \verb|?|, by \verb|*|, or by \verb|+|.
A single character class reads the next character from the input
if it belongs to the class, otherwise it fails.
A character class followed by \verb|?| reads the next character
@@ -2811,6 +2820,9 @@ it never fails.
A character class followed by \verb|*| reads until a character that
does not belong to the class, or end of file;
since it can match a sequence of zero characters, it never fails.
A character class followed by \verb|+| reads until a character that
does not belong to the class, or end of file;
it fails if it cannot read at least one character.
Note that the behavior of read patterns is slightly different from
the regular pattern matching behavior,
where a \verb|*| expands to the maximum length \emph{such that}
@@ -2836,7 +2848,7 @@ It is equivalent to the pattern \verb|".*"|.
\item[``*w''] returns the next word
(maximal sequence of non white-space characters),
skipping spaces if necessary, or \nil\ on end of file.
It is equivalent to the pattern \verb|"{%s*}%S%S*"|.
It is equivalent to the pattern \verb|"{%s*}%S+"|.
\end{description}
\subsubsection*{\ff \T{write ([filehandle, ] value1, ...)}}\Deffunc{write}