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. >> started only in the 2nd line of a function.
--- Version 3.1 alpha --- Version 3.1 alpha
** lua.c ** lua.c
@@ -13,7 +14,7 @@ Thu Jan 15 14:34:58 EDT 1998
** lbuiltin.c / lobject.h ** lbuiltin.c / lobject.h
Thu Jan 15 14:34:58 EDT 1998 Thu Jan 15 14:34:58 EDT 1998
>> MAX_WORD may be bigger than MAX_INT >> MAX_WORD may be bigger than MAX_INT
(by lhf)
** llex.c ** llex.c
Mon Jan 19 18:17:18 EDT 1998 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. >> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
--- Version 3.1 --- Version 3.1
** liolib.c / lauxlib.c ** liolib.c / lauxlib.c
@@ -52,11 +54,13 @@ of view) when functions have upvalues.
** lstrlib.c ** lstrlib.c
Tue Nov 10 17:29:36 EDT 1998 Tue Nov 10 17:29:36 EDT 1998
>> gsub/strfind do not check whether captures are properly finished. >> gsub/strfind do not check whether captures are properly finished.
(by roberto/tomas)
** lbuiltin.c ** lbuiltin.c
Fri Dec 18 11:22:55 EDT 1998 Fri Dec 18 11:22:55 EDT 1998
>> "tonumber" goes crazy with negative numbers in other bases (not 10), >> "tonumber" goes crazy with negative numbers in other bases (not 10),
because "strtol" returns long, not unsigned long. because "strtol" returns long, not unsigned long.
(by Visual C++)
** lstrlib.c ** lstrlib.c
Mon Jan 4 10:41:40 EDT 1999 Mon Jan 4 10:41:40 EDT 1999
@@ -70,8 +74,31 @@ lua_isnumber can modify it.
** lstrlib.c ** lstrlib.c
Thu Feb 4 17:08:50 EDT 1999 Thu Feb 4 17:08:50 EDT 1999
>> format "%s" may break limit of "sprintf" on some machines. >> format "%s" may break limit of "sprintf" on some machines.
(by Marcelo Sales)
** lzio.c ** lzio.c
Thu Mar 4 11:49:37 EST 1999 Thu Mar 4 11:49:37 EST 1999
>> file stream cannot call fread after EOF. >> 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 ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -131,7 +131,7 @@ int lua_callfunction (lua_Object function)
else { else {
luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base); luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
set_normalized(L->stack.stack+L->Cstack.base, Address(function)); 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); checkCparams(2);
if (ttype(L->stack.top-2) != LUA_T_ARRAY) if (ttype(L->stack.top-2) != LUA_T_ARRAY)
lua_error("indexed expression not a table in rawgettable"); 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-2) = *luaH_get(avalue(L->stack.top-2), L->stack.top-1); --L->stack.top;
--L->stack.top;
}
return put_luaObjectonTop(); return put_luaObjectonTop();
} }
@@ -368,14 +365,11 @@ void luaA_pushobject (TObject *o)
incr_top; incr_top;
} }
void lua_pushobject (lua_Object o) void lua_pushobject (lua_Object o) {
{
if (o == LUA_NOOBJECT) if (o == LUA_NOOBJECT)
lua_error("API error - attempt to push a NOOBJECT"); lua_error("API error - attempt to push a NOOBJECT");
else { set_normalized(L->stack.top, Address(o));
set_normalized(L->stack.top, Address(o)); incr_top;
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) { void lua_funcinfo (lua_Object func, char **source, int *linedefined) {
if (!lua_isfunction(func)) 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 { else {
TObject *f = luaA_protovalue(Address(func)); TObject *f = luaA_protovalue(Address(func));
if (normalized_type(f) == LUA_T_PROTO) { if (normalized_type(f) == LUA_T_PROTO) {
@@ -637,16 +631,19 @@ char *lua_getobjname (lua_Object o, char **name)
*/ */
void lua_beginblock (void) #ifndef MAX_C_BLOCKS
{ #define MAX_C_BLOCKS 1000 /* arbitrary limit */
if (L->numCblocks >= MAX_C_BLOCKS) #endif
lua_error("too many nested blocks");
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->Cblocks[L->numCblocks] = L->Cstack;
L->numCblocks++; L->numCblocks++;
} }
void lua_endblock (void) void lua_endblock (void) {
{
--L->numCblocks; --L->numCblocks;
L->Cstack = L->Cblocks[L->numCblocks]; L->Cstack = L->Cblocks[L->numCblocks];
luaD_adjusttop(L->Cstack.base); 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; int ref;
checkCparams(1); checkCparams(1);
ref = luaC_ref(L->stack.top-1, lock); 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); TObject *o = luaC_getref(ref);
return (o ? put_luaObject(o) : LUA_NOOBJECT); return (o ? put_luaObject(o) : LUA_NOOBJECT);
} }
@@ -680,17 +675,15 @@ lua_Object lua_getref (int ref)
** API: set a function as a fallback ** API: set a function as a fallback
*/ */
static void do_unprotectedrun (lua_CFunction f, int nParams, int nResults) static void do_unprotectedrun (lua_CFunction f, int nParams, int nResults) {
{
StkId base = (L->stack.top-L->stack.stack)-nParams;
luaD_openstack(nParams); luaD_openstack(nParams);
L->stack.stack[base].ttype = LUA_T_CPROTO; (L->stack.top-nParams)->ttype = LUA_T_CPROTO;
L->stack.stack[base].value.f = f; (L->stack.top-nParams)->value.f = f;
luaD_call(base+1, nResults); 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_pushstring(name);
lua_pushcfunction(fallback); lua_pushcfunction(fallback);
do_unprotectedrun(luaT_setfallback, 2, 1); 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 ** Built-in functions
** See Copyright Notice in lua.h ** 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 ** model but changing "fputs" to put the strings at a proper place
** (a console window or a log file, for instance). ** (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) { static void luaB_print (void) {
lua_Object args[MAXPRINT]; lua_Object args[MAXPRINT];
lua_Object obj; lua_Object obj;
@@ -389,12 +392,16 @@ static void luaB_assert (void) {
static void luaB_foreachi (void) { static void luaB_foreachi (void) {
Hash *t = gethash(1); Hash *t = gethash(1);
TObject *f = luaA_Address(luaL_functionarg(2));
int i; int i;
int n = (int)getnarg(t); 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 */ luaD_checkstack(3); /* for f, ref, and val */
for (i=1; i<=n; i++) { 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; ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i;
*(L->stack.top++) = *luaH_getint(t, i); *(L->stack.top++) = *luaH_getint(t, i);
luaD_calln(2, 1); luaD_calln(2, 1);
@@ -407,13 +414,14 @@ static void luaB_foreachi (void) {
static void luaB_foreach (void) { static void luaB_foreach (void) {
Hash *a = gethash(1); Hash *a = gethash(1);
TObject *f = luaA_Address(luaL_functionarg(2));
int i; int i;
TObject f; /* see comment in 'foreachi' */
f = *luaA_Address(luaL_functionarg(2));
luaD_checkstack(3); /* for f, ref, and val */ luaD_checkstack(3); /* for f, ref, and val */
for (i=0; i<a->nhash; i++) { for (i=0; i<a->nhash; i++) {
Node *nd = &(a->node[i]); Node *nd = &(a->node[i]);
if (ttype(val(nd)) != LUA_T_NIL) { if (ttype(val(nd)) != LUA_T_NIL) {
*(L->stack.top++) = *f; *(L->stack.top++) = f;
*(L->stack.top++) = *ref(nd); *(L->stack.top++) = *ref(nd);
*(L->stack.top++) = *val(nd); *(L->stack.top++) = *val(nd);
luaD_calln(2, 1); luaD_calln(2, 1);
@@ -426,14 +434,15 @@ static void luaB_foreach (void) {
static void luaB_foreachvar (void) { static void luaB_foreachvar (void) {
TObject *f = luaA_Address(luaL_functionarg(1));
GCnode *g; 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 */ luaD_checkstack(4); /* for extra var name, f, var name, and globalval */
for (g = L->rootglobal.next; g; g = g->next) { for (g = L->rootglobal.next; g; g = g->next) {
TaggedString *s = (TaggedString *)g; TaggedString *s = (TaggedString *)g;
if (s->u.s.globalval.ttype != LUA_T_NIL) { if (s->u.s.globalval.ttype != LUA_T_NIL) {
pushtagstring(s); /* keep (extra) s on stack to avoid GC */ pushtagstring(s); /* keep (extra) s on stack to avoid GC */
*(L->stack.top++) = *f; *(L->stack.top++) = f;
pushtagstring(s); pushtagstring(s);
*(L->stack.top++) = s->u.s.globalval; *(L->stack.top++) = s->u.s.globalval;
luaD_calln(2, 1); luaD_calln(2, 1);
@@ -464,10 +473,10 @@ static void luaB_tinsert (void) {
v = luaL_nonnullarg(2); v = luaL_nonnullarg(2);
pos = n+1; pos = n+1;
} }
luaV_setn(a, n+1); /* increment field "n" */ luaV_setn(a, n+1); /* a.n = n+1 */
for ( ;n>=pos; n--) for ( ;n>=pos; n--)
luaH_move(a, n, n+1); luaH_move(a, n, n+1); /* a[n+1] = a[n] */
luaH_setint(a, pos, luaA_Address(v)); 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 n = (int)getnarg(a);
int pos = luaL_opt_int(2, n); int pos = luaL_opt_int(2, n);
if (n <= 0) return; /* table is "empty" */ if (n <= 0) return; /* table is "empty" */
luaA_pushobject(luaH_getint(a, pos)); /* push result */ luaA_pushobject(luaH_getint(a, pos)); /* result = a[pos] */
luaV_setn(a, n-1); /* decrement field "n" */
for ( ;pos<n; 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); 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 */ /* notice: the caller (auxsort) must check stack space */
if (f) { if (f != LUA_NOOBJECT) {
*(L->stack.top) = *f; *(L->stack.top) = *luaA_Address(f);
*(L->stack.top+1) = *a; *(L->stack.top+1) = *a;
*(L->stack.top+2) = *b; *(L->stack.top+2) = *b;
L->stack.top += 3; 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; 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 */ while (l < u) { /* for tail recursion */
TObject *P; TObject *P;
int i, j; int i, j;
@@ -560,10 +570,10 @@ static void luaB_sort (void) {
Hash *a = gethash(1); Hash *a = gethash(1);
int n = (int)getnarg(a); int n = (int)getnarg(a);
lua_Object func = lua_getparam(2); lua_Object func = lua_getparam(2);
TObject *f = luaA_Address(func); luaL_arg_check(func == LUA_NOOBJECT || lua_isfunction(func), 2,
luaL_arg_check(!f || lua_isfunction(func), 2, "function expected"); "function expected");
luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */ luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */
auxsort(a, 1, n, f); auxsort(a, 1, n, func);
lua_pushobject(t); 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 ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -29,7 +29,7 @@
#ifndef STACK_LIMIT #ifndef STACK_LIMIT
#define STACK_LIMIT 6000 #define STACK_LIMIT 6000 /* arbitrary limit */
#endif #endif
@@ -37,6 +37,12 @@
#define STACK_UNIT 128 #define STACK_UNIT 128
#ifdef DEBUG
#undef STACK_UNIT
#define STACK_UNIT 2
#endif
void luaD_init (void) { void luaD_init (void) {
L->stack.stack = luaM_newvector(STACK_UNIT, TObject); L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
L->stack.top = L->stack.stack; 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. ** 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, luaO_memup(L->stack.top-nelems+1, L->stack.top-nelems,
nelems*sizeof(TObject)); nelems*sizeof(TObject));
incr_top; incr_top;
} }
void luaD_lineHook (int line) void luaD_lineHook (int line) {
{
struct C_Lua_Stack oldCLS = L->Cstack; struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0; 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; struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0; 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 ** Cstack.num is the number of arguments; Cstack.lua2C points to the
** first argument. Returns an index to the first result from C. ** first argument. Returns an index to the first result from C.
*/ */
static StkId callC (lua_CFunction f, StkId base) static StkId callC (lua_CFunction f, StkId base) {
{ struct C_Lua_Stack *cls = &L->Cstack;
struct C_Lua_Stack *CS = &L->Cstack; struct C_Lua_Stack oldCLS = *cls;
struct C_Lua_Stack oldCLS = *CS;
StkId firstResult; StkId firstResult;
int numarg = (L->stack.top-L->stack.stack) - base; int numarg = (L->stack.top-L->stack.stack) - base;
CS->num = numarg; cls->num = numarg;
CS->lua2C = base; cls->lua2C = base;
CS->base = base+numarg; /* == top-stack */ cls->base = base+numarg; /* == top-stack */
if (L->callhook) if (L->callhook)
luaD_callHook(base, NULL, 0); luaD_callHook(base, NULL, 0);
(*f)(); /* do the actual call */ (*f)(); /* do the actual call */
if (L->callhook) /* func may have changed callhook */ if (L->callhook) /* func may have changed callhook */
luaD_callHook(base, NULL, 1); luaD_callHook(base, NULL, 1);
firstResult = CS->base; firstResult = cls->base;
*CS = oldCLS; *cls = oldCLS;
return firstResult; 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; TObject *pbase;
int nup = cl->nelems; /* number of upvalues */ int nup = cl->nelems; /* number of upvalues */
luaD_checkstack(nup); 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, ** Call a function (C or Lua). The parameters must be on the stack,
** between [L->stack.stack+base,L->stack.top). The function to be called is at L->stack.stack+base-1. ** between [top-nArgs,top). The function to be called is right below the
** When returns, the results are on the L->stack.stack, between [L->stack.stack+base-1,L->stack.top). ** arguments.
** When returns, the results are on the stack, between [top-nArgs-1,top).
** The number of results is nResults, unless nResults=MULT_RET. ** 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; StkId firstResult;
TObject *func = L->stack.stack+base-1;
int i; int i;
switch (ttype(func)) { switch (ttype(func)) {
case LUA_T_CPROTO: case LUA_T_CPROTO:
@@ -199,24 +202,20 @@ void luaD_call (StkId base, int nResults)
TObject *im = luaT_getimbyObj(func, IM_FUNCTION); TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
if (ttype(im) == LUA_T_NIL) if (ttype(im) == LUA_T_NIL)
lua_error("call expression not a function"); 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; return;
} }
} }
/* adjust the number of results */ /* adjust the number of results */
if (nResults != MULT_RET) if (nResults == MULT_RET)
nResults = (S->top-S->stack)-firstResult;
else
luaD_adjusttop(firstResult+nResults); luaD_adjusttop(firstResult+nResults);
/* move results to base-1 (to erase parameters and function) */ /* move results to base-1 (to erase parameters and function) */
base--; base--;
nResults = L->stack.top - (L->stack.stack+firstResult); /* actual number of results */
for (i=0; i<nResults; i++) for (i=0; i<nResults; i++)
*(L->stack.stack+base+i) = *(L->stack.stack+firstResult+i); *(S->stack+base+i) = *(S->stack+firstResult+i);
L->stack.top -= firstResult-base; S->top -= firstResult-base;
}
void luaD_calln (int nArgs, int nResults) {
luaD_call((L->stack.top-L->stack.stack)-nArgs, nResults);
} }
@@ -249,39 +248,30 @@ static void message (char *s) {
void lua_error (char *s) { void lua_error (char *s) {
if (s) message(s); if (s) message(s);
if (L->errorJmp) if (L->errorJmp)
longjmp(*((jmp_buf *)L->errorJmp), 1); longjmp(L->errorJmp->b, 1);
else { else {
message("exit(1). Unable to recover.\n"); message("exit(1). Unable to recover.\n");
exit(1); 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 ** Execute a protected call. Assumes that function is at L->Cstack.base and
** parameters are on top of it. Leave nResults on the stack. ** 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; volatile struct C_Lua_Stack oldCLS = L->Cstack;
jmp_buf myErrorJmp; struct lua_longjmp myErrorJmp;
volatile int status; volatile int status;
jmp_buf *volatile oldErr = L->errorJmp; struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp; L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp) == 0) { if (setjmp(myErrorJmp.b) == 0) {
do_callinc(nResults); 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; status = 0;
} }
else { /* an error occurred: restore L->Cstack and L->stack.top */ 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) { static int protectedparser (ZIO *z, int bin) {
volatile struct C_Lua_Stack oldCLS = L->Cstack; volatile struct C_Lua_Stack oldCLS = L->Cstack;
jmp_buf myErrorJmp; struct lua_longjmp myErrorJmp;
volatile int status; volatile int status;
TProtoFunc *volatile tf; TProtoFunc *volatile tf;
jmp_buf *volatile oldErr = L->errorJmp; struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp; L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp) == 0) { if (setjmp(myErrorJmp.b) == 0) {
tf = bin ? luaU_undump1(z) : luaY_parser(z); tf = bin ? luaU_undump1(z) : luaY_parser(z);
status = 0; status = 0;
} }
@@ -336,7 +326,7 @@ static int do_main (ZIO *z, int bin) {
else { else {
unsigned long newelems2 = 2*(L->nblocks-old_blocks); unsigned long newelems2 = 2*(L->nblocks-old_blocks);
L->GCthreshold += newelems2; L->GCthreshold += newelems2;
status = luaD_protectedrun(MULT_RET); status = luaD_protectedrun();
L->GCthreshold -= newelems2; L->GCthreshold -= newelems2;
} }
} while (bin && status == 0); } 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 ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -35,10 +35,9 @@ void luaD_adjusttop (StkId newtop);
void luaD_openstack (int nelems); void luaD_openstack (int nelems);
void luaD_lineHook (int line); void luaD_lineHook (int line);
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn); 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_calln (int nArgs, int nResults);
void luaD_callTM (TObject *f, int nParams, 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_gcIM (TObject *o);
void luaD_travstack (int (*fn)(TObject *)); void luaD_travstack (int (*fn)(TObject *));
void luaD_checkstack (int n); 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 ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** 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) { static void setreturn (FILE *f, char *name) {
int tag = gettag(); if (f == NULL)
setfile(f, name, tag); pushresult(0);
lua_pushusertag(f, tag); else {
int tag = gettag();
setfile(f, name, tag);
lua_pushusertag(f, tag);
}
} }
@@ -175,10 +179,6 @@ static void io_readfrom (void) {
else { else {
char *s = luaL_check_string(FIRSTARG); char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
if (current == NULL) {
pushresult(0);
return;
}
} }
setreturn(current, FINPUT); setreturn(current, FINPUT);
} }
@@ -196,21 +196,14 @@ static void io_writeto (void) {
else { else {
char *s = luaL_check_string(FIRSTARG); char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w"); current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w");
if (current == NULL) {
pushresult(0);
return;
}
} }
setreturn(current, FOUTPUT); setreturn(current, FOUTPUT);
} }
static void io_appendto (void) { static void io_appendto (void) {
FILE *fp = fopen(luaL_check_string(FIRSTARG), "a"); FILE *current = fopen(luaL_check_string(FIRSTARG), "a");
if (fp != NULL) setreturn(current, FOUTPUT);
setreturn(fp, FOUTPUT);
else
pushresult(0);
} }
@@ -244,23 +237,25 @@ static int read_pattern (FILE *f, char *p) {
p++; p++;
continue; continue;
default: { default: {
char *ep; /* get what is next */ char *ep = luaI_classend(p); /* get what is next */
int m; /* match result */ int m; /* match result */
if (c == NEED_OTHER) c = getc(f); if (c == NEED_OTHER) c = getc(f);
if (c != EOF) m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
m = luaI_singlematch(c, p, &ep);
else {
luaI_singlematch(0, p, &ep); /* to set "ep" */
m = 0; /* EOF matches no pattern */
}
if (m) { if (m) {
if (!inskip) luaL_addchar(c); if (!inskip) luaL_addchar(c);
c = NEED_OTHER; c = NEED_OTHER;
} }
switch (*ep) { switch (*ep) {
case '*': /* repetition */ case '+': /* repetition (1 or more) */
if (!m) p = ep+1; /* else stay in (repeat) the same item */ if (!m) goto break_while; /* pattern fails? */
continue; /* 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 */ case '?': /* optional */
p = ep+1; /* continues reading the pattern */ p = ep+1; /* continues reading the pattern */
continue; continue;
@@ -336,7 +331,7 @@ static void io_read (void) {
success = 1; /* always success */ success = 1; /* always success */
break; break;
case 4: /* word */ case 4: /* word */
success = read_pattern(f, "{%s*}%S%S*"); success = read_pattern(f, "{%s*}%S+");
break; break;
default: default:
success = read_pattern(f, p); success = read_pattern(f, p);
@@ -475,7 +470,7 @@ static void io_debug (void) {
#define MAXMESSAGE (MESSAGESIZE*10) #define MAXMESSAGE (MESSAGESIZE*10)
#define MAXSRC 40 #define MAXSRC 60
static void errorfb (void) { static void errorfb (void) {
@@ -492,7 +487,7 @@ static void errorfb (void) {
lua_funcinfo(func, &chunkname, &linedefined); lua_funcinfo(func, &chunkname, &linedefined);
luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk)); luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk));
if (level == 2) strcat(buff, "Active Stack:\n"); if (level == 2) strcat(buff, "Active Stack:\n");
strcat(buff, "\t"); strcat(buff, " ");
if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) { if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) {
strcat(buff, "...\n"); strcat(buff, "...\n");
break; /* buffer is full */ break; /* buffer is full */
@@ -506,11 +501,11 @@ static void errorfb (void) {
break; break;
default: { default: {
if (linedefined == 0) if (linedefined == 0)
sprintf(buff+strlen(buff), "main of %.50s", buffchunk); sprintf(buff+strlen(buff), "main of %.70s", buffchunk);
else if (linedefined < 0) else if (linedefined < 0)
sprintf(buff+strlen(buff), "%.50s", buffchunk); sprintf(buff+strlen(buff), "%.70s", buffchunk);
else else
sprintf(buff+strlen(buff), "function <%d:%.50s>", sprintf(buff+strlen(buff), "function <%d:%.70s>",
linedefined, buffchunk); linedefined, buffchunk);
chunkname = NULL; chunkname = NULL;
} }
@@ -518,7 +513,7 @@ static void errorfb (void) {
if ((currentline = lua_currentline(func)) > 0) if ((currentline = lua_currentline(func)) > 0)
sprintf(buff+strlen(buff), " at line %d", currentline); sprintf(buff+strlen(buff), " at line %d", currentline);
if (chunkname) if (chunkname)
sprintf(buff+strlen(buff), " [%.50s]", buffchunk); sprintf(buff+strlen(buff), " [%.70s]", buffchunk);
strcat(buff, "\n"); strcat(buff, "\n");
} }
func = lua_rawgetglobal("_ALERT"); 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 ** Lexical Analyzer
** See Copyright Notice in lua.h ** 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) { void luaX_syntaxerror (LexState *ls, char *s, char *token) {
char buff[MAXSRC]; char buff[MAXSRC];
luaL_chunkid(buff, zname(ls->lex_z), sizeof(buff)); luaL_chunkid(buff, zname(ls->lex_z), sizeof(buff));
if (token[0] == '\0') if (token[0] == '\0')
token = "<eof>"; 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); s, token, ls->linenumber, buff);
} }
@@ -70,7 +70,7 @@ void luaX_token2str (int token, char *s) {
static void luaX_invalidchar (LexState *ls, int c) { static void luaX_invalidchar (LexState *ls, int c) {
char buff[10]; char buff[8];
sprintf(buff, "0x%02X", c); sprintf(buff, "0x%02X", c);
luaX_syntaxerror(ls, "invalid control char", buff); 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') while (LS->current == ' ' || LS->current == '\t' || LS->current == '\r')
next(LS); next(LS);
} }
static int checkcond (LexState *LS, char *buff) static int checkcond (LexState *LS, char *buff) {
{
static char *opts[] = {"nil", "1", NULL}; static char *opts[] = {"nil", "1", NULL};
int i = luaL_findstring(buff, opts); int i = luaL_findstring(buff, opts);
if (i >= 0) return i; 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; int i = 0;
skipspace(LS); skipspace(LS);
while (isalnum(LS->current) || LS->current == '_') { while (isalnum(LS->current) || LS->current == '_') {
@@ -148,8 +147,7 @@ static void readname (LexState *LS, char *buff)
static void inclinenumber (LexState *LS); static void inclinenumber (LexState *LS);
static void ifskip (LexState *LS) static void ifskip (LexState *LS) {
{
while (LS->ifstate[LS->iflevel].skip) { while (LS->ifstate[LS->iflevel].skip) {
if (LS->current == '\n') if (LS->current == '\n')
inclinenumber(LS); inclinenumber(LS);
@@ -160,8 +158,7 @@ static void ifskip (LexState *LS)
} }
static void inclinenumber (LexState *LS) static void inclinenumber (LexState *LS) {
{
static char *pragmas [] = static char *pragmas [] =
{"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL}; {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
next(LS); /* skip '\n' */ 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 ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -25,7 +25,9 @@ enum RESERVED {
NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS}; 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. */ /* "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 ** Lua standard mathematical library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -13,6 +13,7 @@
#include "lualib.h" #include "lualib.h"
#undef PI
#define PI (3.14159265358979323846) #define PI (3.14159265358979323846)
#define RADIANS_PER_DEGREE (PI/180.0) #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 ** Interface to Memory Manager
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -22,12 +22,10 @@
#endif #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) { static unsigned long power2 (unsigned long n) {
unsigned long p = MINSIZE; 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, void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
char *errormsg, unsigned long limit) { char *errormsg, unsigned long limit) {
unsigned long newn = nelems+inc; unsigned long newn = nelems+inc;
if (newn >= limit) lua_error(errormsg);
if ((newn ^ nelems) <= nelems || /* still the same power of 2 limit? */ if ((newn ^ nelems) <= nelems || /* still the same power of 2 limit? */
(nelems > 0 && newn < MINSIZE)) /* or block already is MINSIZE? */ (nelems > 0 && newn < MINSIZE)) /* or block already is MINSIZE? */
return block; /* do not need to reallocate */ return block; /* do not need to reallocate */
else { /* it crossed a power of 2 boundary; grow to next power */ else /* it crossed a power of 2 boundary; grow to next power */
if (newn >= limit) return luaM_realloc(block, power2(newn)*size);
lua_error(errormsg);
newn = power2(newn);
if (newn > limit)
newn = limit;
return luaM_realloc(block, newn*size);
}
} }
#ifndef DEBUG
/* /*
** generic allocation routine. ** generic allocation routine.
*/ */
@@ -78,57 +73,67 @@ void *luaM_realloc (void *block, unsigned long size) {
#include <string.h> #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 HEADER (sizeof(double))
#define MARKSIZE 16
#define MARK 55 #define MARK 55
#define blocksize(b) ((unsigned long *)((char *)(b) - HEADER))
unsigned long numblocks = 0; unsigned long numblocks = 0;
unsigned long totalmem = 0; unsigned long totalmem = 0;
static void *checkblock (void *block) { static void *checkblock (void *block) {
unsigned long *b = (unsigned long *)((char *)block - HEADER); if (block == NULL)
unsigned long size = *b; return NULL;
LUA_ASSERT(*(((char *)b)+size+HEADER) == MARK, else {
"corrupted block"); unsigned long *b = blocksize(block);
numblocks--; unsigned long size = *b;
totalmem -= size; int i;
return b; 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) { 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) if (realsize != (size_t)realsize)
lua_error("memory allocation error: block too big"); lua_error("memory allocation error: block too big");
if (size == 0) { if (size == 0) {
if (block) { freeblock(block);
unsigned long *b = (unsigned long *)((char *)block - HEADER);
memset(block, -1, *b); /* erase block */
block = checkblock(block);
}
free(block);
return NULL; return NULL;
} }
if (block) else {
block = checkblock(block); char *newblock = malloc(realsize);
block = (unsigned long *)realloc(block, realsize); int i;
if (block == NULL) if (block) {
lua_error(memEM); unsigned long oldsize = *blocksize(block);
totalmem += size; if (oldsize > size) oldsize = size;
numblocks++; memcpy(newblock+HEADER, block, oldsize);
*(unsigned long *)block = size; freeblock(block); /* erase (and check) old copy */
*(((char *)block)+size+HEADER) = MARK; }
return (unsigned long *)((char *)block+HEADER); 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 ** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h ** 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 RFIELDS_PER_FLUSH 32 /* records (SETMAP) */
#define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) */ #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" */ /* 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 ** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -22,35 +22,48 @@
#include "lzio.h" #include "lzio.h"
/* for limit numbers in error messages */
#define MES_LIM(x) "(limit=" x ")"
/* size of a "normal" jump instruction: OpCode + 1 byte */ /* size of a "normal" jump instruction: OpCode + 1 byte */
#define JMPSIZE 2 #define JMPSIZE 2
/* maximum number of local variables */ /* maximum number of local variables */
#define MAXLOCALS 32 #ifndef MAXLOCALS
#define SMAXLOCALS "32" #define MAXLOCALS 200 /* arbitrary limit (<256) */
#endif
/* maximum number of upvalues */ /* maximum number of upvalues */
#define MAXUPVALUES 16 #ifndef MAXUPVALUES
#define SMAXUPVALUES "16" #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: ** 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. ** 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; varkind k;
int info; int info;
} vardesc; } vardesc;
@@ -62,7 +75,7 @@ typedef struct {
** and, if last expression is open (a function call), ** and, if last expression is open (a function call),
** where is its pc index of "nparam" ** where is its pc index of "nparam"
*/ */
typedef struct { typedef struct listdesc {
int n; int n;
int pc; /* 0 if last expression is closed */ int pc; /* 0 if last expression is closed */
} listdesc; } listdesc;
@@ -74,7 +87,7 @@ typedef struct {
** it is a list constructor (k = 0) or a record constructor (k = 1) ** it is a list constructor (k = 0) or a record constructor (k = 1)
** or empty (k = ';' or '}') ** or empty (k = ';' or '}')
*/ */
typedef struct { typedef struct constdesc {
int n; int n;
int k; int k;
} constdesc; } 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) { static void check_pc (FuncState *fs, int n) {
luaM_growvector(fs->f->code, fs->pc, n, Byte, codeEM, MAX_INT); 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] = (Byte)op;
code[pc+1] = (Byte)arg; 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] = (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); 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) { static int codesize (int arg) {
if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */ if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */
else if (arg <= MAX_WORD) return 3; /* opcode + 1 word */ else if (arg <= MAX_WORD) return 3; /* opcode + 1 word (2 bytes) */
else return 2+codesize(arg&0xFFFF); /* LONGARG + 1 byte + original opcode */ 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) { static void store_localvar (LexState *ls, TaggedString *name, int n) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
if (fs->nlocalvar+n >= MAXLOCALS) checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables");
luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS));
fs->localvar[fs->nlocalvar+n] = name; fs->localvar[fs->nlocalvar+n] = name;
luaI_registerlocalvar(fs, name, ls->linenumber); luaI_registerlocalvar(fs, name, ls->linenumber);
} }
@@ -361,9 +383,8 @@ static int indexupvalue (LexState *ls, TaggedString *n) {
return i; return i;
} }
/* new one */ /* new one */
if (++(fs->nupvalues) > MAXUPVALUES) ++(fs->nupvalues);
luaX_error(ls, "too many upvalues in a single function " checklimit(ls, fs->nupvalues, MAXUPVALUES, "upvalues");
MES_LIM(SMAXUPVALUES));
fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */ fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */
return i; 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) { static void code_args (LexState *ls, int nparams, int dots) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
fs->nlocalvar += nparams; /* "self" may already be there */ fs->nlocalvar += nparams; /* "self" may already be there */
checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters");
nparams = fs->nlocalvar; nparams = fs->nlocalvar;
if (!dots) { if (!dots) {
fs->f->code[1] = (Byte)nparams; /* fill-in arg information */ fs->f->code[1] = (Byte)nparams; /* fill-in arg information */
@@ -529,7 +551,8 @@ static void func_onstack (LexState *ls, FuncState *func) {
else { else {
for (i=0; i<func->nupvalues; i++) for (i=0; i<func->nupvalues; i++)
lua_pushvar(ls, &func->upvalues[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); 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, static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP,
LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP}; 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 ops[MAXOPS];
int top; int top;
} stack_op; } stack_op;
@@ -1217,6 +1240,7 @@ static void decinit (LexState *ls, listdesc *d) {
static int assignment (LexState *ls, vardesc *v, int nvars) { static int assignment (LexState *ls, vardesc *v, int nvars) {
int left = 0; int left = 0;
checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment");
unloaddot(ls, v); unloaddot(ls, v);
if (ls->token == ',') { /* assignment -> ',' NAME assignment */ if (ls->token == ',') { /* assignment -> ',' NAME assignment */
vardesc nv; 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 ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -32,6 +32,7 @@ void lua_open (void)
L->Mbuffbase = 0; L->Mbuffbase = 0;
L->Mbuffsize = 0; L->Mbuffsize = 0;
L->Mbuffnext = 0; L->Mbuffnext = 0;
L->Cblocks = NULL;
L->numCblocks = 0; L->numCblocks = 0;
L->debug = 0; L->debug = 0;
L->callhook = NULL; L->callhook = NULL;
@@ -73,6 +74,7 @@ void lua_close (void)
luaM_free(L->IMtable); luaM_free(L->IMtable);
luaM_free(L->refArray); luaM_free(L->refArray);
luaM_free(L->Mbuffer); luaM_free(L->Mbuffer);
luaM_free(L->Cblocks);
luaM_free(L); luaM_free(L);
L = NULL; L = NULL;
#ifdef DEBUG #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 ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -14,13 +14,21 @@
#include "luadebug.h" #include "luadebug.h"
#define MAX_C_BLOCKS 10
#define GARBAGE_BLOCK 150 #define GARBAGE_BLOCK 150
typedef int StkId; /* index to stack elements */ 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 { struct Stack {
TObject *top; TObject *top;
TObject *stack; TObject *stack;
@@ -35,7 +43,7 @@ struct C_Lua_Stack {
}; };
typedef struct { typedef struct stringtable {
int size; int size;
int nuse; /* number of elements (including EMPTYs) */ int nuse; /* number of elements (including EMPTYs) */
TaggedString **hash; TaggedString **hash;
@@ -54,12 +62,12 @@ struct lua_State {
/* thread-specific state */ /* thread-specific state */
struct Stack stack; /* Lua stack */ struct Stack stack; /* Lua stack */
struct C_Lua_Stack Cstack; /* C2lua struct */ 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 */ char *Mbuffer; /* global buffer */
int Mbuffbase; /* current first position of Mbuffer */ int Mbuffbase; /* current first position of Mbuffer */
int Mbuffsize; /* size of Mbuffer */ int Mbuffsize; /* size of Mbuffer */
int Mbuffnext; /* next position to fill in 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 numCblocks; /* number of nested Cblocks */
int debug; int debug;
lua_CHFunction callhook; 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 ** Standard library for strings and pattern-matching
** See Copyright Notice in lua.h ** 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 { struct Capture {
char *src_end; /* end ('\0') of source string */ char *src_end; /* end ('\0') of source string */
@@ -130,7 +133,7 @@ struct Capture {
#define ESC '%' #define ESC '%'
#define SPECIALS "^$*?.([%-" #define SPECIALS "^$*+?.([%-"
static void push_captures (struct Capture *cap) { 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) { char *luaI_classend (char *p) {
return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']'); 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) { switch (*p) {
case '.': /* matches any char */ case '.': /* matches any char */
*ep = p+1;
return 1; return 1;
case '\0': /* end of pattern; matches nothing */
*ep = p;
return 0;
case ESC: case ESC:
if (*(++p) == '\0') return matchclass(c, (unsigned char)*(p+1));
luaL_verror("incorrect pattern (ends with `%c')", ESC); case '[':
*ep = p+1; return matchbracketclass(c, p, ep-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;
}
default: default:
*ep = p+1;
return ((unsigned char)*p == c); return ((unsigned char)*p == c);
} }
} }
static char *matchbalance (char *s, int b, int e, struct Capture *cap) { static char *match (char *s, char *p, struct Capture *cap);
if (*s != b) return NULL;
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 { else {
int b = *p;
int e = *(p+1);
int cont = 1; int cont = 1;
while (++s < cap->src_end) { while (++s < cap->src_end) {
if (*s == e) { 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) { static char *max_expand (char *s, char *p, char *ep, struct Capture *cap) {
if (*p == ESC) { int i = 0; /* counts maximum expand for item */
p++; while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep))
if (isdigit((unsigned char)*p)) { /* capture */ i++;
int l = check_cap(*p, cap); /* keeps trying to match mith the maximum repetitions */
int len = cap->capture[l].len; while (i>=0) {
*ep = p+1; char *res = match((s+i), ep+1, cap);
if (cap->src_end-s >= len && memcmp(cap->capture[l].init, s, len) == 0) if (res) return res;
return s+len; i--; /* else didn't match; reduce 1 repetition to try again */
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 */
} }
/* "luaI_singlematch" sets "ep" (so must be called even at the end of "s" */ return NULL;
return (luaI_singlematch((unsigned char)*s, p, ep) && s<cap->src_end) ? }
s+1 : 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) { static char *match (char *s, char *p, struct Capture *cap) {
init: /* using goto's to optimize tail recursion */ init: /* using goto's to optimize tail recursion */
switch (*p) { switch (*p) {
case '(': { /* start capture */ case '(': /* start capture */
char *res; return start_capt(s, p, cap);
if (cap->level >= MAX_CAPT) lua_error("too many captures"); case ')': /* end capture */
cap->capture[cap->level].init = s; return end_capt(s, p, cap);
cap->capture[cap->level].len = -1; case ESC: /* may be %[0-9] or %b */
cap->level++; if (isdigit((unsigned char)(*(p+1)))) { /* capture? */
if ((res=match(s, p+1, cap)) == NULL) /* match failed? */ s = match_capture(s, *(p+1), cap);
cap->level--; /* undo capture */ if (s == NULL) return NULL;
return res; p+=2; goto init; /* else return match(p+2, s, cap) */
} }
case ')': { /* end capture */ else if (*(p+1) == 'b') { /* balanced string? */
int l = capture_to_close(cap); s = matchbalance(s, p+2, cap);
char *res; if (s == NULL) return NULL;
cap->capture[l].len = s - cap->capture[l].init; /* close capture */ p+=4; goto init; /* else return match(p+4, s, cap); */
if ((res = match(s, p+1, cap)) == NULL) /* match failed? */ }
cap->capture[l].len = -1; /* undo capture */ else goto dflt; /* case default */
return res; case '\0': /* end of pattern */
} return s; /* match succeeded */
case '\0': case '$': /* (possibly) end of pattern */ case '$':
if (*p == 0 || (*(p+1) == 0 && s == cap->src_end)) if (*(p+1) == '\0') /* is the '$' the last char in pattern? */
return s; return (s == cap->src_end) ? s : NULL; /* check end of string */
/* else go through */ else goto dflt;
default: { /* it is a pattern item */ default: dflt: { /* it is a pattern item */
char *ep; /* will point to what is next */ char *ep = luaI_classend(p); /* points to what is next */
char *s1 = matchitem(s, p, cap, &ep); int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep);
switch (*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 */ case '?': { /* optional */
char *res; char *res;
if (s1 && ((res=match(s1, ep+1, cap)) != NULL)) if (m && ((res=match(s+1, ep+1, cap)) != NULL))
return res; return res;
p=ep+1; goto init; /* else return match(s, ep+1, cap); */ p=ep+1; goto init; /* else return match(s, ep+1, cap); */
} }
case '-': { /* repetition */ case '*': /* 0 or more repetitions */
char *res; return max_expand(s, p, ep, cap);
if ((res = match(s, ep+1, cap)) != NULL) case '+': /* 1 or more repetitions */
return res; return (m ? max_expand(s+1, p, ep, cap) : NULL);
else if (s1 && s1>s) { case '-': /* 0 or more repetitions (minimum) */
s = s1; return min_expand(s, p, ep, cap);
goto init; /* return match(s1, p, cap); */
}
else
return NULL;
}
default: default:
if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, cap); */ if (!m) return NULL;
else 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') */ /* 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) { static void str_format (void) {
int arg = 1; 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) ** Lua tables (hash)
** See Copyright Notice in lua.h ** 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) if (ttype(ref(n)) != LUA_T_NIL)
*val(n) = *val; *val(n) = *val;
else { 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) { if ((long)nuse(t)*3L > (long)nhash(t)*2L) {
rehash(t); rehash(t);
n = luaH_present(t, ref); 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 ** Tag methods
** See Copyright Notice in lua.h ** 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) { void luaT_settagmethod (int t, char *event, TObject *func) {
TObject temp = *func; TObject temp;
int e = luaI_checkevent(event, luaT_eventname); int e = luaI_checkevent(event, luaT_eventname);
checktag(t); checktag(t);
if (!luaT_validevent(t, e)) if (!luaT_validevent(t, e))
@@ -137,6 +137,7 @@ void luaT_settagmethod (int t, char *event, TObject *func) {
luaT_eventname[e], luaO_typenames[-t], luaT_eventname[e], luaO_typenames[-t],
(t == LUA_T_ARRAY || t == LUA_T_USERDATA) ? " with default tag" (t == LUA_T_ARRAY || t == LUA_T_USERDATA) ? " with default tag"
: ""); : "");
temp = *func;
*func = *luaT_getim(t,e); *func = *luaT_getim(t,e);
*luaT_getim(t, e) = temp; *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 ** Lua stand-alone interpreter
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -15,12 +15,6 @@
#include "lualib.h" #include "lualib.h"
#ifndef OLD_ANSI
#include <locale.h>
#else
#define setlocale(a,b) 0
#endif
#ifdef _POSIX_SOURCE #ifdef _POSIX_SOURCE
#include <unistd.h> #include <unistd.h>
#else #else
@@ -51,6 +45,8 @@ static void lstop (void) {
static void laction (int i) { 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_linehook = lua_setlinehook((lua_LHFunction)lstop);
old_callhook = lua_setcallhook((lua_CHFunction)lstop); old_callhook = lua_setcallhook((lua_CHFunction)lstop);
} }
@@ -131,7 +127,6 @@ int main (int argc, char *argv[])
int i; int i;
lua_open(); lua_open();
lua_pushstring("> "); lua_setglobal("_PROMPT"); lua_pushstring("> "); lua_setglobal("_PROMPT");
setlocale(LC_ALL, "");
lua_userinit(); lua_userinit();
if (argc < 2) { /* no arguments? */ if (argc < 2) { /* no arguments? */
if (isatty(0)) { 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 ** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua@tecgraf.puc-rio.br ** e-mail: lua@tecgraf.puc-rio.br
@@ -11,7 +11,7 @@
#ifndef lua_h #ifndef lua_h
#define 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_COPYRIGHT "Copyright (C) 1994-1999 TeCGraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" #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 ** Lua standard libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -29,7 +29,8 @@ void lua_userinit (void);
/* Auxiliary functions (private) */ /* 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 #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 ** load bytecodes from files
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -15,12 +15,6 @@
#define LoadBlock(b,size,Z) ezread(Z,b,size) #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) static void unexpectedEOZ (ZIO* Z)
{ {
luaL_verror("unexpected end of file in %s",zname(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; return (hi<<16)|lo;
} }
static real LoadNumber (ZIO* Z) /*
* convert number from text
*/
double luaU_str2d (char* b, char* where)
{ {
char b[256]; int negative=(b[0]=='-');
int size=ezgetc(Z); double x=luaO_str2d(b+negative);
LoadBlock(b,size,Z); if (x<0) luaL_verror("cannot convert number '%s' in %s",b,where);
b[size]=0; return negative ? -x : x;
if (b[0]=='-') }
return -luaO_str2d(b+1);
static real LoadNumber (ZIO* Z, int native)
{
real x;
if (native)
{
LoadBlock(&x,sizeof(x),Z);
return x;
}
else 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) static int LoadInt (ZIO* Z, char* message)
@@ -112,9 +123,9 @@ static void LoadLocals (TProtoFunc* tf, ZIO* Z)
tf->locvars[i].varname=NULL; 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"); int i,n=LoadInt(Z,"too many constants (%ld) in %s");
tf->nconsts=n; tf->nconsts=n;
@@ -127,13 +138,13 @@ static void LoadConstants (TProtoFunc* tf, ZIO* Z)
switch (ttype(o)) switch (ttype(o))
{ {
case LUA_T_NUMBER: case LUA_T_NUMBER:
doLoadNumber(nvalue(o),Z); nvalue(o)=LoadNumber(Z,native);
break; break;
case LUA_T_STRING: case LUA_T_STRING:
tsvalue(o)=LoadTString(Z); tsvalue(o)=LoadTString(Z);
break; break;
case LUA_T_PROTO: case LUA_T_PROTO:
tfvalue(o)=LoadFunction(Z); tfvalue(o)=LoadFunction(Z,native);
break; break;
case LUA_T_NIL: case LUA_T_NIL:
break; 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(); TProtoFunc* tf=luaF_newproto();
tf->lineDefined=LoadInt(Z,"lineDefined too large (%ld) in %s"); 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)); if (tf->source==NULL) tf->source=luaS_new(zname(Z));
tf->code=LoadCode(Z); tf->code=LoadCode(Z);
LoadLocals(tf,Z); LoadLocals(tf,Z);
LoadConstants(tf,Z); LoadConstants(tf,Z,native);
return tf; return tf;
} }
@@ -164,9 +175,10 @@ static void LoadSignature (ZIO* Z)
if (*s!=0) luaL_verror("bad signature in %s",zname(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 version,sizeofR;
int native;
LoadSignature(Z); LoadSignature(Z);
version=ezgetc(Z); version=ezgetc(Z);
if (version>VERSION) if (version>VERSION)
@@ -177,36 +189,29 @@ static void LoadHeader (ZIO* Z)
luaL_verror( luaL_verror(
"%s too old: version=0x%02x; expected at least 0x%02x", "%s too old: version=0x%02x; expected at least 0x%02x",
zname(Z),version,VERSION0); zname(Z),version,VERSION0);
sizeofR=ezgetc(Z); /* test number representation */ sizeofR=ezgetc(Z);
#if LUAC_NATIVE native=(sizeofR!=0);
if (sizeofR==0) if (native) /* test number representation */
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
{ {
real f=-TEST_NUMBER,tf=TEST_NUMBER; if (sizeofR!=sizeof(real))
doLoadNumber(f,Z); luaL_verror("unknown number size in %s: read %d; expected %d",
if (f!=tf) zname(Z),sizeofR,sizeof(real));
luaL_verror("unknown number representation in %s: " else
"read " NUMBER_FMT "; expected " NUMBER_FMT, {
zname(Z),f,tf); 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 return native;
if (sizeofR!=0)
luaL_verror("cannot read numbers in %s: "
"support for native format not enabled",
zname(Z));
#endif
} }
static TProtoFunc* LoadChunk (ZIO* Z) static TProtoFunc* LoadChunk (ZIO* Z)
{ {
LoadHeader(Z); return LoadFunction(Z,LoadHeader(Z));
return LoadFunction(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 ** load pre-compiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -13,6 +13,8 @@
TProtoFunc* luaU_undump1 (ZIO* Z); /* load one chunk */ TProtoFunc* luaU_undump1 (ZIO* Z); /* load one chunk */
void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf); void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf);
/* handle cases that cannot happen */ /* handle cases that cannot happen */
double luaU_str2d (char* b, char* where);
/* convert number from text */
/* definitions for headers of binary files */ /* definitions for headers of binary files */
#define VERSION 0x32 /* last format change was in 3.2 */ #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 */ #define NUMBER_FMT "%.16g" /* LUA_NUMBER */
#endif #endif
/* LUA_NUMBER /* a multiple of PI for testing native format */
* 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 */
/* multiplying by 1E8 gives non-trivial integer values */ /* multiplying by 1E8 gives non-trivial integer values */
#define TEST_NUMBER 3.14159265358979323846E8 #define TEST_NUMBER 3.14159265358979323846E8
#endif
#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 ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -214,7 +214,8 @@ void luaV_setglobal (TaggedString *ts) {
else { else {
/* WARNING: caller must assure stack space */ /* WARNING: caller must assure stack space */
struct Stack *S = &L->stack; struct Stack *S = &L->stack;
TObject newvalue = *(S->top-1); TObject newvalue;
newvalue = *(S->top-1);
ttype(S->top-1) = LUA_T_STRING; ttype(S->top-1) = LUA_T_STRING;
tsvalue(S->top-1) = ts; tsvalue(S->top-1) = ts;
*S->top++ = *oldvalue; *S->top++ = *oldvalue;
@@ -341,11 +342,11 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
goto ret; goto ret;
case CALL: aux = *pc++; case CALL: aux = *pc++;
luaD_call((S->top-S->stack)-(*pc++), aux); luaD_calln(*pc++, aux);
break; break;
case TAILCALL: aux = *pc++; case TAILCALL: aux = *pc++;
luaD_call((S->top-S->stack)-(*pc++), MULT_RET); luaD_calln(*pc++, MULT_RET);
base += aux; base += aux;
goto ret; goto ret;
@@ -403,7 +404,8 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
case PUSHSELFW: aux += highbyte(*pc++); case PUSHSELFW: aux += highbyte(*pc++);
case PUSHSELF: aux += *pc++; { case PUSHSELF: aux += *pc++; {
TObject receiver = *(S->top-1); TObject receiver;
receiver = *(S->top-1);
*S->top++ = consts[aux]; *S->top++ = consts[aux];
luaV_gettable(); luaV_gettable();
*S->top++ = receiver; *S->top++ = receiver;
@@ -439,17 +441,17 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
case SETLISTW: aux += highbyte(*pc++); case SETLISTW: aux += highbyte(*pc++);
case SETLIST: aux += *pc++; { case SETLIST: aux += *pc++; {
int n = *(pc++); int n = *(pc++);
TObject *arr = S->top-n-1; Hash *arr = avalue(S->top-n-1);
aux *= LFIELDS_PER_FLUSH; aux *= LFIELDS_PER_FLUSH;
for (; n; n--) for (; n; n--)
luaH_setint(avalue(arr), n+aux, --S->top); luaH_setint(arr, n+aux, --S->top);
break; break;
} }
case SETMAP: aux = *pc++; { case SETMAP: aux = *pc++; {
TObject *arr = S->top-(2*aux)-3; Hash *arr = avalue(S->top-(2*aux)-3);
do { do {
luaH_set(avalue(arr), S->top-2, S->top-1); luaH_set(arr, S->top-2, S->top-1);
S->top-=2; S->top-=2;
} while (aux--); } while (aux--);
break; break;
@@ -620,7 +622,8 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
goto switchentry; /* do not reset "aux" */ goto switchentry; /* do not reset "aux" */
case CHECKSTACK: aux = *pc++; 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; 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} \documentclass[11pt]{article}
\usepackage{fullpage,bnf} \usepackage{fullpage,bnf}
@@ -41,7 +41,7 @@ Waldemar Celes
\tecgraf\ --- Computer Science Department --- PUC-Rio \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 \maketitle
@@ -1719,9 +1719,9 @@ equivalent to the Lua code:
lua_pushnumber(4); /* 3rd argument */ lua_pushnumber(4); /* 3rd argument */
lua_callfunction(lua_getglobal("f")); /* call Lua function */ lua_callfunction(lua_getglobal("f")); /* call Lua function */
lua_pushobject(lua_getresult(1)); /* push first result of the call */ lua_pushobject(lua_getresult(1)); /* push first result of the call */
lua_setglobal("a"); /* sets global variable 'a' */ lua_setglobal("a"); /* set global variable 'a' */
lua_pushobject(lua_getresult(2)); /* push second result of the call */ lua_pushobject(lua_getresult(2)); /* push second result of the call */
lua_setglobal("b"); /* sets global variable 'b' */ lua_setglobal("b"); /* set global variable 'b' */
\end{verbatim} \end{verbatim}
Some special Lua functions have exclusive interfaces. Some special Lua functions have exclusive interfaces.
@@ -2152,10 +2152,11 @@ This function could be defined in Lua:
\begin{verbatim} \begin{verbatim}
function getn (t) function getn (t)
if type(t.n) == 'number' then return t.n end if type(t.n) == 'number' then return t.n end
local i = nil
local max = 0 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 if type(i) == 'number' and i>max then max=i end
i = next(t, i)
end end
return max return max
end end
@@ -2198,10 +2199,11 @@ as the final value of \verb|foreachi|.
This function could be defined in Lua: This function could be defined in Lua:
\begin{verbatim} \begin{verbatim}
function foreachi (t, f) function foreachi (t, f)
local i, n = 0, getn(t) local i, n = 1, getn(t)
while (i=i+1)<=n do while i <= n do
local res = f(i, t[i]) local res = f(i, t[i])
if res then return res end if res then return res end
i = i+1
end end
end end
\end{verbatim} \end{verbatim}
@@ -2279,11 +2281,12 @@ except that the table accesses are all raw (that is, without tag methods):
pos = pos or n pos = pos or n
local value = t[pos] local value = t[pos]
if n<=0 then return end if n<=0 then return end
t.n = n-1
while pos < n do while pos < n do
t[pos] = t[pos+1] t[pos] = t[pos+1]
pos = pos+1 pos = pos+1
end end
t[n] = nil
t.n = n-1
return value return value
end end
\end{verbatim} \end{verbatim}
@@ -2457,27 +2460,27 @@ For instance, when \verb|n| is 1 only the first occurrence of
Here are some examples: Here are some examples:
\begin{verbatim} \begin{verbatim}
x = gsub("hello world", "(%w%w*)", "%1 %1") x = gsub("hello world", "(%w+)", "%1 %1")
--> x="hello hello world world" --> 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="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="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="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" --> x="4+5 = 9"
local t = {name="lua", version="3.1"} local t = {name="lua", version="3.2"}
x = gsub("$name - $version", "$(%w%w*)", function (v) return %t[v] end) x = gsub("$name - $version", "%$(%w+)", function (v) return %t[v] end)
--> x="lua - 3.1" --> x="lua - 3.2"
t = {n=0} 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} --> t={"first", "second", "word"; n=3}
\end{verbatim} \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: The following combinations are allowed in describing a character class:
\begin{description} \begin{description}
\item[\emph{x}] (where \emph{x} is any character not in the list \item[\emph{x}] (where \emph{x} is any character not in the list
\verb|()%.[]*-?|) \verb|^$()%.[]*+-?|)
--- represents the character \emph{x} itself. --- represents the character \emph{x} itself.
\item[\T{.}] --- (a dot) represents all characters. \item[\T{.}] --- (a dot) represents all characters.
\item[\T{\%a}] --- represents all letters. \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) --- \item[\T{\%\M{x}}] (where \M{x} is any non alphanumeric character) ---
represents the character \M{x}. represents the character \M{x}.
This is the standard way to escape the magic characters \verb|()%.[]*-?|. 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]}] --- \item[\T{[char-set]}] ---
Represents the class which is the union of all Represents the class which is the union of all
characters in char-set. 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. The second form should be preferred for more portable programs.
\paragraph{Pattern Item:} \paragraph{Pattern Item:}
a \Def{pattern item} may be: a \Def{pattern item} may be
\begin{itemize} \begin{itemize}
\item \item
a single character class, a single character class,
@@ -2539,12 +2544,16 @@ which matches any single character in the class;
\item \item
a single character class followed by \verb|*|, a single character class followed by \verb|*|,
which matches 0 or more repetitions of characters in the class. 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 \item
a single character class followed by \verb|-|, a single character class followed by \verb|-|,
which also matches 0 or more repetitions of characters in the class. which also matches 0 or more repetitions of characters in the class.
Unlike \verb|*|, Unlike \verb|*|,
these repetition items will always match the shortest possible sequence. these repetition items will always match the shortest possible sequence;
\item \item
a single character class followed by \verb|?|, a single character class followed by \verb|?|,
which matches 0 or 1 occurrence of a character in the class; 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. A \Def{read pattern} is a sequence of read pattern items.
An item may be a single character class 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 A single character class reads the next character from the input
if it belongs to the class, otherwise it fails. if it belongs to the class, otherwise it fails.
A character class followed by \verb|?| reads the next character 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 A character class followed by \verb|*| reads until a character that
does not belong to the class, or end of file; does not belong to the class, or end of file;
since it can match a sequence of zero characters, it never fails. 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 Note that the behavior of read patterns is slightly different from
the regular pattern matching behavior, the regular pattern matching behavior,
where a \verb|*| expands to the maximum length \emph{such that} 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 \item[``*w''] returns the next word
(maximal sequence of non white-space characters), (maximal sequence of non white-space characters),
skipping spaces if necessary, or \nil\ on end of file. 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} \end{description}
\subsubsection*{\ff \T{write ([filehandle, ] value1, ...)}}\Deffunc{write} \subsubsection*{\ff \T{write ([filehandle, ] value1, ...)}}\Deffunc{write}