[Scummvm-cvs-logs] CVS: residual/lua lapi.cpp,NONE,1.1 lapi.h,NONE,1.1 lauxlib.cpp,NONE,1.1 lauxlib.h,NONE,1.1 lbuffer.cpp,NONE,1.1 lbuiltin.cpp,NONE,1.1 lbuiltin.h,NONE,1.1 ldo.cpp,NONE,1.1 ldo.h,NONE,1.1 lfunc.cpp,NONE,1.1 lfunc.h,NONE,1.1 lgc.cpp,NONE,1.1 lgc.h,NONE,1.1 liolib.cpp,NONE,1.1 llex.cpp,NONE,1.1 llex.h,NONE,1.1 lmathlib.cpp,NONE,1.1 lmem.cpp,NONE,1.1 lmem.h,NONE,1.1 lobject.cpp,NONE,1.1 lobject.h,NONE,1.1 lopcodes.h,NONE,1.1 lparser.cpp,NONE,1.1 lparser.h,NONE,1.1 lstate.cpp,NONE,1.1 lstate.h,NONE,1.1 lstring.cpp,NONE,1.1 lstring.h,NONE,1.1 lstrlib.cpp,NONE,1.1 ltable.cpp,NONE,1.1 ltable.h,NONE,1.1 ltask.cpp,NONE,1.1 ltask.h,NONE,1.1 ltm.cpp,NONE,1.1 ltm.h,NONE,1.1 lua.h,NONE,1.1 luadebug.h,NONE,1.1 lualib.h,NONE,1.1 lundump.cpp,NONE,1.1 lundump.h,NONE,1.1 lvm.cpp,NONE,1.1 lvm.h,NONE,1.1 lzio.cpp,NONE,1.1 lzio.h,NONE,1.1 Makefile,1.2,1.3 COPYRIGHT,1.1.1.1,NONE HISTORY,1.1.1.1,NONE INSTALL,1.1.1.1,NONE MANIFEST,1.1.1.1,NONE README,1.1.1.1,NONE config,1.3,NONE

Pawel Kolodziejski aquadran at users.sourceforge.net
Wed Oct 6 12:09:47 CEST 2004


Update of /cvsroot/scummvm/residual/lua
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14388

Modified Files:
	Makefile 
Added Files:
	lapi.cpp lapi.h lauxlib.cpp lauxlib.h lbuffer.cpp lbuiltin.cpp 
	lbuiltin.h ldo.cpp ldo.h lfunc.cpp lfunc.h lgc.cpp lgc.h 
	liolib.cpp llex.cpp llex.h lmathlib.cpp lmem.cpp lmem.h 
	lobject.cpp lobject.h lopcodes.h lparser.cpp lparser.h 
	lstate.cpp lstate.h lstring.cpp lstring.h lstrlib.cpp 
	ltable.cpp ltable.h ltask.cpp ltask.h ltm.cpp ltm.h lua.h 
	luadebug.h lualib.h lundump.cpp lundump.h lvm.cpp lvm.h 
	lzio.cpp lzio.h 
Removed Files:
	COPYRIGHT HISTORY INSTALL MANIFEST README config 
Log Message:
restructured lua sources to flat structure

--- NEW FILE: lapi.cpp ---
/*
** $Id: lapi.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua API
** See Copyright Notice in lua.h
*/


#include <stdlib.h>
#include <string.h>

#include "lapi.h"
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lua.h"
#include "luadebug.h"
#include "lvm.h"


char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
                   "$Autores:  " LUA_AUTHORS " $";



TObject *luaA_Address (lua_Object o)
{
  return Address(o);
}


static int normalized_type (TObject *o)
{
  int t = ttype(o);
  switch (t) {
    case LUA_T_PMARK:
      return LUA_T_PROTO;
    case LUA_T_CMARK:
      return LUA_T_CPROTO;
    case LUA_T_CLMARK:
      return LUA_T_CLOSURE;
    default:
      return t;
  }
}


static void set_normalized (TObject *d, TObject *s)
{
  d->value = s->value;
  d->ttype = (lua_Type)normalized_type(s);
}


static TObject *luaA_protovalue (TObject *o)
{
  return (normalized_type(o) == LUA_T_CLOSURE) ?  protovalue(o) : o;
}


void luaA_packresults (void)
{
  luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
  incr_top;
}


int luaA_passresults (void)
{
  luaD_checkstack(L->Cstack.num);
  memcpy(L->stack.top, L->Cstack.lua2C+L->stack.stack,
         L->Cstack.num*sizeof(TObject));
  L->stack.top += L->Cstack.num;
  return L->Cstack.num;
}


static void checkCparams (int nParams)
{
  if (L->stack.top-L->stack.stack < L->Cstack.base+nParams)
    lua_error("API error - wrong number of arguments in C2lua stack");
}


static lua_Object put_luaObject (TObject *o)
{
  luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
  L->stack.stack[L->Cstack.base++] = *o;
  return L->Cstack.base;  /* this is +1 real position (see Ref) */
}


static lua_Object put_luaObjectonTop (void)
{
  luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
  L->stack.stack[L->Cstack.base++] = *(--L->stack.top);
  return L->Cstack.base;  /* this is +1 real position (see Ref) */
}


lua_Object lua_pop (void)
{
  checkCparams(1);
  return put_luaObjectonTop();
}


/*
** Get a parameter, returning the object handle or LUA_NOOBJECT on error.
** 'number' must be 1 to get the first parameter.
*/
lua_Object lua_lua2C (int number)
{
  if (number <= 0 || number > L->Cstack.num) return LUA_NOOBJECT;
  /* Ref(L->stack.stack+(L->Cstack.lua2C+number-1)) ==
     L->stack.stack+(L->Cstack.lua2C+number-1)-L->stack.stack+1 == */
  return L->Cstack.lua2C+number;
}


int lua_callfunction (lua_Object function)
{
  if (function == LUA_NOOBJECT)
    return 1;
  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);
  }
}


lua_Object lua_gettagmethod (int tag, char *event)
{
  return put_luaObject(luaT_gettagmethod(tag, event));
}


lua_Object lua_settagmethod (int tag, char *event)
{
  checkCparams(1);
  luaT_settagmethod(tag, event, L->stack.top-1);
  return put_luaObjectonTop();
}


lua_Object lua_seterrormethod (void)
{
  TObject temp = L->errorim;
  checkCparams(1);
  L->errorim = *(--L->stack.top);
  return put_luaObject(&temp);
}


lua_Object lua_gettable (void)
{
  checkCparams(2);
  luaV_gettable();
  return put_luaObjectonTop();
}


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 {
    TObject *h = luaH_get(avalue(L->stack.top-2), L->stack.top-1);
    --L->stack.top;
    if (h != NULL)
      *(L->stack.top-1) = *h;
    else
      ttype(L->stack.top-1) = LUA_T_NIL;
  }
  return put_luaObjectonTop();
}


void lua_settable (void)
{
  checkCparams(3);
  luaV_settable(L->stack.top-3, 1);
}


void lua_rawsettable (void)
{
  checkCparams(3);
  luaV_settable(L->stack.top-3, 0);
}


lua_Object lua_createtable (void)
{
  TObject o;
  luaC_checkGC();
  avalue(&o) = luaH_new(0);
  ttype(&o) = LUA_T_ARRAY;
  return put_luaObject(&o);
}


lua_Object lua_getglobal (char *name)
{
  luaD_checkstack(2);  /* may need that to call T.M. */
  luaV_getglobal(luaS_new(name));
  return put_luaObjectonTop();
}


lua_Object lua_rawgetglobal (char *name)
{
  TaggedString *ts = luaS_new(name);
  return put_luaObject(&ts->u.s.globalval);
}


void lua_setglobal (char *name)
{
  checkCparams(1);
  luaD_checkstack(2);  /* may need that to call T.M. */
  luaV_setglobal(luaS_new(name));
}


void lua_rawsetglobal (char *name)
{
  TaggedString *ts = luaS_new(name);
  checkCparams(1);
  luaS_rawsetglobal(ts, --L->stack.top);
}



int lua_isnil (lua_Object o)
{
  return (o == LUA_NOOBJECT) || (ttype(Address(o)) == LUA_T_NIL);
}

int lua_istable (lua_Object o)
{
  return (o!= LUA_NOOBJECT) && (ttype(Address(o)) == LUA_T_ARRAY);
}

int lua_isuserdata (lua_Object o)
{
  return (o!= LUA_NOOBJECT) && (ttype(Address(o)) == LUA_T_USERDATA);
}

int lua_iscfunction (lua_Object o)
{
  return (lua_tag(o) == LUA_T_CPROTO);
}

int lua_isnumber (lua_Object o)
{
  return (o!= LUA_NOOBJECT) && (tonumber(Address(o)) == 0);
}

int lua_isstring (lua_Object o)
{
  int t = lua_tag(o);
  return (t == LUA_T_STRING) || (t == LUA_T_NUMBER);
}

int lua_isfunction (lua_Object o)
{
  int t = lua_tag(o);
  return (t == LUA_T_PROTO) || (t == LUA_T_CPROTO);
}


double lua_getnumber (lua_Object object)
{
 if (object == LUA_NOOBJECT) return 0.0;
 if (tonumber(Address(object))) return 0.0;
 else return (nvalue(Address(object)));
}

char *lua_getstring (lua_Object object)
{
  luaC_checkGC();  /* "tostring" may create a new string */
  if (object == LUA_NOOBJECT || tostring(Address(object)))
    return NULL;
  else return (svalue(Address(object)));
}

long lua_strlen (lua_Object object)
{
  luaC_checkGC();  /* "tostring" may create a new string */
  if (object == LUA_NOOBJECT || tostring(Address(object)))
    return 0L;
  else return (tsvalue(Address(object))->u.s.len);
}

void *lua_getuserdata (lua_Object object)
{
  if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA)
    return NULL;
  else return tsvalue(Address(object))->u.d.v;
}

lua_CFunction lua_getcfunction (lua_Object object)
{
  if (!lua_iscfunction(object))
    return NULL;
  else return fvalue(luaA_protovalue(Address(object)));
}


void lua_pushnil (void)
{
  ttype(L->stack.top) = LUA_T_NIL;
  incr_top;
}

void lua_pushnumber (double n)
{
  ttype(L->stack.top) = LUA_T_NUMBER;
  nvalue(L->stack.top) = n;
  incr_top;
}

void lua_pushlstring (char *s, long len)
{
  tsvalue(L->stack.top) = luaS_newlstr(s, len);
  ttype(L->stack.top) = LUA_T_STRING;
  incr_top;
  luaC_checkGC();
}

void lua_pushstring (char *s)
{
  if (s == NULL)
    lua_pushnil();
  else
    lua_pushlstring(s, strlen(s));
}

void lua_pushcclosure (lua_CFunction fn, int n)
{
  if (fn == NULL)
    lua_error("API error - attempt to push a NULL Cfunction");
  checkCparams(n);
  ttype(L->stack.top) = LUA_T_CPROTO;
  fvalue(L->stack.top) = fn;
  incr_top;
  luaV_closure(n);
  luaC_checkGC();
}

void lua_pushusertag (void *u, int tag)
{
  if (tag < 0 && tag != LUA_ANYTAG)
    luaT_realtag(tag);  /* error if tag is not valid */
  tsvalue(L->stack.top) = luaS_createudata(u, tag);
  ttype(L->stack.top) = LUA_T_USERDATA;
  incr_top;
  luaC_checkGC();
}

void luaA_pushobject (TObject *o)
{
  *L->stack.top = *o;
  incr_top;
}

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;
  }
}


int lua_tag (lua_Object lo)
{
  if (lo == LUA_NOOBJECT)
     return LUA_T_NIL;
  else {
    TObject *o = Address(lo);
    int t;
    switch (t = ttype(o)) {
      case LUA_T_USERDATA:
        return o->value.ts->u.d.tag;
      case LUA_T_ARRAY:
        return o->value.a->htag;
      case LUA_T_PMARK:
        return LUA_T_PROTO;
      case LUA_T_CMARK:
        return LUA_T_CPROTO;
      case LUA_T_CLOSURE: case LUA_T_CLMARK:
        return o->value.cl->consts[0].ttype;
#ifdef DEBUG
      case LUA_T_LINE:
        LUA_INTERNALERROR("invalid type");
#endif
      default:
        return t;
    }
  }
}


void lua_settag (int tag)
{
  checkCparams(1);
  luaT_realtag(tag);
  switch (ttype(L->stack.top-1)) {
    case LUA_T_ARRAY:
      (L->stack.top-1)->value.a->htag = tag;
      break;
    case LUA_T_USERDATA:
      (L->stack.top-1)->value.ts->u.d.tag = tag;
      break;
    default:
      luaL_verror("cannot change the tag of a %.20s",
                  luaO_typenames[-ttype((L->stack.top-1))]);
  }
  L->stack.top--;
}


/*
** =======================================================
** Debug interface
** =======================================================
*/


/* Hooks */
lua_CHFunction lua_callhook = NULL;
lua_LHFunction lua_linehook = NULL;


lua_Function lua_stackedfunction (int level)
{
  StkId i;
  for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) {
    int t = L->stack.stack[i].ttype;
    if (t == LUA_T_CLMARK || t == LUA_T_PMARK || t == LUA_T_CMARK)
      if (level-- == 0)
        return Ref(L->stack.stack+i);
  }
  return LUA_NOOBJECT;
}


int lua_currentline (lua_Function func)
{
  TObject *f = Address(func);
  return (f+1 < L->stack.top && (f+1)->ttype == LUA_T_LINE) ?
             (f+1)->value.i : -1;
}


lua_Object lua_getlocal (lua_Function func, int local_number, char **name)
{
  /* check whether func is a Lua function */
  if (lua_tag(func) != LUA_T_PROTO)
    return LUA_NOOBJECT;
  else {
    TObject *f = Address(func);
    TProtoFunc *fp = luaA_protovalue(f)->value.tf;
    *name = luaF_getlocalname(fp, local_number, lua_currentline(func));
    if (*name) {
      /* if "*name", there must be a LUA_T_LINE */
      /* therefore, f+2 points to function base */
      return Ref((f+2)+(local_number-1));
    }
    else
      return LUA_NOOBJECT;
  }
}


int lua_setlocal (lua_Function func, int local_number)
{
  /* check whether func is a Lua function */
  if (lua_tag(func) != LUA_T_PROTO)
    return 0;
  else {
    TObject *f = Address(func);
    TProtoFunc *fp = luaA_protovalue(f)->value.tf;
    char *name = luaF_getlocalname(fp, local_number, lua_currentline(func));
    checkCparams(1);
    --L->stack.top;
    if (name) {
      /* if "name", there must be a LUA_T_LINE */
      /* therefore, f+2 points to function base */
      *((f+2)+(local_number-1)) = *L->stack.top;
      return 1;
    }
    else
      return 0;
  }
}


void lua_funcinfo (lua_Object func, char **filename, int *linedefined)
{
  if (!lua_isfunction(func))
    lua_error("API - `funcinfo' called with a non-function value");
  else {
    TObject *f = luaA_protovalue(Address(func));
    if (normalized_type(f) == LUA_T_PROTO) {
      *filename = tfvalue(f)->fileName->str;
      *linedefined = tfvalue(f)->lineDefined;
    }
    else {
      *filename = "(C)";
      *linedefined = -1;
    }
  }
}


static int checkfunc (TObject *o)
{
  return luaO_equalObj(o, L->stack.top);
}


char *lua_getobjname (lua_Object o, char **name)
{ /* try to find a name for given function */
  set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc */
  if ((*name = luaT_travtagmethods(checkfunc)) != NULL)
    return "tag-method";
  else if ((*name = luaS_travsymbol(checkfunc)) != NULL)
    return "global";
  else return "";
}

/*
** =======================================================
** BLOCK mechanism
** =======================================================
*/


void lua_beginblock (void)
{
  if (L->numCblocks >= MAX_C_BLOCKS)
    lua_error("too many nested blocks");
  L->Cblocks[L->numCblocks] = L->Cstack;
  L->numCblocks++;
}

void lua_endblock (void)
{
  --L->numCblocks;
  L->Cstack = L->Cblocks[L->numCblocks];
  luaD_adjusttop(L->Cstack.base);
}



int lua_ref (int lock)
{
  int ref;
  checkCparams(1);
  ref = luaC_ref(L->stack.top-1, lock);
  L->stack.top--;
  return ref;
}



lua_Object lua_getref (int ref)
{
  TObject *o = luaC_getref(ref);
  return (o ? put_luaObject(o) : LUA_NOOBJECT);
}


/*
** =======================================================
** Derived functions
** =======================================================
*/
int (lua_call) (char *name) { return lua_call(name); }

void (lua_pushref) (int ref) { lua_pushref(ref); }

int (lua_refobject) (lua_Object o, int l) { return lua_refobject(o, l); }

void (lua_register) (char *n, lua_CFunction f) { lua_register(n, f); }

void (lua_pushuserdata) (void *u) { lua_pushuserdata(u); }

void (lua_pushcfunction) (lua_CFunction f) { lua_pushcfunction(f); }

int (lua_clonetag) (int t) { return lua_clonetag(t); }




#ifdef LUA_COMPAT2_5
/*
** 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;
  luaD_openstack(nParams);
  L->stack.stack[base].ttype = LUA_T_CPROTO;
  L->stack.stack[base].value.f = f;
  luaD_call(base+1, nResults);
}

lua_Object lua_setfallback (char *name, lua_CFunction fallback)
{
  lua_pushstring(name);
  lua_pushcfunction(fallback);
  do_unprotectedrun(luaT_setfallback, 2, 1);
  return put_luaObjectonTop();
}
#endif


--- NEW FILE: lapi.h ---
/*
** $Id: lapi.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/

#ifndef lapi_h
#define lapi_h


#include "lua.h"
#include "lobject.h"


TObject *luaA_Address (lua_Object o);
void luaA_pushobject (TObject *o);
void luaA_packresults (void);
int luaA_passresults (void);

#endif

--- NEW FILE: lauxlib.cpp ---
/*
** $Id: lauxlib.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/


#include <stdarg.h>
#include <stdio.h>
#include <string.h>

/* Please Notice: This file uses only the official API of Lua
** Any function declared here could be written as an application
** function. With care, these functions can be used by other libraries.
*/
#include "lauxlib.h"
#include "lua.h"
#include "luadebug.h"



int luaL_findstring (char *name, char *list[]) {
  int i;
  for (i=0; list[i]; i++)
    if (strcmp(list[i], name) == 0)
      return i;
  return -1;  /* name not found */
}

void luaL_argerror (int numarg, char *extramsg)
{
  char *funcname;
  lua_getobjname(lua_stackedfunction(0), &funcname);
  if (funcname == NULL)
    funcname = "???";
  if (extramsg == NULL)
    luaL_verror("bad argument #%d to function `%.50s'", numarg, funcname);
  else
    luaL_verror("bad argument #%d to function `%.50s' (%.100s)",
                    numarg, funcname, extramsg);
}

char *luaL_check_lstr (int numArg, long *len)
{
  lua_Object o = lua_getparam(numArg);
  luaL_arg_check(lua_isstring(o), numArg, "string expected");
  if (len) *len = lua_strlen(o);
  return lua_getstring(o);
}

char *luaL_opt_lstr (int numArg, char *def, long *len)
{
  return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
                              luaL_check_lstr(numArg, len);
}

double luaL_check_number (int numArg)
{
  lua_Object o = lua_getparam(numArg);
  luaL_arg_check(lua_isnumber(o), numArg, "number expected");
  return lua_getnumber(o);
}


double luaL_opt_number (int numArg, double def)
{
  return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
                              luaL_check_number(numArg);
}  


lua_Object luaL_tablearg (int arg)
{
  lua_Object o = lua_getparam(arg);
  luaL_arg_check(lua_istable(o), arg, "table expected");
  return o;
}

lua_Object luaL_functionarg (int arg)
{
  lua_Object o = lua_getparam(arg);
  luaL_arg_check(lua_isfunction(o), arg, "function expected");
  return o;
}

lua_Object luaL_nonnullarg (int numArg)
{
  lua_Object o = lua_getparam(numArg);
  luaL_arg_check(o != LUA_NOOBJECT, numArg, "value expected");
  return o;
}

void luaL_openlib (struct luaL_reg *l, int n)
{
  int i;
  lua_open();  /* make sure lua is already open */
  for (i=0; i<n; i++)
    lua_register(l[i].name, l[i].func);
}


void luaL_verror (char *fmt, ...)
{
  char buff[500];
  va_list argp;
  va_start(argp, fmt);
  vsprintf(buff, fmt, argp);
  va_end(argp);
  lua_error(buff);
}


--- NEW FILE: lauxlib.h ---
/*
** $Id: lauxlib.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/


#ifndef auxlib_h
#define auxlib_h


#include "lua.h"


struct luaL_reg {
  char *name;
  lua_CFunction func;
};


#define luaL_arg_check(cond,numarg,extramsg) if (!(cond)) \
                                               luaL_argerror(numarg,extramsg)

void luaL_openlib (struct luaL_reg *l, int n);
void luaL_argerror (int numarg, char *extramsg);
#define luaL_check_string(n)  (luaL_check_lstr((n), NULL))
char *luaL_check_lstr (int numArg, long *len);
#define luaL_opt_string(n, d) (luaL_opt_lstr((n), (d), NULL))
char *luaL_opt_lstr (int numArg, char *def, long *len);
double luaL_check_number (int numArg);
double luaL_opt_number (int numArg, double def);
lua_Object luaL_functionarg (int arg);
lua_Object luaL_tablearg (int arg);
lua_Object luaL_nonnullarg (int numArg);
void luaL_verror (char *fmt, ...);
char *luaL_openspace (int size);
void luaL_resetbuffer (void);
void luaL_addchar (int c);
int luaL_getsize (void);
void luaL_addsize (int n);
int luaL_newbuffer (int size);
void luaL_oldbuffer (int old);
char *luaL_buffer (void);
int luaL_findstring (char *name, char *list[]);


#endif

--- NEW FILE: lbuffer.cpp ---
/*
** $Id: lbuffer.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/


#include <stdio.h>

#include "lauxlib.h"
#include "lmem.h"
#include "lstate.h"


/*-------------------------------------------------------
**  Auxiliary buffer
-------------------------------------------------------*/

#define BUFF_STEP	32

#define openspace(size)  if (L->Mbuffnext+(size) > L->Mbuffsize) Openspace(size)

static void Openspace (int size)
{
  lua_State *l = L;  /* to optimize */
  int base = l->Mbuffbase-l->Mbuffer;
  l->Mbuffsize *= 2;
  if (l->Mbuffnext+size > l->Mbuffsize)  /* still not big enough? */
    l->Mbuffsize = l->Mbuffnext+size;
  l->Mbuffer = (char *)luaM_realloc(l->Mbuffer, l->Mbuffsize);
  l->Mbuffbase = l->Mbuffer+base;
}


char *luaL_openspace (int size)
{
  openspace(size);
  return L->Mbuffer+L->Mbuffnext;
}


void luaL_addchar (int c)
{
  openspace(BUFF_STEP);
  L->Mbuffer[L->Mbuffnext++] = c;
}


void luaL_resetbuffer (void)
{
  L->Mbuffnext = L->Mbuffbase-L->Mbuffer;
}


void luaL_addsize (int n)
{
  L->Mbuffnext += n;
}

int luaL_getsize (void)
{
  return L->Mbuffnext-(L->Mbuffbase-L->Mbuffer);
}

int luaL_newbuffer (int size)
{
  int old = L->Mbuffbase-L->Mbuffer;
  openspace(size);
  L->Mbuffbase = L->Mbuffer+L->Mbuffnext;
  return old;
}


void luaL_oldbuffer (int old)
{
  L->Mbuffnext = L->Mbuffbase-L->Mbuffer;
  L->Mbuffbase = L->Mbuffer+old;
}


char *luaL_buffer (void)
{
  return L->Mbuffbase;
}


--- NEW FILE: lbuiltin.cpp ---
/*
** $Id: lbuiltin.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Built-in functions
** See Copyright Notice in lua.h
*/


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lapi.h"
#include "lauxlib.h"
#include "lbuiltin.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltask.h"
#include "ltm.h"
#include "lua.h"
#include "lundump.h"



static void pushstring (TaggedString *s)
{
  TObject o;
  o.ttype = LUA_T_STRING;
  o.value.ts = s;
  luaA_pushobject(&o);
}


static void nextvar (void)
{
  TObject *o = luaA_Address(luaL_nonnullarg(1));
  TaggedString *g;
  if (ttype(o) == LUA_T_NIL)
    g = (TaggedString *)L->rootglobal.next;
  else {
    luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected");
    g = tsvalue(o);
    /* check whether name is in global var list */
    luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected");
    g = (TaggedString *)g->head.next;
  }
  while (g && g->u.s.globalval.ttype == LUA_T_NIL)  /* skip globals with nil */
    g = (TaggedString *)g->head.next;
  if (g) {
    pushstring(g);
    luaA_pushobject(&g->u.s.globalval);
  }
  else lua_pushnil();
}


static void foreachvar (void)
{
  TObject f = *luaA_Address(luaL_functionarg(1));
  GCnode *g;
  StkId name = L->Cstack.base++;  /* place to keep var name (to avoid GC) */
  ttype(L->stack.stack+name) = LUA_T_NIL;
  L->stack.top++;
  for (g = L->rootglobal.next; g; g = g->next) {
    TaggedString *s = (TaggedString *)g;
    if (s->u.s.globalval.ttype != LUA_T_NIL) {
      ttype(L->stack.stack+name) = LUA_T_STRING;
      tsvalue(L->stack.stack+name) = s;  /* keep s on stack to avoid GC */
      luaA_pushobject(&f);
      pushstring(s);
      luaA_pushobject(&s->u.s.globalval);
      luaD_call((L->stack.top-L->stack.stack)-2, 1);
      if (ttype(L->stack.top-1) != LUA_T_NIL)
        return;
      L->stack.top--;
    }
  }
}


static void next (void)
{
  lua_Object o = luaL_tablearg(1);
  lua_Object r = luaL_nonnullarg(2);
  Node *n = luaH_next(luaA_Address(o), luaA_Address(r));
  if (n) {
    luaA_pushobject(&n->ref);
    luaA_pushobject(&n->val);
  }
  else lua_pushnil();
}


static void foreach (void)
{
  TObject t = *luaA_Address(luaL_tablearg(1));
  TObject f = *luaA_Address(luaL_functionarg(2));
  int i;
  for (i=0; i<avalue(&t)->nhash; i++) {
    Node *nd = &(avalue(&t)->node[i]);
    if (ttype(ref(nd)) != LUA_T_NIL && ttype(val(nd)) != LUA_T_NIL) {
      luaA_pushobject(&f);
      luaA_pushobject(ref(nd));
      luaA_pushobject(val(nd));
      luaD_call((L->stack.top-L->stack.stack)-2, 1);
      if (ttype(L->stack.top-1) != LUA_T_NIL)
        return;
      L->stack.top--;
    }
  }
}


static void internaldostring (void)
{
  long l;
  char *s = luaL_check_lstr(1, &l);
  if (*s == ID_CHUNK)
    lua_error("`dostring' cannot run pre-compiled code");
  if (lua_dobuffer(s, l, luaL_opt_string(2, NULL)) == 0)
    if (luaA_passresults() == 0)
      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
}


static void internaldofile (void)
{
  char *fname = luaL_opt_string(1, NULL);
  if (lua_dofile(fname) == 0)
    if (luaA_passresults() == 0)
      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
}


static void to_string (void) {
  lua_Object obj = lua_getparam(1);
  char *buff = luaL_openspace(30);
  TObject *o = luaA_Address(obj);
  switch (ttype(o)) {
    case LUA_T_NUMBER:
      lua_pushstring(lua_getstring(obj));
      return;
    case LUA_T_STRING:
      lua_pushobject(obj);
      return;
    case LUA_T_ARRAY: {
      sprintf(buff, "table: %p", (void *)o->value.a);
      break;
    }
    case LUA_T_CLOSURE: {
      sprintf(buff, "function: %p", (void *)o->value.cl);
      break;
    }
    case LUA_T_PROTO: {
      sprintf(buff, "function: %p", (void *)o->value.tf);
      break;
    }
    case LUA_T_CPROTO: {
      sprintf(buff, "function: %p", (void *)o->value.f);
      break;
    }
    case LUA_T_USERDATA: {
      sprintf(buff, "userdata: %p", o->value.ts->u.d.v);
      break;
    }
    case LUA_T_NIL:
      lua_pushstring("nil");
      return;
    default:
      LUA_INTERNALERROR("invalid type");
  }
  lua_pushstring(buff);
}


static void luaI_print (void) {
  TaggedString *ts = luaS_new("tostring");
  lua_Object obj;
  int i = 1;
  while ((obj = lua_getparam(i++)) != LUA_NOOBJECT) {
    luaA_pushobject(&ts->u.s.globalval);
    lua_pushobject(obj);
    luaD_call((L->stack.top-L->stack.stack)-1, 1);
    if (ttype(L->stack.top-1) != LUA_T_STRING)
      lua_error("`tostring' must return a string to `print'");
    printf("%s\t", svalue(L->stack.top-1));
    L->stack.top--;
  }
  printf("\n");
}


static void luaI_type (void)
{
  lua_Object o = luaL_nonnullarg(1);
  lua_pushstring(luaO_typenames[-ttype(luaA_Address(o))]);
  lua_pushnumber(lua_tag(o));
}


static void tonumber (void)
{
  int base = luaL_opt_number(2, 10);
  if (base == 10) {  /* standard conversion */
    lua_Object o = lua_getparam(1);
    if (lua_isnumber(o))
      lua_pushnumber(lua_getnumber(o));
  }
  else {
    char *s = luaL_check_string(1);
    unsigned long n;
    luaL_arg_check(0 <= base && base <= 36, 2, "base out of range");
    n = strtol(s, &s, base);
    while (isspace(*s)) s++;  /* skip trailing spaces */
    if (*s) lua_pushnil();  /* invalid format: return nil */
    else lua_pushnumber(n);
  }
}


static void luaI_error (void)
{
  lua_error(lua_getstring(lua_getparam(1)));
}


static void luaI_assert (void)
{
  lua_Object p = lua_getparam(1);
  if (p == LUA_NOOBJECT || lua_isnil(p))
    luaL_verror("assertion failed!  %.100s", luaL_opt_string(2, ""));
}


static void setglobal (void)
{
  char *n = luaL_check_string(1);
  lua_Object value = luaL_nonnullarg(2);
  lua_pushobject(value);
  lua_setglobal(n);
  lua_pushobject(value);  /* return given value */
}

static void rawsetglobal (void)
{
  char *n = luaL_check_string(1);
  lua_Object value = luaL_nonnullarg(2);
  lua_pushobject(value);
  lua_rawsetglobal(n);
  lua_pushobject(value);  /* return given value */
}

static void getglobal (void)
{
  lua_pushobject(lua_getglobal(luaL_check_string(1)));
}

static void rawgetglobal (void)
{
  lua_pushobject(lua_rawgetglobal(luaL_check_string(1)));
}

static void luatag (void)
{
  lua_pushnumber(lua_tag(lua_getparam(1)));
}


static int getnarg (lua_Object table)
{
  lua_Object temp;
  /* temp = table.n */
  lua_pushobject(table); lua_pushstring("n"); temp = lua_rawgettable();
  return (lua_isnumber(temp) ? lua_getnumber(temp) : MAX_INT);
}

static void luaI_call (void)
{
  lua_Object f = luaL_nonnullarg(1);
  lua_Object arg = luaL_tablearg(2);
  char *options = luaL_opt_string(3, "");
  lua_Object err = lua_getparam(4);
  int narg = getnarg(arg);
  int i, status;
  if (err != LUA_NOOBJECT) {  /* set new error method */
    lua_pushobject(err);
    err = lua_seterrormethod();
  }
  /* push arg[1...n] */
  for (i=0; i<narg; i++) {
    lua_Object temp;
    /* temp = arg[i+1] */
    lua_pushobject(arg); lua_pushnumber(i+1); temp = lua_rawgettable();
    if (narg == MAX_INT && lua_isnil(temp))
      break;
    lua_pushobject(temp);
  }
  status = lua_callfunction(f);
  if (err != LUA_NOOBJECT) {  /* restore old error method */
    lua_pushobject(err);
    lua_seterrormethod();
  }
  if (status != 0) {  /* error in call? */
    if (strchr(options, 'x')) {
      lua_pushnil();
      return;  /* return nil to signal the error */
    }
    else
      lua_error(NULL);
  }
  else { /* no errors */
    if (strchr(options, 'p'))
      luaA_packresults();
    else
      luaA_passresults();
  }
}


static void settag (void)
{
  lua_Object o = luaL_tablearg(1);
  lua_pushobject(o);
  lua_settag(luaL_check_number(2));
  lua_pushobject(o);  /* returns first argument */
}


static void newtag (void)
{
  lua_pushnumber(lua_newtag());
}


static void copytagmethods (void)
{
  lua_pushnumber(lua_copytagmethods(luaL_check_number(1),
                                    luaL_check_number(2)));
}


static void rawgettable (void)
{
  lua_pushobject(luaL_nonnullarg(1));
  lua_pushobject(luaL_nonnullarg(2));
  lua_pushobject(lua_rawgettable());
}


static void rawsettable (void)
{
  lua_pushobject(luaL_nonnullarg(1));
  lua_pushobject(luaL_nonnullarg(2));
  lua_pushobject(luaL_nonnullarg(3));
  lua_rawsettable();
}


static void settagmethod (void)
{
  lua_Object nf = luaL_nonnullarg(3);
  lua_pushobject(nf);
  lua_pushobject(lua_settagmethod((int)luaL_check_number(1),
                                  luaL_check_string(2)));
}


static void gettagmethod (void)
{
  lua_pushobject(lua_gettagmethod((int)luaL_check_number(1),
                                  luaL_check_string(2)));
}


static void seterrormethod (void)
{
  lua_Object nf = luaL_functionarg(1);
  lua_pushobject(nf);
  lua_pushobject(lua_seterrormethod());
}


static void luaI_collectgarbage (void)
{
  lua_pushnumber(lua_collectgarbage(luaL_opt_number(1, 0)));
}


/*
** =======================================================
** some DEBUG functions
** =======================================================
*/
#ifdef DEBUG

static void mem_query (void)
{
  lua_pushnumber(totalmem);
  lua_pushnumber(numblocks);
}


static void countlist (void)
{
  char *s = luaL_check_string(1);
  GCnode *l = (s[0]=='t') ? L->roottable.next : (s[0]=='c') ? L->rootcl.next :
              (s[0]=='p') ? L->rootproto.next : L->rootglobal.next;
  int i=0;
  while (l) {
    i++;
    l = l->next;
  }
  lua_pushnumber(i);
}


static void testC (void)
{
#define getnum(s)	((*s++) - '0')
#define getname(s)	(nome[0] = *s++, nome)

  static int locks[10];
  lua_Object reg[10];
  char nome[2];
  char *s = luaL_check_string(1);
  nome[1] = 0;
  while (1) {
    switch (*s++) {
      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
        lua_pushnumber(*(s-1) - '0');
        break;

      case 'c': reg[getnum(s)] = lua_createtable(); break;
      case 'C': { lua_CFunction f = lua_getcfunction(lua_getglobal(getname(s)));
                  lua_pushcclosure(f, getnum(s));
                  break;
                }
      case 'P': reg[getnum(s)] = lua_pop(); break;
      case 'g': { int n=getnum(s); reg[n]=lua_getglobal(getname(s)); break; }
      case 'G': { int n = getnum(s);
                  reg[n] = lua_rawgetglobal(getname(s));
                  break;
                }
      case 'l': locks[getnum(s)] = lua_ref(1); break;
      case 'L': locks[getnum(s)] = lua_ref(0); break;
      case 'r': { int n=getnum(s); reg[n]=lua_getref(locks[getnum(s)]); break; }
      case 'u': lua_unref(locks[getnum(s)]); break;
      case 'p': { int n = getnum(s); reg[n] = lua_getparam(getnum(s)); break; }
      case '=': lua_setglobal(getname(s)); break;
      case 's': lua_pushstring(getname(s)); break;
      case 'o': lua_pushobject(reg[getnum(s)]); break;
      case 'f': (lua_call)(getname(s)); break;
      case 'i': reg[getnum(s)] = lua_gettable(); break;
      case 'I': reg[getnum(s)] = lua_rawgettable(); break;
      case 't': lua_settable(); break;
      case 'T': lua_rawsettable(); break;
      default: luaL_verror("unknown command in `testC': %c", *(s-1));
    }
  if (*s == 0) return;
  if (*s++ != ' ') lua_error("missing ` ' between commands in `testC'");
  }
}

#endif


/*
** Internal functions
*/
static struct luaL_reg int_funcs[] = {
#ifdef LUA_COMPAT2_5
  {"setfallback", luaT_setfallback},
#endif
#ifdef DEBUG
  {"testC", testC},
  {"totalmem", mem_query},
  {"count", countlist},
#endif
  {"assert", luaI_assert},
  {"call", luaI_call},
  {"collectgarbage", luaI_collectgarbage},
  {"dofile", internaldofile},
  {"copytagmethods", copytagmethods},
  {"dostring", internaldostring},
  {"error", luaI_error},
  {"foreach", foreach},
  {"foreachvar", foreachvar},
  {"getglobal", getglobal},
  {"newtag", newtag},
  {"next", next},
  {"nextvar", nextvar},
  {"print", luaI_print},
  {"rawgetglobal", rawgetglobal},
  {"rawgettable", rawgettable},
  {"rawsetglobal", rawsetglobal},
  {"rawsettable", rawsettable},
  {"seterrormethod", seterrormethod},
  {"setglobal", setglobal},
  {"settagmethod", settagmethod},
  {"gettagmethod", gettagmethod},
  {"settag", settag},
  {"tonumber", tonumber},
  {"tostring", to_string},
  {"tag", luatag},
  {"type", luaI_type},
  {"start_script", start_script},
  {"stop_script", stop_script},
  {"next_script", next_script},
  {"identify_script", identify_script},
  {"find_script", find_script},
  {"break_here", break_here},
  {"GetCurrentScript", GetCurrentScript}
};


#define INTFUNCSIZE (sizeof(int_funcs)/sizeof(int_funcs[0]))


void luaB_predefine (void)
{
  /* pre-register mem error messages, to avoid loop when error arises */
  luaS_newfixedstring(tableEM);
  luaS_newfixedstring(memEM);
  task_tag = lua_newtag();
  lua_pushcfunction(gc_task);
  lua_settagmethod(task_tag, "gc");
  luaL_openlib(int_funcs, (sizeof(int_funcs)/sizeof(int_funcs[0])));
  lua_pushstring(LUA_VERSION);
  lua_setglobal("_VERSION");
}


--- NEW FILE: lbuiltin.h ---
/*
** $Id: lbuiltin.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Built-in functions
** See Copyright Notice in lua.h
*/

#ifndef lbuiltin_h
#define lbuiltin_h


void luaB_predefine (void);


#endif

--- NEW FILE: ldo.cpp ---
/*
** $Id: ldo.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/


#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
#include "lstate.h"
#include "ltm.h"
#include "lua.h"
#include "luadebug.h"
#include "lundump.h"
#include "lvm.h"
#include "lzio.h"



#ifndef STACK_LIMIT
#define STACK_LIMIT     6000
#endif



/* Extra stack size to run a function: LUA_T_LINE(1), TM calls(2), ... */
#define	EXTRA_STACK	5


/*
** Error messages
*/

static void stderrorim (void)
{
  fprintf(stderr, "lua error: %s\n", lua_getstring(lua_getparam(1)));
}



#define STACK_UNIT	128

/* Initial size for CallInfo array */
#define BASIC_CI_SIZE	8

void luaD_init (void)
{
  ttype(&L->errorim) = LUA_T_CPROTO;
  fvalue(&L->errorim) = stderrorim;
}

void luaD_initthr (void)
{
  L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
  L->stack.top = L->stack.stack;
  L->stack.last = L->stack.stack+(STACK_UNIT-1);
  L->base_ci = luaM_newvector(BASIC_CI_SIZE, struct CallInfo);
  L->ci = L->base_ci;
  L->ci->tf = NULL;
  L->end_ci = L->base_ci + BASIC_CI_SIZE;
}


void luaD_checkstack (int n)
{
  struct Stack *S = &L->stack;
  if (S->last-S->top <= n) {
    StkId top = S->top-S->stack;
    int stacksize = (S->last-S->stack)+1+STACK_UNIT+n;
    S->stack = luaM_reallocvector(S->stack, stacksize, TObject);
    S->last = S->stack+(stacksize-1);
    S->top = S->stack + top;
    if (stacksize >= STACK_LIMIT) {  /* stack overflow? */
      if (lua_stackedfunction(100) == LUA_NOOBJECT)  /* 100 funcs on stack? */
        lua_error("Lua2C - C2Lua overflow"); /* doesn't look like a rec. loop */
      else
        lua_error("stack size overflow");
    }
  }
}


/*
** Adjust stack. Set top to the given value, pushing NILs if needed.
*/
void luaD_adjusttop (StkId newtop)
{
  int diff = newtop-(L->stack.top-L->stack.stack);
  if (diff <= 0)
    L->stack.top += diff;
  else {
    luaD_checkstack(diff);
    while (diff--)
      ttype(L->stack.top++) = LUA_T_NIL;
  }
}


/*
** Open a hole below "nelems" from the L->stack.top.
*/
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)
{
  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;
  (*lua_linehook)(line);
  L->stack.top = L->stack.stack+old_top;
  L->Cstack = oldCLS;
}


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;
  if (isreturn)
    (*lua_callhook)(LUA_NOOBJECT, "(return)", 0);
  else {
    TObject *f = L->stack.stack+base-1;
    if (tf)
      (*lua_callhook)(Ref(f), tf->fileName->str, tf->lineDefined);
    else
      (*lua_callhook)(Ref(f), "(C)", -1);
  }
  L->stack.top = L->stack.stack+old_top;
  L->Cstack = oldCLS;
}


/*
** Call a C function.
** 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;
  StkId firstResult;
  int numarg = (L->stack.top-L->stack.stack) - base;
  CS->num = numarg;
  CS->lua2C = base;
  CS->base = base+numarg;  /* == top-stack */
  if (lua_callhook)
    luaD_callHook(base, NULL, 0);
  (*f)();  /* do the actual call */
  if (lua_callhook)  /* func may have changed lua_callhook */
    luaD_callHook(base, NULL, 1);
  firstResult = CS->base;
  *CS = oldCLS;
  return firstResult;
}


static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base)
{
  TObject *pbase;
  int nup = cl->nelems;  /* number of upvalues */
  luaD_checkstack(nup);
  pbase = L->stack.stack+base;  /* care: previous call may change this */
  /* open space for upvalues as extra arguments */
  luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject));
  /* copy upvalues into stack */
  memcpy(pbase, cl->consts+1, nup*sizeof(TObject));
  L->stack.top += nup;
  return callC(f, base);
}


void luaD_callTM (TObject *f, int nParams, int nResults)
{
  luaD_openstack(nParams);
  *(L->stack.top-nParams-1) = *f;
  luaD_call((L->stack.top-L->stack.stack)-nParams, nResults);
}

static void adjust_varargs (StkId first_extra_arg)
{
  TObject arg;
  luaV_pack(first_extra_arg,
       (L->stack.top-L->stack.stack)-first_extra_arg, &arg);
  luaD_adjusttop(first_extra_arg);
  *L->stack.top++ = arg;
}



/*
** Prepare the stack for calling a Lua function.
*/
void luaD_precall (TObject *f, StkId base, int nResults)
{
  /* Create a new CallInfo record */
  if (L->ci+1 == L->end_ci) {
    int size_ci = L->end_ci - L->base_ci;
    int index_ci = L->ci - L->base_ci;
    L->base_ci = luaM_reallocvector(L->base_ci, size_ci * 2,
				    struct CallInfo);
    L->ci = L->base_ci + index_ci;
    L->end_ci = L->base_ci + size_ci * 2;
  }
  L->ci++;
  if (ttype(f) == LUA_T_CLOSURE) {
    L->ci->c = clvalue(f);
    f = &L->ci->c->consts[0];  /* Get the actual function */
  }
  else
    L->ci->c = NULL;
  L->ci->base = base;
  L->ci->nResults = nResults;
  if (ttype(f)==LUA_T_CPROTO) {
    L->ci->tf = NULL;
    L->ci->pc = NULL;
  }
  else {
    Byte *pc = tfvalue(f)->code;
    if (lua_callhook)
      luaD_callHook(base, tfvalue(f), 0);
    luaD_checkstack((*pc++)+EXTRA_STACK);
    if (*pc < ZEROVARARG)
      luaD_adjusttop(base+*(pc++));
    else {  /* varargs */
      luaC_checkGC();
      adjust_varargs(base+(*pc++)-ZEROVARARG);
    }
    L->ci->tf = tfvalue(f);
    L->ci->pc = pc;
  }
}

/*
** Adjust the stack to the desired number of results
*/
void luaD_postret (StkId firstResult) {
  int i;
  StkId base = L->ci->base;
  int nResults = L->ci->nResults;
  if (L->ci == L->base_ci)
    lua_error("call stack underflow");
  /* adjust the number of results */
  if (nResults != MULT_RET)
    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;
  /* pop off the current CallInfo */
  L->ci--;
}

/*
** 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).
** The number of results is nResults, unless nResults=MULT_RET.
*/
void luaD_call (StkId base, int nResults)
{
  StkId firstResult;
  TObject *func = L->stack.stack+base-1;
  switch (ttype(func)) {
    case LUA_T_CPROTO:
      luaD_precall(func, base, nResults);
      ttype(func) = LUA_T_CMARK;
      firstResult = callC(fvalue(func), base);
      break;
    case LUA_T_PROTO:
      luaD_precall(func, base, nResults);
      ttype(func) = LUA_T_PMARK;
      firstResult = luaV_execute(L->ci);
      break;
    case LUA_T_CLOSURE: {
      Closure *c = clvalue(func);
      TObject *proto = &(c->consts[0]);
      luaD_precall(func, base, nResults);
      ttype(func) = LUA_T_CLMARK;
      firstResult = (ttype(proto) == LUA_T_CPROTO) ?
                       callCclosure(c, fvalue(proto), base) :
                       luaV_execute(L->ci);
      break;
    }
    default: { /* func is not a function */
      /* Check the tag method for invalid functions */
      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);
      return;
    }
  }
  luaD_postret(firstResult);
}


static void travstack (struct Stack *S, int (*fn)(TObject *)) {
  StkId i;
  for (i = (S->top-1)-S->stack; i>=0; i--)
    fn(S->stack+i);
}

/*
** Traverse all objects on L->stack.stack, and all other active stacks
*/
void luaD_travstack (int (*fn)(TObject *))
{
  struct lua_Task *t;
  travstack(&L->stack, fn);
  for (t = L->root_task; t != NULL; t = t->next)
    if (t != L->curr_task && t->Tstate != DONE)
      travstack(&t->stack, fn);
}



static void message (char *s)
{
  TObject im = L->errorim;
  if (ttype(&im) != LUA_T_NIL) {
    lua_pushstring(s);
    luaD_callTM(&im, 1, 0);
  }
}

/*
** Reports an error, and jumps up to the available recover label
*/
void lua_error (char *s)
{
  if (s) message(s);
  if (L->errorJmp)
    longjmp(*((jmp_buf *)L->errorJmp), 1);
  else {
    fprintf (stderr, "lua: 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 luaM_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 L->stack.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)
{
  jmp_buf myErrorJmp;
  int status;
  struct C_Lua_Stack oldCLS = L->Cstack;
  jmp_buf *oldErr = L->errorJmp;
  int ci_len = L->ci - L->base_ci;
  L->errorJmp = &myErrorJmp;
  if (setjmp(myErrorJmp) == 0) {
    do_callinc(nResults);
    status = 0;
  }
  else { /* an error occurred: restore L->Cstack and L->stack.top */
    L->Cstack = oldCLS;
    L->stack.top = L->stack.stack+L->Cstack.base;
    L->ci = L->base_ci + ci_len;
    status = 1;
  }
  L->errorJmp = oldErr;
  return status;
}


/*
** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load
*/
static int protectedparser (ZIO *z, int bin)
{
  volatile int status;
  TProtoFunc *volatile tf;
  jmp_buf myErrorJmp;
  jmp_buf *volatile oldErr = L->errorJmp;
  L->errorJmp = &myErrorJmp;
  if (setjmp(myErrorJmp) == 0) {
    tf = bin ? luaU_undump1(z) : luaY_parser(z);
    status = 0;
  }
  else {
    tf = NULL;
    status = 1;
  }
  L->errorJmp = oldErr;
  if (status) return 1;  /* error code */
  if (tf == NULL) return 2;  /* 'natural' end */
  luaD_adjusttop(L->Cstack.base+1);  /* one slot for the pseudo-function */
  L->stack.stack[L->Cstack.base].ttype = LUA_T_PROTO;
  L->stack.stack[L->Cstack.base].value.tf = tf;
  luaV_closure(0);
  return 0;
}


static int do_main (ZIO *z, int bin)
{
  int status;
  do {
    long old_blocks = (luaC_checkGC(), L->nblocks);
    status = protectedparser(z, bin);
    if (status == 1) return 1;  /* error */
    else if (status == 2) return 0;  /* 'natural' end */
    else {
      unsigned long newelems2 = 2*(L->nblocks-old_blocks);
      L->GCthreshold += newelems2;
      status = luaD_protectedrun(MULT_RET);
      L->GCthreshold -= newelems2;
    }
  } while (bin && status == 0);
  return status;
}


void luaD_gcIM (TObject *o)
{
  TObject *im = luaT_getimbyObj(o, IM_GC);
  if (ttype(im) != LUA_T_NIL) {
    *L->stack.top = *o;
    incr_top;
    luaD_callTM(im, 1, 0);
  }
}


int lua_dofile (char *filename)
{
  ZIO z;
  int status;
  int c;
  int bin;
  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
  if (f == NULL)
    return 2;
  if (filename == NULL)
    filename = "(stdin)";
  c = fgetc(f);
  ungetc(c, f);
  bin = (c == ID_CHUNK);
  if (bin)
    f = freopen(filename, "rb", f);  /* set binary mode */
  luaZ_Fopen(&z, f, filename);
  status = do_main(&z, bin);
  if (f != stdin)
    fclose(f);
  return status;
}


#define SIZE_PREF 20  /* size of string prefix to appear in error messages */
#define SSIZE_PREF "20"


static void build_name (char *str, char *name) {
  if (str == NULL || *str == ID_CHUNK)
    strcpy(name, "(buffer)");
  else {
    char *temp;
    sprintf(name, "(dostring) >> \"%." SSIZE_PREF "s\"", str);
    temp = strchr(name, '\n');
    if (temp) {  /* end string after first line */
     *temp = '"';
     *(temp+1) = 0;
    }
  }
}


int lua_dostring (char *str) {
  return lua_dobuffer(str, strlen(str), NULL);
}


int lua_dobuffer (char *buff, int size, char *name) {
  char newname[SIZE_PREF+25];
  ZIO z;
  int status;
  if (name==NULL) {
    build_name(buff, newname);
    name = newname;
  }
  luaZ_mopen(&z, buff, size, name);
  status = do_main(&z, buff[0]==ID_CHUNK);
  return status;
}


--- NEW FILE: ldo.h ---
/*
** $Id: ldo.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/

#ifndef ldo_h
#define ldo_h


#include "lobject.h"
#include "lstate.h"


#define MULT_RET        255



/*
** macro to increment stack top.
** There must be always an empty slot at the L->stack.top
*/
#define incr_top { if (L->stack.top >= L->stack.last) luaD_checkstack(1); \
                   L->stack.top++; }


/* macros to convert from lua_Object to (TObject *) and back */

#define Address(lo)     ((lo)+L->stack.stack-1)
#define Ref(st)         ((st)-L->stack.stack+1)


void luaD_init (void);
void luaD_initthr (void);
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_precall (TObject *f, StkId base, int nResults);
void luaD_postret (StkId firstResult);
void luaD_call (StkId base, int nResults);
void luaD_callTM (TObject *f, int nParams, int nResults);
int luaD_protectedrun (int nResults);
void luaD_gcIM (TObject *o);
void luaD_travstack (int (*fn)(TObject *));
void luaD_checkstack (int n);


#endif

--- NEW FILE: lfunc.cpp ---
/*
** $Id: lfunc.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/


#include <stdlib.h>

#include "lfunc.h"
#include "lmem.h"
#include "lstate.h"

#define gcsizeproto(p)	5  /* approximate "weight" for a prototype */
#define gcsizeclosure(c) 1  /* approximate "weight" for a closure */



Closure *luaF_newclosure (int nelems)
{
  Closure *c = (Closure *)luaM_malloc(sizeof(Closure)+nelems*sizeof(TObject));
  luaO_insertlist(&(L->rootcl), (GCnode *)c);
  L->nblocks += gcsizeclosure(c);
  c->nelems = nelems;
  return c;
}


TProtoFunc *luaF_newproto (void)
{
  TProtoFunc *f = luaM_new(TProtoFunc);
  f->code = NULL;
  f->lineDefined = 0;
  f->fileName = NULL;
  f->consts = NULL;
  f->nconsts = 0;
  f->locvars = NULL;
  luaO_insertlist(&(L->rootproto), (GCnode *)f);
  L->nblocks += gcsizeproto(f);
  return f;
}



static void freefunc (TProtoFunc *f)
{
  luaM_free(f->code);
  luaM_free(f->locvars);
  luaM_free(f->consts);
  luaM_free(f);
}


void luaF_freeproto (TProtoFunc *l)
{
  while (l) {
    TProtoFunc *next = (TProtoFunc *)l->head.next;
    L->nblocks -= gcsizeproto(l);
    freefunc(l);
    l = next;
  }
}


void luaF_freeclosure (Closure *l)
{
  while (l) {
    Closure *next = (Closure *)l->head.next;
    L->nblocks -= gcsizeclosure(l);
    luaM_free(l);
    l = next;
  }
}


/*
** Look for n-th local variable at line "line" in function "func".
** Returns NULL if not found.
*/
char *luaF_getlocalname (TProtoFunc *func, int local_number, int line)
{
  int count = 0;
  char *varname = NULL;
  LocVar *lv = func->locvars;
  if (lv == NULL)
    return NULL;
  for (; lv->line != -1 && lv->line < line; lv++) {
    if (lv->varname) {  /* register */
      if (++count == local_number)
        varname = lv->varname->str;
    }
    else  /* unregister */
      if (--count < local_number)
        varname = NULL;
  }
  return varname;
}


--- NEW FILE: lfunc.h ---
/*
** $Id: lfunc.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua Function structures
** See Copyright Notice in lua.h
*/

#ifndef lfunc_h
#define lfunc_h


#include "lobject.h"



TProtoFunc *luaF_newproto (void);
Closure *luaF_newclosure (int nelems);
void luaF_freeproto (TProtoFunc *l);
void luaF_freeclosure (Closure *l);

char *luaF_getlocalname (TProtoFunc *func, int local_number, int line);


#endif

--- NEW FILE: lgc.cpp ---
/*
** $Id: lgc.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/


#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lua.h"



static int markobject (TObject *o);



/*
** =======================================================
** REF mechanism
** =======================================================
*/


int luaC_ref (TObject *o, int lock)
{
  int ref;
  if (ttype(o) == LUA_T_NIL)
    ref = -1;   /* special ref for nil */
  else {
    for (ref=0; ref<L->refSize; ref++)
      if (L->refArray[ref].status == FREE)
        goto found;
    /* no more empty spaces */ {
      int oldSize = L->refSize;
      L->refSize = luaM_growvector(&L->refArray, L->refSize, struct ref,
                                   refEM, MAX_INT);
      for (ref=oldSize; ref<L->refSize; ref++)
        L->refArray[ref].status = FREE;
      ref = oldSize;
    } found:
    L->refArray[ref].o = *o;
    L->refArray[ref].status = lock ? LOCK : HOLD;
  }
  return ref;
}


void lua_unref (int ref)
{
  if (ref >= 0 && ref < L->refSize)
    L->refArray[ref].status = FREE;
}


TObject* luaC_getref (int ref)
{
  if (ref == -1)
    return &luaO_nilobject;
  if (ref >= 0 && ref < L->refSize &&
      (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD))
    return &L->refArray[ref].o;
  else
    return NULL;
}


static void travlock (void)
{
  int i;
  for (i=0; i<L->refSize; i++)
    if (L->refArray[i].status == LOCK)
      markobject(&L->refArray[i].o);
}


static int ismarked (TObject *o)
{
  /* valid only for locked objects */
  switch (o->ttype) {
    case LUA_T_STRING: case LUA_T_USERDATA:
      return o->value.ts->head.marked;
    case LUA_T_ARRAY:
      return o->value.a->head.marked;
    case LUA_T_CLOSURE:
      return o->value.cl->head.marked;
    case LUA_T_PROTO:
      return o->value.tf->head.marked;
#ifdef DEBUG
    case LUA_T_LINE: case LUA_T_CLMARK:
    case LUA_T_CMARK: case LUA_T_PMARK:
      LUA_INTERNALERROR("invalid type");
#endif
    default:  /* nil, number or cproto */
      return 1;
  }
}


static void invalidaterefs (void)
{
  int i;
  for (i=0; i<L->refSize; i++)
    if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o))
      L->refArray[i].status = COLLECTED;
}



void luaC_hashcallIM (Hash *l)
{
  TObject t;
  ttype(&t) = LUA_T_ARRAY;
  for (; l; l=(Hash *)l->head.next) {
    avalue(&t) = l;
    luaD_gcIM(&t);
  }
}


void luaC_strcallIM (TaggedString *l)
{
  TObject o;
  ttype(&o) = LUA_T_USERDATA;
  for (; l; l=(TaggedString *)l->head.next)
    if (l->constindex == -1) {  /* is userdata? */
      tsvalue(&o) = l;
      luaD_gcIM(&o);
    }
}



static GCnode *listcollect (GCnode *l)
{
  GCnode *frees = NULL;
  while (l) {
    GCnode *next = l->next;
    l->marked = 0;
    while (next && !next->marked) {
      l->next = next->next;
      next->next = frees;
      frees = next;
      next = l->next;
    }
    l = next;
  }
  return frees;
}


static void strmark (TaggedString *s)
{
  if (!s->head.marked)
    s->head.marked = 1;
}


static void protomark (TProtoFunc *f)
{
  if (!f->head.marked) {
    LocVar *v = f->locvars;
    int i;
    f->head.marked = 1;
    if (f->fileName)
      strmark(f->fileName);
    for (i=0; i<f->nconsts; i++)
      markobject(&f->consts[i]);
    if (v) {
      for (; v->line != -1; v++)
        if (v->varname)
          strmark(v->varname);
    }
  }
}


static void closuremark (Closure *f)
{
  if (!f->head.marked) {
    int i;
    f->head.marked = 1;
    for (i=f->nelems; i>=0; i--)
      markobject(&f->consts[i]);
  }
}


static void hashmark (Hash *h)
{
  if (!h->head.marked) {
    int i;
    h->head.marked = 1;
    for (i=0; i<nhash(h); i++) {
      Node *n = node(h,i);
      if (ttype(ref(n)) != LUA_T_NIL) {
        markobject(&n->ref);
        markobject(&n->val);
      }
    }
  }
}


static void globalmark (void)
{
  TaggedString *g;
  for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){
    LUA_ASSERT(g->constindex >= 0, "userdata in global list");
    if (g->u.s.globalval.ttype != LUA_T_NIL) {
      markobject(&g->u.s.globalval);
      strmark(g);  /* cannot collect non nil global variables */
    }
  }
}


static int markobject (TObject *o)
{
  switch (ttype(o)) {
    case LUA_T_USERDATA:  case LUA_T_STRING:
      strmark(tsvalue(o));
      break;
    case LUA_T_ARRAY:
      hashmark(avalue(o));
      break;
    case LUA_T_CLOSURE:  case LUA_T_CLMARK:
      closuremark(o->value.cl);
      break;
    case LUA_T_PROTO: case LUA_T_PMARK:
      protomark(o->value.tf);
      break;
    default: break;  /* numbers, cprotos, etc */
  }
  return 0;
}



static void markall (void)
{
  luaD_travstack(markobject); /* mark stack objects */
  globalmark();  /* mark global variable values and names */
  travlock(); /* mark locked objects */
  luaT_travtagmethods(markobject);  /* mark fallbacks */
}


long lua_collectgarbage (long limit)
{
  unsigned long recovered = L->nblocks;  /* to subtract nblocks after gc */
  Hash *freetable;
  TaggedString *freestr;
  TProtoFunc *freefunc;
  Closure *freeclos;
  markall();
  invalidaterefs();
  freestr = luaS_collector();
  freetable = (Hash *)listcollect(&(L->roottable));
  freefunc = (TProtoFunc *)listcollect(&(L->rootproto));
  freeclos = (Closure *)listcollect(&(L->rootcl));
  L->GCthreshold *= 4;  /* to avoid GC during GC */
  luaC_hashcallIM(freetable);  /* GC tag methods for tables */
  luaC_strcallIM(freestr);  /* GC tag methods for userdata */
  luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
  luaH_free(freetable);
  luaS_free(freestr);
  luaF_freeproto(freefunc);
  luaF_freeclosure(freeclos);
  recovered = recovered-L->nblocks;
  L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
  return recovered;
}


void luaC_checkGC (void)
{
  if (L->nblocks >= L->GCthreshold)
    lua_collectgarbage(0);
}


--- NEW FILE: lgc.h ---
/*
** $Id: lgc.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/

#ifndef lgc_h
#define lgc_h


#include "lobject.h"


void luaC_checkGC (void);
TObject* luaC_getref (int ref);
int luaC_ref (TObject *o, int lock);
void luaC_hashcallIM (Hash *l);
void luaC_strcallIM (TaggedString *l);


#endif

--- NEW FILE: liolib.cpp ---
/*
** $Id: liolib.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/


#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "lauxlib.h"
#include "lua.h"
#include "luadebug.h"
#include "lualib.h"


#ifndef OLD_ANSI
#include <locale.h>
#else
#define setlocale(a,b)	0
#define LC_ALL		0
#define LC_COLLATE	0
#define LC_CTYPE	0
#define LC_MONETARY	0
#define LC_NUMERIC	0
#define LC_TIME		0
#define strerror(e)	"(no error message provided by operating system)"
#endif


#define CLOSEDTAG	2
#define IOTAG		1

#define FIRSTARG      3  /* 1st and 2nd are upvalues */

#define FINPUT		"_INPUT"
#define FOUTPUT		"_OUTPUT"


#ifdef POPEN
FILE *popen();
int pclose();
#else
#define popen(x,y) NULL  /* that is, popen always fails */
#define pclose(x)  (-1)
#endif


static int gettag (int i)
{
  return lua_getnumber(lua_getparam(i));
}


static void pushresult (int i)
{
  if (i)
    lua_pushuserdata(NULL);
  else {
    lua_pushnil();
    lua_pushstring(strerror(errno));
  }
}


static int ishandler (lua_Object f)
{
  if (lua_isuserdata(f)) {
    if (lua_tag(f) == gettag(CLOSEDTAG))
      lua_error("cannot access a closed file");
    return lua_tag(f) == gettag(IOTAG);
  }
  else return 0;
}

static FILE *getfile (char *name)
{
  lua_Object f = lua_getglobal(name);
  if (!ishandler(f))
      luaL_verror("global variable `%.50s' is not a file handle", name);
  return (FILE *)lua_getuserdata(f);
}


static FILE *getfileparam (char *name, int *arg)
{
  lua_Object f = lua_getparam(*arg);
  if (ishandler(f)) {
    (*arg)++;
    return (FILE *)lua_getuserdata(f);
  }
  else
    return getfile(name);
}


static void closefile (char *name)
{
  FILE *f = getfile(name);
  if (f == stdin || f == stdout) return;
  if (pclose(f) == -1)
    fclose(f);
  lua_pushobject(lua_getglobal(name));
  lua_settag(gettag(CLOSEDTAG));
}


static void setfile (FILE *f, char *name, int tag)
{
  lua_pushusertag(f, tag);
  lua_setglobal(name);
}


static void setreturn (FILE *f, char *name)
{
  int tag = gettag(IOTAG);
  setfile(f, name, tag);
  lua_pushusertag(f, tag);
}


static void io_readfrom (void)
{
  FILE *current;
  lua_Object f = lua_getparam(FIRSTARG);
  if (f == LUA_NOOBJECT) {
    closefile(FINPUT);
    current = stdin;
  }
  else if (lua_tag(f) == gettag(IOTAG))
    current = (FILE *)lua_getuserdata(f);
  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);
}


static void io_writeto (void)
{
  FILE *current;
  lua_Object f = lua_getparam(FIRSTARG);
  if (f == LUA_NOOBJECT) {
    closefile(FOUTPUT);
    current = stdout;
  }
  else if (lua_tag(f) == gettag(IOTAG))
    current = (FILE *)lua_getuserdata(f);
  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)
{
  char *s = luaL_check_string(FIRSTARG);
  FILE *fp = fopen (s, "a");
  if (fp != NULL)
    setreturn(fp, FOUTPUT);
  else
    pushresult(0);
}


#define NEED_OTHER (EOF-1)  /* just some flag different from EOF */


static void read_until (FILE *f, int lim) {
  int l = 0;
  int c;
  for (c = getc(f); c != EOF && c != lim; c = getc(f)) {
    luaL_addchar(c);
    l++;
  }
  if (l > 0 || c == lim)  /* read anything? */
    lua_pushlstring(luaL_buffer(), l);
}

static void io_read (void) {
  int arg = FIRSTARG;
  FILE *f = getfileparam(FINPUT, &arg);
  char *p = luaL_opt_string(arg, NULL);
  luaL_resetbuffer();
  if (p == NULL)  /* default: read a line */
    read_until(f, '\n');
  else if (p[0] == '.' && p[1] == '*' && p[2] == 0)  /* p = ".*" */
    read_until(f, EOF);
  else {
    int l = 0;  /* number of chars read in buffer */
    int inskip = 0;  /* to control {skips} */
    int c = NEED_OTHER;
    while (*p) {
      switch (*p) {
        case '{':
          inskip++;
          p++;
          continue;
        case '}':
          if (inskip == 0)
            lua_error("unbalanced braces in read pattern");
          inskip--;
          p++;
          continue;
        default: {
          char *ep;  /* get what is next */
          int m;  /* match result */
          if (c == NEED_OTHER) c = getc(f);
          if (c == EOF) {
            luaI_singlematch(0, p, &ep);  /* to set "ep" */
            m = 0;
          }
          else {
            m = luaI_singlematch(c, p, &ep);
            if (m) {
              if (inskip == 0) {
                luaL_addchar(c);
                l++;
              }
              c = NEED_OTHER;
            }
          }
          switch (*ep) {
            case '*':  /* repetition */
              if (!m) p = ep+1;  /* else stay in (repeat) the same item */
              continue;
            case '?':  /* optional */
              p = ep+1;  /* continues reading the pattern */
              continue;
            default:
              if (m) p = ep;  /* continues reading the pattern */
              else
                goto break_while;   /* pattern fails */
          }
        }
      }
    } break_while:
    if (c >= 0)  /* not EOF nor NEED_OTHER? */
       ungetc(c, f);
    if (l > 0 || *p == 0)  /* read something or did not fail? */
      lua_pushlstring(luaL_buffer(), l);
  }
}


static void io_write (void)
{
  int arg = FIRSTARG;
  FILE *f = getfileparam(FOUTPUT, &arg);
  int status = 1;
  char *s;
  long l;
  while ((s = luaL_opt_lstr(arg++, NULL, &l)) != NULL)
    status = status && (fwrite(s, 1, l, f) == l);
  pushresult(status);
}


static void io_execute (void)
{
  lua_pushnumber(system(luaL_check_string(1)));
}


static void io_remove  (void)
{
  pushresult(remove(luaL_check_string(1)) == 0);
}


static void io_rename (void)
{
  pushresult(rename(luaL_check_string(1),
                    luaL_check_string(2)) == 0);
}


static void io_tmpname (void)
{
  lua_pushstring(tmpnam(NULL));
}



static void io_getenv (void)
{
  lua_pushstring(getenv(luaL_check_string(1)));  /* if NULL push nil */
}


static void io_clock (void) {
  lua_pushnumber(((double)clock())/CLOCKS_PER_SEC);
}


static void io_date (void)
{
  time_t t;
  struct tm *tm;
  char *s = luaL_opt_string(1, "%c");
  char b[BUFSIZ];
  time(&t); tm = localtime(&t);
  if (strftime(b,sizeof(b),s,tm))
    lua_pushstring(b);
  else
    lua_error("invalid `date' format");
}


static void setloc (void)
{
  static int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC,
                      LC_TIME};
  static char *catnames[] = {"all", "collate", "ctype", "monetary",
     "numeric", "time", NULL};
  int op = luaL_findstring(luaL_opt_string(2, "all"), catnames);
  luaL_arg_check(op != -1, 2, "invalid option");
  lua_pushstring(setlocale(cat[op], luaL_check_string(1)));
}


static void io_exit (void)
{
  lua_Object o = lua_getparam(1);
  exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1);
}


static void io_debug (void)
{
  while (1) {
    char buffer[250];
    fprintf(stderr, "lua_debug> ");
    if (fgets(buffer, sizeof(buffer), stdin) == 0) return;
    if (strcmp(buffer, "cont\n") == 0) return;
    lua_dostring(buffer);
  }
}


static void lua_printstack (FILE *f)
{
  int level = 1;  /* skip level 0 (it's this function) */
  lua_Object func;
  while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) {
    char *name;
    int currentline;
    char *filename;
    int linedefined;
    lua_funcinfo(func, &filename, &linedefined);
    fprintf(f, (level==2) ? "Active Stack:\n\t" : "\t");
    switch (*lua_getobjname(func, &name)) {
      case 'g':
        fprintf(f, "function %s", name);
        break;
      case 't':
        fprintf(f, "`%s' tag method", name);
        break;
      default: {
        if (linedefined == 0)
          fprintf(f, "main of %s", filename);
        else if (linedefined < 0)
          fprintf(f, "%s", filename);
        else
          fprintf(f, "function (%s:%d)", filename, linedefined);
        filename = NULL;
      }
    }
    if ((currentline = lua_currentline(func)) > 0)
      fprintf(f, " at line %d", currentline);
    if (filename)
      fprintf(f, " [in file %s]", filename);
    fprintf(f, "\n");
  }
}


static void errorfb (void)
{
  fprintf(stderr, "lua: %s\n", lua_getstring(lua_getparam(1)));
  lua_printstack(stderr);
}



static struct luaL_reg iolib[] = {
{"setlocale", setloc},
{"execute",  io_execute},
{"remove",   io_remove},
{"rename",   io_rename},
{"tmpname",   io_tmpname},
{"getenv",   io_getenv},
{"date",     io_date},
{"clock",     io_clock},
{"exit",     io_exit},
{"debug",    io_debug},
{"print_stack", errorfb}
};

static struct luaL_reg iolibtag[] = {
{"readfrom", io_readfrom},
{"writeto",  io_writeto},
{"appendto", io_appendto},
{"read",     io_read},
{"write",    io_write}
};

static void openwithtags (void)
{
  int iotag = lua_newtag();
  int closedtag = lua_newtag();
  int i;
  for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
    /* put both tags as upvalues for these functions */
    lua_pushnumber(iotag);
    lua_pushnumber(closedtag);
    lua_pushcclosure(iolibtag[i].func, 2);
    lua_setglobal(iolibtag[i].name);
  }
  setfile(stdin, FINPUT, iotag);
  setfile(stdout, FOUTPUT, iotag);
  setfile(stdin, "_STDIN", iotag);
  setfile(stdout, "_STDOUT", iotag);
  setfile(stderr, "_STDERR", iotag);
}

void lua_iolibopen (void)
{
  luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
  openwithtags();
  lua_pushcfunction(errorfb);
  lua_seterrormethod();
}

--- NEW FILE: llex.cpp ---
/*
** $Id: llex.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lexical Analizer
** See Copyright Notice in lua.h
*/


#include <ctype.h>
#include <string.h>

#include "lauxlib.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "luadebug.h"
#include "lzio.h"



int lua_debug=0;


#define next(LS) (LS->current = zgetc(LS->lex_z))


#define save(c)	luaL_addchar(c)
#define save_and_next(LS)  (save(LS->current), next(LS))


char *reserved [] = {"and", "do", "else", "elseif", "end", "function",
    "if", "local", "nil", "not", "or", "repeat", "return", "then",
    "until", "while"};


void luaX_init (void)
{
  int i;
  for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) {
    TaggedString *ts = luaS_new(reserved[i]);
    ts->head.marked = FIRST_RESERVED+i;  /* reserved word  (always > 255) */
  }
}


void luaX_syntaxerror (LexState *ls, char *s, char *token) {
  if (token[0] == 0)
    token = "<eof>";
  luaL_verror("%.100s;\n  last token read: `%.50s' at line %d in chunk `%.50s'",
              s, token, ls->linenumber, zname(ls->lex_z));
}


void luaX_error (LexState *ls, char *s) {
  save(0);
  luaX_syntaxerror(ls, s, luaL_buffer());
}


void luaX_token2str (LexState *ls, int token, char *s) {
  if (token < 255) {
    s[0] = token;
    s[1] = 0;
  }
  else
    strcpy(s, reserved[token-FIRST_RESERVED]);
}


static void luaX_invalidchar (LexState *ls, int c) {
  char buff[10];
  sprintf(buff, "0x%X", c);
  luaX_syntaxerror(ls, "invalid control char", buff);
}


static void firstline (LexState *LS)
{
  int c = zgetc(LS->lex_z);
  if (c == '#')
    while ((c=zgetc(LS->lex_z)) != '\n' && c != EOZ) /* skip first line */;
  zungetc(LS->lex_z);
}


void luaX_setinput (LexState *LS, ZIO *z)
{
  LS->current = '\n';
  LS->linenumber = 0;
  LS->iflevel = 0;
  LS->ifstate[0].skip = 0;
  LS->ifstate[0].elsepart = 1;  /* to avoid a free $else */
  LS->lex_z = z;
  LS->fs = NULL;
  firstline(LS);
  luaL_resetbuffer();
}



/*
** =======================================================
** PRAGMAS
** =======================================================
*/

#define PRAGMASIZE	20

static void skipspace (LexState *LS)
{
  while (LS->current == ' ' || LS->current == '\t' || LS->current == '\r')
    next(LS);
}


static int checkcond (LexState *LS, char *buff)
{
  static char *opts[] = {"nil", "1", NULL};
  int i = luaL_findstring(buff, opts);
  if (i >= 0) return i;
  else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
    return luaS_globaldefined(buff);
  else {
    luaX_syntaxerror(LS, "invalid $if condition", buff);
    return 0;  /* to avoid warnings */
  }
}


static void readname (LexState *LS, char *buff)
{
  int i = 0;
  skipspace(LS);
  while (isalnum(LS->current) || LS->current == '_') {
    if (i >= PRAGMASIZE) {
      buff[PRAGMASIZE] = 0;
      luaX_syntaxerror(LS, "pragma too long", buff);
    }
    buff[i++] = LS->current;
    next(LS);
  }
  buff[i] = 0;
}


static void inclinenumber (LexState *LS);


static void ifskip (LexState *LS)
{
  while (LS->ifstate[LS->iflevel].skip) {
    if (LS->current == '\n')
      inclinenumber(LS);
    else if (LS->current == EOZ)
      luaX_error(LS, "input ends inside a $if");
    else next(LS);
  }
}


static void inclinenumber (LexState *LS)
{
  static char *pragmas [] =
    {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
  next(LS);  /* skip '\n' */
  ++LS->linenumber;
  if (LS->current == '$') {  /* is a pragma? */
    char buff[PRAGMASIZE+1];
    int ifnot = 0;
    int skip = LS->ifstate[LS->iflevel].skip;
    next(LS);  /* skip $ */
    readname(LS, buff);
    switch (luaL_findstring(buff, pragmas)) {
      case 0:  /* debug */
        if (!skip) lua_debug = 1;
        break;
      case 1:  /* nodebug */
        if (!skip) lua_debug = 0;
        break;
      case 2:  /* endinput */
        if (!skip) {
          LS->current = EOZ;
          LS->iflevel = 0;  /* to allow $endinput inside a $if */
        }
        break;
      case 3:  /* end */
        if (LS->iflevel-- == 0)
          luaX_syntaxerror(LS, "unmatched $end", "$end");
        break;
      case 4:  /* ifnot */
        ifnot = 1;
        /* go through */
      case 5:  /* if */
        if (LS->iflevel == MAX_IFS-1)
          luaX_syntaxerror(LS, "too many nested $ifs", "$if");
        readname(LS, buff);
        LS->iflevel++;
        LS->ifstate[LS->iflevel].elsepart = 0;
        LS->ifstate[LS->iflevel].condition = checkcond(LS, buff) ? !ifnot : ifnot;
        LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition;
        break;
      case 6:  /* else */
        if (LS->ifstate[LS->iflevel].elsepart)
          luaX_syntaxerror(LS, "unmatched $else", "$else");
        LS->ifstate[LS->iflevel].elsepart = 1;
        LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip ||
                                      LS->ifstate[LS->iflevel].condition;
        break;
      default:
        luaX_syntaxerror(LS, "unknown pragma", buff);
    }
    skipspace(LS);
    if (LS->current == '\n')  /* pragma must end with a '\n' ... */
      inclinenumber(LS);
    else if (LS->current != EOZ)  /* or eof */
      luaX_syntaxerror(LS, "invalid pragma format", buff);
    ifskip(LS);
  }
}


/*
** =======================================================
** LEXICAL ANALIZER
** =======================================================
*/





static int read_long_string (LexState *LS)
{
  int cont = 0;
  while (1) {
    switch (LS->current) {
      case EOZ:
        luaX_error(LS, "unfinished long string");
        return EOS;  /* to avoid warnings */
      case '[':
        save_and_next(LS);
        if (LS->current == '[') {
          cont++;
          save_and_next(LS);
        }
        continue;
      case ']':
        save_and_next(LS);
        if (LS->current == ']') {
          if (cont == 0) goto endloop;
          cont--;
          save_and_next(LS);
        }
        continue;
      case '\n':
        save('\n');
        inclinenumber(LS);
        continue;
      default:
        save_and_next(LS);
    }
  } endloop:
  save_and_next(LS);  /* pass the second ']' */
  LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+2,
                          L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-4);
  return STRING;
}


int luaX_lex (LexState *LS) {
  double a;
  luaL_resetbuffer();
  while (1) {
    switch (LS->current) {

      case ' ': case '\t': case '\r':  /* CR: to avoid problems with DOS */
        next(LS);
        continue;

      case '\n':
        inclinenumber(LS);
        continue;

      case '-':
        save_and_next(LS);
        if (LS->current != '-') return '-';
        do { next(LS); } while (LS->current != '\n' && LS->current != EOZ);
        luaL_resetbuffer();
        continue;

      case '[':
        save_and_next(LS);
        if (LS->current != '[') return '[';
        else {
          save_and_next(LS);  /* pass the second '[' */
          return read_long_string(LS);
        }

      case '=':
        save_and_next(LS);
        if (LS->current != '=') return '=';
        else { save_and_next(LS); return EQ; }

      case '<':
        save_and_next(LS);
        if (LS->current != '=') return '<';
        else { save_and_next(LS); return LE; }

      case '>':
        save_and_next(LS);
        if (LS->current != '=') return '>';
        else { save_and_next(LS); return GE; }

      case '~':
        save_and_next(LS);
        if (LS->current != '=') return '~';
        else { save_and_next(LS); return NE; }

      case '"':
      case '\'': {
        int del = LS->current;
        save_and_next(LS);
        while (LS->current != del) {
          switch (LS->current) {
            case EOZ:
            case '\n':
              luaX_error(LS, "unfinished string");
              return EOS;  /* to avoid warnings */
            case '\\':
              next(LS);  /* do not save the '\' */
              switch (LS->current) {
                case 'a': save('\a'); next(LS); break;
                case 'b': save('\b'); next(LS); break;
                case 'f': save('\f'); next(LS); break;
                case 'n': save('\n'); next(LS); break;
                case 'r': save('\r'); next(LS); break;
                case 't': save('\t'); next(LS); break;
                case 'v': save('\v'); next(LS); break;
                case '\n': save('\n'); inclinenumber(LS); break;
                default : {
                  if (isdigit(LS->current)) {
                    int c = 0;
                    int i = 0;
                    do {
                      c = 10*c + (LS->current-'0');
                      next(LS);
                    } while (++i<3 && isdigit(LS->current));
                    if (c >= 256)
                      luaX_error(LS, "escape sequence too large");
                    save(c);
                  }
                  else {  /* handles \, ", ', and ? */
                    save(LS->current);
                    next(LS);
                  }
                  break;
                }
              }
              break;
            default:
              save_and_next(LS);
          }
        }
        save_and_next(LS);  /* skip delimiter */
        LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+1,
                                L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-2);
        return STRING;
      }

      case '.':
        save_and_next(LS);
        if (LS->current == '.')
        {
          save_and_next(LS);
          if (LS->current == '.')
          {
            save_and_next(LS);
            return DOTS;   /* ... */
          }
          else return CONC;   /* .. */
        }
        else if (!isdigit(LS->current)) return '.';
        /* LS->current is a digit: goes through to number */
	a=0.0;
        goto fraction;

      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
	a=0.0;
        do {
          a = 10.0*a + (LS->current-'0');
          save_and_next(LS);
        } while (isdigit(LS->current));
        if (LS->current == '.') {
          save_and_next(LS);
          if (LS->current == '.') {
            save('.');
            luaX_error(LS, 
              "ambiguous syntax (decimal point x string concatenation)");
          }
        }
      fraction:
	{ double da=0.1;
	  while (isdigit(LS->current))
	  {
            a += (LS->current-'0')*da;
            da /= 10.0;
            save_and_next(LS);
          }
          if (toupper(LS->current) == 'E') {
	    int e = 0;
	    int neg;
	    double ea;
            save_and_next(LS);
	    neg = (LS->current=='-');
            if (LS->current == '+' || LS->current == '-') save_and_next(LS);
            if (!isdigit(LS->current))
              luaX_error(LS, "invalid numeral format");
            do {
              e = 10*e + (LS->current-'0');
              save_and_next(LS);
            } while (isdigit(LS->current));
	    for (ea=neg?0.1:10.0; e>0; e>>=1)
	    {
	      if (e & 1) a *= ea;
	      ea *= ea;
	    }
          }
          LS->seminfo.r = a;
          return NUMBER;
        }

      case EOZ:
        if (LS->iflevel > 0)
          luaX_error(LS, "input ends inside a $if");
        return EOS;

      default:
        if (LS->current != '_' && !isalpha(LS->current)) {
          int c = LS->current;
          if (iscntrl(c))
            luaX_invalidchar(LS, c);
          save_and_next(LS);
          return c;
        }
        else {  /* identifier or reserved word */
          TaggedString *ts;
          do {
            save_and_next(LS);
          } while (isalnum(LS->current) || LS->current == '_');
          save(0);
          ts = luaS_new(L->Mbuffbase);
          if (ts->head.marked >= 'A')
            return ts->head.marked;  /* reserved word */
          LS->seminfo.ts = ts;
          return NAME;
        }
    }
  }
}


--- NEW FILE: llex.h ---
/*
** $Id: llex.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lexical Analizer
** See Copyright Notice in lua.h
*/

#ifndef llex_h
#define llex_h

#include "lobject.h"
#include "lzio.h"


#define FIRST_RESERVED	260

/* maximum length of a reserved word (+1 for terminal 0) */
#define TOKEN_LEN	15

enum RESERVED {
  /* terminal symbols denoted by reserved words */
  AND = FIRST_RESERVED,
  DO, ELSE, ELSEIF, END, FUNCTION, IF, LOCAL, NIL, NOT, OR,
  REPEAT, RETURN, THEN, UNTIL, WHILE,
  /* other terminal symbols */
  NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS};


#define MAX_IFS 5

/* "ifstate" keeps the state of each nested $if the lexical is dealing with. */

struct ifState {
  int elsepart;  /* true if its in the $else part */
  int condition;  /* true if $if condition is true */
  int skip;  /* true if part must be skipped */
};


typedef struct LexState {
  int current;  /* look ahead character */
  int token;  /* look ahead token */
  struct FuncState *fs;  /* 'FuncState' is private for the parser */
  union {
    real r;
    TaggedString *ts;
  } seminfo;  /* semantics information */
  struct zio *lex_z;  /* input stream */
  int linenumber;  /* input line counter */
  int iflevel;  /* level of nested $if's (for lexical analysis) */
  struct ifState ifstate[MAX_IFS];
} LexState;


void luaX_init (void);
void luaX_setinput (LexState *LS, ZIO *z);
int luaX_lex (LexState *LS);
void luaX_syntaxerror (LexState *ls, char *s, char *token);
void luaX_error (LexState *ls, char *s);
void luaX_token2str (LexState *ls, int token, char *s);


#endif

--- NEW FILE: lmathlib.cpp ---
/*
** $Id: lmathlib.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua standard mathematical library
** See Copyright Notice in lua.h
*/


#include <stdlib.h>
#include <math.h>

#include "lauxlib.h"
#include "lua.h"
#include "lualib.h"

#ifdef M_PI
#define PI                      M_PI
#else
#define PI          ((double)3.14159265358979323846)
#endif


#define FROMRAD(a) ((a)*(180.0/PI))
#define TORAD(a)    ((a)*(PI/180.0))


static void math_abs (void)
{
  double d = luaL_check_number(1);
  if (d < 0) d = -d;
  lua_pushnumber(d);
}

static void math_sin (void)
{
  lua_pushnumber(sin(TORAD(luaL_check_number(1))));
}

static void math_cos (void)
{
  lua_pushnumber(cos(TORAD(luaL_check_number(1))));
}

static void math_tan (void)
{
  lua_pushnumber(tan(TORAD(luaL_check_number(1))));
}

static void math_asin (void)
{
  lua_pushnumber(FROMRAD(asin(luaL_check_number(1))));
}

static void math_acos (void)
{
  lua_pushnumber(FROMRAD(acos(luaL_check_number(1))));
}

static void math_atan (void)
{
  lua_pushnumber(FROMRAD(atan(luaL_check_number(1))));
}

static void math_atan2 (void)
{
  lua_pushnumber(FROMRAD(atan2(luaL_check_number(1), luaL_check_number(2))));
}

static void math_ceil (void)
{
  lua_pushnumber(ceil(luaL_check_number(1)));
}

static void math_floor (void)
{
  lua_pushnumber(floor(luaL_check_number(1)));
}

static void math_mod (void)
{
  lua_pushnumber(fmod(luaL_check_number(1), luaL_check_number(2)));
}

static void math_sqrt (void)
{
  lua_pushnumber(sqrt(luaL_check_number(1)));
}

static void math_pow (void)
{
  lua_pushnumber(pow(luaL_check_number(1), luaL_check_number(2)));
}

static void math_log (void)
{
  lua_pushnumber(log(luaL_check_number(1)));
}

static void math_log10 (void)
{
  lua_pushnumber(log10(luaL_check_number(1)));
}

static void math_exp (void)
{
  lua_pushnumber(exp(luaL_check_number(1)));
}

static void math_deg (void)
{
  lua_pushnumber(luaL_check_number(1)*(180.0/PI));
}

static void math_rad (void)
{
  lua_pushnumber(luaL_check_number(1)*(PI/180.0));
}

static void math_frexp (void) {
  int e;
  lua_pushnumber(frexp(luaL_check_number(1), &e));
  lua_pushnumber(e);
}

static void math_ldexp (void) {
  lua_pushnumber(ldexp(luaL_check_number(1), luaL_check_number(2)));
}



static void math_min (void)
{
  int i = 1;
  double dmin = luaL_check_number(i);
  while (lua_getparam(++i) != LUA_NOOBJECT) {
    double d = luaL_check_number(i);
    if (d < dmin)
      dmin = d;
  }
  lua_pushnumber(dmin);
}


static void math_max (void)
{
  int i = 1;
  double dmax = luaL_check_number(i);
  while (lua_getparam(++i) != LUA_NOOBJECT) {
    double d = luaL_check_number(i);
    if (d > dmax)
      dmax = d;
  }
  lua_pushnumber(dmax);
}


static void math_random (void)
{
  /* the '%' is needed because on some systems (SunOS!) "rand()" may */
  /* return a value bigger than RAND_MAX... */
  double r = (double)(rand()%RAND_MAX) / (double)RAND_MAX;
  double l = luaL_opt_number(1, 0);
  if (l == 0)
    lua_pushnumber(r);
  else
    lua_pushnumber((int)(r*l)+1);
}


static void math_randomseed (void)
{
  srand(luaL_check_number(1));
}


static struct luaL_reg mathlib[] = {
{"abs",   math_abs},
{"sin",   math_sin},
{"cos",   math_cos},
{"tan",   math_tan},
{"asin",  math_asin},
{"acos",  math_acos},
{"atan",  math_atan},
{"atan2", math_atan2},
{"ceil",  math_ceil},
{"floor", math_floor},
{"mod",   math_mod},
{"frexp", math_frexp},
{"ldexp", math_ldexp},
{"sqrt",  math_sqrt},
{"min",   math_min},
{"max",   math_max},
{"log",   math_log},
{"log10", math_log10},
{"exp",   math_exp},
{"deg",   math_deg},
{"rad",   math_rad},
{"random",     math_random},
{"randomseed", math_randomseed}
};

/*
** Open math library
*/
void lua_mathlibopen (void)
{
  luaL_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0])));
  lua_pushstring("deg"); lua_setglobal("_TRIGMODE");
  lua_pushcfunction(math_pow);
  lua_pushnumber(0);  /* to get its tag */
  lua_settagmethod(lua_tag(lua_pop()), "pow");
  lua_pushnumber(PI); lua_setglobal("PI");
}


--- NEW FILE: lmem.cpp ---
/*
** $Id: lmem.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/


#include <stdlib.h>

#include "lmem.h"
#include "lstate.h"
#include "lua.h"



int luaM_growaux (void **block, unsigned long nelems, int size,
                       char *errormsg, unsigned long limit)
{
  if (nelems >= limit)
    lua_error(errormsg);
  nelems = (nelems == 0) ? 32 : nelems*2;
  if (nelems > limit)
    nelems = limit;
  *block = luaM_realloc(*block, nelems*size);
  return (int)nelems;
}



#ifndef DEBUG

/*
** generic allocation routine.
** real ANSI systems do not need some of these tests,
** since realloc(NULL, s)==malloc(s) and realloc(b, 0)==free(b).
** But some systems (e.g. Sun OS) are not that ANSI...
*/
void *luaM_realloc (void *block, unsigned long size)
{
  size_t s = (size_t)size;
  if (s != size)
    lua_error("Allocation Error: Block too big");
  if (size == 0) {
    if (block) {
      free(block);
    }
    return NULL;
  }
  block = block ? realloc(block, s) : malloc(s);
  if (block == NULL)
    lua_error(memEM);
  return block;
}



#else
/* DEBUG */

#include <string.h>


#define HEADER	(sizeof(double))

#define MARK    55

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;
}


void *luaM_realloc (void *block, unsigned long size)
{
  unsigned long realsize = HEADER+size+1;
  if (realsize != (size_t)realsize)
    lua_error("Allocation Error: Block too big");
  if (size == 0) {  /* ANSI dosen't need this, but some machines... */
    if (block) {
      unsigned long *b = (unsigned long *)((char *)block - HEADER);
      memset(block, -1, *b);  /* erase block */
      block = checkblock(block);
      free(block);
    }
    return NULL;
  }
  if (block) {
    block = checkblock(block);
    block = (unsigned long *)realloc(block, realsize);
  }
  else
    block = (unsigned long *)malloc(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);
}


#endif

--- NEW FILE: lmem.h ---
/*
** $Id: lmem.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/

#ifndef lmem_h
#define lmem_h


#ifndef NULL
#define NULL 0
#endif


/* memory error messages */
#define codeEM   "code size overflow"
#define constantEM   "constant table overflow"
#define refEM   "reference table overflow"
#define tableEM  "table overflow"
#define memEM "not enough memory"

void *luaM_realloc (void *oldblock, unsigned long size);
int luaM_growaux (void **block, unsigned long nelems, int size,
                       char *errormsg, unsigned long limit);

#define luaM_free(b)	luaM_realloc((b), 0)
#define luaM_malloc(t)	luaM_realloc(NULL, (t))
#define luaM_new(t)          ((t *)luaM_malloc(sizeof(t)))
#define luaM_newvector(n,t)  ((t *)luaM_malloc((n)*sizeof(t)))
#define luaM_growvector(old,n,t,e,l) \
          (luaM_growaux((void**)old,n,sizeof(t),e,l))
#define luaM_reallocvector(v,n,t) ((t *)luaM_realloc(v,(n)*sizeof(t)))


#ifdef DEBUG
extern unsigned long numblocks;
extern unsigned long totalmem;
#endif


#endif


--- NEW FILE: lobject.cpp ---
/*
** $Id: lobject.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/

#include <stdlib.h>

#include "lobject.h"
#include "lua.h"


char *luaO_typenames[] = { /* ORDER LUA_T */
    "userdata", "number", "string", "table", "function", "function",
    "nil", "function", "mark", "mark", "mark", "line", NULL
};


TObject luaO_nilobject = {LUA_T_NIL, {NULL}};



/* hash dimensions values */
static long dimensions[] =
 {5L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
  12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
  1644817L, 3289613L, 6579211L, 13158023L, MAX_INT};


int luaO_redimension (int oldsize)
{
  int i;
  for (i=0; dimensions[i]<MAX_INT; i++) {
    if (dimensions[i] > oldsize)
      return dimensions[i];
  }
  lua_error("table overflow");
  return 0;  /* to avoid warnings */
}


int luaO_equalObj (TObject *t1, TObject *t2)
{
  if (ttype(t1) != ttype(t2)) return 0;
  switch (ttype(t1)) {
    case LUA_T_NIL: return 1;
    case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
    case LUA_T_STRING: case LUA_T_USERDATA: return svalue(t1) == svalue(t2);
    case LUA_T_ARRAY: return avalue(t1) == avalue(t2);
    case LUA_T_PROTO: return tfvalue(t1)  == tfvalue(t2);
    case LUA_T_CPROTO: return fvalue(t1)  == fvalue(t2);
    case LUA_T_CLOSURE: return t1->value.cl == t2->value.cl;
    default:
     LUA_INTERNALERROR("invalid type");
     return 0; /* UNREACHABLE */
  }
}


void luaO_insertlist (GCnode *root, GCnode *node)
{
  node->next = root->next;
  root->next = node;
  node->marked = 0;
}

#ifdef OLD_ANSI
void luaO_memup (void *dest, void *src, int size)
{
  char *d = dest;
  char *s = src;
  while (size--) d[size]=s[size];
}

void luaO_memdown (void *dest, void *src, int size)
{
  char *d = dest;
  char *s = src;
  int i;
  for (i=0; i<size; i++) d[i]=s[i];
}
#endif


--- NEW FILE: lobject.h ---
/*
** $Id: lobject.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/

#ifndef lobject_h
#define lobject_h


#include <limits.h>

#include "lua.h"


#ifdef DEBUG
#include "lauxlib.h"
#define LUA_INTERNALERROR(s)	\
	luaL_verror("INTERNAL ERROR - %s [%s:%d]",(s),__FILE__,__LINE__)
#define LUA_ASSERT(c,s) { if (!(c)) LUA_INTERNALERROR(s); }
#else
#define LUA_INTERNALERROR(s)  /* empty */
#define LUA_ASSERT(c,s)  /* empty */
#endif


/*
** "real" is the type "number" of Lua
** GREP LUA_NUMBER to change that
*/
#ifndef LUA_NUM_TYPE
#define LUA_NUM_TYPE float
#endif

/*
** format to convert number to strings
*/
#define NUMBER_FMT  "%g"

typedef LUA_NUM_TYPE real;

#define Byte lua_Byte	/* some systems have Byte as a predefined type */
typedef unsigned char  Byte;  /* unsigned 8 bits */


#define MAX_INT   (INT_MAX-2)  /* maximum value of an int (-2 for safety) */

/* maximum value of a word of 2 bytes (-2 for safety); must fit in an "int" */
#if MAX_INT < 65534
#define MAX_WORD	MAX_INT
#else
#define MAX_WORD	65534
#endif

typedef unsigned int IntPoint; /* unsigned with same size as a pointer (for hashing) */


/*
** Lua TYPES
** WARNING: if you change the order of this enumeration,
** grep "ORDER LUA_T"
*/
typedef enum {
  LUA_T_USERDATA =  0,  /* tag default for userdata */
  LUA_T_NUMBER   = -1,  /* fixed tag for numbers */
  LUA_T_STRING   = -2,  /* fixed tag for strings */
  LUA_T_ARRAY    = -3,  /* tag default for tables (or arrays) */
  LUA_T_PROTO    = -4,  /* fixed tag for functions */
  LUA_T_CPROTO   = -5,  /* fixed tag for Cfunctions */
  LUA_T_NIL      = -6,  /* last "pre-defined" tag */
  LUA_T_CLOSURE  = -7,
  LUA_T_CLMARK   = -8,  /* mark for closures */
  LUA_T_PMARK    = -9,  /* mark for Lua prototypes */
  LUA_T_CMARK    = -10, /* mark for C prototypes */
  LUA_T_LINE     = -11
} lua_Type;

#define NUM_TYPES 11
#define NUM_TAGS  7


typedef union {
  lua_CFunction f;  /* LUA_T_CPROTO, LUA_T_CMARK */
  real n;  /* LUA_T_NUMBER */
  struct TaggedString *ts;  /* LUA_T_STRING, LUA_T_USERDATA */
  struct TProtoFunc *tf;  /* LUA_T_PROTO, LUA_T_PMARK */
  struct Closure *cl;  /* LUA_T_CLOSURE, LUA_T_CLMARK */
  struct Hash *a;  /* LUA_T_ARRAY */
  int i;  /* LUA_T_LINE */
} Value;


typedef struct TObject {
  lua_Type ttype;
  Value value;
} TObject;



/*
** generic header for garbage collector lists
*/
typedef struct GCnode {
  struct GCnode *next;
  int marked;
} GCnode;


/*
** String headers for string table
*/

typedef struct TaggedString {
  GCnode head;
  unsigned long hash;
  int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
  union {
    struct {
      TObject globalval;
      long len;  /* if this is a string, here is its length */
    } s;
    struct {
      int tag;
      void *v;  /* if this is a userdata, here is its value */
    } d;
  } u;
  char str[1];   /* \0 byte already reserved */
} TaggedString;




/*
** Function Prototypes
*/
typedef struct TProtoFunc {
  GCnode head;
  struct TObject *consts;
  int nconsts;
  Byte *code;  /* ends with opcode ENDCODE */
  int lineDefined;
  TaggedString  *fileName;
  struct LocVar *locvars;  /* ends with line = -1 */
} TProtoFunc;

typedef struct LocVar {
  TaggedString *varname;           /* NULL signals end of scope */
  int line;
} LocVar;





/* Macros to access structure members */
#define ttype(o)        ((o)->ttype)
#define nvalue(o)       ((o)->value.n)
#define svalue(o)       ((o)->value.ts->str)
#define tsvalue(o)      ((o)->value.ts)
#define clvalue(o)      ((o)->value.cl)
#define avalue(o)       ((o)->value.a)
#define fvalue(o)       ((o)->value.f)
#define tfvalue(o)	((o)->value.tf)

#define protovalue(o)	((o)->value.cl->consts)


/*
** Closures
*/
typedef struct Closure {
  GCnode head;
  int nelems;  /* not included the first one (always the prototype) */
  TObject consts[1];  /* at least one for prototype */
} Closure;



typedef struct node {
  TObject ref;
  TObject val;
} Node;

typedef struct Hash {
  GCnode head;
  Node *node;
  int nhash;
  int nuse;
  int htag;
} Hash;


extern char *luaO_typenames[];

extern TObject luaO_nilobject;

int luaO_equalObj (TObject *t1, TObject *t2);
int luaO_redimension (int oldsize);
void luaO_insertlist (GCnode *root, GCnode *node);

#ifdef OLD_ANSI
void luaO_memup (void *dest, void *src, int size);
void luaO_memdown (void *dest, void *src, int size);
#else
#include <string.h>
#define luaO_memup(d,s,n)	memmove(d,s,n)
#define luaO_memdown(d,s,n)	memmove(d,s,n)
#endif

#endif

--- NEW FILE: lopcodes.h ---
/*
** $Id: lopcodes.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/

#ifndef lopcodes_h
#define lopcodes_h


/*
** NOTICE: variants of the same opcode must be consecutive: First, those
** with byte parameter, then with built-in parameters, and last with
** word parameter.
*/


typedef enum {
/* name          parm    before          after           side effect
-----------------------------------------------------------------------------*/
ENDCODE,/*	-	-		-  */

PUSHNIL,/*	b	-		nil_0...nil_b  */
PUSHNIL0,/*	-	-		nil  */

PUSHNUMBER,/*	b	-		(float)b  */
PUSHNUMBER0,/*	-	-		0.0  */
PUSHNUMBER1,/*	-	-		1.0  */
PUSHNUMBER2,/*	-	-		2.0  */
PUSHNUMBERW,/*	w	-		(float)w  */

PUSHCONSTANT,/*	b	-		CNST[b] */
PUSHCONSTANT0,/*-	-		CNST[0] */
PUSHCONSTANT1,/*-	-		CNST[1] */
PUSHCONSTANT2,/*-	-		CNST[2] */
PUSHCONSTANT3,/*-	-		CNST[3] */
PUSHCONSTANT4,/*-	-		CNST[4] */
PUSHCONSTANT5,/*-	-		CNST[5] */
PUSHCONSTANT6,/*-	-		CNST[6] */
PUSHCONSTANT7,/*-	-		CNST[7] */
PUSHCONSTANTW,/*w	-		CNST[w] */

PUSHUPVALUE,/*	b	-		Closure[b] */
PUSHUPVALUE0,/*	-	-		Closure[0] */
PUSHUPVALUE1,/*	-	-		Closure[1] */

PUSHLOCAL,/*	b	-		LOC[b]  */
PUSHLOCAL0,/*	-	-		LOC[0]  */
PUSHLOCAL1,/*	-	-		LOC[1]  */
PUSHLOCAL2,/*	-	-		LOC[2]  */
PUSHLOCAL3,/*	-	-		LOC[3]  */
PUSHLOCAL4,/*	-	-		LOC[4]  */
PUSHLOCAL5,/*	-	-		LOC[5]  */
PUSHLOCAL6,/*	-	-		LOC[6]  */
PUSHLOCAL7,/*	-	-		LOC[7]  */

GETGLOBAL,/*	b 	-		VAR[CNST[b]]  */
GETGLOBAL0,/*	-	-		VAR[CNST[0]]  */
GETGLOBAL1,/*	-	-		VAR[CNST[1]]  */
GETGLOBAL2,/*	-	-		VAR[CNST[2]]  */
GETGLOBAL3,/*	-	-		VAR[CNST[3]]  */
GETGLOBAL4,/*	-	-		VAR[CNST[4]]  */
GETGLOBAL5,/*	-	-		VAR[CNST[5]]  */
GETGLOBAL6,/*	-	-		VAR[CNST[6]]  */
GETGLOBAL7,/*	-	-		VAR[CNST[7]]  */
GETGLOBALW,/*	w	-		VAR[CNST[w]]  */

GETTABLE,/*	-	i t		t[i]  */

GETDOTTED,/*	b	t		t[CNST[b]]  */
GETDOTTED0,/*	-	t		t[CNST[0]]  */
GETDOTTED1,/*	-	t		t[CNST[1]]  */
GETDOTTED2,/*	-	t		t[CNST[2]]  */
GETDOTTED3,/*	-	t		t[CNST[3]]  */
GETDOTTED4,/*	-	t		t[CNST[4]]  */
GETDOTTED5,/*	-	t		t[CNST[5]]  */
GETDOTTED6,/*	-	t		t[CNST[6]]  */
GETDOTTED7,/*	-	t		t[CNST[7]]  */
GETDOTTEDW,/*	w	t		t[CNST[w]]  */

PUSHSELF,/*	b	t		t t[CNST[b]]  */
PUSHSELF0,/*	-	t		t t[CNST[0]]  */
PUSHSELF1,/*	-	t		t t[CNST[1]]  */
PUSHSELF2,/*	-	t		t t[CNST[2]]  */
PUSHSELF3,/*	-	t		t t[CNST[3]]  */
PUSHSELF4,/*	-	t		t t[CNST[4]]  */
PUSHSELF5,/*	-	t		t t[CNST[5]]  */
PUSHSELF6,/*	-	t		t t[CNST[6]]  */
PUSHSELF7,/*	-	t		t t[CNST[7]]  */
PUSHSELFW,/*	w	t		t t[CNST[w]]  */

CREATEARRAY,/*	b	-		newarray(size = b)  */
CREATEARRAY0,/*	-	-		newarray(size = 0)  */
CREATEARRAY1,/*	-	-		newarray(size = 1)  */
CREATEARRAYW,/*	w	-		newarray(size = w)  */

SETLOCAL,/*	b	x		-		LOC[b]=x  */
SETLOCAL0,/*	-	x		-		LOC[0]=x  */
SETLOCAL1,/*	-	x		-		LOC[1]=x  */
SETLOCAL2,/*	-	x		-		LOC[2]=x  */
SETLOCAL3,/*	-	x		-		LOC[3]=x  */
SETLOCAL4,/*	-	x		-		LOC[4]=x  */
SETLOCAL5,/*	-	x		-		LOC[5]=x  */
SETLOCAL6,/*	-	x		-		LOC[6]=x  */
SETLOCAL7,/*	-	x		-		LOC[7]=x  */

SETGLOBAL,/*	b	x		-		VAR[CNST[b]]=x  */
SETGLOBAL0,/*	-	x		-		VAR[CNST[0]]=x  */
SETGLOBAL1,/*	-	x		-		VAR[CNST[1]]=x  */
SETGLOBAL2,/*	-	x		-		VAR[CNST[2]]=x  */
SETGLOBAL3,/*	-	x		-		VAR[CNST[3]]=x  */
SETGLOBAL4,/*	-	x		-		VAR[CNST[4]]=x  */
SETGLOBAL5,/*	-	x		-		VAR[CNST[5]]=x  */
SETGLOBAL6,/*	-	x		-		VAR[CNST[6]]=x  */
SETGLOBAL7,/*	-	x		-		VAR[CNST[7]]=x  */
SETGLOBALW,/*	w	x		-		VAR[CNST[w]]=x  */

SETTABLE0,/*	-	v i t		-		t[i]=v  */

SETTABLE,/*	b	v a_b...a_1 i t	a_b...a_1 i t	t[i]=v  */

SETLIST,/*	b c	v_c...v_1 t	-		t[i+b*FPF]=v_i  */
SETLIST0,/*	b	v_b...v_1 t	-		t[i]=v_i  */
SETLISTW,/*	w c	v_c...v_1 t	-		t[i+w*FPF]=v_i  */

SETMAP,/*	b	v_b k_b ...v_0 k_0 t	t	t[k_i]=v_i  */
SETMAP0,/*	-	v_0 k_0 t		t	t[k_0]=v_0  */

EQOP,/*		-	y x		(x==y)? 1 : nil  */
NEQOP,/*	-	y x		(x~=y)? 1 : nil  */
LTOP,/*		-	y x		(x<y)? 1 : nil  */
LEOP,/*		-	y x		(x<y)? 1 : nil  */
GTOP,/*		-	y x		(x>y)? 1 : nil  */
GEOP,/*		-	y x		(x>=y)? 1 : nil  */
ADDOP,/*	-	y x		x+y  */
SUBOP,/*	-	y x		x-y  */
MULTOP,/*	-	y x		x*y  */
DIVOP,/*	-	y x		x/y  */
POWOP,/*	-	y x		x^y  */
CONCOP,/*	-	y x		x..y  */
MINUSOP,/*	-	x		-x  */
NOTOP,/*	-	x		(x==nil)? 1 : nil  */

ONTJMP,/*	b	x		(x!=nil)? x : -	(x!=nil)? PC+=b  */
ONTJMPW,/*	w	x		(x!=nil)? x : -	(x!=nil)? PC+=w  */
ONFJMP,/*	b	x		(x==nil)? x : -	(x==nil)? PC+=b  */
ONFJMPW,/*	w	x		(x==nil)? x : -	(x==nil)? PC+=w  */
JMP,/*		b	-		-		PC+=b  */
JMPW,/*		w	-		-		PC+=w  */
IFFJMP,/*	b	x		-		(x==nil)? PC+=b  */
IFFJMPW,/*	w	x		-		(x==nil)? PC+=w  */
IFTUPJMP,/*	b	x		-		(x!=nil)? PC-=b  */
IFTUPJMPW,/*	w	x		-		(x!=nil)? PC-=w  */
IFFUPJMP,/*	b	x		-		(x==nil)? PC-=b  */
IFFUPJMPW,/*	w	x		-		(x==nil)? PC-=w  */

CLOSURE,/*	c	f v_c...v_1	closure(f, v_c...v_1) */
CLOSURE0,/*	-	f		closure(f) */
CLOSURE1,/*	-	f v		closure(f, v) */

CALLFUNC,/*	b c	v_c...v_1 f	r_b...r_1	f(v1,...,v_c)  */
CALLFUNC0,/*	b	v_b...v_1 f	-		f(v1,...,v_b)  */
CALLFUNC1,/*	b	v_b...v_1 f	r_1		f(v1,...,v_b)  */

RETCODE,/*	b	-		-  */

SETLINE,/*	b	-		-		LINE=b  */
SETLINEW,/*	w	-		-		LINE=w  */

POP,/*		b	-		-		TOP-=(b+1)  */
POP0,/*		-	-		-		TOP-=1  */
POP1/*		-	-		-		TOP-=2  */

} OpCode;


#define RFIELDS_PER_FLUSH 32	/* records (SETMAP) */
#define LFIELDS_PER_FLUSH 64    /* lists (SETLIST) */

#define ZEROVARARG	64

#endif

--- NEW FILE: lparser.cpp ---
/*
** $Id: lparser.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/


#include <stdio.h>

#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "llex.h"
#include "lmem.h"
#include "lopcodes.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "lua.h"
[...1294 lines suppressed...]

static void recfield (LexState *ls) {
  /* recfield -> (NAME | '['exp1']') = exp1 */
  switch (ls->token) {
    case NAME:
      code_string(ls, checkname(ls));
      break;

    case '[':
      next(ls);
      exp1(ls);
      check(ls, ']');
      break;

    default: luaX_error(ls, "NAME or `[' expected");
  }
  check(ls, '=');
  exp1(ls);
}


--- NEW FILE: lparser.h ---
/*
** $Id: lparser.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Syntax analizer and code generator
** See Copyright Notice in lua.h
*/

#ifndef lparser_h
#define lparser_h

#include "lobject.h"
#include "lzio.h"


void luaY_codedebugline (int line);
TProtoFunc *luaY_parser (ZIO *z);
void luaY_error (char *s);
void luaY_syntaxerror (char *s, char *token);


#endif

--- NEW FILE: lstate.cpp ---
/*
** $Id: lstate.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Global State
** See Copyright Notice in lua.h
*/


#include "lbuiltin.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "llex.h"
#include "lmem.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"


lua_State *lua_state = NULL;

static void lua_openthr (void)
{
  L->numCblocks = 0;
  L->Cstack.base = 0;
  L->Cstack.lua2C = 0;
  L->Cstack.num = 0;
  L->errorJmp = NULL;
  L->Mbuffsize = 0;
  L->Mbuffnext = 0;
  L->Mbuffbase = NULL;
  L->Mbuffer = NULL;
  L->Tstate = RUN;
}

void lua_open (void)
{
  if (lua_state) return;
  lua_state = luaM_new(lua_State);
  lua_openthr();
  L->rootproto.next = NULL;
  L->rootproto.marked = 0;
  L->rootcl.next = NULL;
  L->rootcl.marked = 0;
  L->rootglobal.next = NULL;
  L->rootglobal.marked = 0;
  L->roottable.next = NULL;
  L->roottable.marked = 0;
  L->refArray = NULL;
  L->refSize = 0;
  L->GCthreshold = GARBAGE_BLOCK;
  L->nblocks = 0;
  L->root_task = luaM_new(struct lua_Task);
  L->root_task->next = NULL;
  L->last_task = L->root_task;
  L->curr_task = L->root_task;
  luaD_init();
  luaD_initthr();
  luaS_init();
  luaX_init();
  luaT_init();
  luaB_predefine();
}


void lua_close (void)
{
  TaggedString *alludata = luaS_collectudata();
  L->GCthreshold = MAX_INT;  /* to avoid GC during GC */
  luaC_hashcallIM((Hash *)L->roottable.next);  /* GC t.methods for tables */
  luaC_strcallIM(alludata);  /* GC tag methods for userdata */
  luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
  luaH_free((Hash *)L->roottable.next);
  luaF_freeproto((TProtoFunc *)L->rootproto.next);
  luaF_freeclosure((Closure *)L->rootcl.next);
  luaS_free(alludata);
  luaS_freeall();
  luaM_free(L->stack.stack);
  luaM_free(L->IMtable);
  luaM_free(L->refArray);
  luaM_free(L->Mbuffer);
  luaM_free(L);
  L = NULL;
#ifdef DEBUG
  printf("total de blocos: %ld\n", numblocks);
  printf("total de memoria: %ld\n", totalmem);
#endif
}


lua_State *lua_setstate (lua_State *st) {
  lua_State *old = lua_state;
  lua_state = st;
  return old;
}


static void savetask (struct lua_Task *t) {
  t->stack = L->stack;
  t->Cstack = L->Cstack;
  t->errorJmp = L->errorJmp;
  t->ci = L->ci;
  t->base_ci = L->base_ci;
  t->end_ci = L->end_ci;
  t->Mbuffer = L->Mbuffer;
  t->Mbuffbase = L->Mbuffbase;
  t->Mbuffsize = L->Mbuffsize;
  t->Mbuffnext = L->Mbuffnext;
  memcpy(t->Cblocks, L->Cblocks, sizeof(L->Cblocks));;
  t->numCblocks = L->numCblocks;
  t->Tstate = L->Tstate;
}

static void loadtask (struct lua_Task *t) {
  L->stack = t->stack;
  L->Cstack = t->Cstack;
  L->errorJmp = t->errorJmp;
  L->ci = t->ci;
  L->base_ci = t->base_ci;
  L->end_ci = t->end_ci;
  L->Mbuffer = t->Mbuffer;
  L->Mbuffbase = t->Mbuffbase;
  L->Mbuffsize = t->Mbuffsize;
  L->Mbuffnext = t->Mbuffnext;
  memcpy(L->Cblocks, t->Cblocks, sizeof(L->Cblocks));
  L->numCblocks = t->numCblocks;
  L->Tstate = t->Tstate;
}

void luaI_switchtask(struct lua_Task *t) {
  savetask(L->curr_task);
  L->curr_task = t;
  loadtask(t);
}

struct lua_Task *luaI_newtask (void) {
  struct lua_Task *result;

  savetask(L->curr_task);
  result = luaM_new(struct lua_Task);
  L->curr_task = result;
  result->next = NULL;
  result->auto_delete = 0;
  lua_openthr();
  luaD_initthr();
  return result;
}

--- NEW FILE: lstate.h ---
/*
** $Id: lstate.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Global State
** See Copyright Notice in lua.h
*/

#ifndef lstate_h
#define lstate_h

#include <setjmp.h>

#include "lobject.h"
#include "lua.h"


#define MAX_C_BLOCKS 10

#define GARBAGE_BLOCK 150


typedef int StkId;  /* index to stack elements */

struct Stack {
  TObject *top;
  TObject *stack;
  TObject *last;
};

struct C_Lua_Stack {
  StkId base;  /* when Lua calls C or C calls Lua, points to */
               /* the first slot after the last parameter. */
  StkId lua2C; /* points to first element of "array" lua2C */
  int num;     /* size of "array" lua2C */
};


typedef struct {
  int size;
  int nuse;  /* number of elements (including EMPTYs) */
  TaggedString **hash;
} stringtable;


enum Status {LOCK, HOLD, FREE, COLLECTED};

struct ref {
  TObject o;
  enum Status status;
};


struct CallInfo {
  Closure *c;
  TProtoFunc *tf;  /* Set to NULL for C function */
  StkId base;
  Byte *pc;
  int nResults;
};


enum TaskState {RUN, YIELD, DONE};

struct lua_Task {
  struct Stack stack;
  struct C_Lua_Stack Cstack;
  jmp_buf *errorJmp;
  struct CallInfo *ci;
  struct CallInfo *base_ci;
  struct CallInfo *end_ci;
  char *Mbuffer;
  char *Mbuffbase;
  int Mbuffsize;
  int Mbuffnext;
  struct C_Lua_Stack Cblocks[MAX_C_BLOCKS];
  int numCblocks;
  enum TaskState Tstate;
  struct lua_Task *next;
  int auto_delete;  /* Set to 1 if no userdata references this task */
};

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 CallInfo *ci;  /* call info for current function */
  struct CallInfo *base_ci;  /* array of CallInfo's */
  struct CallInfo *end_ci;  /* points after end of ci array */
  char *Mbuffer;  /* global buffer */
  char *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];
  int numCblocks;  /* number of nested Cblocks */
  enum TaskState Tstate;  /* state of current thread */
  /* global state */
  struct lua_Task *root_task;  /* first task created */
  struct lua_Task *curr_task;
  struct lua_Task *last_task;
  TObject errorim;  /* error tag method */
  GCnode rootproto;  /* list of all prototypes */
  GCnode rootcl;  /* list of all closures */
  GCnode roottable;  /* list of all tables */
  GCnode rootglobal;  /* list of strings with global values */
  stringtable *string_root;  /* array of hash tables for strings and udata */
  struct IM *IMtable;  /* table for tag methods */
  int IMtable_size;  /* size of IMtable */
  int last_tag;  /* last used tag in IMtable */
  struct ref *refArray;  /* locked objects */
  int refSize;  /* size of refArray */
  unsigned long GCthreshold;
  unsigned long nblocks;  /* number of 'blocks' currently allocated */
};


extern lua_State *lua_state;


#define L	lua_state


/* Switch to the given task */
void luaI_switchtask(struct lua_Task *t);

/* Create a new task and switch to it */
struct lua_Task *luaI_newtask(void);

#endif

--- NEW FILE: lstring.cpp ---
/*
** $Id: lstring.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/


#include <string.h>

#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lua.h"


#define NUM_HASHS  61


#define gcsizestring(l)	(1+(l/64))  /* "weight" for a string with length 'l' */



static TaggedString EMPTY = {{NULL, 2}, 0L, 0,
                            {{{LUA_T_NIL, {NULL}}, 0L}}, {0}};


void luaS_init (void)
{
  int i;
  L->string_root = luaM_newvector(NUM_HASHS, stringtable);
  for (i=0; i<NUM_HASHS; i++) {
    L->string_root[i].size = 0;
    L->string_root[i].nuse = 0;
    L->string_root[i].hash = NULL;
  }
}


static unsigned long hash_s (char *s, long l)
{
  unsigned long h = 0;
  while (l--)
    h = ((h<<5)-h)^(unsigned char)*(s++);
  return h;
}

static int newsize (stringtable *tb)
{
  int size = tb->size;
  int realuse = 0;
  int i;
  /* count how many entries are really in use */
  for (i=0; i<size; i++)
    if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY)
      realuse++;
  if (2*(realuse+1) <= size)  /* +1 is the new element */
    return size;  /* don't need to grow, just rehash to clear EMPTYs */
  else
    return luaO_redimension(size);
}


static void grow (stringtable *tb)
{
  
  int ns = newsize(tb);
  TaggedString **newhash = luaM_newvector(ns, TaggedString *);
  int i;
  for (i=0; i<ns; i++)
    newhash[i] = NULL;
  /* rehash */
  tb->nuse = 0;
  for (i=0; i<tb->size; i++) {
    if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) {
      int h = tb->hash[i]->hash%ns;
      while (newhash[h])
        h = (h+1)%ns;
      newhash[h] = tb->hash[i];
      tb->nuse++;
    }
  }
  luaM_free(tb->hash);
  tb->size = ns;
  tb->hash = newhash;
}


static TaggedString *newone_s (char *str, long l, unsigned long h)
{
  TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l);
  memcpy(ts->str, str, l);
  ts->str[l] = 0;  /* ending 0 */
  ts->u.s.globalval.ttype = LUA_T_NIL;  /* initialize global value */
  ts->u.s.len = l;
  ts->constindex = 0;
  L->nblocks += gcsizestring(l);
  ts->head.marked = 0;
  ts->head.next = (GCnode *)ts;  /* signal it is in no list */
  ts->hash = h;
  return ts;
}

static TaggedString *newone_u (char *buff, int tag, unsigned long h)
{
  TaggedString *ts = luaM_new(TaggedString);
  ts->u.d.v = buff;
  ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
  ts->constindex = -1;  /* tag -> this is a userdata */
  L->nblocks++;
  ts->head.marked = 0;
  ts->head.next = (GCnode *)ts;  /* signal it is in no list */
  ts->hash = h;
  return ts;
}

static TaggedString *insert_s (char *str, long l, stringtable *tb)
{
  TaggedString *ts;
  unsigned long h = hash_s(str, l);
  int size = tb->size;
  int i;
  int j = -1;
  if ((long)tb->nuse*3 >= (long)size*2) {
    grow(tb);
    size = tb->size;
  }
  for (i = h%size; (ts = tb->hash[i]) != NULL; ) {
    if (ts == &EMPTY)
      j = i;
    else if (ts->constindex >= 0 &&
             ts->u.s.len == l &&
             (memcmp(str, ts->str, l) == 0))
      return ts;
    if (++i == size) i=0;
  }
  /* not found */
  if (j != -1)  /* is there an EMPTY space? */
    i = j;
  else
    tb->nuse++;
  ts = tb->hash[i] = newone_s(str, l, h);
  return ts;
}

static TaggedString *insert_u (void *buff, int tag, stringtable *tb)
{
  TaggedString *ts;
  unsigned long h = (unsigned long)buff;
  int size = tb->size;
  int i;
  int j = -1;
  if ((long)tb->nuse*3 >= (long)size*2) {
    grow(tb);
    size = tb->size;
  }
  for (i = h%size; (ts = tb->hash[i]) != NULL; ) {
    if (ts == &EMPTY)
      j = i;
    else if (ts->constindex < 0 &&  /* is a udata? */
             (tag == ts->u.d.tag || tag == LUA_ANYTAG) &&
             buff == ts->u.d.v)
      return ts;
    if (++i == size) i=0;
  }
  /* not found */
  if (j != -1)  /* is there an EMPTY space? */
    i = j;
  else
    tb->nuse++;
  ts = tb->hash[i] = newone_u((char*)buff, tag, h);
  return ts;
}

TaggedString *luaS_createudata (void *udata, int tag)
{
  return insert_u(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]);
}

TaggedString *luaS_newlstr (char *str, long l)
{
  int i = (l==0)?0:(unsigned char)str[0];
  return insert_s(str, l, &L->string_root[i%NUM_HASHS]);
}

TaggedString *luaS_new (char *str)
{
  return luaS_newlstr(str, strlen(str));
}

TaggedString *luaS_newfixedstring (char *str)
{
  TaggedString *ts = luaS_new(str);
  if (ts->head.marked == 0)
    ts->head.marked = 2;  /* avoid GC */
  return ts;
}


void luaS_free (TaggedString *l)
{
  while (l) {
    TaggedString *next = (TaggedString *)l->head.next;
    L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len);
    luaM_free(l);
    l = next;
  }
}


/*
** Garbage collection functions.
*/

static void remove_from_list (GCnode *l)
{
  while (l) {
    GCnode *next = l->next;
    while (next && !next->marked)
      next = l->next = next->next;
    l = next;
  }
}


TaggedString *luaS_collector (void)
{
  TaggedString *frees = NULL;
  int i;
  remove_from_list(&(L->rootglobal));
  for (i=0; i<NUM_HASHS; i++) {
    stringtable *tb = &L->string_root[i];
    int j;
    for (j=0; j<tb->size; j++) {
      TaggedString *t = tb->hash[j];
      if (t == NULL) continue;
      if (t->head.marked == 1)
        t->head.marked = 0;
      else if (!t->head.marked) {
        t->head.next = (GCnode *)frees;
        frees = t;
        tb->hash[j] = &EMPTY;
      }
    }
  }
  return frees;
}


TaggedString *luaS_collectudata (void)
{
  TaggedString *frees = NULL;
  int i;
  L->rootglobal.next = NULL;  /* empty list of globals */
  for (i=0; i<NUM_HASHS; i++) {
    stringtable *tb = &L->string_root[i];
    int j;
    for (j=0; j<tb->size; j++) {
      TaggedString *t = tb->hash[j];
      if (t == NULL || t == &EMPTY || t->constindex != -1)
        continue;  /* get only user data */
      t->head.next = (GCnode *)frees;
      frees = t;
      tb->hash[j] = &EMPTY;
    }
  }
  return frees;
}


void luaS_freeall (void)
{
  int i;
  for (i=0; i<NUM_HASHS; i++) {
    stringtable *tb = &L->string_root[i];
    int j;
    for (j=0; j<tb->size; j++) {
      TaggedString *t = tb->hash[j];
      if (t == &EMPTY) continue;
      luaM_free(t);
    }
    luaM_free(tb->hash);
  }
  luaM_free(L->string_root);
}


void luaS_rawsetglobal (TaggedString *ts, TObject *newval)
{
  ts->u.s.globalval = *newval;
  if (ts->head.next == (GCnode *)ts) {  /* is not in list? */
    ts->head.next = L->rootglobal.next;
    L->rootglobal.next = (GCnode *)ts;
  }
}


char *luaS_travsymbol (int (*fn)(TObject *))
{
  TaggedString *g;
  for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next)
    if (fn(&g->u.s.globalval))
      return g->str;
  return NULL;
}


int luaS_globaldefined (char *name)
{
  TaggedString *ts = luaS_new(name);
  return ts->u.s.globalval.ttype != LUA_T_NIL;
}


--- NEW FILE: lstring.h ---
/*
** $Id: lstring.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/

#ifndef lstring_h
#define lstring_h


#include "lobject.h"


void luaS_init (void);
TaggedString *luaS_createudata (void *udata, int tag);
TaggedString *luaS_collector (void);
void luaS_free (TaggedString *l);
TaggedString *luaS_newlstr (char *str, long l);
TaggedString *luaS_new (char *str);
TaggedString *luaS_newfixedstring (char *str);
void luaS_rawsetglobal (TaggedString *ts, TObject *newval);
char *luaS_travsymbol (int (*fn)(TObject *));
int luaS_globaldefined (char *name);
TaggedString *luaS_collectudata (void);
void luaS_freeall (void);


#endif

--- NEW FILE: lstrlib.cpp ---
/*
** $Id: lstrlib.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Standard library for strings and pattern-matching
** See Copyright Notice in lua.h
*/


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lauxlib.h"
#include "lua.h"
#include "lualib.h"



static void addnchar (char *s, int n)
{
  char *b = luaL_openspace(n);
  memcpy(b, s, n);
  luaL_addsize(n);
}


static void str_len (void)
{
  long l;
  luaL_check_lstr(1, &l);
  lua_pushnumber(l);
}


static void closeandpush (void)
{
  lua_pushlstring(luaL_buffer(), luaL_getsize());
}


static long posrelat (long pos, long len)
{
  /* relative string position: negative means back from end */
  return (pos>=0) ? pos : len+pos+1;
}


static void str_sub (void)
{
  long l;
  char *s = luaL_check_lstr(1, &l);
  long start = posrelat(luaL_check_number(2), l);
  long end = posrelat(luaL_opt_number(3, -1), l);
  if (1 <= start && start <= end && end <= l)
    lua_pushlstring(s+start-1, end-start+1);
  else lua_pushstring("");
}


static void str_lower (void)
{
  long l;
  int i;
  char *s = luaL_check_lstr(1, &l);
  luaL_resetbuffer();
  for (i=0; i<l; i++)
    luaL_addchar(tolower((unsigned char)(s[i])));
  closeandpush();
}


static void str_upper (void)
{
  long l;
  int i;
  char *s = luaL_check_lstr(1, &l);
  luaL_resetbuffer();
  for (i=0; i<l; i++)
    luaL_addchar(toupper((unsigned char)(s[i])));
  closeandpush();
}

static void str_rep (void)
{
  long l;
  char *s = luaL_check_lstr(1, &l);
  int n = (int)luaL_check_number(2);
  luaL_resetbuffer();
  while (n-- > 0)
    addnchar(s, l);
  closeandpush();
}


static void str_byte (void)
{
  long l;
  char *s = luaL_check_lstr(1, &l);
  long pos = posrelat(luaL_opt_number(2, 1), l);
  luaL_arg_check(0<pos && pos<=l, 2,  "out of range");
  lua_pushnumber((unsigned char)s[pos-1]);
}

static void str_char (void) {
  int i = 0;
  luaL_resetbuffer();
  while (lua_getparam(++i) != LUA_NOOBJECT) {
    double c = luaL_check_number(i);
    luaL_arg_check((unsigned char)c == c, i, "invalid value");
    luaL_addchar((int)c);
  }
  closeandpush();
}


/*
** =======================================================
** PATTERN MATCHING
** =======================================================
*/

#define MAX_CAPT 9

struct Capture {
  int level;  /* total number of captures (finished or unfinished) */
  char *src_end;  /* end ('\0') of source string */
  struct {
    char *init;
    int len;  /* -1 signals unfinished capture */
  } capture[MAX_CAPT];
};


#define ESC	'%'
#define SPECIALS  "^$*?.([%-"


static void push_captures (struct Capture *cap)
{
  int i;
  for (i=0; i<cap->level; i++)
    lua_pushlstring(cap->capture[i].init, cap->capture[i].len);
}


static int check_cap (int l, struct Capture *cap)
{
  l -= '1';
  if (!(0 <= l && l < cap->level && cap->capture[l].len != -1))
    lua_error("invalid capture index");
  return l;
}


static int capture_to_close (struct Capture *cap)
{
  int level = cap->level;
  for (level--; level>=0; level--)
    if (cap->capture[level].len == -1) return level;
  lua_error("invalid pattern capture");
  return 0;  /* to avoid warnings */
}


static char *bracket_end (char *p)
{
  return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']');
}


static int matchclass (int c, int cl)
{
  int res;
  switch (tolower(cl)) {
    case 'a' : res = isalpha(c); break;
    case 'c' : res = iscntrl(c); break;
    case 'd' : res = isdigit(c); break;
    case 'l' : res = islower(c); break;
    case 'p' : res = ispunct(c); break;
    case 's' : res = isspace(c); break;
    case 'u' : res = isupper(c); break;
    case 'w' : res = isalnum(c); break;
    case 'z' : res = (c == '\0'); break;
    default: return (cl == c);
  }
  return (islower((unsigned char)cl) ? res : !res);
}


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 ((unsigned char)*(p-2) <= c && c <= (unsigned char)*p)
            return sig;
        }
        else if ((unsigned char)*p == c) return sig;
      }
      return !sig;
    }
    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;
  else {
    int cont = 1;
    while (++s < cap->src_end) {
      if (*s == e) {
        if (--cont == 0) return s+1;
      }
      else if (*s == b) cont++;
    }
  }
  return NULL;  /* string ends out of balance */
}


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 */
  }
  /* "luaI_singlematch" sets "ep" (so must be called even when *s == 0) */
  return (luaI_singlematch((unsigned char)*s, p, ep) && s<cap->src_end) ?
                    s+1 : 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;  /* get what is next */
      char *s1 = matchitem(s, p, cap, &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))
            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;
        }
        default:
          if (s1) { s=s1; p=ep; goto init; }  /* return match(s1, ep, cap); */
          else return NULL;
      }
    }
  }
}


static void str_find (void)
{
  long l;
  char *s = luaL_check_lstr(1, &l);
  char *p = luaL_check_string(2);
  long init = posrelat(luaL_opt_number(3, 1), l) - 1;
  struct Capture cap;
  luaL_arg_check(0 <= init && init <= l, 3, "out of range");
  if (lua_getparam(4) != LUA_NOOBJECT ||
      strpbrk(p, SPECIALS) == NULL) {  /* no special characters? */
    char *s2 = strstr(s+init, p);
    if (s2) {
      lua_pushnumber(s2-s+1);
      lua_pushnumber(s2-s+strlen(p));
      return;
    }
  }
  else {
    int anchor = (*p == '^') ? (p++, 1) : 0;
    char *s1=s+init;
    cap.src_end = s+l;
    do {
      char *res;
      cap.level = 0;
      if ((res=match(s1, p, &cap)) != NULL) {
        lua_pushnumber(s1-s+1);  /* start */
        lua_pushnumber(res-s);   /* end */
        push_captures(&cap);
        return;
      }
    } while (s1++<cap.src_end && !anchor);
  }
  lua_pushnil();  /* if arrives here, it didn't find */
}


static void add_s (lua_Object newp, struct Capture *cap)
{
  if (lua_isstring(newp)) {
    char *news = lua_getstring(newp);
    int l = lua_strlen(newp);
    int i;
    for (i=0; i<l; i++) {
      if (news[i] != ESC)
        luaL_addchar(news[i]);
      else {
        i++;  /* skip ESC */
        if (!isdigit((unsigned char)news[i]))
          luaL_addchar(news[i]);
        else {
          int level = check_cap(news[i], cap);
          addnchar(cap->capture[level].init, cap->capture[level].len);
        }
      }
    }
  }
  else {  /* is a function */
    lua_Object res;
    int status;
    int oldbuff;
    lua_beginblock();
    push_captures(cap);
    /* function may use buffer, so save it and create a new one */
    oldbuff = luaL_newbuffer(0);
    status = lua_callfunction(newp);
    /* restore old buffer */
    luaL_oldbuffer(oldbuff);
    if (status != 0) {
      lua_endblock();
      lua_error(NULL);
    }
    res = lua_getresult(1);
    if (lua_isstring(res))
      addnchar(lua_getstring(res), lua_strlen(res));
    lua_endblock();
  }
}


static void str_gsub (void)
{
  long srcl;
  char *src = luaL_check_lstr(1, &srcl);
  char *p = luaL_check_string(2);
  lua_Object newp = lua_getparam(3);
  int max_s = (int)luaL_opt_number(4, srcl+1);
  int anchor = (*p == '^') ? (p++, 1) : 0;
  int n = 0;
  struct Capture cap;
  luaL_arg_check(lua_isstring(newp) || lua_isfunction(newp), 3,
                 "string or function expected");
  luaL_resetbuffer();
  cap.src_end = src+srcl;
  while (n < max_s) {
    char *e;
    cap.level = 0;
    e = match(src, p, &cap);
    if (e) {
      n++;
      add_s(newp, &cap);
    }
    if (e && e>src) /* non empty match? */
      src = e;  /* skip it */
    else if (src < cap.src_end)
      luaL_addchar(*src++);
    else break;
    if (anchor) break;
  }
  addnchar(src, cap.src_end-src);
  closeandpush();
  lua_pushnumber(n);  /* number of substitutions */
}


static void luaI_addquoted (char *s)
{
  luaL_addchar('"');
  for (; *s; s++) {
    if (strchr("\"\\\n", *s))
      luaL_addchar('\\');
    luaL_addchar(*s);
  }
  luaL_addchar('"');
}

#define MAX_FORMAT 200

static void str_format (void)
{
  int arg = 1;
  char *strfrmt = luaL_check_string(arg);
  struct Capture cap;
  cap.src_end = strfrmt+strlen(strfrmt)+1;
  luaL_resetbuffer();
  while (*strfrmt) {
    if (*strfrmt != '%')
      luaL_addchar(*strfrmt++);
    else if (*++strfrmt == '%')
      luaL_addchar(*strfrmt++);  /* %% */
    else { /* format item */
      char form[MAX_FORMAT];      /* store the format ('%...') */
      char *buff;
      char *initf = strfrmt;
      form[0] = '%';
      cap.level = 0;
      if (isdigit((unsigned char)initf[0]) && initf[1] == '$') {
        arg = initf[0] - '0';
        initf += 2;  /* skip the 'n$' */
      }
      arg++;
      strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
      if (cap.capture[0].len > 2 || cap.capture[1].len > 2)  /* < 100? */
        lua_error("invalid format (width or precision too long)");
      strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
      form[strfrmt-initf+2] = 0;
      buff = luaL_openspace(1000);  /* to store the formatted value */
      switch (*strfrmt++) {
        case 'q':
          luaI_addquoted(luaL_check_string(arg));
          continue;
        case 's': {
          char *s = luaL_check_string(arg);
          buff = luaL_openspace(strlen(s));
          sprintf(buff, form, s);
          break;
        }
        case 'c':  case 'd':  case 'i':
          sprintf(buff, form, (int)luaL_check_number(arg));
          break;
        case 'o':  case 'u':  case 'x':  case 'X':
          sprintf(buff, form, (unsigned int)luaL_check_number(arg));
          break;
        case 'e':  case 'E': case 'f': case 'g': case 'G':
          sprintf(buff, form, luaL_check_number(arg));
          break;
        default:  /* also treat cases 'pnLlh' */
          lua_error("invalid option in `format'");
      }
      luaL_addsize(strlen(buff));
    }
  }
  closeandpush();  /* push the result */
}


static struct luaL_reg strlib[] = {
{"strlen", str_len},
{"strsub", str_sub},
{"strlower", str_lower},
{"strupper", str_upper},
{"strchar", str_char},
{"strrep", str_rep},
{"ascii", str_byte},  /* for compatibility */
{"strbyte", str_byte},
{"format", str_format},
{"strfind", str_find},
{"gsub", str_gsub}
};


/*
** Open string library
*/
void strlib_open (void)
{
  luaL_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0])));
}

--- NEW FILE: ltable.cpp ---
/*
** $Id: ltable.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/

#include <stdlib.h>

#include "lauxlib.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "ltable.h"
#include "lua.h"


#define gcsize(n)	(1+(n/16))

#define nuse(t)		((t)->nuse)
#define nodevector(t)	((t)->node)


#define REHASH_LIMIT    0.70    /* avoid more than this % full */

#define TagDefault LUA_T_ARRAY;



static long int hashindex (TObject *ref)
{
  long int h;
  switch (ttype(ref)) {
    case LUA_T_NUMBER:
      h = (long int)nvalue(ref);
      break;
    case LUA_T_STRING: case LUA_T_USERDATA:
      h = (IntPoint)tsvalue(ref);
      break;
    case LUA_T_ARRAY:
      h = (IntPoint)avalue(ref);
      break;
    case LUA_T_PROTO:
      h = (IntPoint)tfvalue(ref);
      break;
    case LUA_T_CPROTO:
      h = (IntPoint)fvalue(ref);
      break;
    case LUA_T_CLOSURE:
      h = (IntPoint)clvalue(ref);
      break;
    default:
      lua_error("unexpected type to index table");
      h = 0;  /* to avoid warnings */
  }
  return (h >= 0 ? h : -(h+1));
}


static int present (Hash *t, TObject *key)
{
  int tsize = nhash(t);
  long int h = hashindex(key);
  int h1 = h%tsize;
  TObject *rf = ref(node(t, h1));
  if (ttype(rf) != LUA_T_NIL && !luaO_equalObj(key, rf)) {
    int h2 = h%(tsize-2) + 1;
    do {
      h1 += h2;
      if (h1 >= tsize) h1 -= tsize;
      rf = ref(node(t, h1));
    } while (ttype(rf) != LUA_T_NIL && !luaO_equalObj(key, rf));
  }
  return h1;
}


/*
** Alloc a vector node
*/
static Node *hashnodecreate (int nhash)
{
  Node *v = luaM_newvector(nhash, Node);
  int i;
  for (i=0; i<nhash; i++)
    ttype(ref(&v[i])) = LUA_T_NIL;
  return v;
}

/*
** Delete a hash
*/
static void hashdelete (Hash *t)
{
  luaM_free(nodevector(t));
  luaM_free(t);
}


void luaH_free (Hash *frees)
{
  while (frees) {
    Hash *next = (Hash *)frees->head.next;
    L->nblocks -= gcsize(frees->nhash);
    hashdelete(frees);
    frees = next;
  }
}


Hash *luaH_new (int nhash)
{
  Hash *t = luaM_new(Hash);
  nhash = luaO_redimension((int)((float)nhash/REHASH_LIMIT));
  nodevector(t) = hashnodecreate(nhash);
  nhash(t) = nhash;
  nuse(t) = 0;
  t->htag = TagDefault;
  luaO_insertlist(&(L->roottable), (GCnode *)t);
  L->nblocks += gcsize(nhash);
  return t;
}


static int newsize (Hash *t)
{
  Node *v = t->node;
  int size = nhash(t);
  int realuse = 0;
  int i;
  for (i=0; i<size; i++) {
    if (ttype(ref(v+i)) != LUA_T_NIL && ttype(val(v+i)) != LUA_T_NIL)
      realuse++;
  }
  if (2*(realuse+1) <= size)  /* +1 is the new element */
    return size;  /* don't need to grow, just rehash */
  else
    return luaO_redimension(size);
}

static void rehash (Hash *t)
{
  int nold = nhash(t);
  Node *vold = nodevector(t);
  int nnew = newsize(t);
  int i;
  nodevector(t) = hashnodecreate(nnew);
  nhash(t) = nnew;
  for (i=0; i<nold; i++) {
    Node *n = vold+i;
    if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL)
      *node(t, present(t, ref(n))) = *n;  /* copy old node to luaM_new hash */
  }
  L->nblocks += gcsize(nnew)-gcsize(nold);
  luaM_free(vold);
}

/*
** If the hash node is present, return its pointer, otherwise return
** null.
*/
TObject *luaH_get (Hash *t, TObject *ref)
{
 int h = present(t, ref);
 if (ttype(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
 else return NULL;
}


/*
** If the hash node is present, return its pointer, otherwise create a luaM_new
** node for the given reference and also return its pointer.
*/
TObject *luaH_set (Hash *t, TObject *ref)
{
  Node *n = node(t, present(t, ref));
  if (ttype(ref(n)) == LUA_T_NIL) {
    nuse(t)++;
    if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT) {
      rehash(t);
      n = node(t, present(t, ref));
    }
    *ref(n) = *ref;
    ttype(val(n)) = LUA_T_NIL;
  }
  return (val(n));
}


static Node *hashnext (Hash *t, int i)
{
  Node *n;
  int tsize = nhash(t);
  if (i >= tsize)
    return NULL;
  n = node(t, i);
  while (ttype(ref(n)) == LUA_T_NIL || ttype(val(n)) == LUA_T_NIL) {
    if (++i >= tsize)
      return NULL;
    n = node(t, i);
  }
  return node(t, i);
}

Node *luaH_next (TObject *o, TObject *r)
{
  Hash *t = avalue(o);
  if (ttype(r) == LUA_T_NIL)
    return hashnext(t, 0);
  else {
    int i = present(t, r);
    Node *n = node(t, i);
    luaL_arg_check(ttype(ref(n))!=LUA_T_NIL && ttype(val(n))!=LUA_T_NIL,
                   2, "key not found");
    return hashnext(t, i+1);
  }
}

--- NEW FILE: ltable.h ---
/*
** $Id: ltable.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/

#ifndef ltable_h
#define ltable_h

#include "lobject.h"


#define node(t,i)       (&(t)->node[i])
#define ref(n)		(&(n)->ref)
#define val(n)		(&(n)->val)
#define nhash(t)	((t)->nhash)

Hash *luaH_new (int nhash);
void luaH_free (Hash *frees);
TObject *luaH_get (Hash *t, TObject *ref);
TObject *luaH_set (Hash *t, TObject *ref);
Node *luaH_next (TObject *o, TObject *r);

#endif

--- NEW FILE: ltask.cpp ---
#include "ltask.h"
#include "lmem.h"
#include "ldo.h"
#include "lvm.h"

int task_tag;

void start_script (void) {
  struct lua_Task *old_task = L->curr_task, *new_task;
  TObject *f;
  int i;

  f = L->stack.stack + L->Cstack.lua2C;
  if (ttype(f) == LUA_T_CLOSURE)
    f = &clvalue(f)->consts[0];
  if (ttype(f) != LUA_T_PROTO)
    lua_error("can only start_script with a Lua function");

  /* Create a new task with an empty stack */
  new_task = luaI_newtask();

  /* Put the function and arguments onto the new task's stack */
  for (i = 0; i < old_task->Cstack.num; i++) {
    *(L->stack.top) = *(old_task->stack.stack + old_task->Cstack.lua2C + i);
    incr_top;
  }

  /* Create a CallInfo frame */
  luaD_precall(L->stack.stack, 1, MULT_RET);
  ttype(L->stack.stack) = (ttype(L->stack.stack) == LUA_T_CLOSURE) ?
    LUA_T_CLMARK : LUA_T_PMARK;

  /* Switch back to the old task */
  L->Tstate = YIELD;
  luaI_switchtask(old_task);
  L->curr_task = old_task;

  /* Insert new task at end of list */
  L->last_task->next = new_task;
  L->last_task = new_task;

  /* Return task handle */
  lua_pushusertag(new_task, task_tag);
}

void stop_script (void) {
  struct lua_Task *prev, *t;
  TObject *f = L->stack.stack + L->Cstack.lua2C;
  int match;

  if (ttype(f) != LUA_T_CLOSURE && ttype(f) != LUA_T_PROTO &&
      ! (ttype(f) == LUA_T_USERDATA && f->value.ts->u.d.tag == task_tag))
    lua_error("Bad argument to stop_script");
  prev = L->root_task;
  while ((t = prev->next) != NULL) {
    switch (ttype(f)) {
    case LUA_T_CLOSURE:
      match = (ttype(t->stack.stack) == LUA_T_CLMARK &&
	       clvalue(t->stack.stack) == clvalue(f));
      break;
    case LUA_T_PROTO:
      match = (ttype(t->stack.stack) == LUA_T_PMARK &&
	       tfvalue(t->stack.stack) == tfvalue(f));
      break;
    case LUA_T_USERDATA:
      match = (t == f->value.ts->u.d.v);
      break;
    default:  /* Shut up gcc */
      break;
    }
    if (match) {
      prev->next = t->next;  /* Remove from list of active tasks */
      t->next = NULL;
      if (prev->next == NULL)
	L->last_task = prev;
      if (t == L->curr_task)
	L->Tstate = DONE;
      else {
	t->Tstate = DONE;
	if (t->auto_delete)
	  luaM_free(t);
      }
    }
    else
      prev = t;
  }
}

void next_script (void) {
  struct lua_Task *t;

  if (lua_isnil(lua_getparam(1)))
    t = L->root_task;
  else if (lua_isuserdata(lua_getparam(1)) &&
	   lua_tag(lua_getparam(1)) == task_tag)
    t = (struct lua_Task *) lua_getuserdata(lua_getparam(1));
  else
    lua_error("Bad argument to next_script");
  t = t->next;
  if (t == NULL)
    lua_pushnil();
  else {
    t->auto_delete = 0;
    lua_pushusertag(t, task_tag);
  }
}

void identify_script (void) {
  struct lua_Task *t;

  if (! lua_isuserdata(lua_getparam(1)) ||
      lua_tag(lua_getparam(1)) != task_tag)
    lua_error("Bad argument to identify_script");
  t = (struct lua_Task *) lua_getuserdata(lua_getparam(1));
  if (t->Tstate == DONE)
    ttype(L->stack.top) = LUA_T_NIL;
  else
    *L->stack.top = *t->stack.stack;
  incr_top;
}

void find_script (void) {
  struct lua_Task *t;
  TObject *f = L->stack.stack + L->Cstack.lua2C;

  switch (ttype(f)) {
  case LUA_T_CLOSURE:
    for (t = L->root_task->next; t != NULL; t = t->next)
      if ((ttype(t->stack.stack) == LUA_T_CLOSURE ||
	   ttype(t->stack.stack) == LUA_T_CMARK) &&
	  clvalue(t->stack.stack) == clvalue(f))
	break;
    break;
  case LUA_T_PROTO:
    for (t = L->root_task->next; t != NULL; t = t->next)
      if ((ttype(t->stack.stack) == LUA_T_PROTO ||
	   ttype(t->stack.stack) == LUA_T_PMARK) &&
	  tfvalue(t->stack.stack) == tfvalue(f))
	break;
    break;
  case LUA_T_USERDATA:
    if (f->value.ts->u.d.tag != task_tag)
      lua_error("Bad argument to find_script");
    /* Shortcut: just see whether it's still running */
    t = (lua_Task *)f->value.ts->u.d.v;
    if (t->Tstate == DONE)
      lua_pushnil();
    else
      lua_pushusertag(t, task_tag);
    return;
  default:
    lua_error("Bad argument to find_script");
  }
  if (t == NULL)
    lua_pushnil();
  else {
    t->auto_delete = 0;
    lua_pushusertag(t, task_tag);
  }
}

void break_here (void) {
  struct CallInfo *ci;

  if (L->curr_task == L->root_task)
    lua_error("Cannot break in root thread");
  /* Check for any C functions in the call stack */
  for (ci = L->ci-1; ci > L->base_ci; ci--)
    if (ci->tf == NULL)
      lua_error("Cannot yield through C function");

  L->Tstate = YIELD;
}

void GetCurrentScript (void) {
  if (L->curr_task == L->root_task)
    lua_pushnil();
  else {
    L->curr_task->auto_delete = 0;
    lua_pushusertag(L->curr_task, task_tag);
  }
}

void lua_runtasks (void) {
  struct lua_Task *t, *prev;
  struct lua_Task *old_task = L->curr_task;
  jmp_buf myErrorJmp;

  prev = L->root_task;
  while ((t = prev->next) != NULL) {
    luaI_switchtask(t);
    L->errorJmp = &myErrorJmp;
    L->Tstate = RUN;
    if (setjmp(myErrorJmp) == 0) {
      luaV_execute(L->base_ci+1);
      if (L->Tstate == RUN)	/* Must have run to completion */
	L->Tstate = DONE;
    }
    else /* an error occurred */
      L->Tstate = DONE;
    L->errorJmp = NULL;
    if (L->Tstate == DONE) {	/* Remove from list of active tasks */
      luaI_switchtask(old_task);
      prev->next = t->next;
      t->next = NULL;
      if (prev->next == NULL)
	L->last_task = prev;
      if (t->auto_delete)
	luaM_free(t);
    }
    else
      prev = t;
  }
  if (L->curr_task != old_task)
    luaI_switchtask(old_task);
}

void gc_task (void) {
  struct lua_Task *t = (struct lua_Task *) lua_getuserdata(lua_getparam(1));

  t->auto_delete = 1;
  if (t != L->curr_task && t->Tstate == DONE)
    luaM_free(t);
}

--- NEW FILE: ltask.h ---
#ifndef ltask_h
#define ltask_h

#include "lua.h"
#include "lstate.h"

extern int task_tag;

void start_script (void);
void stop_script (void);
void next_script (void);
void identify_script (void);
void find_script (void);
void break_here (void);
void GetCurrentScript (void);

void gc_task (void);

#endif

--- NEW FILE: ltm.cpp ---
/*
** $Id: ltm.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Tag methods
** See Copyright Notice in lua.h
*/


#include <stdio.h>
#include <string.h>

#include "lauxlib.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "ltm.h"


char *luaT_eventname[] = {  /* ORDER IM */
  "gettable", "settable", "index", "getglobal", "setglobal", "add",
  "sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge",
  "concat", "gc", "function", NULL
};


static int luaI_checkevent (char *name, char *list[])
{
  int e = luaL_findstring(name, list);
  if (e < 0)
    luaL_verror("`%.50s' is not a valid event name", name);
  return e;
}



/* events in LUA_T_NIL are all allowed, since this is used as a
*  'placeholder' for "default" fallbacks
*/
static char validevents[NUM_TAGS][IM_N] = { /* ORDER LUA_T, ORDER IM */
{1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},  /* LUA_T_USERDATA */
{1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},  /* LUA_T_NUMBER */
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},  /* LUA_T_STRING */
{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},  /* LUA_T_ARRAY */
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},  /* LUA_T_PROTO */
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},  /* LUA_T_CPROTO */
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}   /* LUA_T_NIL */
};


static int validevent (int t, int e)
{ /* ORDER LUA_T */
  return (t < LUA_T_NIL) ?  1 : validevents[-t][e];
}


static void init_entry (int tag)
{
  int i;
  for (i=0; i<IM_N; i++)
    ttype(luaT_getim(tag, i)) = LUA_T_NIL;
}


void luaT_init (void)
{
  int t;
  L->IMtable_size = NUM_TAGS*2;
  L->last_tag = -(NUM_TAGS-1);
  L->IMtable = luaM_newvector(L->IMtable_size, struct IM);
  for (t=L->last_tag; t<=0; t++)
    init_entry(t);
}


int lua_newtag (void)
{
  --L->last_tag;
  if ((-L->last_tag) >= L->IMtable_size)
    L->IMtable_size = luaM_growvector(&L->IMtable, L->IMtable_size,
                                   struct IM, memEM, MAX_INT);
  init_entry(L->last_tag);
  return L->last_tag;
}


static void checktag (int tag)
{
  if (!(L->last_tag <= tag && tag <= 0))
    luaL_verror("%d is not a valid tag", tag);
}

void luaT_realtag (int tag)
{
  if (!(L->last_tag <= tag && tag < LUA_T_NIL))
    luaL_verror("tag %d is not result of `newtag'", tag);
}


int lua_copytagmethods (int tagto, int tagfrom)
{
  int e;
  checktag(tagto);
  checktag(tagfrom);
  for (e=0; e<IM_N; e++) {
    if (validevent(tagto, e))
      *luaT_getim(tagto, e) = *luaT_getim(tagfrom, e);
  }
  return tagto;
}


int luaT_efectivetag (TObject *o)
{
  int t;
  switch (t = ttype(o)) {
    case LUA_T_ARRAY:
      return o->value.a->htag;
    case LUA_T_USERDATA: {
      int tag = o->value.ts->u.d.tag;
      return (tag >= 0) ? LUA_T_USERDATA : tag;
    }
    case LUA_T_CLOSURE:
      return o->value.cl->consts[0].ttype;
#ifdef DEBUG
    case LUA_T_PMARK: case LUA_T_CMARK:
    case LUA_T_CLMARK: case LUA_T_LINE:
      LUA_INTERNALERROR("invalid type");
#endif
    default:
      return t;
  }
}


TObject *luaT_gettagmethod (int t, char *event)
{
  int e = luaI_checkevent(event, luaT_eventname);
  checktag(t);
  if (validevent(t, e))
    return luaT_getim(t,e);
  else
    return &luaO_nilobject;
}


void luaT_settagmethod (int t, char *event, TObject *func)
{
  TObject temp = *func;
  int e = luaI_checkevent(event, luaT_eventname);
  checktag(t);
  if (!validevent(t, e))
    luaL_verror("settagmethod: cannot change tag method `%.20s' for tag %d",
                luaT_eventname[e], t);
  *func = *luaT_getim(t,e);
  *luaT_getim(t, e) = temp;
}


char *luaT_travtagmethods (int (*fn)(TObject *))
{
  int e;
  if (fn(&L->errorim))
    return "error";
  for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) {  /* ORDER IM */
    int t;
    for (t=0; t>=L->last_tag; t--)
      if (fn(luaT_getim(t,e)))
        return luaT_eventname[e];
  }
  return NULL;
}


/*
* ===================================================================
* compatibility with old fallback system
*/
#ifdef LUA_COMPAT2_5

#include "lapi.h"

static void errorFB (void)
{
  lua_Object o = lua_getparam(1);
  if (lua_isstring(o))
    fprintf(stderr, "lua: %s\n", lua_getstring(o));
  else
    fprintf(stderr, "lua: unknown error\n");
}


static void nilFB (void) { }


static void typeFB (void)
{
  lua_error("unexpected type");
}


static void fillvalids (IMS e, TObject *func)
{
  int t;
  for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
    if (validevent(t, e))
      *luaT_getim(t, e) = *func;
}


void luaT_setfallback (void)
{
  static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL};
  TObject oldfunc;
  lua_CFunction replace;
  char *name = luaL_check_string(1);
  lua_Object func = lua_getparam(2);
  luaL_arg_check(lua_isfunction(func), 2, "function expected");
  switch (luaL_findstring(name, oldnames)) {
    case 0:  /* old error fallback */
      oldfunc = L->errorim;
      L->errorim = *luaA_Address(func);
      replace = errorFB;
      break;
    case 1:  /* old getglobal fallback */
      oldfunc = *luaT_getim(LUA_T_NIL, IM_GETGLOBAL);
      *luaT_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaA_Address(func);
      replace = nilFB;
      break;
    case 2: {  /* old arith fallback */
      int i;
      oldfunc = *luaT_getim(LUA_T_NUMBER, IM_POW);
      for (i=IM_ADD; i<=IM_UNM; i++)  /* ORDER IM */
        fillvalids(i, luaA_Address(func));
      replace = typeFB;
      break;
    }
    case 3: {  /* old order fallback */
      int i;
      oldfunc = *luaT_getim(LUA_T_NIL, IM_LT);
      for (i=IM_LT; i<=IM_GE; i++)  /* ORDER IM */
        fillvalids(i, luaA_Address(func));
      replace = typeFB;
      break;
    }
    default: {
      int e;
      if ((e = luaL_findstring(name, luaT_eventname)) >= 0) {
        oldfunc = *luaT_getim(LUA_T_NIL, e);
        fillvalids(e, luaA_Address(func));
        replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB;
      }
      else {
        luaL_verror("`%.50s' is not a valid fallback name", name);
        replace = NULL;  /* to avoid warnings */
      }
    }
  }
  if (oldfunc.ttype != LUA_T_NIL)
    luaA_pushobject(&oldfunc);
  else
    lua_pushcfunction(replace);
}
#endif


--- NEW FILE: ltm.h ---
/*
** $Id: ltm.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Tag methods
** See Copyright Notice in lua.h
*/

#ifndef ltm_h
#define ltm_h


#include "lobject.h"
#include "lstate.h"

/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER IM"
*/
typedef enum {
  IM_GETTABLE = 0,
  IM_SETTABLE,
  IM_INDEX,
  IM_GETGLOBAL,
  IM_SETGLOBAL,
  IM_ADD,
  IM_SUB,
  IM_MUL,
  IM_DIV,
  IM_POW,
  IM_UNM,
  IM_LT,
  IM_LE,
  IM_GT,
  IM_GE,
  IM_CONCAT,
  IM_GC,
  IM_FUNCTION
} IMS;

#define IM_N 18


struct IM {
  TObject int_method[IM_N];
};


#define luaT_getim(tag,event) (&L->IMtable[-(tag)].int_method[event])
#define luaT_getimbyObj(o,e)  (luaT_getim(luaT_efectivetag(o),(e)))

extern char *luaT_eventname[];


void luaT_init (void);
void luaT_realtag (int tag);
int luaT_efectivetag (TObject *o);
void luaT_settagmethod (int t, char *event, TObject *func);
TObject *luaT_gettagmethod (int t, char *event);
char *luaT_travtagmethods (int (*fn)(TObject *));

void luaT_setfallback (void);  /* only if LUA_COMPAT2_5 */

#endif

--- NEW FILE: lua.h ---
/*
** $Id: lua.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua at tecgraf.puc-rio.br
** www: http://www.tecgraf.puc-rio.br/lua/
** See Copyright Notice at the end of this file
*/


#ifndef lua_h
#define lua_h

#define LUA_VERSION	"Lua 3.1"
#define LUA_COPYRIGHT	"Copyright (C) 1994-1998 TeCGraf, PUC-Rio"
#define LUA_AUTHORS 	"W. Celes, R. Ierusalimschy & L. H. de Figueiredo"


#define LUA_NOOBJECT  0

#define LUA_ANYTAG    (-1)

typedef void (*lua_CFunction) (void);
typedef unsigned int lua_Object;

typedef struct lua_State lua_State;
extern lua_State *lua_state;

void	       lua_open			(void);
void           lua_close		(void);
lua_State      *lua_setstate		(lua_State *st);

lua_Object     lua_settagmethod	(int tag, char *event); /* In: new method */
lua_Object     lua_gettagmethod	(int tag, char *event);
lua_Object     lua_seterrormethod (void);  /* In: new method */

int            lua_newtag		(void);
int            lua_copytagmethods	(int tagto, int tagfrom);
void           lua_settag		(int tag); /* In: object */

void           lua_error		(char *s);
int            lua_dofile 		(char *filename); /* Out: returns */
int            lua_dostring 		(char *string); /* Out: returns */
int            lua_dobuffer		(char *buff, int size, char *name);
					  /* Out: returns */
int            lua_callfunction		(lua_Object f);
					  /* In: parameters; Out: returns */

void	       lua_beginblock		(void);
void	       lua_endblock		(void);

lua_Object     lua_lua2C 		(int number);
#define	       lua_getparam(_)		lua_lua2C(_)
#define	       lua_getresult(_)		lua_lua2C(_)

int            lua_isnil                (lua_Object object);
int            lua_istable              (lua_Object object);
int            lua_isuserdata           (lua_Object object);
int            lua_iscfunction          (lua_Object object);
int            lua_isnumber             (lua_Object object);
int            lua_isstring             (lua_Object object);
int            lua_isfunction           (lua_Object object);

double         lua_getnumber 		(lua_Object object);
char          *lua_getstring 		(lua_Object object);
long           lua_strlen 		(lua_Object object);
lua_CFunction  lua_getcfunction 	(lua_Object object);
void	      *lua_getuserdata		(lua_Object object);


void 	       lua_pushnil 		(void);
void           lua_pushnumber 		(double n);
void           lua_pushlstring		(char *s, long len);
void           lua_pushstring 		(char *s);
void           lua_pushcclosure		(lua_CFunction fn, int n);
void           lua_pushusertag          (void *u, int tag);
void           lua_pushobject       	(lua_Object object);

lua_Object     lua_pop			(void);

lua_Object     lua_getglobal 		(char *name);
lua_Object     lua_rawgetglobal		(char *name);
void           lua_setglobal		(char *name); /* In: value */
void           lua_rawsetglobal		(char *name); /* In: value */

void           lua_settable	(void); /* In: table, index, value */
void           lua_rawsettable	(void); /* In: table, index, value */
lua_Object     lua_gettable 		(void); /* In: table, index */
lua_Object     lua_rawgettable		(void); /* In: table, index */

int            lua_tag			(lua_Object object);


int            lua_ref			(int lock); /* In: value */
lua_Object     lua_getref		(int ref);
void	       lua_unref		(int ref);

lua_Object     lua_createtable		(void);

long	       lua_collectgarbage	(long limit);

void	       lua_runtasks		(void);


/* =============================================================== */
/* some useful macros/derived functions */

int     (lua_call) (char *name);
#define lua_call(name)		lua_callfunction(lua_getglobal(name))

void    (lua_pushref) (int ref);
#define lua_pushref(ref)	lua_pushobject(lua_getref(ref))

int     (lua_refobject) (lua_Object o, int l);
#define lua_refobject(o,l)	(lua_pushobject(o), lua_ref(l))

void    (lua_register) (char *n, lua_CFunction f);
#define lua_register(n,f)	(lua_pushcfunction(f), lua_setglobal(n))

void    (lua_pushuserdata) (void *u);
#define lua_pushuserdata(u)     lua_pushusertag(u, 0)

void    (lua_pushcfunction) (lua_CFunction f);
#define lua_pushcfunction(f)	lua_pushcclosure(f, 0)

int     (lua_clonetag) (int t);
#define lua_clonetag(t)		lua_copytagmethods(lua_newtag(), (t))


/* ==========================================================================
** for compatibility with old versions. Avoid using these macros/functions
** If your program does need any of these, define LUA_COMPAT2_5
*/


#ifdef LUA_COMPAT2_5


lua_Object     lua_setfallback		(char *event, lua_CFunction fallback);

#define lua_storeglobal		lua_setglobal
#define lua_type		lua_tag

#define lua_lockobject(o)  lua_refobject(o,1)
#define	lua_lock() lua_ref(1)
#define lua_getlocked lua_getref
#define	lua_pushlocked lua_pushref
#define	lua_unlock lua_unref

#define lua_pushliteral(o)  lua_pushstring(o)

#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_gettable())
#define lua_getfield(o,f)   (lua_pushobject(o), lua_pushstring(f), lua_gettable())

#define lua_copystring(o) (strdup(lua_getstring(o)))

#define lua_getsubscript  lua_gettable
#define lua_storesubscript  lua_settable

#endif

#endif



/******************************************************************************
* Copyright (c) 1994-1998 TeCGraf, PUC-Rio.  All rights reserved.
* 
* Permission is hereby granted, without written agreement and without license
* or royalty fees, to use, copy, modify, and distribute this software and its
* documentation for any purpose, including commercial applications, subject to
* the following conditions:
* 
*  - The above copyright notice and this permission notice shall appear in all
*    copies or substantial portions of this software.
* 
*  - The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software in a
*    product, an acknowledgment in the product documentation would be greatly
*    appreciated (but it is not required).
* 
*  - Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
*    
* The authors specifically disclaim any warranties, including, but not limited
* to, the implied warranties of merchantability and fitness for a particular
* purpose.  The software provided hereunder is on an "as is" basis, and the
* authors have no obligation to provide maintenance, support, updates,
* enhancements, or modifications.  In no event shall TeCGraf, PUC-Rio, or the
* authors be held liable to any party for direct, indirect, special,
* incidental, or consequential damages arising out of the use of this software
* and its documentation.
* 
* The Lua language and this implementation have been entirely designed and
* written by Waldemar Celes Filho, Roberto Ierusalimschy and
* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio.
* This implementation contains no third-party code.
******************************************************************************/

--- NEW FILE: luadebug.h ---
/*
** $Id: luadebug.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Debugging API
** See Copyright Notice in lua.h
*/


#ifndef luadebug_h
#define luadebug_h


#include "lua.h"

typedef lua_Object lua_Function;

typedef void (*lua_LHFunction) (int line);
typedef void (*lua_CHFunction) (lua_Function func, char *file, int line);

lua_Function lua_stackedfunction (int level);
void lua_funcinfo (lua_Object func, char **filename, int *linedefined);
int lua_currentline (lua_Function func);
char *lua_getobjname (lua_Object o, char **name);

lua_Object lua_getlocal (lua_Function func, int local_number, char **name);
int lua_setlocal (lua_Function func, int local_number);


extern lua_LHFunction lua_linehook;
extern lua_CHFunction lua_callhook;
extern int lua_debug;


#endif

--- NEW FILE: lualib.h ---
/*
** $Id: lualib.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/


#ifndef lualib_h
#define lualib_h

#include "lua.h"


void lua_iolibopen   (void);
void lua_strlibopen  (void);
void lua_mathlibopen (void);




/* To keep compatibility with old versions */

#define iolib_open	lua_iolibopen
#define strlib_open	lua_strlibopen
#define mathlib_open	lua_mathlibopen



/* Auxiliary functions (private) */

int luaI_singlematch (int c, char *p, char **ep);

#endif


--- NEW FILE: lundump.cpp ---
/*
** $Id: lundump.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** load bytecodes from files
** See Copyright Notice in lua.h
*/

#include <stdio.h>
#include <string.h>
#include "lauxlib.h"
#include "lfunc.h"
#include "lmem.h"
#include "lstring.h"
#include "lundump.h"

#include <SDL_byteorder.h>

#define	LoadBlock(b,size,Z)	ezread(Z,b,size)
#define	LoadNative(t,Z)		LoadBlock(&t,sizeof(t),Z)

#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
	#define doLoadNumber(f,Z)	LoadNative(f,Z)
#else
	#define doLoadNumber(f,Z)	f=LoadNumber(Z)
#endif


static float conv_float(const char *data) {
        const unsigned char *udata = (const unsigned char *)(data);
        unsigned char fdata[4];
        fdata[0] = udata[3];
        fdata[1] = udata[2];
        fdata[2] = udata[1];
        fdata[3] = udata[0];
        return *(const float *)(fdata);
}

static void unexpectedEOZ(ZIO* Z)
{
 luaL_verror("unexpected end of file in %s",zname(Z));
}

static int ezgetc(ZIO* Z)
{
 int c=zgetc(Z);
 if (c==EOZ) unexpectedEOZ(Z);
 return c;
}

static void ezread(ZIO* Z, void* b, int n)
{
 int r=zread(Z,b,n);
 if (r!=0) unexpectedEOZ(Z);
}

static unsigned int LoadWord(ZIO* Z)
{
 unsigned int hi=ezgetc(Z);
 unsigned int lo=ezgetc(Z);
 return (hi<<8)|lo;
}

static unsigned long LoadLong(ZIO* Z)
{
 unsigned long hi=LoadWord(Z);
 unsigned long lo=LoadWord(Z);
 return (hi<<16)|lo;
}

#if ID_NUMBER==ID_REAL4
/* LUA_NUMBER */
/* assumes sizeof(long)==4 and sizeof(float)==4 (IEEE) */
static float LoadFloat(ZIO* Z)
{
 unsigned long l=LoadLong(Z);
 return conv_float((const char *)&l);
}
#endif

#if ID_NUMBER==ID_REAL8
/* LUA_NUMBER */
/* assumes sizeof(long)==4 and sizeof(double)==8 (IEEE) */
static double LoadDouble(ZIO* Z)
{
 unsigned long l[2];
 double f;
 int x=1;
 if (*(char*)&x==1)			/* little-endian */
 {
  l[1]=LoadLong(Z);
  l[0]=LoadLong(Z);
 }
 else					/* big-endian */
 {
  l[0]=LoadLong(Z);
  l[1]=LoadLong(Z);
 }
 memcpy(&f,l,sizeof(f));
 return f;
}
#endif

static Byte* LoadCode(ZIO* Z)
{
 unsigned long size=LoadLong(Z);
 unsigned int s=size;
 void* b;
 if (s!=size) luaL_verror("code too long (%ld bytes) in %s",size,zname(Z));
 b=luaM_malloc(size);
 LoadBlock(b,size,Z);
 return (Byte *)b;
}

static TaggedString* LoadTString(ZIO* Z)
{
 int size=LoadWord(Z);
 int i;
 if (size==0)
  return NULL;
 else
 {
  char* s=luaL_openspace(size);
  LoadBlock(s,size,Z);
  for (i=0; i<size; i++)
   s[i]^=0xff;
  return luaS_newlstr(s,size-1);
 }
}

static void LoadLocals(TProtoFunc* tf, ZIO* Z)
{
 int i,n=LoadWord(Z);
 if (n==0) return;
 tf->locvars=luaM_newvector(n+1,LocVar);
 for (i=0; i<n; i++)
 {
  tf->locvars[i].line=LoadWord(Z);
  tf->locvars[i].varname=LoadTString(Z);
 }
 tf->locvars[i].line=-1;		/* flag end of vector */
 tf->locvars[i].varname=NULL;
}

static TProtoFunc* LoadFunction(ZIO* Z);

static void LoadConstants(TProtoFunc* tf, ZIO* Z)
{
 int i,n=LoadWord(Z);
 tf->nconsts=n;
 if (n==0) return;
 tf->consts=luaM_newvector(n,TObject);
 for (i=0; i<n; i++)
 {
  TObject* o=tf->consts+i;
  ttype(o)=(lua_Type)-ezgetc(Z);
  switch (ttype(o))
  {
   case -'N':
        ttype(o)=LUA_T_NUMBER;
   case LUA_T_NUMBER:
	doLoadNumber(nvalue(o),Z);
	break;
   case -'S':
	ttype(o)=LUA_T_STRING;
   case LUA_T_STRING:
	tsvalue(o)=LoadTString(Z);
	break;
   case -'F':
	ttype(o)=LUA_T_PROTO;
   case LUA_T_PROTO:
	break;
   case LUA_T_NIL:
	break;
   default:
	luaL_verror("bad constant #%d in %s: type=%d [%s]",
		i,zname(Z),ttype(o),luaO_typename(o));
	break;
  }
 }
}

static void LoadSubfunctions(TProtoFunc* tf, ZIO* Z) {
  char t;
  do {
    t = ezgetc(Z);
    switch (t) {
    case '#': {
      int i = LoadWord(Z);
      if (ttype(tf->consts+i) != LUA_T_PROTO)
	luaL_verror("trying to load function into nonfunction constant (type=%d)",
		    ttype(tf->consts+i));
      tfvalue(tf->consts+i) = LoadFunction(Z);
      break;
    }
    case '$':
      break;
    default:
      luaL_verror("invalid subfunction type %c",t);
    }
  } while (t != '$');
}

static TProtoFunc* LoadFunction(ZIO* Z)
{
 TProtoFunc* tf=luaF_newproto();
 tf->lineDefined=LoadWord(Z);
 tf->fileName=LoadTString(Z);
 tf->code=LoadCode(Z);
 LoadConstants(tf,Z);
 LoadLocals(tf,Z);
 LoadSubfunctions(tf,Z);
 return tf;
}

static void LoadSignature(ZIO* Z)
{
 char* s=SIGNATURE;
 while (*s!=0 && ezgetc(Z)==*s)
  ++s;
 if (*s!=0) luaL_verror("bad signature in %s",zname(Z));
}

static void LoadHeader(ZIO* Z)
{
 int version,id,sizeofR;
 real f=(real)-TEST_NUMBER,tf=(real)TEST_NUMBER;
 LoadSignature(Z);
 version=ezgetc(Z);
 if (version>VERSION)
  luaL_verror(
	"%s too new: version=0x%02x; expected at most 0x%02x",
	zname(Z),version,VERSION);
 if (version<VERSION0)			/* check last major change */
  luaL_verror(
	"%s too old: version=0x%02x; expected at least 0x%02x",
	zname(Z),version,VERSION0);
 sizeofR=ezgetc(Z);			/* test number representation */
 id=ezgetc(Z);
 if (id!=ID_NUMBER || sizeofR!=sizeof(real))
 {
  luaL_verror("unknown number signature in %s: "
	"read 0x%02x%02x; expected 0x%02x%02x",
	zname(Z),id,sizeofR,ID_NUMBER,sizeof(real));
 }
#if 0
 doLoadNumber(f,Z);
 if (f!=tf)
  luaL_verror("unknown number representation in %s: "
	"read " NUMBER_FMT "; expected " NUMBER_FMT,	/* LUA_NUMBER */
	zname(Z),f,tf);
#endif
  ezgetc(Z); ezgetc(Z); ezgetc(Z);
}

static TProtoFunc* LoadChunk(ZIO* Z)
{
 LoadHeader(Z);
 return LoadFunction(Z);
}

/*
** load one chunk from a file or buffer
** return main if ok and NULL at EOF
*/
TProtoFunc* luaU_undump1(ZIO* Z)
{
 int c=zgetc(Z);
 if (c==ID_CHUNK)
  return LoadChunk(Z);
 else if (c!=EOZ)
  luaL_verror("%s is not a Lua binary file",zname(Z));
 return NULL;
}

--- NEW FILE: lundump.h ---
/*
** $Id: lundump.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/

#ifndef lundump_h
#define lundump_h

#include "lobject.h"
#include "lzio.h"

TProtoFunc* luaU_undump1(ZIO* Z);	/* load one chunk */

#define	SIGNATURE	"Lua"
#define	VERSION		0x31		/* last format change was in 3.1 */
#define	VERSION0	0x31		/* last major  change was in 3.1 */
#define ID_CHUNK	27		/* ESC */

#define IsMain(f)	(f->lineDefined==0)
#define luaO_typename(o)	luaO_typenames[-ttype(o)]

/* number representation */
#define ID_INT4		'l'		/* 4-byte integers */
#define ID_REAL4	'F'		/* 4-byte reals */
#define ID_REAL8	'd'		/* 8-byte reals */
#define ID_NATIVE	'?'		/* whatever your machine uses */

/*
* use a multiple of PI for testing number representation.
* multiplying by 1E8 gives notrivial integer values.
*/
#define	TEST_NUMBER	3.14159265358979323846E8

/* LUA_NUMBER
* choose one below for the number representation in precompiled chunks.
* the default is ID_REAL8 because the default for LUA_NUM_TYPE is double.
* if your machine does not use IEEE 754, use ID_NATIVE.
* the next version will support conversion to/from IEEE 754.
*
* if you change LUA_NUM_TYPE, make sure you set ID_NUMBER accordingly,
* specially if sizeof(long)!=4.
* for types other than the ones listed below, you'll have to write your own
* dump and undump routines.
*/

#ifndef ID_NUMBER
#define	ID_NUMBER	ID_REAL4
#endif

#if 0
#define	ID_NUMBER	ID_INT4
#define	ID_NUMBER	ID_REAL4
#define	ID_NUMBER	ID_REAL8
#define	ID_NUMBER	ID_NATIVE
#endif

#endif

#if   ID_NUMBER==ID_REAL4
	#define	DumpNumber	DumpFloat
	#define	LoadNumber	LoadFloat
	#define SIZEOF_NUMBER	4
#elif ID_NUMBER==ID_REAL8
	#define	DumpNumber	DumpDouble
	#define	LoadNumber	LoadDouble
	#define SIZEOF_NUMBER	8
#elif ID_NUMBER==ID_INT4
	#define	DumpNumber	DumpLong
	#define	LoadNumber	LoadLong
	#define SIZEOF_NUMBER	4
#elif ID_NUMBER==ID_NATIVE
	#define	DumpNumber	DumpNative
	#define	LoadNumber	LoadNative
	#define SIZEOF_NUMBER	sizeof(real)
#else
	#error	bad ID_NUMBER
#endif

--- NEW FILE: lvm.cpp ---
/*
** $Id: lvm.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/


#include <stdio.h>
#include <string.h>

#include <SDL_byteorder.h>

#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "luadebug.h"
#include "lvm.h"

#ifdef OLD_ANSI
#define strcoll(a,b)	strcmp(a,b)
#endif


#define skip_word(pc)	(pc+=2)

#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
#define get_word(pc)	(*((unsigned short*)(pc)))
#else
#define get_word(pc)    ((*((pc)+1)<<8)|(*(pc)))
#endif

#define next_word(pc)   (pc+=2, get_word(pc-2))


static TaggedString *strconc (TaggedString *l, TaggedString *r)
{
  size_t nl = l->u.s.len;
  size_t nr = r->u.s.len;
  char *buffer = luaL_openspace(nl+nr+1);
  memcpy(buffer, l->str, nl);
  memcpy(buffer+nl, r->str, nr);
  return luaS_newlstr(buffer, nl+nr);
}


int luaV_tonumber (TObject *obj)
{  /* LUA_NUMBER */
  double t;
  char c;
  if (ttype(obj) != LUA_T_STRING)
    return 1;
  else if (sscanf(svalue(obj), "%lf %c",&t, &c) == 1) {
    nvalue(obj) = (real)t;
    ttype(obj) = LUA_T_NUMBER;
    return 0;
  }
  else
    return 2;
}


int luaV_tostring (TObject *obj)
{ /* LUA_NUMBER */
  /* The Lua scripts for Grim Fandango sometimes end up executing
     str..nil.  The nil shows up in the original engine as "(nil)"... */
  if (ttype(obj) == LUA_T_NIL) {
    tsvalue(obj) = luaS_new("(nil)");
    ttype(obj) = LUA_T_STRING;
    return 0;
  }
  else if (ttype(obj) != LUA_T_NUMBER)
    return 1;
  else {
    char s[60];
    real f = nvalue(obj);
    int i;
    if ((real)(-MAX_INT) <= f && f <= (real)MAX_INT && (real)(i=(int)f) == f)
      sprintf (s, "%d", i);
    else
      sprintf (s, NUMBER_FMT, nvalue(obj));
    tsvalue(obj) = luaS_new(s);
    ttype(obj) = LUA_T_STRING;
    return 0;
  }
}


void luaV_closure (int nelems)
{
  if (nelems > 0) {
    struct Stack *S = &L->stack;
    Closure *c = luaF_newclosure(nelems);
    c->consts[0] = *(S->top-1);
    memcpy(&c->consts[1], S->top-(nelems+1), nelems*sizeof(TObject));
    S->top -= nelems;
    ttype(S->top-1) = LUA_T_CLOSURE;
    (S->top-1)->value.cl = c;
  }
}


/*
** Function to index a table.
** Receives the table at top-2 and the index at top-1.
*/
void luaV_gettable (void)
{
  struct Stack *S = &L->stack;
  TObject *im;
  if (ttype(S->top-2) != LUA_T_ARRAY)  /* not a table, get "gettable" method */
    im = luaT_getimbyObj(S->top-2, IM_GETTABLE);
  else {  /* object is a table... */
    int tg = (S->top-2)->value.a->htag;
    im = luaT_getim(tg, IM_GETTABLE);
    if (ttype(im) == LUA_T_NIL) {  /* and does not have a "gettable" method */
      TObject *h = luaH_get(avalue(S->top-2), S->top-1);
      if (h != NULL && ttype(h) != LUA_T_NIL) {
        --S->top;
        *(S->top-1) = *h;
      }
      else if (ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL)
        luaD_callTM(im, 2, 1);
      else {
        --S->top;
        ttype(S->top-1) = LUA_T_NIL;
      }
      return;
    }
    /* else it has a "gettable" method, go through to next command */
  }
  /* object is not a table, or it has a "gettable" method */
  if (ttype(im) != LUA_T_NIL)
    luaD_callTM(im, 2, 1);
  else
    lua_error("indexed expression not a table");
}


/*
** Function to store indexed based on values at the stack.top
** mode = 0: raw store (without tag methods)
** mode = 1: normal store (with tag methods)
** mode = 2: "deep L->stack.stack" store (with tag methods)
*/
void luaV_settable (TObject *t, int mode)
{
  struct Stack *S = &L->stack;
  TObject *im = (mode == 0) ? NULL : luaT_getimbyObj(t, IM_SETTABLE);
  if (ttype(t) == LUA_T_ARRAY && (im == NULL || ttype(im) == LUA_T_NIL)) {
    TObject *h = luaH_set(avalue(t), t+1);
    *h = *(S->top-1);
    S->top -= (mode == 2) ? 1 : 3;
  }
  else {  /* object is not a table, and/or has a specific "settable" method */
    if (im && ttype(im) != LUA_T_NIL) {
      if (mode == 2) {
        *(S->top+1) = *(L->stack.top-1);
        *(S->top) = *(t+1);
        *(S->top-1) = *t;
        S->top += 2;  /* WARNING: caller must assure stack space */
      }
      luaD_callTM(im, 3, 0);
    }
    else
      lua_error("indexed expression not a table");
  }
}


void luaV_getglobal (TaggedString *ts)
{
  /* WARNING: caller must assure stack space */
  TObject *value = &ts->u.s.globalval;
  TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL);
  if (ttype(im) == LUA_T_NIL) {  /* default behavior */
    *L->stack.top++ = *value;
  }
  else {
    struct Stack *S = &L->stack;
    ttype(S->top) = LUA_T_STRING;
    tsvalue(S->top) = ts;
    S->top++;
    *S->top++ = *value;
    luaD_callTM(im, 2, 1);
  }
}


void luaV_setglobal (TaggedString *ts)
{
  TObject *oldvalue = &ts->u.s.globalval;
  TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
  if (ttype(im) == LUA_T_NIL)  /* default behavior */
    luaS_rawsetglobal(ts, --L->stack.top);
  else {
    /* WARNING: caller must assure stack space */
    struct Stack *S = &L->stack;
    TObject newvalue = *(S->top-1);
    ttype(S->top-1) = LUA_T_STRING;
    tsvalue(S->top-1) = ts;
    *S->top++ = *oldvalue;
    *S->top++ = newvalue;
    luaD_callTM(im, 3, 0);
  }
}


static void call_binTM (IMS event, char *msg)
{
  TObject *im = luaT_getimbyObj(L->stack.top-2, event);/* try first operand */
  if (ttype(im) == LUA_T_NIL) {
    im = luaT_getimbyObj(L->stack.top-1, event);  /* try second operand */
    if (ttype(im) == LUA_T_NIL) {
      im = luaT_getim(0, event);  /* try a 'global' i.m. */
      if (ttype(im) == LUA_T_NIL)
        lua_error(msg);
    }
  }
  lua_pushstring(luaT_eventname[event]);
  luaD_callTM(im, 3, 1);
}


static void call_arith (IMS event)
{
  call_binTM(event, "unexpected type in arithmetic operation");
}


static int strcomp (char *l, long ll, char *r, long lr)
{
  for (;;) {
    long temp = strcoll(l, r);
    if (temp != 0) return temp;
    /* strings are equal up to a '\0' */
    temp = strlen(l);  /* index of first '\0' in both strings */
    if (temp == ll)  /* l is finished? */
      return (temp == lr) ? 0 : -1;  /* l is equal or smaller than r */
    else if (temp == lr)  /* r is finished? */
      return 1;  /* l is greater than r (because l is not finished) */
    /* both strings longer than temp; go on comparing (after the '\0') */
    temp++;
    l += temp; ll -= temp; r += temp; lr -= temp;
  }
}

static void comparison (lua_Type ttype_less, lua_Type ttype_equal,
                        lua_Type ttype_great, IMS op)
{
  struct Stack *S = &L->stack;
  TObject *l = S->top-2;
  TObject *r = S->top-1;
  int result;
  if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER)
    result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1;
  else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING)
    result = strcomp(svalue(l), tsvalue(l)->u.s.len,
                     svalue(r), tsvalue(r)->u.s.len);
  else {
    call_binTM(op, "unexpected type in comparison");
    return;
  }
  S->top--;
  nvalue(S->top-1) = 1;
  ttype(S->top-1) = (result < 0) ? ttype_less :
                                (result == 0) ? ttype_equal : ttype_great;
}


void luaV_pack (StkId firstel, int nvararg, TObject *tab)
{
  TObject *firstelem = L->stack.stack+firstel;
  int i;
  if (nvararg < 0) nvararg = 0;
  avalue(tab)  = luaH_new(nvararg+1);  /* +1 for field 'n' */
  ttype(tab) = LUA_T_ARRAY;
  for (i=0; i<nvararg; i++) {
    TObject index;
    ttype(&index) = LUA_T_NUMBER;
    nvalue(&index) = i+1;
    *(luaH_set(avalue(tab), &index)) = *(firstelem+i);
  }
  /* store counter in field "n" */ {
    TObject index, extra;
    ttype(&index) = LUA_T_STRING;
    tsvalue(&index) = luaS_new("n");
    ttype(&extra) = LUA_T_NUMBER;
    nvalue(&extra) = nvararg;
    *(luaH_set(avalue(tab), &index)) = extra;
  }
}


/*
** Execute the given opcode, until a RET. Parameters are between
** [stack+base,top). Returns n such that the the results are between
** [stack+n,top).
*/
StkId luaV_execute (struct CallInfo *ci)
{
  /* Save index in case CallInfo array is realloc'd */
  int ci_index = ci - L->base_ci;
  struct Stack *S = &L->stack;  /* to optimize */
  Closure *cl;
  TProtoFunc *tf;
  StkId base;
  Byte *pc;
  TObject *consts;
 newfunc:
  cl = L->ci->c;
  tf = L->ci->tf;
  base = L->ci->base;
  if (S->top-S->stack > base && ttype(S->stack+base) == LUA_T_LINE)
    base++;
  pc = L->ci->pc;
  consts = tf->consts;
  while (1) {
    int aux;
    switch ((OpCode)(aux = *pc++)) {

      case PUSHNIL0:
        ttype(S->top++) = LUA_T_NIL;
        break;

      case PUSHNIL:
        aux = *pc++;
        do {
          ttype(S->top++) = LUA_T_NIL;
        } while (aux--);
        break;

      case PUSHNUMBER:
        aux = *pc++; goto pushnumber;

      case PUSHNUMBERW:
        aux = next_word(pc); goto pushnumber;

      case PUSHNUMBER0: case PUSHNUMBER1: case PUSHNUMBER2:
        aux -= PUSHNUMBER0;
      pushnumber:
        ttype(S->top) = LUA_T_NUMBER;
        nvalue(S->top) = aux;
        S->top++;
        break;

      case PUSHLOCAL:
        aux = *pc++; goto pushlocal;

      case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3:
      case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7:
        aux -= PUSHLOCAL0;
      pushlocal:
        *S->top++ = *((S->stack+base) + aux);
        break;

      case GETGLOBALW:
        aux = next_word(pc); goto getglobal;

      case GETGLOBAL:
        aux = *pc++; goto getglobal;

      case GETGLOBAL0: case GETGLOBAL1: case GETGLOBAL2: case GETGLOBAL3:
      case GETGLOBAL4: case GETGLOBAL5: case GETGLOBAL6: case GETGLOBAL7:
        aux -= GETGLOBAL0;
      getglobal:
        luaV_getglobal(tsvalue(&consts[aux]));
        break;

      case GETTABLE:
       luaV_gettable();
       break;

      case GETDOTTEDW:
        aux = next_word(pc); goto getdotted;

      case GETDOTTED:
        aux = *pc++; goto getdotted;

      case GETDOTTED0: case GETDOTTED1: case GETDOTTED2: case GETDOTTED3:
      case GETDOTTED4: case GETDOTTED5: case GETDOTTED6: case GETDOTTED7:
        aux -= GETDOTTED0;
      getdotted:
        *S->top++ = consts[aux];
        luaV_gettable();
        break;

      case PUSHSELFW:
        aux = next_word(pc); goto pushself;

      case PUSHSELF:
        aux = *pc++; goto pushself;

      case PUSHSELF0: case PUSHSELF1: case PUSHSELF2: case PUSHSELF3:
      case PUSHSELF4: case PUSHSELF5: case PUSHSELF6: case PUSHSELF7:
        aux -= PUSHSELF0;
      pushself: {
        TObject receiver = *(S->top-1);
        *S->top++ = consts[aux];
        luaV_gettable();
        *S->top++ = receiver;
        break;
      }

      case PUSHCONSTANTW:
        aux = next_word(pc); goto pushconstant;

      case PUSHCONSTANT:
        aux = *pc++; goto pushconstant;

      case PUSHCONSTANT0: case PUSHCONSTANT1: case PUSHCONSTANT2:
      case PUSHCONSTANT3: case PUSHCONSTANT4: case PUSHCONSTANT5:
      case PUSHCONSTANT6: case PUSHCONSTANT7:
        aux -= PUSHCONSTANT0;
      pushconstant:
        *S->top++ = consts[aux];
        break;

      case PUSHUPVALUE:
        aux = *pc++; goto pushupvalue;

      case PUSHUPVALUE0: case PUSHUPVALUE1:
        aux -= PUSHUPVALUE0;
      pushupvalue:
        *S->top++ = cl->consts[aux+1];
        break;

      case SETLOCAL:
        aux = *pc++; goto setlocal;

      case SETLOCAL0: case SETLOCAL1: case SETLOCAL2: case SETLOCAL3:
      case SETLOCAL4: case SETLOCAL5: case SETLOCAL6: case SETLOCAL7:
        aux -= SETLOCAL0;
      setlocal:
        *((S->stack+base) + aux) = *(--S->top);
        break;

      case SETGLOBALW:
        aux = next_word(pc); goto setglobal;

      case SETGLOBAL:
        aux = *pc++; goto setglobal;

      case SETGLOBAL0: case SETGLOBAL1: case SETGLOBAL2: case SETGLOBAL3:
      case SETGLOBAL4: case SETGLOBAL5: case SETGLOBAL6: case SETGLOBAL7:
        aux -= SETGLOBAL0;
      setglobal:
        luaV_setglobal(tsvalue(&consts[aux]));
        break;

      case SETTABLE0:
       luaV_settable(S->top-3, 1);
       break;

      case SETTABLE:
        luaV_settable(S->top-3-(*pc++), 2);
        break;

      case SETLISTW:
        aux = next_word(pc); aux *= LFIELDS_PER_FLUSH; goto setlist;

      case SETLIST:
        aux = *(pc++) * LFIELDS_PER_FLUSH; goto setlist;

      case SETLIST0:
        aux = 0;
      setlist: {
        int n = *(pc++);
        TObject *arr = S->top-n-1;
        for (; n; n--) {
          ttype(S->top) = LUA_T_NUMBER;
          nvalue(S->top) = n+aux;
          *(luaH_set(avalue(arr), S->top)) = *(S->top-1);
          S->top--;
        }
        break;
      }

      case SETMAP0:
        aux = 0; goto setmap;

      case SETMAP:
        aux = *pc++;
      setmap: {
        TObject *arr = S->top-(2*aux)-3;
        do {
          *(luaH_set(avalue(arr), S->top-2)) = *(S->top-1);
          S->top-=2;
        } while (aux--);
        break;
      }

      case POP:
        aux = *pc++; goto pop;

      case POP0: case POP1:
        aux -= POP0;
      pop:
        S->top -= (aux+1);
        break;

      case CREATEARRAYW:
        aux = next_word(pc); goto createarray;

      case CREATEARRAY0: case CREATEARRAY1:
        aux -= CREATEARRAY0; goto createarray;

      case CREATEARRAY:
        aux = *pc++;
      createarray:
        luaC_checkGC();
        avalue(S->top) = luaH_new(aux);
        ttype(S->top) = LUA_T_ARRAY;
        S->top++;
        break;

      case EQOP: case NEQOP: {
        int res = luaO_equalObj(S->top-2, S->top-1);
        S->top--;
        if (aux == NEQOP) res = !res;
        ttype(S->top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
        nvalue(S->top-1) = 1;
        break;
      }

       case LTOP:
         comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
         break;

      case LEOP:
        comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE);
        break;

      case GTOP:
        comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT);
        break;

      case GEOP:
        comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE);
        break;

      case ADDOP: {
        TObject *l = S->top-2;
        TObject *r = S->top-1;
        if (tonumber(r) || tonumber(l))
          call_arith(IM_ADD);
        else {
          nvalue(l) += nvalue(r);
          --S->top;
        }
        break;
      }

      case SUBOP: {
        TObject *l = S->top-2;
        TObject *r = S->top-1;
        if (tonumber(r) || tonumber(l))
          call_arith(IM_SUB);
        else {
          nvalue(l) -= nvalue(r);
          --S->top;
        }
        break;
      }

      case MULTOP: {
        TObject *l = S->top-2;
        TObject *r = S->top-1;
        if (tonumber(r) || tonumber(l))
          call_arith(IM_MUL);
        else {
          nvalue(l) *= nvalue(r);
          --S->top;
        }
        break;
      }

      case DIVOP: {
        TObject *l = S->top-2;
        TObject *r = S->top-1;
        if (tonumber(r) || tonumber(l))
          call_arith(IM_DIV);
        else {
          nvalue(l) /= nvalue(r);
          --S->top;
        }
        break;
      }

      case POWOP:
        call_binTM(IM_POW, "undefined operation");
        break;

      case CONCOP: {
        TObject *l = S->top-2;
        TObject *r = S->top-1;
        if (tostring(l) || tostring(r))
          call_binTM(IM_CONCAT, "unexpected type for concatenation");
        else {
          tsvalue(l) = strconc(tsvalue(l), tsvalue(r));
          --S->top;
        }
        luaC_checkGC();
        break;
      }

      case MINUSOP:
        if (tonumber(S->top-1)) {
          ttype(S->top) = LUA_T_NIL;
          S->top++;
          call_arith(IM_UNM);
        }
        else
          nvalue(S->top-1) = - nvalue(S->top-1);
        break;

      case NOTOP:
        ttype(S->top-1) =
           (ttype(S->top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL;
        nvalue(S->top-1) = 1;
        break;

      case ONTJMPW:
        aux = next_word(pc); goto ontjmp;

      case ONTJMP:
        aux = *pc++;
      ontjmp:
        if (ttype(S->top-1) != LUA_T_NIL) pc += aux;
        else S->top--;
        break;

      case ONFJMPW:
        aux = next_word(pc); goto onfjmp;

      case ONFJMP:
        aux = *pc++;
      onfjmp:
        if (ttype(S->top-1) == LUA_T_NIL) pc += aux;
        else S->top--;
        break;

      case JMPW:
        aux = next_word(pc); goto jmp;

      case JMP:
        aux = *pc++;
      jmp:
        pc += aux;
        break;

      case IFFJMPW:
        aux = next_word(pc); goto iffjmp;

      case IFFJMP:
        aux = *pc++;
      iffjmp:
        if (ttype(--S->top) == LUA_T_NIL) pc += aux;
        break;

      case IFTUPJMPW:
        aux = next_word(pc); goto iftupjmp;

      case IFTUPJMP:
        aux = *pc++;
      iftupjmp:
        if (ttype(--S->top) != LUA_T_NIL) pc -= aux;
        break;

      case IFFUPJMPW:
        aux = next_word(pc); goto iffupjmp;

      case IFFUPJMP:
        aux = *pc++;
      iffupjmp:
        if (ttype(--S->top) == LUA_T_NIL) pc -= aux;
        break;

    case CLOSURE:
      aux = *pc++;
      goto closure;

    case CLOSURE0:
      aux = 0;
      goto closure;

    case CLOSURE1:
      aux = 1;
      closure:
        luaV_closure(aux);
        luaC_checkGC();
        break;

      case CALLFUNC:
        aux = *pc++; goto callfunc;

      case CALLFUNC0: case CALLFUNC1:
        aux -= CALLFUNC0;
      callfunc: {
        StkId newBase = (S->top-S->stack)-(*pc++);
	TObject *func = S->stack+newBase-1;
	L->ci->pc = pc;
	if (ttype(func) == LUA_T_PROTO ||
	    (ttype(func) == LUA_T_CLOSURE &&
	     ttype(&clvalue(func)->consts[0]) == LUA_T_PROTO)) {

	  /* Calling another Lua function */
	  luaD_precall(func, newBase, aux);
	  ttype(func) = (ttype(func) == LUA_T_PROTO) ?
	    LUA_T_PMARK : LUA_T_CLMARK;
	  goto newfunc;
	}
        luaD_call(newBase, aux);

	if (L->Tstate != RUN) {
	  if (ci_index > 1)	/* C functions detected by break_here */
	    lua_error("Cannot yield through method call");
	  return -1;
	}
        break;
      }

      case ENDCODE:
        S->top = S->stack + base;
        /* goes through */
      case RETCODE: {
	StkId firstResult = (base + ((aux==RETCODE) ? *pc : 0));
        if (lua_callhook)
          luaD_callHook(base, NULL, 1);
	/* If returning from the original stack frame, terminate */
	if (L->ci == L->base_ci + ci_index)
	  return firstResult;
	luaD_postret(firstResult);
	goto newfunc;
      }

      case SETLINEW:
        aux = next_word(pc); goto setline;

      case SETLINE:
        aux = *pc++;
      setline:
        if ((S->stack+base-1)->ttype != LUA_T_LINE) {
          /* open space for LINE value */
          luaD_openstack((S->top-S->stack)-base);
          base++;
          (S->stack+base-1)->ttype = LUA_T_LINE;
        }
        (S->stack+base-1)->value.i = aux;
        if (lua_linehook)
          luaD_lineHook(aux);
        break;

#ifdef DEBUG
      default:
        LUA_INTERNALERROR("opcode doesn't match");
#endif
    }
  }
}


--- NEW FILE: lvm.h ---
/*
** $Id: lvm.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/

#ifndef lvm_h
#define lvm_h


#include "ldo.h"
#include "lobject.h"


#define tonumber(o) ((ttype(o) != LUA_T_NUMBER) && (luaV_tonumber(o) != 0))
#define tostring(o) ((ttype(o) != LUA_T_STRING) && (luaV_tostring(o) != 0))


void luaV_pack (StkId firstel, int nvararg, TObject *tab);
int luaV_tonumber (TObject *obj);
int luaV_tostring (TObject *obj);
void luaV_gettable (void);
void luaV_settable (TObject *t, int mode);
void luaV_getglobal (TaggedString *ts);
void luaV_setglobal (TaggedString *ts);
StkId luaV_execute (struct CallInfo *ci);
void luaV_closure (int nelems);

#endif

--- NEW FILE: lzio.cpp ---
/*
** $Id: lzio.cpp,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** a generic input stream interface
** See Copyright Notice in lua.h
*/



#include <stdio.h>
#include <string.h>

#include "lzio.h"



/* ----------------------------------------------------- memory buffers --- */

static int zmfilbuf (ZIO* z)
{
 return EOZ;
}

ZIO* zmopen (ZIO* z, char* b, int size, char *name)
{
 if (b==NULL) return NULL;
 z->n=size;
 z->p= (unsigned char *)b;
 z->filbuf=zmfilbuf;
 z->u=NULL;
 z->name=name;
 return z;
}

/* ------------------------------------------------------------ strings --- */

ZIO* zsopen (ZIO* z, char* s, char *name)
{
 if (s==NULL) return NULL;
 return zmopen(z,s,strlen(s),name);
}

/* -------------------------------------------------------------- FILEs --- */

static int zffilbuf (ZIO* z)
{
 int n=fread(z->buffer,1,ZBSIZE,(FILE *)z->u);
 if (n==0) return EOZ;
 z->n=n-1;
 z->p=z->buffer;
 return *(z->p++);
}


ZIO* zFopen (ZIO* z, FILE* f, char *name)
{
 if (f==NULL) return NULL;
 z->n=0;
 z->p=z->buffer;
 z->filbuf=zffilbuf;
 z->u=f;
 z->name=name;
 return z;
}


/* --------------------------------------------------------------- read --- */
int zread (ZIO *z, void *b, int n)
{
  while (n) {
    int m;
    if (z->n == 0) {
      if (z->filbuf(z) == EOZ)
        return n;  /* retorna quantos faltaram ler */
      zungetc(z);  /* poe o resultado de filbuf no buffer */
    }
    m = (n <= z->n) ? n : z->n;  /* minimo de n e z->n */
    memcpy(b, z->p, m);
    z->n -= m;
    z->p += m;
    b = (char *)b + m;
    n -= m;
  }
  return 0;
}

--- NEW FILE: lzio.h ---
/*
** $Id: lzio.h,v 1.1 2004/10/06 19:07:53 aquadran Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/


#ifndef lzio_h
#define lzio_h

#include <stdio.h>



/* For Lua only */
#define zFopen	luaZ_Fopen
#define zsopen	luaZ_sopen
#define zmopen	luaZ_mopen
#define zread	luaZ_read

#define EOZ	(-1)			/* end of stream */

typedef struct zio ZIO;

ZIO* zFopen (ZIO* z, FILE* f, char *name);		/* open FILEs */
ZIO* zsopen (ZIO* z, char* s, char *name);		/* string */
ZIO* zmopen (ZIO* z, char* b, int size, char *name);	/* memory */

int zread (ZIO* z, void* b, int n);	/* read next n bytes */

#define zgetc(z)	(--(z)->n>=0 ? ((int)*(z)->p++): (z)->filbuf(z))
#define zungetc(z)	(++(z)->n,--(z)->p)
#define zname(z)	((z)->name)


/* --------- Private Part ------------------ */

#define ZBSIZE	256			/* buffer size */

struct zio {
 int n;					/* bytes still unread */
 unsigned char* p;			/* current position in buffer */
 int (*filbuf)(ZIO* z);
 void* u;				/* additional data */
 char *name;
 unsigned char buffer[ZBSIZE];		/* buffer */
};


#endif

Index: Makefile
===================================================================
RCS file: /cvsroot/scummvm/residual/lua/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile	18 Dec 2003 22:54:01 -0000	1.2
+++ Makefile	6 Oct 2004 19:07:53 -0000	1.3
@@ -1,8 +1,81 @@
-# makefile for lua hierarchy
+# makefile for lua basic library
 
-all co clean klean:
-	cd include; $(MAKE) $@
-	cd src; $(MAKE) $@
-	cd src/luac; $(MAKE) $@
-	cd src/lib; $(MAKE) $@
-	cd src/lua; $(MAKE) $@
+LUA= ..
+
+include $(LUA)/config
+
+OBJS=	\
+	lapi.o \
+	lauxlib.o \
+	lbuffer.o \
+	lbuiltin.o \
+	ldo.o \
+	lfunc.o \
+	lgc.o \
+	llex.o \
+	lmem.o \
+	lobject.o \
+	lparser.o \
+	lstate.o \
+	lstring.o \
+	ltable.o \
+	ltask.o \
+	ltm.o \
+	lundump.o \
+	lvm.o \
+	lzio.o
+
+SRCS=	\
+	lapi.c \
+	lauxlib.c \
+	lbuffer.c \
+	lbuiltin.c \
+	ldo.c \
+	lfunc.c \
+	lgc.c \
+	llex.c \
+	lmem.c \
+	lobject.c \
+	lparser.c \
+	lstate.c \
+	lstring.c \
+	ltable.c \
+	ltask.c \
+	ltm.c \
+	lundump.c \
+	lvm.c \
+	lzio.c \
+	lapi.h \
+	lbuiltin.h \
+	ldo.h \
+	lfunc.h \
+	lgc.h \
+	llex.h \
+	lmem.h \
+	lobject.h \
+	lopcodes.h \
+	lparser.h \
+	lstate.h \
+	lstring.h \
+	ltable.h \
+	ltm.h \
+	lundump.h \
+	lvm.h \
+	lzio.h
+
+T= $(LIB)/liblua.a
+
+all: $T
+
+$T: $(OBJS)
+	$(AR) $@ $(OBJS)
+	$(RANLIB) $@
+
+clean:
+	rm -f $(OBJS) $T
+
+co:
+	co -q -f -M $(SRCS)
+
+klean:	clean
+	rm -f $(SRCS)

--- COPYRIGHT DELETED ---

--- HISTORY DELETED ---

--- INSTALL DELETED ---

--- MANIFEST DELETED ---

--- README DELETED ---

--- config DELETED ---





More information about the Scummvm-git-logs mailing list