mirror of
https://github.com/lua/lua.git
synced 2026-07-30 18:09:05 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16024861bd | ||
|
|
3f43aaa23f | ||
|
|
3b4c831ca9 | ||
|
|
3fdab3981b | ||
|
|
88b65da4d7 | ||
|
|
521b38532a | ||
|
|
36b6fe8d17 | ||
|
|
d4dce57f5c | ||
|
|
5c19ed2a13 | ||
|
|
5caf7f4a33 | ||
|
|
3b533ea7c7 | ||
|
|
995775e1cb | ||
|
|
abfc885079 | ||
|
|
613b60c156 | ||
|
|
cdd0fe9946 | ||
|
|
bc8619342a | ||
|
|
48326500d0 | ||
|
|
c8d219798a | ||
|
|
34695d4f4a | ||
|
|
924bbe020b | ||
|
|
3aa500b524 | ||
|
|
f1861ee210 | ||
|
|
705eae9fe4 | ||
|
|
6eb1399a1c | ||
|
|
c390f73e3b | ||
|
|
73308c7605 | ||
|
|
288fa05602 | ||
|
|
7808ea3a5f | ||
|
|
732741b62f | ||
|
|
cc0f635ef7 |
31
bugs
31
bugs
@@ -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
59
lapi.c
@@ -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);
|
||||
|
||||
52
lbuiltin.c
52
lbuiltin.c
@@ -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
106
ldo.c
@@ -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
5
ldo.h
@@ -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);
|
||||
|
||||
63
liolib.c
63
liolib.c
@@ -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
27
llex.c
@@ -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
6
llex.h
@@ -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. */
|
||||
|
||||
|
||||
@@ -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
95
lmem.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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" */
|
||||
|
||||
94
lparser.c
94
lparser.c
@@ -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;
|
||||
|
||||
4
lstate.c
4
lstate.c
@@ -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
|
||||
|
||||
20
lstate.h
20
lstate.h
@@ -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
253
lstrlib.c
@@ -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;
|
||||
|
||||
5
ltable.c
5
ltable.c
@@ -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
5
ltm.c
@@ -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
11
lua.c
@@ -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
4
lua.h
@@ -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"
|
||||
|
||||
|
||||
5
lualib.h
5
lualib.h
@@ -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
|
||||
|
||||
|
||||
97
lundump.c
97
lundump.c
@@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
17
lundump.h
17
lundump.h
@@ -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
23
lvm.c
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
62
manual.tex
62
manual.tex
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user