++
++
++#include "llimits.h"
++#include "lua.h"
++
++
++/* tags for values visible from Lua */
++#define LAST_TAG LUA_TTHREAD
++
++#define NUM_TAGS (LAST_TAG+1)
++
++
++/*
++** Extra tags for non-values
++*/
++#define LUA_TPROTO (LAST_TAG+1)
++#define LUA_TUPVAL (LAST_TAG+2)
++#define LUA_TDEADKEY (LAST_TAG+3)
++
++
++/*
++** Union of all collectable objects
++*/
++typedef union GCObject GCObject;
++
++
++/*
++** Common Header for all collectable objects (in macro form, to be
++** included in other objects)
++*/
++#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
++
++
++/*
++** Common header in struct form
++*/
++typedef struct GCheader {
++ CommonHeader;
++} GCheader;
++
++
++
++
++/*
++** Union of all Lua values
++*/
++typedef union {
++ GCObject *gc;
++ void *p;
++ lua_Number n;
++ int b;
++} Value;
++
++
++/*
++** Tagged Values
++*/
++
++#define TValuefields Value value; int tt
++
++typedef struct lua_TValue {
++ TValuefields;
++} TValue;
++
++
++/* Macros to test type */
++#define ttisnil(o) (ttype(o) == LUA_TNIL)
++#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
++#define ttisstring(o) (ttype(o) == LUA_TSTRING)
++#define ttistable(o) (ttype(o) == LUA_TTABLE)
++#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
++#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
++#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
++#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
++#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
++
++/* Macros to access values */
++#define ttype(o) ((o)->tt)
++#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
++#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
++#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
++#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
++#define tsvalue(o) (&rawtsvalue(o)->tsv)
++#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
++#define uvalue(o) (&rawuvalue(o)->uv)
++#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
++#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
++#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
++#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
++
++#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
++
++/*
++** for internal debug only
++*/
++#define checkconsistency(obj) \
++ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
++
++#define checkliveness(g,obj) \
++ lua_assert(!iscollectable(obj) || \
++ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
++
++
++/* Macros to set values */
++#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
++
++#define setnvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
++
++#define setpvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
++
++#define setbvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
++
++#define setsvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
++ checkliveness(G(L),i_o); }
++
++#define setuvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
++ checkliveness(G(L),i_o); }
++
++#define setthvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
++ checkliveness(G(L),i_o); }
++
++#define setclvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
++ checkliveness(G(L),i_o); }
++
++#define sethvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
++ checkliveness(G(L),i_o); }
++
++#define setptvalue(L,obj,x) \
++ { TValue *i_o=(obj); \
++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
++ checkliveness(G(L),i_o); }
++
++
++
++
++#define setobj(L,obj1,obj2) \
++ { const TValue *o2=(obj2); TValue *o1=(obj1); \
++ o1->value = o2->value; o1->tt=o2->tt; \
++ checkliveness(G(L),o1); }
++
++
++/*
++** different types of sets, according to destination
++*/
++
++/* from stack to (same) stack */
++#define setobjs2s setobj
++/* to stack (not from same stack) */
++#define setobj2s setobj
++#define setsvalue2s setsvalue
++#define sethvalue2s sethvalue
++#define setptvalue2s setptvalue
++/* from table to same table */
++#define setobjt2t setobj
++/* to table */
++#define setobj2t setobj
++/* to new object */
++#define setobj2n setobj
++#define setsvalue2n setsvalue
++
++#define setttype(obj, tt) (ttype(obj) = (tt))
++
++
++#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++
++
++
++typedef TValue *StkId; /* index to stack elements */
++
++
++/*
++** String headers for string table
++*/
++typedef union TString {
++ L_Umaxalign dummy; /* ensures maximum alignment for strings */
++ struct {
++ CommonHeader;
++ lu_byte reserved;
++ unsigned int hash;
++ size_t len;
++ } tsv;
++} TString;
++
++
++#define getstr(ts) cast(const char *, (ts) + 1)
++#define svalue(o) getstr(rawtsvalue(o))
++
++
++
++typedef union Udata {
++ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
++ struct {
++ CommonHeader;
++ struct Table *metatable;
++ struct Table *env;
++ size_t len;
++ } uv;
++} Udata;
++
++
++
++
++/*
++** Function Prototypes
++*/
++typedef struct Proto {
++ CommonHeader;
++ TValue *k; /* constants used by the function */
++ Instruction *code;
++ struct Proto **p; /* functions defined inside the function */
++ int *lineinfo; /* map from opcodes to source lines */
++ struct LocVar *locvars; /* information about local variables */
++ TString **upvalues; /* upvalue names */
++ TString *source;
++ int sizeupvalues;
++ int sizek; /* size of `k' */
++ int sizecode;
++ int sizelineinfo;
++ int sizep; /* size of `p' */
++ int sizelocvars;
++ int linedefined;
++ int lastlinedefined;
++ GCObject *gclist;
++ lu_byte nups; /* number of upvalues */
++ lu_byte numparams;
++ lu_byte is_vararg;
++ lu_byte maxstacksize;
++} Proto;
++
++
++/* masks for new-style vararg */
++#define VARARG_HASARG 1
++#define VARARG_ISVARARG 2
++#define VARARG_NEEDSARG 4
++
++
++typedef struct LocVar {
++ TString *varname;
++ int startpc; /* first point where variable is active */
++ int endpc; /* first point where variable is dead */
++} LocVar;
++
++
++
++/*
++** Upvalues
++*/
++
++typedef struct UpVal {
++ CommonHeader;
++ TValue *v; /* points to stack or to its own value */
++ union {
++ TValue value; /* the value (when closed) */
++ struct { /* double linked list (when open) */
++ struct UpVal *prev;
++ struct UpVal *next;
++ } l;
++ } u;
++} UpVal;
++
++
++/*
++** Closures
++*/
++
++#define ClosureHeader \
++ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
++ struct Table *env
++
++typedef struct CClosure {
++ ClosureHeader;
++ lua_CFunction f;
++ TValue upvalue[1];
++} CClosure;
++
++
++typedef struct LClosure {
++ ClosureHeader;
++ struct Proto *p;
++ UpVal *upvals[1];
++} LClosure;
++
++
++typedef union Closure {
++ CClosure c;
++ LClosure l;
++} Closure;
++
++
++#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
++#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
++
++
++/*
++** Tables
++*/
++
++typedef union TKey {
++ struct {
++ TValuefields;
++ struct Node *next; /* for chaining */
++ } nk;
++ TValue tvk;
++} TKey;
++
++
++typedef struct Node {
++ TValue i_val;
++ TKey i_key;
++} Node;
++
++
++typedef struct Table {
++ CommonHeader;
++ lu_byte flags; /* 1<lsizenode))
++
++
++#define luaO_nilobject (&luaO_nilobject_)
++
++LUAI_DATA const TValue luaO_nilobject_;
++
++#define ceillog2(x) (luaO_log2((x)-1) + 1)
++
++LUAI_FUNC int luaO_log2 (unsigned int x);
++LUAI_FUNC int luaO_int2fb (unsigned int x);
++LUAI_FUNC int luaO_fb2int (int x);
++LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
++LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
++ va_list argp);
++LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
++LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
++
++
++#endif
++
+--- /dev/null
++++ b/extensions/LUA/lua/lopcodes.c
+@@ -0,0 +1,102 @@
++/*
++** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
++** See Copyright Notice in lua.h
++*/
++
++
++#define lopcodes_c
++#define LUA_CORE
++
++
++#include "lopcodes.h"
++
++
++/* ORDER OP */
++
++const char *const luaP_opnames[NUM_OPCODES+1] = {
++ "MOVE",
++ "LOADK",
++ "LOADBOOL",
++ "LOADNIL",
++ "GETUPVAL",
++ "GETGLOBAL",
++ "GETTABLE",
++ "SETGLOBAL",
++ "SETUPVAL",
++ "SETTABLE",
++ "NEWTABLE",
++ "SELF",
++ "ADD",
++ "SUB",
++ "MUL",
++ "DIV",
++ "MOD",
++ "POW",
++ "UNM",
++ "NOT",
++ "LEN",
++ "CONCAT",
++ "JMP",
++ "EQ",
++ "LT",
++ "LE",
++ "TEST",
++ "TESTSET",
++ "CALL",
++ "TAILCALL",
++ "RETURN",
++ "FORLOOP",
++ "FORPREP",
++ "TFORLOOP",
++ "SETLIST",
++ "CLOSE",
++ "CLOSURE",
++ "VARARG",
++ NULL
++};
++
++
++#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
++
++const lu_byte luaP_opmodes[NUM_OPCODES] = {
++/* T A B C mode opcode */
++ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
++ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
++ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
++ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
++ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
++ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
++ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
++ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
++ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
++};
++
+--- /dev/null
++++ b/extensions/LUA/lua/lopcodes.h
+@@ -0,0 +1,268 @@
++/*
++** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
++** Opcodes for Lua virtual machine
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lopcodes_h
++#define lopcodes_h
++
++#include "llimits.h"
++
++
++/*===========================================================================
++ We assume that instructions are unsigned numbers.
++ All instructions have an opcode in the first 6 bits.
++ Instructions can have the following fields:
++ `A' : 8 bits
++ `B' : 9 bits
++ `C' : 9 bits
++ `Bx' : 18 bits (`B' and `C' together)
++ `sBx' : signed Bx
++
++ A signed argument is represented in excess K; that is, the number
++ value is the unsigned value minus K. K is exactly the maximum value
++ for that argument (so that -max is represented by 0, and +max is
++ represented by 2*max), which is half the maximum for the corresponding
++ unsigned argument.
++===========================================================================*/
++
++
++enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
++
++
++/*
++** size and position of opcode arguments.
++*/
++#define SIZE_C 9
++#define SIZE_B 9
++#define SIZE_Bx (SIZE_C + SIZE_B)
++#define SIZE_A 8
++
++#define SIZE_OP 6
++
++#define POS_OP 0
++#define POS_A (POS_OP + SIZE_OP)
++#define POS_C (POS_A + SIZE_A)
++#define POS_B (POS_C + SIZE_C)
++#define POS_Bx POS_C
++
++
++/*
++** limits for opcode arguments.
++** we use (signed) int to manipulate most arguments,
++** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
++*/
++#if SIZE_Bx < LUAI_BITSINT-1
++#define MAXARG_Bx ((1<>1) /* `sBx' is signed */
++#else
++#define MAXARG_Bx MAX_INT
++#define MAXARG_sBx MAX_INT
++#endif
++
++
++#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0)))
++#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
++ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0)))
++#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
++ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0)))
++#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
++ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0)))
++#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
++ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0)))
++#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
++ ((cast(Instruction, b)< C) then pc++ */
++OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
++
++OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
++OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
++OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
++
++OP_FORLOOP,/* A sBx R(A)+=R(A+2);
++ if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
++OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
++
++OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
++ if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
++OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
++
++OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
++OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
++
++OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
++} OpCode;
++
++
++#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
++
++
++
++/*===========================================================================
++ Notes:
++ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
++ and can be 0: OP_CALL then sets `top' to last_result+1, so
++ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
++
++ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
++ set top (like in OP_CALL with C == 0).
++
++ (*) In OP_RETURN, if (B == 0) then return up to `top'
++
++ (*) In OP_SETLIST, if (B == 0) then B = `top';
++ if (C == 0) then next `instruction' is real C
++
++ (*) For comparisons, A specifies what condition the test should accept
++ (true or false).
++
++ (*) All `skips' (pc++) assume that next instruction is a jump
++===========================================================================*/
++
++
++/*
++** masks for instruction properties. The format is:
++** bits 0-1: op mode
++** bits 2-3: C arg mode
++** bits 4-5: B arg mode
++** bit 6: instruction set register A
++** bit 7: operator is a test
++*/
++
++enum OpArgMask {
++ OpArgN, /* argument is not used */
++ OpArgU, /* argument is used */
++ OpArgR, /* argument is a register or a jump offset */
++ OpArgK /* argument is a constant or register/constant */
++};
++
++LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
++
++#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
++#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
++#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
++#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
++#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
++
++
++LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
++
++
++/* number of list items to accumulate before a SETLIST instruction */
++#define LFIELDS_PER_FLUSH 50
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lparser.c
+@@ -0,0 +1,1339 @@
++/*
++** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
++** Lua Parser
++** See Copyright Notice in lua.h
++*/
++
++
++#include
++
++#define lparser_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "lcode.h"
++#include "ldebug.h"
++#include "ldo.h"
++#include "lfunc.h"
++#include "llex.h"
++#include "lmem.h"
++#include "lobject.h"
++#include "lopcodes.h"
++#include "lparser.h"
++#include "lstate.h"
++#include "lstring.h"
++#include "ltable.h"
++
++
++
++#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
++
++#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
++
++#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
++
++
++/*
++** nodes for block list (list of active blocks)
++*/
++typedef struct BlockCnt {
++ struct BlockCnt *previous; /* chain */
++ int breaklist; /* list of jumps out of this loop */
++ lu_byte nactvar; /* # active locals outside the breakable structure */
++ lu_byte upval; /* true if some variable in the block is an upvalue */
++ lu_byte isbreakable; /* true if `block' is a loop */
++} BlockCnt;
++
++
++
++/*
++** prototypes for recursive non-terminal functions
++*/
++static void chunk (LexState *ls);
++static void expr (LexState *ls, expdesc *v);
++
++
++static void anchor_token (LexState *ls) {
++ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
++ TString *ts = ls->t.seminfo.ts;
++ luaX_newstring(ls, getstr(ts), ts->tsv.len);
++ }
++}
++
++
++static void error_expected (LexState *ls, int token) {
++ luaX_syntaxerror(ls,
++ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
++}
++
++
++static void errorlimit (FuncState *fs, int limit, const char *what) {
++ const char *msg = (fs->f->linedefined == 0) ?
++ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
++ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
++ fs->f->linedefined, limit, what);
++ luaX_lexerror(fs->ls, msg, 0);
++}
++
++
++static int testnext (LexState *ls, int c) {
++ if (ls->t.token == c) {
++ luaX_next(ls);
++ return 1;
++ }
++ else return 0;
++}
++
++
++static void check (LexState *ls, int c) {
++ if (ls->t.token != c)
++ error_expected(ls, c);
++}
++
++static void checknext (LexState *ls, int c) {
++ check(ls, c);
++ luaX_next(ls);
++}
++
++
++#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
++
++
++
++static void check_match (LexState *ls, int what, int who, int where) {
++ if (!testnext(ls, what)) {
++ if (where == ls->linenumber)
++ error_expected(ls, what);
++ else {
++ luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
++ LUA_QS " expected (to close " LUA_QS " at line %d)",
++ luaX_token2str(ls, what), luaX_token2str(ls, who), where));
++ }
++ }
++}
++
++
++static TString *str_checkname (LexState *ls) {
++ TString *ts;
++ check(ls, TK_NAME);
++ ts = ls->t.seminfo.ts;
++ luaX_next(ls);
++ return ts;
++}
++
++
++static void init_exp (expdesc *e, expkind k, int i) {
++ e->f = e->t = NO_JUMP;
++ e->k = k;
++ e->u.s.info = i;
++}
++
++
++static void codestring (LexState *ls, expdesc *e, TString *s) {
++ init_exp(e, VK, luaK_stringK(ls->fs, s));
++}
++
++
++static void checkname(LexState *ls, expdesc *e) {
++ codestring(ls, e, str_checkname(ls));
++}
++
++
++static int registerlocalvar (LexState *ls, TString *varname) {
++ FuncState *fs = ls->fs;
++ Proto *f = fs->f;
++ int oldsize = f->sizelocvars;
++ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
++ LocVar, SHRT_MAX, "too many local variables");
++ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
++ f->locvars[fs->nlocvars].varname = varname;
++ luaC_objbarrier(ls->L, f, varname);
++ return fs->nlocvars++;
++}
++
++
++#define new_localvarliteral(ls,v,n) \
++ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
++
++
++static void new_localvar (LexState *ls, TString *name, int n) {
++ FuncState *fs = ls->fs;
++ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
++ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
++}
++
++
++static void adjustlocalvars (LexState *ls, int nvars) {
++ FuncState *fs = ls->fs;
++ fs->nactvar = cast_byte(fs->nactvar + nvars);
++ for (; nvars; nvars--) {
++ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
++ }
++}
++
++
++static void removevars (LexState *ls, int tolevel) {
++ FuncState *fs = ls->fs;
++ while (fs->nactvar > tolevel)
++ getlocvar(fs, --fs->nactvar).endpc = fs->pc;
++}
++
++
++static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
++ int i;
++ Proto *f = fs->f;
++ int oldsize = f->sizeupvalues;
++ for (i=0; inups; i++) {
++ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
++ lua_assert(f->upvalues[i] == name);
++ return i;
++ }
++ }
++ /* new one */
++ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
++ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
++ TString *, MAX_INT, "");
++ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
++ f->upvalues[f->nups] = name;
++ luaC_objbarrier(fs->L, f, name);
++ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
++ fs->upvalues[f->nups].k = cast_byte(v->k);
++ fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
++ return f->nups++;
++}
++
++
++static int searchvar (FuncState *fs, TString *n) {
++ int i;
++ for (i=fs->nactvar-1; i >= 0; i--) {
++ if (n == getlocvar(fs, i).varname)
++ return i;
++ }
++ return -1; /* not found */
++}
++
++
++static void markupval (FuncState *fs, int level) {
++ BlockCnt *bl = fs->bl;
++ while (bl && bl->nactvar > level) bl = bl->previous;
++ if (bl) bl->upval = 1;
++}
++
++
++static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
++ if (fs == NULL) { /* no more levels? */
++ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
++ return VGLOBAL;
++ }
++ else {
++ int v = searchvar(fs, n); /* look up at current level */
++ if (v >= 0) {
++ init_exp(var, VLOCAL, v);
++ if (!base)
++ markupval(fs, v); /* local will be used as an upval */
++ return VLOCAL;
++ }
++ else { /* not found at current level; try upper one */
++ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
++ return VGLOBAL;
++ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
++ var->k = VUPVAL; /* upvalue in this level */
++ return VUPVAL;
++ }
++ }
++}
++
++
++static void singlevar (LexState *ls, expdesc *var) {
++ TString *varname = str_checkname(ls);
++ FuncState *fs = ls->fs;
++ if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
++ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
++}
++
++
++static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
++ FuncState *fs = ls->fs;
++ int extra = nvars - nexps;
++ if (hasmultret(e->k)) {
++ extra++; /* includes call itself */
++ if (extra < 0) extra = 0;
++ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
++ if (extra > 1) luaK_reserveregs(fs, extra-1);
++ }
++ else {
++ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
++ if (extra > 0) {
++ int reg = fs->freereg;
++ luaK_reserveregs(fs, extra);
++ luaK_nil(fs, reg, extra);
++ }
++ }
++}
++
++
++static void enterlevel (LexState *ls) {
++ if (++ls->L->nCcalls > LUAI_MAXCCALLS)
++ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
++}
++
++
++#define leavelevel(ls) ((ls)->L->nCcalls--)
++
++
++static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
++ bl->breaklist = NO_JUMP;
++ bl->isbreakable = isbreakable;
++ bl->nactvar = fs->nactvar;
++ bl->upval = 0;
++ bl->previous = fs->bl;
++ fs->bl = bl;
++ lua_assert(fs->freereg == fs->nactvar);
++}
++
++
++static void leaveblock (FuncState *fs) {
++ BlockCnt *bl = fs->bl;
++ fs->bl = bl->previous;
++ removevars(fs->ls, bl->nactvar);
++ if (bl->upval)
++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
++ /* a block either controls scope or breaks (never both) */
++ lua_assert(!bl->isbreakable || !bl->upval);
++ lua_assert(bl->nactvar == fs->nactvar);
++ fs->freereg = fs->nactvar; /* free registers */
++ luaK_patchtohere(fs, bl->breaklist);
++}
++
++
++static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
++ FuncState *fs = ls->fs;
++ Proto *f = fs->f;
++ int oldsize = f->sizep;
++ int i;
++ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
++ MAXARG_Bx, "constant table overflow");
++ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
++ f->p[fs->np++] = func->f;
++ luaC_objbarrier(ls->L, f, func->f);
++ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
++ for (i=0; if->nups; i++) {
++ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
++ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
++ }
++}
++
++
++static void open_func (LexState *ls, FuncState *fs) {
++ lua_State *L = ls->L;
++ Proto *f = luaF_newproto(L);
++ fs->f = f;
++ fs->prev = ls->fs; /* linked list of funcstates */
++ fs->ls = ls;
++ fs->L = L;
++ ls->fs = fs;
++ fs->pc = 0;
++ fs->lasttarget = -1;
++ fs->jpc = NO_JUMP;
++ fs->freereg = 0;
++ fs->nk = 0;
++ fs->np = 0;
++ fs->nlocvars = 0;
++ fs->nactvar = 0;
++ fs->bl = NULL;
++ f->source = ls->source;
++ f->maxstacksize = 2; /* registers 0/1 are always valid */
++ fs->h = luaH_new(L, 0, 0);
++ /* anchor table of constants and prototype (to avoid being collected) */
++ sethvalue2s(L, L->top, fs->h);
++ incr_top(L);
++ setptvalue2s(L, L->top, f);
++ incr_top(L);
++}
++
++
++static void close_func (LexState *ls) {
++ lua_State *L = ls->L;
++ FuncState *fs = ls->fs;
++ Proto *f = fs->f;
++ removevars(ls, 0);
++ luaK_ret(fs, 0, 0); /* final return */
++ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
++ f->sizecode = fs->pc;
++ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
++ f->sizelineinfo = fs->pc;
++ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
++ f->sizek = fs->nk;
++ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
++ f->sizep = fs->np;
++ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
++ f->sizelocvars = fs->nlocvars;
++ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
++ f->sizeupvalues = f->nups;
++ lua_assert(luaG_checkcode(f));
++ lua_assert(fs->bl == NULL);
++ ls->fs = fs->prev;
++ L->top -= 2; /* remove table and prototype from the stack */
++ /* last token read was anchored in defunct function; must reanchor it */
++ if (fs) anchor_token(ls);
++}
++
++
++Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
++ struct LexState lexstate;
++ struct FuncState funcstate;
++ lexstate.buff = buff;
++ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
++ open_func(&lexstate, &funcstate);
++ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
++ luaX_next(&lexstate); /* read first token */
++ chunk(&lexstate);
++ check(&lexstate, TK_EOS);
++ close_func(&lexstate);
++ lua_assert(funcstate.prev == NULL);
++ lua_assert(funcstate.f->nups == 0);
++ lua_assert(lexstate.fs == NULL);
++ return funcstate.f;
++}
++
++
++
++/*============================================================*/
++/* GRAMMAR RULES */
++/*============================================================*/
++
++
++static void field (LexState *ls, expdesc *v) {
++ /* field -> ['.' | ':'] NAME */
++ FuncState *fs = ls->fs;
++ expdesc key;
++ luaK_exp2anyreg(fs, v);
++ luaX_next(ls); /* skip the dot or colon */
++ checkname(ls, &key);
++ luaK_indexed(fs, v, &key);
++}
++
++
++static void yindex (LexState *ls, expdesc *v) {
++ /* index -> '[' expr ']' */
++ luaX_next(ls); /* skip the '[' */
++ expr(ls, v);
++ luaK_exp2val(ls->fs, v);
++ checknext(ls, ']');
++}
++
++
++/*
++** {======================================================================
++** Rules for Constructors
++** =======================================================================
++*/
++
++
++struct ConsControl {
++ expdesc v; /* last list item read */
++ expdesc *t; /* table descriptor */
++ int nh; /* total number of `record' elements */
++ int na; /* total number of array elements */
++ int tostore; /* number of array elements pending to be stored */
++};
++
++
++static void recfield (LexState *ls, struct ConsControl *cc) {
++ /* recfield -> (NAME | `['exp1`]') = exp1 */
++ FuncState *fs = ls->fs;
++ int reg = ls->fs->freereg;
++ expdesc key, val;
++ int rkkey;
++ if (ls->t.token == TK_NAME) {
++ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
++ checkname(ls, &key);
++ }
++ else /* ls->t.token == '[' */
++ yindex(ls, &key);
++ cc->nh++;
++ checknext(ls, '=');
++ rkkey = luaK_exp2RK(fs, &key);
++ expr(ls, &val);
++ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
++ fs->freereg = reg; /* free registers */
++}
++
++
++static void closelistfield (FuncState *fs, struct ConsControl *cc) {
++ if (cc->v.k == VVOID) return; /* there is no list item */
++ luaK_exp2nextreg(fs, &cc->v);
++ cc->v.k = VVOID;
++ if (cc->tostore == LFIELDS_PER_FLUSH) {
++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
++ cc->tostore = 0; /* no more items pending */
++ }
++}
++
++
++static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
++ if (cc->tostore == 0) return;
++ if (hasmultret(cc->v.k)) {
++ luaK_setmultret(fs, &cc->v);
++ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
++ cc->na--; /* do not count last expression (unknown number of elements) */
++ }
++ else {
++ if (cc->v.k != VVOID)
++ luaK_exp2nextreg(fs, &cc->v);
++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
++ }
++}
++
++
++static void listfield (LexState *ls, struct ConsControl *cc) {
++ expr(ls, &cc->v);
++ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
++ cc->na++;
++ cc->tostore++;
++}
++
++
++static void constructor (LexState *ls, expdesc *t) {
++ /* constructor -> ?? */
++ FuncState *fs = ls->fs;
++ int line = ls->linenumber;
++ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
++ struct ConsControl cc;
++ cc.na = cc.nh = cc.tostore = 0;
++ cc.t = t;
++ init_exp(t, VRELOCABLE, pc);
++ init_exp(&cc.v, VVOID, 0); /* no value (yet) */
++ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */
++ checknext(ls, '{');
++ do {
++ lua_assert(cc.v.k == VVOID || cc.tostore > 0);
++ if (ls->t.token == '}') break;
++ closelistfield(fs, &cc);
++ switch(ls->t.token) {
++ case TK_NAME: { /* may be listfields or recfields */
++ luaX_lookahead(ls);
++ if (ls->lookahead.token != '=') /* expression? */
++ listfield(ls, &cc);
++ else
++ recfield(ls, &cc);
++ break;
++ }
++ case '[': { /* constructor_item -> recfield */
++ recfield(ls, &cc);
++ break;
++ }
++ default: { /* constructor_part -> listfield */
++ listfield(ls, &cc);
++ break;
++ }
++ }
++ } while (testnext(ls, ',') || testnext(ls, ';'));
++ check_match(ls, '}', '{', line);
++ lastlistfield(fs, &cc);
++ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
++ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
++}
++
++/* }====================================================================== */
++
++
++
++static void parlist (LexState *ls) {
++ /* parlist -> [ param { `,' param } ] */
++ FuncState *fs = ls->fs;
++ Proto *f = fs->f;
++ int nparams = 0;
++ f->is_vararg = 0;
++ if (ls->t.token != ')') { /* is `parlist' not empty? */
++ do {
++ switch (ls->t.token) {
++ case TK_NAME: { /* param -> NAME */
++ new_localvar(ls, str_checkname(ls), nparams++);
++ break;
++ }
++ case TK_DOTS: { /* param -> `...' */
++ luaX_next(ls);
++#if defined(LUA_COMPAT_VARARG)
++ /* use `arg' as default name */
++ new_localvarliteral(ls, "arg", nparams++);
++ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
++#endif
++ f->is_vararg |= VARARG_ISVARARG;
++ break;
++ }
++ default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected");
++ }
++ } while (!f->is_vararg && testnext(ls, ','));
++ }
++ adjustlocalvars(ls, nparams);
++ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
++ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
++}
++
++
++static void body (LexState *ls, expdesc *e, int needself, int line) {
++ /* body -> `(' parlist `)' chunk END */
++ FuncState new_fs;
++ open_func(ls, &new_fs);
++ new_fs.f->linedefined = line;
++ checknext(ls, '(');
++ if (needself) {
++ new_localvarliteral(ls, "self", 0);
++ adjustlocalvars(ls, 1);
++ }
++ parlist(ls);
++ checknext(ls, ')');
++ chunk(ls);
++ new_fs.f->lastlinedefined = ls->linenumber;
++ check_match(ls, TK_END, TK_FUNCTION, line);
++ close_func(ls);
++ pushclosure(ls, &new_fs, e);
++}
++
++
++static int explist1 (LexState *ls, expdesc *v) {
++ /* explist1 -> expr { `,' expr } */
++ int n = 1; /* at least one expression */
++ expr(ls, v);
++ while (testnext(ls, ',')) {
++ luaK_exp2nextreg(ls->fs, v);
++ expr(ls, v);
++ n++;
++ }
++ return n;
++}
++
++
++static void funcargs (LexState *ls, expdesc *f) {
++ FuncState *fs = ls->fs;
++ expdesc args;
++ int base, nparams;
++ int line = ls->linenumber;
++ switch (ls->t.token) {
++ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
++ if (line != ls->lastline)
++ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
++ luaX_next(ls);
++ if (ls->t.token == ')') /* arg list is empty? */
++ args.k = VVOID;
++ else {
++ explist1(ls, &args);
++ luaK_setmultret(fs, &args);
++ }
++ check_match(ls, ')', '(', line);
++ break;
++ }
++ case '{': { /* funcargs -> constructor */
++ constructor(ls, &args);
++ break;
++ }
++ case TK_STRING: { /* funcargs -> STRING */
++ codestring(ls, &args, ls->t.seminfo.ts);
++ luaX_next(ls); /* must use `seminfo' before `next' */
++ break;
++ }
++ default: {
++ luaX_syntaxerror(ls, "function arguments expected");
++ return;
++ }
++ }
++ lua_assert(f->k == VNONRELOC);
++ base = f->u.s.info; /* base register for call */
++ if (hasmultret(args.k))
++ nparams = LUA_MULTRET; /* open call */
++ else {
++ if (args.k != VVOID)
++ luaK_exp2nextreg(fs, &args); /* close last argument */
++ nparams = fs->freereg - (base+1);
++ }
++ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
++ luaK_fixline(fs, line);
++ fs->freereg = base+1; /* call remove function and arguments and leaves
++ (unless changed) one result */
++}
++
++
++
++
++/*
++** {======================================================================
++** Expression parsing
++** =======================================================================
++*/
++
++
++static void prefixexp (LexState *ls, expdesc *v) {
++ /* prefixexp -> NAME | '(' expr ')' */
++ switch (ls->t.token) {
++ case '(': {
++ int line = ls->linenumber;
++ luaX_next(ls);
++ expr(ls, v);
++ check_match(ls, ')', '(', line);
++ luaK_dischargevars(ls->fs, v);
++ return;
++ }
++ case TK_NAME: {
++ singlevar(ls, v);
++ return;
++ }
++ default: {
++ luaX_syntaxerror(ls, "unexpected symbol");
++ return;
++ }
++ }
++}
++
++
++static void primaryexp (LexState *ls, expdesc *v) {
++ /* primaryexp ->
++ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
++ FuncState *fs = ls->fs;
++ prefixexp(ls, v);
++ for (;;) {
++ switch (ls->t.token) {
++ case '.': { /* field */
++ field(ls, v);
++ break;
++ }
++ case '[': { /* `[' exp1 `]' */
++ expdesc key;
++ luaK_exp2anyreg(fs, v);
++ yindex(ls, &key);
++ luaK_indexed(fs, v, &key);
++ break;
++ }
++ case ':': { /* `:' NAME funcargs */
++ expdesc key;
++ luaX_next(ls);
++ checkname(ls, &key);
++ luaK_self(fs, v, &key);
++ funcargs(ls, v);
++ break;
++ }
++ case '(': case TK_STRING: case '{': { /* funcargs */
++ luaK_exp2nextreg(fs, v);
++ funcargs(ls, v);
++ break;
++ }
++ default: return;
++ }
++ }
++}
++
++
++static void simpleexp (LexState *ls, expdesc *v) {
++ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
++ constructor | FUNCTION body | primaryexp */
++ switch (ls->t.token) {
++ case TK_NUMBER: {
++ init_exp(v, VKNUM, 0);
++ v->u.nval = ls->t.seminfo.r;
++ break;
++ }
++ case TK_STRING: {
++ codestring(ls, v, ls->t.seminfo.ts);
++ break;
++ }
++ case TK_NIL: {
++ init_exp(v, VNIL, 0);
++ break;
++ }
++ case TK_TRUE: {
++ init_exp(v, VTRUE, 0);
++ break;
++ }
++ case TK_FALSE: {
++ init_exp(v, VFALSE, 0);
++ break;
++ }
++ case TK_DOTS: { /* vararg */
++ FuncState *fs = ls->fs;
++ check_condition(ls, fs->f->is_vararg,
++ "cannot use " LUA_QL("...") " outside a vararg function");
++ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
++ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
++ break;
++ }
++ case '{': { /* constructor */
++ constructor(ls, v);
++ return;
++ }
++ case TK_FUNCTION: {
++ luaX_next(ls);
++ body(ls, v, 0, ls->linenumber);
++ return;
++ }
++ default: {
++ primaryexp(ls, v);
++ return;
++ }
++ }
++ luaX_next(ls);
++}
++
++
++static UnOpr getunopr (int op) {
++ switch (op) {
++ case TK_NOT: return OPR_NOT;
++ case '-': return OPR_MINUS;
++ case '#': return OPR_LEN;
++ default: return OPR_NOUNOPR;
++ }
++}
++
++
++static BinOpr getbinopr (int op) {
++ switch (op) {
++ case '+': return OPR_ADD;
++ case '-': return OPR_SUB;
++ case '*': return OPR_MUL;
++ case '/': return OPR_DIV;
++ case '%': return OPR_MOD;
++ case '^': return OPR_POW;
++ case TK_CONCAT: return OPR_CONCAT;
++ case TK_NE: return OPR_NE;
++ case TK_EQ: return OPR_EQ;
++ case '<': return OPR_LT;
++ case TK_LE: return OPR_LE;
++ case '>': return OPR_GT;
++ case TK_GE: return OPR_GE;
++ case TK_AND: return OPR_AND;
++ case TK_OR: return OPR_OR;
++ default: return OPR_NOBINOPR;
++ }
++}
++
++
++static const struct {
++ lu_byte left; /* left priority for each binary operator */
++ lu_byte right; /* right priority */
++} priority[] = { /* ORDER OPR */
++ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
++ {10, 9}, {5, 4}, /* power and concat (right associative) */
++ {3, 3}, {3, 3}, /* equality and inequality */
++ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
++ {2, 2}, {1, 1} /* logical (and/or) */
++};
++
++#define UNARY_PRIORITY 8 /* priority for unary operators */
++
++
++/*
++** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
++** where `binop' is any binary operator with a priority higher than `limit'
++*/
++static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
++ BinOpr op;
++ UnOpr uop;
++ enterlevel(ls);
++ uop = getunopr(ls->t.token);
++ if (uop != OPR_NOUNOPR) {
++ luaX_next(ls);
++ subexpr(ls, v, UNARY_PRIORITY);
++ luaK_prefix(ls->fs, uop, v);
++ }
++ else simpleexp(ls, v);
++ /* expand while operators have priorities higher than `limit' */
++ op = getbinopr(ls->t.token);
++ while (op != OPR_NOBINOPR && priority[op].left > limit) {
++ expdesc v2;
++ BinOpr nextop;
++ luaX_next(ls);
++ luaK_infix(ls->fs, op, v);
++ /* read sub-expression with higher priority */
++ nextop = subexpr(ls, &v2, priority[op].right);
++ luaK_posfix(ls->fs, op, v, &v2);
++ op = nextop;
++ }
++ leavelevel(ls);
++ return op; /* return first untreated operator */
++}
++
++
++static void expr (LexState *ls, expdesc *v) {
++ subexpr(ls, v, 0);
++}
++
++/* }==================================================================== */
++
++
++
++/*
++** {======================================================================
++** Rules for Statements
++** =======================================================================
++*/
++
++
++static int block_follow (int token) {
++ switch (token) {
++ case TK_ELSE: case TK_ELSEIF: case TK_END:
++ case TK_UNTIL: case TK_EOS:
++ return 1;
++ default: return 0;
++ }
++}
++
++
++static void block (LexState *ls) {
++ /* block -> chunk */
++ FuncState *fs = ls->fs;
++ BlockCnt bl;
++ enterblock(fs, &bl, 0);
++ chunk(ls);
++ lua_assert(bl.breaklist == NO_JUMP);
++ leaveblock(fs);
++}
++
++
++/*
++** structure to chain all variables in the left-hand side of an
++** assignment
++*/
++struct LHS_assign {
++ struct LHS_assign *prev;
++ expdesc v; /* variable (global, local, upvalue, or indexed) */
++};
++
++
++/*
++** check whether, in an assignment to a local variable, the local variable
++** is needed in a previous assignment (to a table). If so, save original
++** local value in a safe place and use this safe copy in the previous
++** assignment.
++*/
++static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
++ FuncState *fs = ls->fs;
++ int extra = fs->freereg; /* eventual position to save local variable */
++ int conflict = 0;
++ for (; lh; lh = lh->prev) {
++ if (lh->v.k == VINDEXED) {
++ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
++ conflict = 1;
++ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
++ }
++ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
++ conflict = 1;
++ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
++ }
++ }
++ }
++ if (conflict) {
++ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
++ luaK_reserveregs(fs, 1);
++ }
++}
++
++
++static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
++ expdesc e;
++ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
++ "syntax error");
++ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
++ struct LHS_assign nv;
++ nv.prev = lh;
++ primaryexp(ls, &nv.v);
++ if (nv.v.k == VLOCAL)
++ check_conflict(ls, lh, &nv.v);
++ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
++ "variables in assignment");
++ assignment(ls, &nv, nvars+1);
++ }
++ else { /* assignment -> `=' explist1 */
++ int nexps;
++ checknext(ls, '=');
++ nexps = explist1(ls, &e);
++ if (nexps != nvars) {
++ adjust_assign(ls, nvars, nexps, &e);
++ if (nexps > nvars)
++ ls->fs->freereg -= nexps - nvars; /* remove extra values */
++ }
++ else {
++ luaK_setoneret(ls->fs, &e); /* close last expression */
++ luaK_storevar(ls->fs, &lh->v, &e);
++ return; /* avoid default */
++ }
++ }
++ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
++ luaK_storevar(ls->fs, &lh->v, &e);
++}
++
++
++static int cond (LexState *ls) {
++ /* cond -> exp */
++ expdesc v;
++ expr(ls, &v); /* read condition */
++ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
++ luaK_goiftrue(ls->fs, &v);
++ return v.f;
++}
++
++
++static void breakstat (LexState *ls) {
++ FuncState *fs = ls->fs;
++ BlockCnt *bl = fs->bl;
++ int upval = 0;
++ while (bl && !bl->isbreakable) {
++ upval |= bl->upval;
++ bl = bl->previous;
++ }
++ if (!bl)
++ luaX_syntaxerror(ls, "no loop to break");
++ if (upval)
++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
++ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
++}
++
++
++static void whilestat (LexState *ls, int line) {
++ /* whilestat -> WHILE cond DO block END */
++ FuncState *fs = ls->fs;
++ int whileinit;
++ int condexit;
++ BlockCnt bl;
++ luaX_next(ls); /* skip WHILE */
++ whileinit = luaK_getlabel(fs);
++ condexit = cond(ls);
++ enterblock(fs, &bl, 1);
++ checknext(ls, TK_DO);
++ block(ls);
++ luaK_patchlist(fs, luaK_jump(fs), whileinit);
++ check_match(ls, TK_END, TK_WHILE, line);
++ leaveblock(fs);
++ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
++}
++
++
++static void repeatstat (LexState *ls, int line) {
++ /* repeatstat -> REPEAT block UNTIL cond */
++ int condexit;
++ FuncState *fs = ls->fs;
++ int repeat_init = luaK_getlabel(fs);
++ BlockCnt bl1, bl2;
++ enterblock(fs, &bl1, 1); /* loop block */
++ enterblock(fs, &bl2, 0); /* scope block */
++ luaX_next(ls); /* skip REPEAT */
++ chunk(ls);
++ check_match(ls, TK_UNTIL, TK_REPEAT, line);
++ condexit = cond(ls); /* read condition (inside scope block) */
++ if (!bl2.upval) { /* no upvalues? */
++ leaveblock(fs); /* finish scope */
++ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
++ }
++ else { /* complete semantics when there are upvalues */
++ breakstat(ls); /* if condition then break */
++ luaK_patchtohere(ls->fs, condexit); /* else... */
++ leaveblock(fs); /* finish scope... */
++ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
++ }
++ leaveblock(fs); /* finish loop */
++}
++
++
++static int exp1 (LexState *ls) {
++ expdesc e;
++ int k;
++ expr(ls, &e);
++ k = e.k;
++ luaK_exp2nextreg(ls->fs, &e);
++ return k;
++}
++
++
++static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
++ /* forbody -> DO block */
++ BlockCnt bl;
++ FuncState *fs = ls->fs;
++ int prep, endfor;
++ adjustlocalvars(ls, 3); /* control variables */
++ checknext(ls, TK_DO);
++ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
++ enterblock(fs, &bl, 0); /* scope for declared variables */
++ adjustlocalvars(ls, nvars);
++ luaK_reserveregs(fs, nvars);
++ block(ls);
++ leaveblock(fs); /* end of scope for declared variables */
++ luaK_patchtohere(fs, prep);
++ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
++ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
++ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
++ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
++}
++
++
++static void fornum (LexState *ls, TString *varname, int line) {
++ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
++ FuncState *fs = ls->fs;
++ int base = fs->freereg;
++ new_localvarliteral(ls, "(for index)", 0);
++ new_localvarliteral(ls, "(for limit)", 1);
++ new_localvarliteral(ls, "(for step)", 2);
++ new_localvar(ls, varname, 3);
++ checknext(ls, '=');
++ exp1(ls); /* initial value */
++ checknext(ls, ',');
++ exp1(ls); /* limit */
++ if (testnext(ls, ','))
++ exp1(ls); /* optional step */
++ else { /* default step = 1 */
++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++ luaK_reserveregs(fs, 1);
++ }
++ forbody(ls, base, line, 1, 1);
++}
++
++
++static void forlist (LexState *ls, TString *indexname) {
++ /* forlist -> NAME {,NAME} IN explist1 forbody */
++ FuncState *fs = ls->fs;
++ expdesc e;
++ int nvars = 0;
++ int line;
++ int base = fs->freereg;
++ /* create control variables */
++ new_localvarliteral(ls, "(for generator)", nvars++);
++ new_localvarliteral(ls, "(for state)", nvars++);
++ new_localvarliteral(ls, "(for control)", nvars++);
++ /* create declared variables */
++ new_localvar(ls, indexname, nvars++);
++ while (testnext(ls, ','))
++ new_localvar(ls, str_checkname(ls), nvars++);
++ checknext(ls, TK_IN);
++ line = ls->linenumber;
++ adjust_assign(ls, 3, explist1(ls, &e), &e);
++ luaK_checkstack(fs, 3); /* extra space to call generator */
++ forbody(ls, base, line, nvars - 3, 0);
++}
++
++
++static void forstat (LexState *ls, int line) {
++ /* forstat -> FOR (fornum | forlist) END */
++ FuncState *fs = ls->fs;
++ TString *varname;
++ BlockCnt bl;
++ enterblock(fs, &bl, 1); /* scope for loop and control variables */
++ luaX_next(ls); /* skip `for' */
++ varname = str_checkname(ls); /* first variable name */
++ switch (ls->t.token) {
++ case '=': fornum(ls, varname, line); break;
++ case ',': case TK_IN: forlist(ls, varname); break;
++ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
++ }
++ check_match(ls, TK_END, TK_FOR, line);
++ leaveblock(fs); /* loop scope (`break' jumps to this point) */
++}
++
++
++static int test_then_block (LexState *ls) {
++ /* test_then_block -> [IF | ELSEIF] cond THEN block */
++ int condexit;
++ luaX_next(ls); /* skip IF or ELSEIF */
++ condexit = cond(ls);
++ checknext(ls, TK_THEN);
++ block(ls); /* `then' part */
++ return condexit;
++}
++
++
++static void ifstat (LexState *ls, int line) {
++ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
++ FuncState *fs = ls->fs;
++ int flist;
++ int escapelist = NO_JUMP;
++ flist = test_then_block(ls); /* IF cond THEN block */
++ while (ls->t.token == TK_ELSEIF) {
++ luaK_concat(fs, &escapelist, luaK_jump(fs));
++ luaK_patchtohere(fs, flist);
++ flist = test_then_block(ls); /* ELSEIF cond THEN block */
++ }
++ if (ls->t.token == TK_ELSE) {
++ luaK_concat(fs, &escapelist, luaK_jump(fs));
++ luaK_patchtohere(fs, flist);
++ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
++ block(ls); /* `else' part */
++ }
++ else
++ luaK_concat(fs, &escapelist, flist);
++ luaK_patchtohere(fs, escapelist);
++ check_match(ls, TK_END, TK_IF, line);
++}
++
++
++static void localfunc (LexState *ls) {
++ expdesc v, b;
++ FuncState *fs = ls->fs;
++ new_localvar(ls, str_checkname(ls), 0);
++ init_exp(&v, VLOCAL, fs->freereg);
++ luaK_reserveregs(fs, 1);
++ adjustlocalvars(ls, 1);
++ body(ls, &b, 0, ls->linenumber);
++ luaK_storevar(fs, &v, &b);
++ /* debug information will only see the variable after this point! */
++ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
++}
++
++
++static void localstat (LexState *ls) {
++ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
++ int nvars = 0;
++ int nexps;
++ expdesc e;
++ do {
++ new_localvar(ls, str_checkname(ls), nvars++);
++ } while (testnext(ls, ','));
++ if (testnext(ls, '='))
++ nexps = explist1(ls, &e);
++ else {
++ e.k = VVOID;
++ nexps = 0;
++ }
++ adjust_assign(ls, nvars, nexps, &e);
++ adjustlocalvars(ls, nvars);
++}
++
++
++static int funcname (LexState *ls, expdesc *v) {
++ /* funcname -> NAME {field} [`:' NAME] */
++ int needself = 0;
++ singlevar(ls, v);
++ while (ls->t.token == '.')
++ field(ls, v);
++ if (ls->t.token == ':') {
++ needself = 1;
++ field(ls, v);
++ }
++ return needself;
++}
++
++
++static void funcstat (LexState *ls, int line) {
++ /* funcstat -> FUNCTION funcname body */
++ int needself;
++ expdesc v, b;
++ luaX_next(ls); /* skip FUNCTION */
++ needself = funcname(ls, &v);
++ body(ls, &b, needself, line);
++ luaK_storevar(ls->fs, &v, &b);
++ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
++}
++
++
++static void exprstat (LexState *ls) {
++ /* stat -> func | assignment */
++ FuncState *fs = ls->fs;
++ struct LHS_assign v;
++ primaryexp(ls, &v.v);
++ if (v.v.k == VCALL) /* stat -> func */
++ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
++ else { /* stat -> assignment */
++ v.prev = NULL;
++ assignment(ls, &v, 1);
++ }
++}
++
++
++static void retstat (LexState *ls) {
++ /* stat -> RETURN explist */
++ FuncState *fs = ls->fs;
++ expdesc e;
++ int first, nret; /* registers with returned values */
++ luaX_next(ls); /* skip RETURN */
++ if (block_follow(ls->t.token) || ls->t.token == ';')
++ first = nret = 0; /* return no values */
++ else {
++ nret = explist1(ls, &e); /* optional return values */
++ if (hasmultret(e.k)) {
++ luaK_setmultret(fs, &e);
++ if (e.k == VCALL && nret == 1) { /* tail call? */
++ SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
++ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
++ }
++ first = fs->nactvar;
++ nret = LUA_MULTRET; /* return all values */
++ }
++ else {
++ if (nret == 1) /* only one single value? */
++ first = luaK_exp2anyreg(fs, &e);
++ else {
++ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
++ first = fs->nactvar; /* return all `active' values */
++ lua_assert(nret == fs->freereg - first);
++ }
++ }
++ }
++ luaK_ret(fs, first, nret);
++}
++
++
++static int statement (LexState *ls) {
++ int line = ls->linenumber; /* may be needed for error messages */
++ switch (ls->t.token) {
++ case TK_IF: { /* stat -> ifstat */
++ ifstat(ls, line);
++ return 0;
++ }
++ case TK_WHILE: { /* stat -> whilestat */
++ whilestat(ls, line);
++ return 0;
++ }
++ case TK_DO: { /* stat -> DO block END */
++ luaX_next(ls); /* skip DO */
++ block(ls);
++ check_match(ls, TK_END, TK_DO, line);
++ return 0;
++ }
++ case TK_FOR: { /* stat -> forstat */
++ forstat(ls, line);
++ return 0;
++ }
++ case TK_REPEAT: { /* stat -> repeatstat */
++ repeatstat(ls, line);
++ return 0;
++ }
++ case TK_FUNCTION: {
++ funcstat(ls, line); /* stat -> funcstat */
++ return 0;
++ }
++ case TK_LOCAL: { /* stat -> localstat */
++ luaX_next(ls); /* skip LOCAL */
++ if (testnext(ls, TK_FUNCTION)) /* local function? */
++ localfunc(ls);
++ else
++ localstat(ls);
++ return 0;
++ }
++ case TK_RETURN: { /* stat -> retstat */
++ retstat(ls);
++ return 1; /* must be last statement */
++ }
++ case TK_BREAK: { /* stat -> breakstat */
++ luaX_next(ls); /* skip BREAK */
++ breakstat(ls);
++ return 1; /* must be last statement */
++ }
++ default: {
++ exprstat(ls);
++ return 0; /* to avoid warnings */
++ }
++ }
++}
++
++
++static void chunk (LexState *ls) {
++ /* chunk -> { stat [`;'] } */
++ int islast = 0;
++ enterlevel(ls);
++ while (!islast && !block_follow(ls->t.token)) {
++ islast = statement(ls);
++ testnext(ls, ';');
++ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
++ ls->fs->freereg >= ls->fs->nactvar);
++ ls->fs->freereg = ls->fs->nactvar; /* free registers */
++ }
++ leavelevel(ls);
++}
++
++/* }====================================================================== */
+--- /dev/null
++++ b/extensions/LUA/lua/lparser.h
+@@ -0,0 +1,82 @@
++/*
++** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $
++** Lua Parser
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lparser_h
++#define lparser_h
++
++#include "llimits.h"
++#include "lobject.h"
++#include "lzio.h"
++
++
++/*
++** Expression descriptor
++*/
++
++typedef enum {
++ VVOID, /* no value */
++ VNIL,
++ VTRUE,
++ VFALSE,
++ VK, /* info = index of constant in `k' */
++ VKNUM, /* nval = numerical value */
++ VLOCAL, /* info = local register */
++ VUPVAL, /* info = index of upvalue in `upvalues' */
++ VGLOBAL, /* info = index of table; aux = index of global name in `k' */
++ VINDEXED, /* info = table register; aux = index register (or `k') */
++ VJMP, /* info = instruction pc */
++ VRELOCABLE, /* info = instruction pc */
++ VNONRELOC, /* info = result register */
++ VCALL, /* info = instruction pc */
++ VVARARG /* info = instruction pc */
++} expkind;
++
++typedef struct expdesc {
++ expkind k;
++ union {
++ struct { int info, aux; } s;
++ lua_Number nval;
++ } u;
++ int t; /* patch list of `exit when true' */
++ int f; /* patch list of `exit when false' */
++} expdesc;
++
++
++typedef struct upvaldesc {
++ lu_byte k;
++ lu_byte info;
++} upvaldesc;
++
++
++struct BlockCnt; /* defined in lparser.c */
++
++
++/* state needed to generate code for a given function */
++typedef struct FuncState {
++ Proto *f; /* current function header */
++ Table *h; /* table to find (and reuse) elements in `k' */
++ struct FuncState *prev; /* enclosing function */
++ struct LexState *ls; /* lexical state */
++ struct lua_State *L; /* copy of the Lua state */
++ struct BlockCnt *bl; /* chain of current blocks */
++ int pc; /* next position to code (equivalent to `ncode') */
++ int lasttarget; /* `pc' of last `jump target' */
++ int jpc; /* list of pending jumps to `pc' */
++ int freereg; /* first free register */
++ int nk; /* number of elements in `k' */
++ int np; /* number of elements in `p' */
++ short nlocvars; /* number of elements in `locvars' */
++ lu_byte nactvar; /* number of active local variables */
++ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
++ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
++} FuncState;
++
++
++LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
++ const char *name);
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lstate.c
+@@ -0,0 +1,214 @@
++/*
++** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
++** Global State
++** See Copyright Notice in lua.h
++*/
++
++
++#include
++
++#define lstate_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "ldebug.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"
++
++
++#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE)
++#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
++#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))
++
++
++/*
++** Main thread combines a thread state and the global state
++*/
++typedef struct LG {
++ lua_State l;
++ global_State g;
++} LG;
++
++
++
++static void stack_init (lua_State *L1, lua_State *L) {
++ /* initialize CallInfo array */
++ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
++ L1->ci = L1->base_ci;
++ L1->size_ci = BASIC_CI_SIZE;
++ L1->end_ci = L1->base_ci + L1->size_ci - 1;
++ /* initialize stack array */
++ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
++ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
++ L1->top = L1->stack;
++ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
++ /* initialize first ci */
++ L1->ci->func = L1->top;
++ setnilvalue(L1->top++); /* `function' entry for this `ci' */
++ L1->base = L1->ci->base = L1->top;
++ L1->ci->top = L1->top + LUA_MINSTACK;
++}
++
++
++static void freestack (lua_State *L, lua_State *L1) {
++ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
++ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
++}
++
++
++/*
++** open parts that may cause memory-allocation errors
++*/
++static void f_luaopen (lua_State *L, void *ud) {
++ global_State *g = G(L);
++ UNUSED(ud);
++ stack_init(L, L); /* init stack */
++ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
++ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
++ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
++ luaT_init(L);
++ luaX_init(L);
++ luaS_fix(luaS_newliteral(L, MEMERRMSG));
++ g->GCthreshold = 4*g->totalbytes;
++}
++
++
++static void preinit_state (lua_State *L, global_State *g) {
++ G(L) = g;
++ L->stack = NULL;
++ L->stacksize = 0;
++ L->errorJmp = NULL;
++ L->hook = NULL;
++ L->hookmask = 0;
++ L->basehookcount = 0;
++ L->allowhook = 1;
++ resethookcount(L);
++ L->openupval = NULL;
++ L->size_ci = 0;
++ L->nCcalls = L->baseCcalls = 0;
++ L->status = 0;
++ L->base_ci = L->ci = NULL;
++ L->savedpc = NULL;
++ L->errfunc = 0;
++ setnilvalue(gt(L));
++}
++
++
++static void close_state (lua_State *L) {
++ global_State *g = G(L);
++ luaF_close(L, L->stack); /* close all upvalues for this thread */
++ luaC_freeall(L); /* collect all objects */
++ lua_assert(g->rootgc == obj2gco(L));
++ lua_assert(g->strt.nuse == 0);
++ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
++ luaZ_freebuffer(L, &g->buff);
++ freestack(L, L);
++ lua_assert(g->totalbytes == sizeof(LG));
++ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
++}
++
++
++lua_State *luaE_newthread (lua_State *L) {
++ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
++ luaC_link(L, obj2gco(L1), LUA_TTHREAD);
++ preinit_state(L1, G(L));
++ stack_init(L1, L); /* init stack */
++ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
++ L1->hookmask = L->hookmask;
++ L1->basehookcount = L->basehookcount;
++ L1->hook = L->hook;
++ resethookcount(L1);
++ lua_assert(iswhite(obj2gco(L1)));
++ return L1;
++}
++
++
++void luaE_freethread (lua_State *L, lua_State *L1) {
++ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
++ lua_assert(L1->openupval == NULL);
++ luai_userstatefree(L1);
++ freestack(L, L1);
++ luaM_freemem(L, fromstate(L1), state_size(lua_State));
++}
++
++
++LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
++ int i;
++ lua_State *L;
++ global_State *g;
++ void *l = (*f)(ud, NULL, 0, state_size(LG));
++ if (l == NULL) return NULL;
++ L = tostate(l);
++ g = &((LG *)L)->g;
++ L->next = NULL;
++ L->tt = LUA_TTHREAD;
++ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
++ L->marked = luaC_white(g);
++ set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
++ preinit_state(L, g);
++ g->frealloc = f;
++ g->ud = ud;
++ g->mainthread = L;
++ g->uvhead.u.l.prev = &g->uvhead;
++ g->uvhead.u.l.next = &g->uvhead;
++ g->GCthreshold = 0; /* mark it as unfinished state */
++ g->strt.size = 0;
++ g->strt.nuse = 0;
++ g->strt.hash = NULL;
++ setnilvalue(registry(L));
++ luaZ_initbuffer(L, &g->buff);
++ g->panic = NULL;
++ g->gcstate = GCSpause;
++ g->rootgc = obj2gco(L);
++ g->sweepstrgc = 0;
++ g->sweepgc = &g->rootgc;
++ g->gray = NULL;
++ g->grayagain = NULL;
++ g->weak = NULL;
++ g->tmudata = NULL;
++ g->totalbytes = sizeof(LG);
++ g->gcpause = LUAI_GCPAUSE;
++ g->gcstepmul = LUAI_GCMUL;
++ g->gcdept = 0;
++ for (i=0; imt[i] = NULL;
++ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
++ /* memory allocation error: free partial state */
++ close_state(L);
++ L = NULL;
++ }
++ else
++ luai_userstateopen(L);
++ return L;
++}
++
++
++static void callallgcTM (lua_State *L, void *ud) {
++ UNUSED(ud);
++ luaC_callGCTM(L); /* call GC metamethods for all udata */
++}
++
++
++LUA_API void lua_close (lua_State *L) {
++ L = G(L)->mainthread; /* only the main thread can be closed */
++ lua_lock(L);
++ luaF_close(L, L->stack); /* close all upvalues for this thread */
++ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
++ L->errfunc = 0; /* no error function during GC metamethods */
++ do { /* repeat until no more errors */
++ L->ci = L->base_ci;
++ L->base = L->top = L->ci->base;
++ L->nCcalls = L->baseCcalls = 0;
++ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
++ lua_assert(G(L)->tmudata == NULL);
++ luai_userstateclose(L);
++ close_state(L);
++}
++
+--- /dev/null
++++ b/extensions/LUA/lua/lstate.h
+@@ -0,0 +1,169 @@
++/*
++** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
++** Global State
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lstate_h
++#define lstate_h
++
++#include "lua.h"
++
++#include "lobject.h"
++#include "ltm.h"
++#include "lzio.h"
++
++
++
++struct lua_longjmp; /* defined in ldo.c */
++
++
++/* table of globals */
++#define gt(L) (&L->l_gt)
++
++/* registry */
++#define registry(L) (&G(L)->l_registry)
++
++
++/* extra stack space to handle TM calls and some other extras */
++#define EXTRA_STACK 5
++
++
++#define BASIC_CI_SIZE 8
++
++#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
++
++
++
++typedef struct stringtable {
++ GCObject **hash;
++ lu_int32 nuse; /* number of elements */
++ int size;
++} stringtable;
++
++
++/*
++** informations about a call
++*/
++typedef struct CallInfo {
++ StkId base; /* base for this function */
++ StkId func; /* function index in the stack */
++ StkId top; /* top for this function */
++ const Instruction *savedpc;
++ int nresults; /* expected number of results from this function */
++ int tailcalls; /* number of tail calls lost under this entry */
++} CallInfo;
++
++
++
++#define curr_func(L) (clvalue(L->ci->func))
++#define ci_func(ci) (clvalue((ci)->func))
++#define f_isLua(ci) (!ci_func(ci)->c.isC)
++#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
++
++
++/*
++** `global state', shared by all threads of this state
++*/
++typedef struct global_State {
++ stringtable strt; /* hash table for strings */
++ lua_Alloc frealloc; /* function to reallocate memory */
++ void *ud; /* auxiliary data to `frealloc' */
++ lu_byte currentwhite;
++ lu_byte gcstate; /* state of garbage collector */
++ int sweepstrgc; /* position of sweep in `strt' */
++ GCObject *rootgc; /* list of all collectable objects */
++ GCObject **sweepgc; /* position of sweep in `rootgc' */
++ GCObject *gray; /* list of gray objects */
++ GCObject *grayagain; /* list of objects to be traversed atomically */
++ GCObject *weak; /* list of weak tables (to be cleared) */
++ GCObject *tmudata; /* last element of list of userdata to be GC */
++ Mbuffer buff; /* temporary buffer for string concatentation */
++ lu_mem GCthreshold;
++ lu_mem totalbytes; /* number of bytes currently allocated */
++ lu_mem estimate; /* an estimate of number of bytes actually in use */
++ lu_mem gcdept; /* how much GC is `behind schedule' */
++ int gcpause; /* size of pause between successive GCs */
++ int gcstepmul; /* GC `granularity' */
++ lua_CFunction panic; /* to be called in unprotected errors */
++ TValue l_registry;
++ struct lua_State *mainthread;
++ UpVal uvhead; /* head of double-linked list of all open upvalues */
++ struct Table *mt[NUM_TAGS]; /* metatables for basic types */
++ TString *tmname[TM_N]; /* array with tag-method names */
++} global_State;
++
++
++/*
++** `per thread' state
++*/
++struct lua_State {
++ CommonHeader;
++ lu_byte status;
++ StkId top; /* first free slot in the stack */
++ StkId base; /* base of current function */
++ global_State *l_G;
++ CallInfo *ci; /* call info for current function */
++ const Instruction *savedpc; /* `savedpc' of current function */
++ StkId stack_last; /* last free slot in the stack */
++ StkId stack; /* stack base */
++ CallInfo *end_ci; /* points after end of ci array*/
++ CallInfo *base_ci; /* array of CallInfo's */
++ int stacksize;
++ int size_ci; /* size of array `base_ci' */
++ unsigned short nCcalls; /* number of nested C calls */
++ unsigned short baseCcalls; /* nested C calls when resuming coroutine */
++ lu_byte hookmask;
++ lu_byte allowhook;
++ int basehookcount;
++ int hookcount;
++ lua_Hook hook;
++ TValue l_gt; /* table of globals */
++ TValue env; /* temporary place for environments */
++ GCObject *openupval; /* list of open upvalues in this stack */
++ GCObject *gclist;
++ struct lua_longjmp *errorJmp; /* current error recover point */
++ ptrdiff_t errfunc; /* current error handling function (stack index) */
++};
++
++
++#define G(L) (L->l_G)
++
++
++/*
++** Union of all collectable objects
++*/
++union GCObject {
++ GCheader gch;
++ union TString ts;
++ union Udata u;
++ union Closure cl;
++ struct Table h;
++ struct Proto p;
++ struct UpVal uv;
++ struct lua_State th; /* thread */
++};
++
++
++/* macros to convert a GCObject into a specific value */
++#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
++#define gco2ts(o) (&rawgco2ts(o)->tsv)
++#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
++#define gco2u(o) (&rawgco2u(o)->uv)
++#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
++#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
++#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
++#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
++#define ngcotouv(o) \
++ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
++#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
++
++/* macro to convert any Lua object into a GCObject */
++#define obj2gco(v) (cast(GCObject *, (v)))
++
++
++LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
++LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
++
++#endif
++
+--- /dev/null
++++ b/extensions/LUA/lua/lstring.c
+@@ -0,0 +1,110 @@
++/*
++** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
++** String table (keeps all strings handled by Lua)
++** See Copyright Notice in lua.h
++*/
++
++#include
++
++#define lstring_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "lmem.h"
++#include "lobject.h"
++#include "lstate.h"
++#include "lstring.h"
++
++
++
++void luaS_resize (lua_State *L, int newsize) {
++ GCObject **newhash;
++ stringtable *tb;
++ int i;
++ if (G(L)->gcstate == GCSsweepstring)
++ return; /* cannot resize during GC traverse */
++ newhash = luaM_newvector(L, newsize, GCObject *);
++ tb = &G(L)->strt;
++ for (i=0; isize; i++) {
++ GCObject *p = tb->hash[i];
++ while (p) { /* for each node in the list */
++ GCObject *next = p->gch.next; /* save next */
++ unsigned int h = gco2ts(p)->hash;
++ int h1 = lmod(h, newsize); /* new position */
++ lua_assert(cast_int(h%newsize) == lmod(h, newsize));
++ p->gch.next = newhash[h1]; /* chain it */
++ newhash[h1] = p;
++ p = next;
++ }
++ }
++ luaM_freearray(L, tb->hash, tb->size, TString *);
++ tb->size = newsize;
++ tb->hash = newhash;
++}
++
++
++static TString *newlstr (lua_State *L, const char *str, size_t l,
++ unsigned int h) {
++ TString *ts;
++ stringtable *tb;
++ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
++ luaM_toobig(L);
++ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
++ ts->tsv.len = l;
++ ts->tsv.hash = h;
++ ts->tsv.marked = luaC_white(G(L));
++ ts->tsv.tt = LUA_TSTRING;
++ ts->tsv.reserved = 0;
++ memcpy(ts+1, str, l*sizeof(char));
++ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
++ tb = &G(L)->strt;
++ h = lmod(h, tb->size);
++ ts->tsv.next = tb->hash[h]; /* chain new entry */
++ tb->hash[h] = obj2gco(ts);
++ tb->nuse++;
++ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
++ luaS_resize(L, tb->size*2); /* too crowded */
++ return ts;
++}
++
++
++TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
++ GCObject *o;
++ unsigned int h = cast(unsigned int, l); /* seed */
++ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
++ size_t l1;
++ for (l1=l; l1>=step; l1-=step) /* compute hash */
++ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
++ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
++ o != NULL;
++ o = o->gch.next) {
++ TString *ts = rawgco2ts(o);
++ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
++ /* string may be dead */
++ if (isdead(G(L), o)) changewhite(o);
++ return ts;
++ }
++ }
++ return newlstr(L, str, l, h); /* not found */
++}
++
++
++Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
++ Udata *u;
++ if (s > MAX_SIZET - sizeof(Udata))
++ luaM_toobig(L);
++ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
++ u->uv.marked = luaC_white(G(L)); /* is not finalized */
++ u->uv.tt = LUA_TUSERDATA;
++ u->uv.len = s;
++ u->uv.metatable = NULL;
++ u->uv.env = e;
++ /* chain it on udata list (after main thread) */
++ u->uv.next = G(L)->mainthread->next;
++ G(L)->mainthread->next = obj2gco(u);
++ return u;
++}
++
+--- /dev/null
++++ b/extensions/LUA/lua/lstring.h
+@@ -0,0 +1,31 @@
++/*
++** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
++** String table (keep all strings handled by Lua)
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lstring_h
++#define lstring_h
++
++
++#include "lgc.h"
++#include "lobject.h"
++#include "lstate.h"
++
++
++#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
++
++#define sizeudata(u) (sizeof(union Udata)+(u)->len)
++
++#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
++#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
++ (sizeof(s)/sizeof(char))-1))
++
++#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
++
++LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
++LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
++LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lstrlib.c
+@@ -0,0 +1,883 @@
++/*
++** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $
++** Standard library for string operations and pattern-matching
++** See Copyright Notice in lua.h
++*/
++
++
++#include
++#include
++#include
++#include
++#include
++
++#define lstrlib_c
++#define LUA_LIB
++
++#include "lua.h"
++
++#include "lauxlib.h"
++#include "lualib.h"
++
++
++/* macro to `unsign' a character */
++#define uchar(c) ((unsigned char)(c))
++
++
++
++static int str_len (lua_State *L) {
++ size_t l;
++ luaL_checklstring(L, 1, &l);
++ lua_pushinteger(L, l);
++ return 1;
++}
++
++
++static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
++ /* relative string position: negative means back from end */
++ if (pos < 0) pos += (ptrdiff_t)len + 1;
++ return (pos >= 0) ? pos : 0;
++}
++
++
++static int str_sub (lua_State *L) {
++ size_t l;
++ const char *s = luaL_checklstring(L, 1, &l);
++ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
++ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
++ if (start < 1) start = 1;
++ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
++ if (start <= end)
++ lua_pushlstring(L, s+start-1, end-start+1);
++ else lua_pushliteral(L, "");
++ return 1;
++}
++
++
++static int str_reverse (lua_State *L) {
++ size_t l;
++ const char *s = luaL_checklstring(L, 1, &l);
++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC);
++ if(!b) luaL_error(L, "str_reverse: cannot allocate memory");
++ luaL_buffinit(L, b);
++ while (l--) luaL_addchar(b, s[l]);
++ luaL_pushresult(b);
++ kfree(b);
++ return 1;
++}
++
++
++static int str_lower (lua_State *L) {
++ size_t l;
++ size_t i;
++ const char *s = luaL_checklstring(L, 1, &l);
++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC);
++ if(!b) luaL_error(L, "str_lower: cannot allocate memory");
++ luaL_buffinit(L, b);
++ for (i=0; i 0)
++ luaL_addlstring(b, s, l);
++ luaL_pushresult(b);
++ kfree(b);
++ return 1;
++}
++
++
++static int str_byte (lua_State *L) {
++ size_t l;
++ const char *s = luaL_checklstring(L, 1, &l);
++ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
++ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
++ int n, i;
++ if (posi <= 0) posi = 1;
++ if ((size_t)pose > l) pose = l;
++ if (posi > pose) return 0; /* empty interval; return no values */
++ n = (int)(pose - posi + 1);
++ if (posi + n <= pose) /* overflow? */
++ luaL_error(L, "string slice too long");
++ luaL_checkstack(L, n, "string slice too long");
++ for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED)
++ return luaL_error(ms->L, "invalid capture index");
++ return l;
++}
++
++
++static int capture_to_close (MatchState *ms) {
++ int level = ms->level;
++ for (level--; level>=0; level--)
++ if (ms->capture[level].len == CAP_UNFINISHED) return level;
++ return luaL_error(ms->L, "invalid pattern capture");
++}
++
++
++static const char *classend (MatchState *ms, const char *p) {
++ switch (*p++) {
++ case L_ESC: {
++ if (*p == '\0')
++ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
++ return p+1;
++ }
++ case '[': {
++ if (*p == '^') p++;
++ do { /* look for a `]' */
++ if (*p == '\0')
++ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
++ if (*(p++) == L_ESC && *p != '\0')
++ p++; /* skip escapes (e.g. `%]') */
++ } while (*p != ']');
++ return p+1;
++ }
++ default: {
++ return p;
++ }
++ }
++}
++
++
++static int match_class (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 'x' : res = isxdigit(c); break;
++ case 'z' : res = (c == 0); break;
++ default: return (cl == c);
++ }
++ return (islower(cl) ? res : !res);
++}
++
++
++static int matchbracketclass (int c, const char *p, const char *ec) {
++ int sig = 1;
++ if (*(p+1) == '^') {
++ sig = 0;
++ p++; /* skip the `^' */
++ }
++ while (++p < ec) {
++ if (*p == L_ESC) {
++ p++;
++ if (match_class(c, uchar(*p)))
++ return sig;
++ }
++ else if ((*(p+1) == '-') && (p+2 < ec)) {
++ p+=2;
++ if (uchar(*(p-2)) <= c && c <= uchar(*p))
++ return sig;
++ }
++ else if (uchar(*p) == c) return sig;
++ }
++ return !sig;
++}
++
++
++static int singlematch (int c, const char *p, const char *ep) {
++ switch (*p) {
++ case '.': return 1; /* matches any char */
++ case L_ESC: return match_class(c, uchar(*(p+1)));
++ case '[': return matchbracketclass(c, p, ep-1);
++ default: return (uchar(*p) == c);
++ }
++}
++
++
++static const char *match (MatchState *ms, const char *s, const char *p);
++
++
++static const char *matchbalance (MatchState *ms, const char *s,
++ const char *p) {
++ if (*p == 0 || *(p+1) == 0)
++ luaL_error(ms->L, "unbalanced pattern");
++ if (*s != *p) return NULL;
++ else {
++ int b = *p;
++ int e = *(p+1);
++ int cont = 1;
++ while (++s < ms->src_end) {
++ if (*s == e) {
++ if (--cont == 0) return s+1;
++ }
++ else if (*s == b) cont++;
++ }
++ }
++ return NULL; /* string ends out of balance */
++}
++
++
++static const char *max_expand (MatchState *ms, const char *s,
++ const char *p, const char *ep) {
++ ptrdiff_t i = 0; /* counts maximum expand for item */
++ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep))
++ i++;
++ /* keeps trying to match with the maximum repetitions */
++ while (i>=0) {
++ const char *res = match(ms, (s+i), ep+1);
++ if (res) return res;
++ i--; /* else didn't match; reduce 1 repetition to try again */
++ }
++ return NULL;
++}
++
++
++static const char *min_expand (MatchState *ms, const char *s,
++ const char *p, const char *ep) {
++ for (;;) {
++ const char *res = match(ms, s, ep+1);
++ if (res != NULL)
++ return res;
++ else if (ssrc_end && singlematch(uchar(*s), p, ep))
++ s++; /* try with one more repetition */
++ else return NULL;
++ }
++}
++
++
++static const char *start_capture (MatchState *ms, const char *s,
++ const char *p, int what) {
++ const char *res;
++ int level = ms->level;
++ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
++ ms->capture[level].init = s;
++ ms->capture[level].len = what;
++ ms->level = level+1;
++ if ((res=match(ms, s, p)) == NULL) /* match failed? */
++ ms->level--; /* undo capture */
++ return res;
++}
++
++
++static const char *end_capture (MatchState *ms, const char *s,
++ const char *p) {
++ int l = capture_to_close(ms);
++ const char *res;
++ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
++ if ((res = match(ms, s, p)) == NULL) /* match failed? */
++ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
++ return res;
++}
++
++
++static const char *match_capture (MatchState *ms, const char *s, int l) {
++ size_t len;
++ l = check_capture(ms, l);
++ len = ms->capture[l].len;
++ if ((size_t)(ms->src_end-s) >= len &&
++ memcmp(ms->capture[l].init, s, len) == 0)
++ return s+len;
++ else return NULL;
++}
++
++
++static const char *match (MatchState *ms, const char *s, const char *p) {
++ init: /* using goto's to optimize tail recursion */
++ switch (*p) {
++ case '(': { /* start capture */
++ if (*(p+1) == ')') /* position capture? */
++ return start_capture(ms, s, p+2, CAP_POSITION);
++ else
++ return start_capture(ms, s, p+1, CAP_UNFINISHED);
++ }
++ case ')': { /* end capture */
++ return end_capture(ms, s, p+1);
++ }
++ case L_ESC: {
++ switch (*(p+1)) {
++ case 'b': { /* balanced string? */
++ s = matchbalance(ms, s, p+2);
++ if (s == NULL) return NULL;
++ p+=4; goto init; /* else return match(ms, s, p+4); */
++ }
++ case 'f': { /* frontier? */
++ const char *ep; char previous;
++ p += 2;
++ if (*p != '[')
++ luaL_error(ms->L, "missing " LUA_QL("[") " after "
++ LUA_QL("%%f") " in pattern");
++ ep = classend(ms, p); /* points to what is next */
++ previous = (s == ms->src_init) ? '\0' : *(s-1);
++ if (matchbracketclass(uchar(previous), p, ep-1) ||
++ !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
++ p=ep; goto init; /* else return match(ms, s, ep); */
++ }
++ default: {
++ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
++ s = match_capture(ms, s, uchar(*(p+1)));
++ if (s == NULL) return NULL;
++ p+=2; goto init; /* else return match(ms, s, p+2) */
++ }
++ goto dflt; /* case default */
++ }
++ }
++ }
++ case '\0': { /* end of pattern */
++ return s; /* match succeeded */
++ }
++ case '$': {
++ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
++ return (s == ms->src_end) ? s : NULL; /* check end of string */
++ else goto dflt;
++ }
++ default: dflt: { /* it is a pattern item */
++ const char *ep = classend(ms, p); /* points to what is next */
++ int m = ssrc_end && singlematch(uchar(*s), p, ep);
++ switch (*ep) {
++ case '?': { /* optional */
++ const char *res;
++ if (m && ((res=match(ms, s+1, ep+1)) != NULL))
++ return res;
++ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
++ }
++ case '*': { /* 0 or more repetitions */
++ return max_expand(ms, s, p, ep);
++ }
++ case '+': { /* 1 or more repetitions */
++ return (m ? max_expand(ms, s+1, p, ep) : NULL);
++ }
++ case '-': { /* 0 or more repetitions (minimum) */
++ return min_expand(ms, s, p, ep);
++ }
++ default: {
++ if (!m) return NULL;
++ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
++ }
++ }
++ }
++ }
++}
++
++
++
++static const char *lmemfind (const char *s1, size_t l1,
++ const char *s2, size_t l2) {
++ if (l2 == 0) return s1; /* empty strings are everywhere */
++ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
++ else {
++ const char *init; /* to search for a `*s2' inside `s1' */
++ l2--; /* 1st char will be checked by `memchr' */
++ l1 = l1-l2; /* `s2' cannot be found after that */
++ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
++ init++; /* 1st char is already checked */
++ if (memcmp(init, s2+1, l2) == 0)
++ return init-1;
++ else { /* correct `l1' and `s1' to try again */
++ l1 -= init-s1;
++ s1 = init;
++ }
++ }
++ return NULL; /* not found */
++ }
++}
++
++
++static void push_onecapture (MatchState *ms, int i, const char *s,
++ const char *e) {
++ if (i >= ms->level) {
++ if (i == 0) /* ms->level == 0, too */
++ lua_pushlstring(ms->L, s, e - s); /* add whole match */
++ else
++ luaL_error(ms->L, "invalid capture index");
++ }
++ else {
++ ptrdiff_t l = ms->capture[i].len;
++ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
++ if (l == CAP_POSITION)
++ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
++ else
++ lua_pushlstring(ms->L, ms->capture[i].init, l);
++ }
++}
++
++
++static int push_captures (MatchState *ms, const char *s, const char *e) {
++ int i;
++ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
++ luaL_checkstack(ms->L, nlevels, "too many captures");
++ for (i = 0; i < nlevels; i++)
++ push_onecapture(ms, i, s, e);
++ return nlevels; /* number of strings pushed */
++}
++
++
++static int str_find_aux (lua_State *L, int find) {
++ size_t l1, l2;
++ const char *s = luaL_checklstring(L, 1, &l1);
++ const char *p = luaL_checklstring(L, 2, &l2);
++ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
++ if (init < 0) init = 0;
++ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
++ if (find && (lua_toboolean(L, 4) || /* explicit request? */
++ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
++ /* do a plain search */
++ const char *s2 = lmemfind(s+init, l1-init, p, l2);
++ if (s2) {
++ lua_pushinteger(L, s2-s+1);
++ lua_pushinteger(L, s2-s+l2);
++ return 2;
++ }
++ }
++ else {
++ MatchState ms;
++ int anchor = (*p == '^') ? (p++, 1) : 0;
++ const char *s1=s+init;
++ ms.L = L;
++ ms.src_init = s;
++ ms.src_end = s+l1;
++ do {
++ const char *res;
++ ms.level = 0;
++ if ((res=match(&ms, s1, p)) != NULL) {
++ if (find) {
++ lua_pushinteger(L, s1-s+1); /* start */
++ lua_pushinteger(L, res-s); /* end */
++ return push_captures(&ms, NULL, 0) + 2;
++ }
++ else
++ return push_captures(&ms, s1, res);
++ }
++ } while (s1++ < ms.src_end && !anchor);
++ }
++ lua_pushnil(L); /* not found */
++ return 1;
++}
++
++
++static int str_find (lua_State *L) {
++ return str_find_aux(L, 1);
++}
++
++
++static int str_match (lua_State *L) {
++ return str_find_aux(L, 0);
++}
++
++
++static int gmatch_aux (lua_State *L) {
++ MatchState ms;
++ size_t ls;
++ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
++ const char *p = lua_tostring(L, lua_upvalueindex(2));
++ const char *src;
++ ms.L = L;
++ ms.src_init = s;
++ ms.src_end = s+ls;
++ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
++ src <= ms.src_end;
++ src++) {
++ const char *e;
++ ms.level = 0;
++ if ((e = match(&ms, src, p)) != NULL) {
++ lua_Integer newstart = e-s;
++ if (e == src) newstart++; /* empty match? go at least one position */
++ lua_pushinteger(L, newstart);
++ lua_replace(L, lua_upvalueindex(3));
++ return push_captures(&ms, src, e);
++ }
++ }
++ return 0; /* not found */
++}
++
++
++static int gmatch (lua_State *L) {
++ luaL_checkstring(L, 1);
++ luaL_checkstring(L, 2);
++ lua_settop(L, 2);
++ lua_pushinteger(L, 0);
++ lua_pushcclosure(L, gmatch_aux, 3);
++ return 1;
++}
++
++
++static int gfind_nodef (lua_State *L) {
++ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
++ LUA_QL("string.gmatch"));
++}
++
++
++static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
++ const char *e) {
++ size_t l, i;
++ const char *news = lua_tolstring(ms->L, 3, &l);
++ for (i = 0; i < l; i++) {
++ if (news[i] != L_ESC)
++ luaL_addchar(b, news[i]);
++ else {
++ i++; /* skip ESC */
++ if (!isdigit(uchar(news[i])))
++ luaL_addchar(b, news[i]);
++ else if (news[i] == '0')
++ luaL_addlstring(b, s, e - s);
++ else {
++ push_onecapture(ms, news[i] - '1', s, e);
++ luaL_addvalue(b); /* add capture to accumulated result */
++ }
++ }
++ }
++}
++
++
++static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
++ const char *e) {
++ lua_State *L = ms->L;
++ switch (lua_type(L, 3)) {
++ case LUA_TNUMBER:
++ case LUA_TSTRING: {
++ add_s(ms, b, s, e);
++ return;
++ }
++ case LUA_TFUNCTION: {
++ int n;
++ lua_pushvalue(L, 3);
++ n = push_captures(ms, s, e);
++ lua_call(L, n, 1);
++ break;
++ }
++ case LUA_TTABLE: {
++ push_onecapture(ms, 0, s, e);
++ lua_gettable(L, 3);
++ break;
++ }
++ }
++ if (!lua_toboolean(L, -1)) { /* nil or false? */
++ lua_pop(L, 1);
++ lua_pushlstring(L, s, e - s); /* keep original text */
++ }
++ else if (!lua_isstring(L, -1))
++ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
++ luaL_addvalue(b); /* add result to accumulator */
++}
++
++
++static int str_gsub (lua_State *L) {
++ size_t srcl;
++ const char *src = luaL_checklstring(L, 1, &srcl);
++ const char *p = luaL_checkstring(L, 2);
++ int tr = lua_type(L, 3);
++ int max_s = luaL_optint(L, 4, srcl+1);
++ int anchor = (*p == '^') ? (p++, 1) : 0;
++ int n = 0;
++ MatchState ms;
++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC);
++ if(!b) luaL_error(L, "str_gsub: cannot allocate memory");
++ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
++ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
++ "string/function/table expected");
++ luaL_buffinit(L, b);
++ ms.L = L;
++ ms.src_init = src;
++ ms.src_end = src+srcl;
++ while (n < max_s) {
++ const char *e;
++ ms.level = 0;
++ e = match(&ms, src, p);
++ if (e) {
++ n++;
++ add_value(&ms, b, src, e);
++ }
++ if (e && e>src) /* non empty match? */
++ src = e; /* skip it */
++ else if (src < ms.src_end)
++ luaL_addchar(b, *src++);
++ else break;
++ if (anchor) break;
++ }
++ luaL_addlstring(b, src, ms.src_end-src);
++ luaL_pushresult(b);
++ lua_pushinteger(L, n); /* number of substitutions */
++ kfree(b);
++ return 2;
++}
++
++/* }====================================================== */
++
++
++/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
++#define MAX_ITEM 512
++/* valid flags in a format specification */
++#define FLAGS "-+ #0"
++/*
++** maximum size of each format specification (such as '%-099.99d')
++** (+10 accounts for %99.99x plus margin of error)
++*/
++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
++
++
++static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
++ size_t l;
++ const char *s = luaL_checklstring(L, arg, &l);
++ luaL_addchar(b, '"');
++ while (l--) {
++ switch (*s) {
++ case '"': case '\\': case '\n': {
++ luaL_addchar(b, '\\');
++ luaL_addchar(b, *s);
++ break;
++ }
++ case '\r': {
++ luaL_addlstring(b, "\\r", 2);
++ break;
++ }
++ case '\0': {
++ luaL_addlstring(b, "\\000", 4);
++ break;
++ }
++ default: {
++ luaL_addchar(b, *s);
++ break;
++ }
++ }
++ s++;
++ }
++ luaL_addchar(b, '"');
++}
++
++static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
++ const char *p = strfrmt;
++ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
++ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
++ luaL_error(L, "invalid format (repeated flags)");
++ if (isdigit(uchar(*p))) p++; /* skip width */
++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
++ if (*p == '.') {
++ p++;
++ if (isdigit(uchar(*p))) p++; /* skip precision */
++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
++ }
++ if (isdigit(uchar(*p)))
++ luaL_error(L, "invalid format (width or precision too long)");
++ *(form++) = '%';
++ strncpy(form, strfrmt, p - strfrmt + 1);
++ form += p - strfrmt + 1;
++ *form = '\0';
++ return p;
++}
++
++
++static void addintlen (char *form) {
++ size_t l = strlen(form);
++ char spec = form[l - 1];
++ strcpy(form + l - 1, LUA_INTFRMLEN);
++ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
++ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
++}
++
++
++static int str_format (lua_State *L) {
++ int arg = 1;
++ size_t sfl;
++ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
++ const char *strfrmt_end = strfrmt+sfl;
++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC);
++ if(!b) luaL_error(L, "str_format: cannot allocate memory");
++ luaL_buffinit(L, b);
++ while (strfrmt < strfrmt_end) {
++ if (*strfrmt != L_ESC)
++ luaL_addchar(b, *strfrmt++);
++ else if (*++strfrmt == L_ESC)
++ luaL_addchar(b, *strfrmt++); /* %% */
++ else { /* format item */
++ char form[MAX_FORMAT]; /* to store the format (`%...') */
++ char buff[MAX_ITEM]; /* to store the formatted item */
++ arg++;
++ strfrmt = scanformat(L, strfrmt, form);
++ switch (*strfrmt++) {
++ case 'c': {
++ sprintf(buff, form, (int)luaL_checknumber(L, arg));
++ break;
++ }
++ case 'd': case 'i': {
++ addintlen(form);
++ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++ break;
++ }
++ case 'o': case 'u': case 'x': case 'X': {
++ addintlen(form);
++ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++ break;
++ }
++ case 'q': {
++ addquoted(L, b, arg);
++ continue; /* skip the 'addsize' at the end */
++ }
++ case 's': {
++ size_t l;
++ const char *s = luaL_checklstring(L, arg, &l);
++ if (!strchr(form, '.') && l >= 100) {
++ /* no precision and string is too long to be formatted;
++ keep original string */
++ lua_pushvalue(L, arg);
++ luaL_addvalue(b);
++ continue; /* skip the `addsize' at the end */
++ }
++ else {
++ sprintf(buff, form, s);
++ break;
++ }
++ }
++ default: { /* also treat cases `pnLlh' */
++ kfree(b);
++ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
++ LUA_QL("format"), *(strfrmt - 1));
++ }
++ }
++ luaL_addlstring(b, buff, strlen(buff));
++ }
++ }
++ luaL_pushresult(b);
++ kfree(b);
++ return 1;
++}
++
++
++static const luaL_Reg strlib[] = {
++ {"byte", str_byte},
++ {"char", str_char},
++ {"dump", str_dump},
++ {"find", str_find},
++ {"format", str_format},
++ {"gfind", gfind_nodef},
++ {"gmatch", gmatch},
++ {"gsub", str_gsub},
++ {"len", str_len},
++ {"lower", str_lower},
++ {"match", str_match},
++ {"rep", str_rep},
++ {"reverse", str_reverse},
++ {"sub", str_sub},
++ {"upper", str_upper},
++ {NULL, NULL}
++};
++
++
++static void createmetatable (lua_State *L) {
++ lua_createtable(L, 0, 1); /* create metatable for strings */
++ lua_pushliteral(L, ""); /* dummy string */
++ lua_pushvalue(L, -2);
++ lua_setmetatable(L, -2); /* set string metatable */
++ lua_pop(L, 1); /* pop dummy string */
++ lua_pushvalue(L, -2); /* string library... */
++ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
++ lua_pop(L, 1); /* pop metatable */
++}
++
++
++/*
++** Open string library
++*/
++LUALIB_API int luaopen_string (lua_State *L) {
++ luaL_register(L, LUA_STRLIBNAME, strlib);
++#if defined(LUA_COMPAT_GFIND)
++ lua_getfield(L, -1, "gmatch");
++ lua_setfield(L, -2, "gfind");
++#endif
++ createmetatable(L);
++ return 1;
++}
+--- /dev/null
++++ b/extensions/LUA/lua/ltable.c
+@@ -0,0 +1,588 @@
++/*
++** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
++** Lua tables (hash)
++** See Copyright Notice in lua.h
++*/
++
++
++/*
++** Implementation of tables (aka arrays, objects, or hash tables).
++** Tables keep its elements in two parts: an array part and a hash part.
++** Non-negative integer keys are all candidates to be kept in the array
++** part. The actual size of the array is the largest `n' such that at
++** least half the slots between 0 and n are in use.
++** Hash uses a mix of chained scatter table with Brent's variation.
++** A main invariant of these tables is that, if an element is not
++** in its main position (i.e. the `original' position that its hash gives
++** to it), then the colliding element is in its own main position.
++** Hence even when the load factor reaches 100%, performance remains good.
++*/
++
++#include
++#include
++
++#define ltable_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "ldebug.h"
++#include "ldo.h"
++#include "lgc.h"
++#include "lmem.h"
++#include "lobject.h"
++#include "lstate.h"
++#include "ltable.h"
++
++
++/*
++** max size of array part is 2^MAXBITS
++*/
++#if LUAI_BITSINT > 26
++#define MAXBITS 26
++#else
++#define MAXBITS (LUAI_BITSINT-2)
++#endif
++
++#define MAXASIZE (1 << MAXBITS)
++
++
++#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
++
++#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
++#define hashboolean(t,p) hashpow2(t, p)
++
++
++/*
++** for some types, it is better to avoid modulus by power of 2, as
++** they tend to have many 2 factors.
++*/
++#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
++
++
++#define hashpointer(t,p) hashmod(t, IntPoint(p))
++
++
++/*
++** number of ints inside a lua_Number
++*/
++#define numints cast_int(sizeof(lua_Number)/sizeof(int))
++
++
++
++#define dummynode (&dummynode_)
++
++static const Node dummynode_ = {
++ {{NULL}, LUA_TNIL}, /* value */
++ {{{NULL}, LUA_TNIL, NULL}} /* key */
++};
++
++
++/*
++** hash for lua_Numbers
++*/
++static Node *hashnum (const Table *t, lua_Number n) {
++ unsigned int a[numints];
++ int i;
++ if (luai_numeq(n, 0)) /* avoid problems with -0 */
++ return gnode(t, 0);
++ memcpy(a, &n, sizeof(a));
++ for (i = 1; i < numints; i++) a[0] += a[i];
++ return hashmod(t, a[0]);
++}
++
++
++
++/*
++** returns the `main' position of an element in a table (that is, the index
++** of its hash value)
++*/
++static Node *mainposition (const Table *t, const TValue *key) {
++ switch (ttype(key)) {
++ case LUA_TNUMBER:
++ return hashnum(t, nvalue(key));
++ case LUA_TSTRING:
++ return hashstr(t, rawtsvalue(key));
++ case LUA_TBOOLEAN:
++ return hashboolean(t, bvalue(key));
++ case LUA_TLIGHTUSERDATA:
++ return hashpointer(t, pvalue(key));
++ default:
++ return hashpointer(t, gcvalue(key));
++ }
++}
++
++
++/*
++** returns the index for `key' if `key' is an appropriate key to live in
++** the array part of the table, -1 otherwise.
++*/
++static int arrayindex (const TValue *key) {
++ if (ttisnumber(key)) {
++ lua_Number n = nvalue(key);
++ int k;
++ lua_number2int(k, n);
++ if (luai_numeq(cast_num(k), n))
++ return k;
++ }
++ return -1; /* `key' did not match some condition */
++}
++
++
++/*
++** returns the index of a `key' for table traversals. First goes all
++** elements in the array part, then elements in the hash part. The
++** beginning of a traversal is signalled by -1.
++*/
++static int findindex (lua_State *L, Table *t, StkId key) {
++ int i;
++ if (ttisnil(key)) return -1; /* first iteration */
++ i = arrayindex(key);
++ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
++ return i-1; /* yes; that's the index (corrected to C) */
++ else {
++ Node *n = mainposition(t, key);
++ do { /* check whether `key' is somewhere in the chain */
++ /* key may be dead already, but it is ok to use it in `next' */
++ if (luaO_rawequalObj(key2tval(n), key) ||
++ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
++ gcvalue(gkey(n)) == gcvalue(key))) {
++ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
++ /* hash elements are numbered after array ones */
++ return i + t->sizearray;
++ }
++ else n = gnext(n);
++ } while (n);
++ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
++ return 0; /* to avoid warnings */
++ }
++}
++
++
++int luaH_next (lua_State *L, Table *t, StkId key) {
++ int i = findindex(L, t, key); /* find original element */
++ for (i++; i < t->sizearray; i++) { /* try first array part */
++ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
++ setnvalue(key, cast_num(i+1));
++ setobj2s(L, key+1, &t->array[i]);
++ return 1;
++ }
++ }
++ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
++ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
++ setobj2s(L, key, key2tval(gnode(t, i)));
++ setobj2s(L, key+1, gval(gnode(t, i)));
++ return 1;
++ }
++ }
++ return 0; /* no more elements */
++}
++
++
++/*
++** {=============================================================
++** Rehash
++** ==============================================================
++*/
++
++
++static int computesizes (int nums[], int *narray) {
++ int i;
++ int twotoi; /* 2^i */
++ int a = 0; /* number of elements smaller than 2^i */
++ int na = 0; /* number of elements to go to array part */
++ int n = 0; /* optimal size for array part */
++ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
++ if (nums[i] > 0) {
++ a += nums[i];
++ if (a > twotoi/2) { /* more than half elements present? */
++ n = twotoi; /* optimal size (till now) */
++ na = a; /* all elements smaller than n will go to array part */
++ }
++ }
++ if (a == *narray) break; /* all elements already counted */
++ }
++ *narray = n;
++ lua_assert(*narray/2 <= na && na <= *narray);
++ return na;
++}
++
++
++static int countint (const TValue *key, int *nums) {
++ int k = arrayindex(key);
++ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
++ nums[ceillog2(k)]++; /* count as such */
++ return 1;
++ }
++ else
++ return 0;
++}
++
++
++static int numusearray (const Table *t, int *nums) {
++ int lg;
++ int ttlg; /* 2^lg */
++ int ause = 0; /* summation of `nums' */
++ int i = 1; /* count to traverse all array keys */
++ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
++ int lc = 0; /* counter */
++ int lim = ttlg;
++ if (lim > t->sizearray) {
++ lim = t->sizearray; /* adjust upper limit */
++ if (i > lim)
++ break; /* no more elements to count */
++ }
++ /* count elements in range (2^(lg-1), 2^lg] */
++ for (; i <= lim; i++) {
++ if (!ttisnil(&t->array[i-1]))
++ lc++;
++ }
++ nums[lg] += lc;
++ ause += lc;
++ }
++ return ause;
++}
++
++
++static int numusehash (const Table *t, int *nums, int *pnasize) {
++ int totaluse = 0; /* total number of elements */
++ int ause = 0; /* summation of `nums' */
++ int i = sizenode(t);
++ while (i--) {
++ Node *n = &t->node[i];
++ if (!ttisnil(gval(n))) {
++ ause += countint(key2tval(n), nums);
++ totaluse++;
++ }
++ }
++ *pnasize += ause;
++ return totaluse;
++}
++
++
++static void setarrayvector (lua_State *L, Table *t, int size) {
++ int i;
++ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
++ for (i=t->sizearray; iarray[i]);
++ t->sizearray = size;
++}
++
++
++static void setnodevector (lua_State *L, Table *t, int size) {
++ int lsize;
++ if (size == 0) { /* no elements to hash part? */
++ t->node = cast(Node *, dummynode); /* use common `dummynode' */
++ lsize = 0;
++ }
++ else {
++ int i;
++ lsize = ceillog2(size);
++ if (lsize > MAXBITS)
++ luaG_runerror(L, "table overflow");
++ size = twoto(lsize);
++ t->node = luaM_newvector(L, size, Node);
++ for (i=0; ilsizenode = cast_byte(lsize);
++ t->lastfree = gnode(t, size); /* all positions are free */
++}
++
++
++static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
++ int i;
++ int oldasize = t->sizearray;
++ int oldhsize = t->lsizenode;
++ Node *nold = t->node; /* save old hash ... */
++ if (nasize > oldasize) /* array part must grow? */
++ setarrayvector(L, t, nasize);
++ /* create new hash part with appropriate size */
++ setnodevector(L, t, nhsize);
++ if (nasize < oldasize) { /* array part must shrink? */
++ t->sizearray = nasize;
++ /* re-insert elements from vanishing slice */
++ for (i=nasize; iarray[i]))
++ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++ }
++ /* shrink array */
++ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
++ }
++ /* re-insert elements from hash part */
++ for (i = twoto(oldhsize) - 1; i >= 0; i--) {
++ Node *old = nold+i;
++ if (!ttisnil(gval(old)))
++ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
++ }
++ if (nold != dummynode)
++ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
++}
++
++
++void luaH_resizearray (lua_State *L, Table *t, int nasize) {
++ int nsize = (t->node == dummynode) ? 0 : sizenode(t);
++ resize(L, t, nasize, nsize);
++}
++
++
++static void rehash (lua_State *L, Table *t, const TValue *ek) {
++ int nasize, na;
++ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
++ int i;
++ int totaluse;
++ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
++ nasize = numusearray(t, nums); /* count keys in array part */
++ totaluse = nasize; /* all those keys are integer keys */
++ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
++ /* count extra key */
++ nasize += countint(ek, nums);
++ totaluse++;
++ /* compute new size for array part */
++ na = computesizes(nums, &nasize);
++ /* resize the table to new computed sizes */
++ resize(L, t, nasize, totaluse - na);
++}
++
++
++
++/*
++** }=============================================================
++*/
++
++
++Table *luaH_new (lua_State *L, int narray, int nhash) {
++ Table *t = luaM_new(L, Table);
++ luaC_link(L, obj2gco(t), LUA_TTABLE);
++ t->metatable = NULL;
++ t->flags = cast_byte(~0);
++ /* temporary values (kept only if some malloc fails) */
++ t->array = NULL;
++ t->sizearray = 0;
++ t->lsizenode = 0;
++ t->node = cast(Node *, dummynode);
++ setarrayvector(L, t, narray);
++ setnodevector(L, t, nhash);
++ return t;
++}
++
++
++void luaH_free (lua_State *L, Table *t) {
++ if (t->node != dummynode)
++ luaM_freearray(L, t->node, sizenode(t), Node);
++ luaM_freearray(L, t->array, t->sizearray, TValue);
++ luaM_free(L, t);
++}
++
++
++static Node *getfreepos (Table *t) {
++ while (t->lastfree-- > t->node) {
++ if (ttisnil(gkey(t->lastfree)))
++ return t->lastfree;
++ }
++ return NULL; /* could not find a free place */
++}
++
++
++
++/*
++** inserts a new key into a hash table; first, check whether key's main
++** position is free. If not, check whether colliding node is in its main
++** position or not: if it is not, move colliding node to an empty place and
++** put new key in its main position; otherwise (colliding node is in its main
++** position), new key goes to an empty position.
++*/
++static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
++ Node *mp = mainposition(t, key);
++ if (!ttisnil(gval(mp)) || mp == dummynode) {
++ Node *othern;
++ Node *n = getfreepos(t); /* get a free place */
++ if (n == NULL) { /* cannot find a free place? */
++ rehash(L, t, key); /* grow table */
++ return luaH_set(L, t, key); /* re-insert key into grown table */
++ }
++ lua_assert(n != dummynode);
++ othern = mainposition(t, key2tval(mp));
++ if (othern != mp) { /* is colliding node out of its main position? */
++ /* yes; move colliding node into free position */
++ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
++ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
++ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
++ gnext(mp) = NULL; /* now `mp' is free */
++ setnilvalue(gval(mp));
++ }
++ else { /* colliding node is in its own main position */
++ /* new node will go into free position */
++ gnext(n) = gnext(mp); /* chain new position */
++ gnext(mp) = n;
++ mp = n;
++ }
++ }
++ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
++ luaC_barriert(L, t, key);
++ lua_assert(ttisnil(gval(mp)));
++ return gval(mp);
++}
++
++
++/*
++** search function for integers
++*/
++const TValue *luaH_getnum (Table *t, int key) {
++ /* (1 <= key && key <= t->sizearray) */
++ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
++ return &t->array[key-1];
++ else {
++ lua_Number nk = cast_num(key);
++ Node *n = hashnum(t, nk);
++ do { /* check whether `key' is somewhere in the chain */
++ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++ return gval(n); /* that's it */
++ else n = gnext(n);
++ } while (n);
++ return luaO_nilobject;
++ }
++}
++
++
++/*
++** search function for strings
++*/
++const TValue *luaH_getstr (Table *t, TString *key) {
++ Node *n = hashstr(t, key);
++ do { /* check whether `key' is somewhere in the chain */
++ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
++ return gval(n); /* that's it */
++ else n = gnext(n);
++ } while (n);
++ return luaO_nilobject;
++}
++
++
++/*
++** main search function
++*/
++const TValue *luaH_get (Table *t, const TValue *key) {
++ switch (ttype(key)) {
++ case LUA_TNIL: return luaO_nilobject;
++ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++ case LUA_TNUMBER: {
++ int k;
++ lua_Number n = nvalue(key);
++ lua_number2int(k, n);
++ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
++ return luaH_getnum(t, k); /* use specialized version */
++ /* else go through */
++ }
++ default: {
++ Node *n = mainposition(t, key);
++ do { /* check whether `key' is somewhere in the chain */
++ if (luaO_rawequalObj(key2tval(n), key))
++ return gval(n); /* that's it */
++ else n = gnext(n);
++ } while (n);
++ return luaO_nilobject;
++ }
++ }
++}
++
++
++TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
++ const TValue *p = luaH_get(t, key);
++ t->flags = 0;
++ if (p != luaO_nilobject)
++ return cast(TValue *, p);
++ else {
++ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
++ else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
++ luaG_runerror(L, "table index is NaN");
++ return newkey(L, t, key);
++ }
++}
++
++
++TValue *luaH_setnum (lua_State *L, Table *t, int key) {
++ const TValue *p = luaH_getnum(t, key);
++ if (p != luaO_nilobject)
++ return cast(TValue *, p);
++ else {
++ TValue k;
++ setnvalue(&k, cast_num(key));
++ return newkey(L, t, &k);
++ }
++}
++
++
++TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
++ const TValue *p = luaH_getstr(t, key);
++ if (p != luaO_nilobject)
++ return cast(TValue *, p);
++ else {
++ TValue k;
++ setsvalue(L, &k, key);
++ return newkey(L, t, &k);
++ }
++}
++
++
++static int unbound_search (Table *t, unsigned int j) {
++ unsigned int i = j; /* i is zero or a present index */
++ j++;
++ /* find `i' and `j' such that i is present and j is not */
++ while (!ttisnil(luaH_getnum(t, j))) {
++ i = j;
++ j *= 2;
++ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
++ /* table was built with bad purposes: resort to linear search */
++ i = 1;
++ while (!ttisnil(luaH_getnum(t, i))) i++;
++ return i - 1;
++ }
++ }
++ /* now do a binary search between them */
++ while (j - i > 1) {
++ unsigned int m = (i+j)/2;
++ if (ttisnil(luaH_getnum(t, m))) j = m;
++ else i = m;
++ }
++ return i;
++}
++
++
++/*
++** Try to find a boundary in table `t'. A `boundary' is an integer index
++** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
++*/
++int luaH_getn (Table *t) {
++ unsigned int j = t->sizearray;
++ if (j > 0 && ttisnil(&t->array[j - 1])) {
++ /* there is a boundary in the array part: (binary) search for it */
++ unsigned int i = 0;
++ while (j - i > 1) {
++ unsigned int m = (i+j)/2;
++ if (ttisnil(&t->array[m - 1])) j = m;
++ else i = m;
++ }
++ return i;
++ }
++ /* else must find a boundary in hash part */
++ else if (t->node == dummynode) /* hash part is empty? */
++ return j; /* that is easy... */
++ else return unbound_search(t, j);
++}
++
++
++
++#if defined(LUA_DEBUG)
++
++Node *luaH_mainposition (const Table *t, const TValue *key) {
++ return mainposition(t, key);
++}
++
++int luaH_isdummy (Node *n) { return n == dummynode; }
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/ltable.h
+@@ -0,0 +1,40 @@
++/*
++** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $
++** Lua tables (hash)
++** See Copyright Notice in lua.h
++*/
++
++#ifndef ltable_h
++#define ltable_h
++
++#include "lobject.h"
++
++
++#define gnode(t,i) (&(t)->node[i])
++#define gkey(n) (&(n)->i_key.nk)
++#define gval(n) (&(n)->i_val)
++#define gnext(n) ((n)->i_key.nk.next)
++
++#define key2tval(n) (&(n)->i_key.tvk)
++
++
++LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
++LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
++LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
++LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
++LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
++LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
++LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
++LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
++LUAI_FUNC void luaH_free (lua_State *L, Table *t);
++LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
++LUAI_FUNC int luaH_getn (Table *t);
++
++
++#if defined(LUA_DEBUG)
++LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
++LUAI_FUNC int luaH_isdummy (Node *n);
++#endif
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/ltablib.c
+@@ -0,0 +1,288 @@
++/*
++** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $
++** Library for Table Manipulation
++** See Copyright Notice in lua.h
++*/
++
++
++#include
++
++#define ltablib_c
++#define LUA_LIB
++
++#include "lua.h"
++
++#include "lauxlib.h"
++#include "lualib.h"
++
++
++#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
++
++
++static int foreachi (lua_State *L) {
++ int i;
++ int n = aux_getn(L, 1);
++ luaL_checktype(L, 2, LUA_TFUNCTION);
++ for (i=1; i <= n; i++) {
++ lua_pushvalue(L, 2); /* function */
++ lua_pushinteger(L, i); /* 1st argument */
++ lua_rawgeti(L, 1, i); /* 2nd argument */
++ lua_call(L, 2, 1);
++ if (!lua_isnil(L, -1))
++ return 1;
++ lua_pop(L, 1); /* remove nil result */
++ }
++ return 0;
++}
++
++
++static int foreach (lua_State *L) {
++ luaL_checktype(L, 1, LUA_TTABLE);
++ luaL_checktype(L, 2, LUA_TFUNCTION);
++ lua_pushnil(L); /* first key */
++ while (lua_next(L, 1)) {
++ lua_pushvalue(L, 2); /* function */
++ lua_pushvalue(L, -3); /* key */
++ lua_pushvalue(L, -3); /* value */
++ lua_call(L, 2, 1);
++ if (!lua_isnil(L, -1))
++ return 1;
++ lua_pop(L, 2); /* remove value and result */
++ }
++ return 0;
++}
++
++
++static int maxn (lua_State *L) {
++ lua_Number max = 0;
++ luaL_checktype(L, 1, LUA_TTABLE);
++ lua_pushnil(L); /* first key */
++ while (lua_next(L, 1)) {
++ lua_pop(L, 1); /* remove value */
++ if (lua_type(L, -1) == LUA_TNUMBER) {
++ lua_Number v = lua_tonumber(L, -1);
++ if (v > max) max = v;
++ }
++ }
++ lua_pushnumber(L, max);
++ return 1;
++}
++
++
++static int getn (lua_State *L) {
++ lua_pushinteger(L, aux_getn(L, 1));
++ return 1;
++}
++
++
++static int setn (lua_State *L) {
++ luaL_checktype(L, 1, LUA_TTABLE);
++#ifndef luaL_setn
++ luaL_setn(L, 1, luaL_checkint(L, 2));
++#else
++ luaL_error(L, LUA_QL("setn") " is obsolete");
++#endif
++ lua_pushvalue(L, 1);
++ return 1;
++}
++
++
++static int tinsert (lua_State *L) {
++ int e = aux_getn(L, 1) + 1; /* first empty element */
++ int pos; /* where to insert new element */
++ switch (lua_gettop(L)) {
++ case 2: { /* called with only 2 arguments */
++ pos = e; /* insert new element at the end */
++ break;
++ }
++ case 3: {
++ int i;
++ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
++ if (pos > e) e = pos; /* `grow' array if necessary */
++ for (i = e; i > pos; i--) { /* move up elements */
++ lua_rawgeti(L, 1, i-1);
++ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
++ }
++ break;
++ }
++ default: {
++ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
++ }
++ }
++ luaL_setn(L, 1, e); /* new size */
++ lua_rawseti(L, 1, pos); /* t[pos] = v */
++ return 0;
++}
++
++
++static int tremove (lua_State *L) {
++ int e = aux_getn(L, 1);
++ int pos = luaL_optint(L, 2, e);
++ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
++ return 0; /* nothing to remove */
++ luaL_setn(L, 1, e - 1); /* t.n = n-1 */
++ lua_rawgeti(L, 1, pos); /* result = t[pos] */
++ for ( ;pos= P */
++ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
++ if (i>u) luaL_error(L, "invalid order function for sorting");
++ lua_pop(L, 1); /* remove a[i] */
++ }
++ /* repeat --j until a[j] <= P */
++ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
++ if (j
++
++#define ltm_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "lobject.h"
++#include "lstate.h"
++#include "lstring.h"
++#include "ltable.h"
++#include "ltm.h"
++
++
++
++const char *const luaT_typenames[] = {
++ "nil", "boolean", "userdata", "number",
++ "string", "table", "function", "userdata", "thread",
++ "proto", "upval"
++};
++
++
++void luaT_init (lua_State *L) {
++ static const char *const luaT_eventname[] = { /* ORDER TM */
++ "__index", "__newindex",
++ "__gc", "__mode", "__eq",
++ "__add", "__sub", "__mul", "__div", "__mod",
++ "__pow", "__unm", "__len", "__lt", "__le",
++ "__concat", "__call"
++ };
++ int i;
++ for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]);
++ luaS_fix(G(L)->tmname[i]); /* never collect these names */
++ }
++}
++
++
++/*
++** function to be used with macro "fasttm": optimized for absence of
++** tag methods
++*/
++const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
++ const TValue *tm = luaH_getstr(events, ename);
++ lua_assert(event <= TM_EQ);
++ if (ttisnil(tm)) { /* no tag method? */
++ events->flags |= cast_byte(1u<metatable;
++ break;
++ case LUA_TUSERDATA:
++ mt = uvalue(o)->metatable;
++ break;
++ default:
++ mt = G(L)->mt[ttype(o)];
++ }
++ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
++}
++
+--- /dev/null
++++ b/extensions/LUA/lua/ltm.h
+@@ -0,0 +1,54 @@
++/*
++** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
++** Tag methods
++** See Copyright Notice in lua.h
++*/
++
++#ifndef ltm_h
++#define ltm_h
++
++
++#include "lobject.h"
++
++
++/*
++* WARNING: if you change the order of this enumeration,
++* grep "ORDER TM"
++*/
++typedef enum {
++ TM_INDEX,
++ TM_NEWINDEX,
++ TM_GC,
++ TM_MODE,
++ TM_EQ, /* last tag method with `fast' access */
++ TM_ADD,
++ TM_SUB,
++ TM_MUL,
++ TM_DIV,
++ TM_MOD,
++ TM_POW,
++ TM_UNM,
++ TM_LEN,
++ TM_LT,
++ TM_LE,
++ TM_CONCAT,
++ TM_CALL,
++ TM_N /* number of elements in the enum */
++} TMS;
++
++
++
++#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
++ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
++
++#define fasttm(l,et,e) gfasttm(G(l), et, e)
++
++LUAI_DATA const char *const luaT_typenames[];
++
++
++LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
++LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
++ TMS event);
++LUAI_FUNC void luaT_init (lua_State *L);
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/luaconf.h
+@@ -0,0 +1,797 @@
++/*
++** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $
++** Configuration file for Lua
++** See Copyright Notice in lua.h
++*/
++
++
++#ifndef lconfig_h
++#define lconfig_h
++
++#include
++
++#if !defined(__KERNEL__)
++#include
++#else
++#define UCHAR_MAX 255
++#define SHRT_MAX 32767
++#define BUFSIZ 8192
++#define NO_FPU
++#endif
++
++/*
++** ==================================================================
++** Search for "@@" to find all configurable definitions.
++** ===================================================================
++*/
++
++
++/*
++@@ LUA_ANSI controls the use of non-ansi features.
++** CHANGE it (define it) if you want Lua to avoid the use of any
++** non-ansi feature or library.
++*/
++#if defined(__STRICT_ANSI__)
++#define LUA_ANSI
++#endif
++
++
++#if !defined(LUA_ANSI) && defined(_WIN32)
++#define LUA_WIN
++#endif
++
++#if defined(LUA_USE_LINUX)
++#define LUA_USE_POSIX
++#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
++#define LUA_USE_READLINE /* needs some extra libraries */
++#endif
++
++#if defined(LUA_USE_MACOSX)
++#define LUA_USE_POSIX
++#define LUA_DL_DYLD /* does not need extra library */
++#endif
++
++
++
++/*
++@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
++@* Interfaces Extension (XSI).
++** CHANGE it (define it) if your system is XSI compatible.
++*/
++#if defined(LUA_USE_POSIX)
++#define LUA_USE_MKSTEMP
++#define LUA_USE_ISATTY
++#define LUA_USE_POPEN
++#define LUA_USE_ULONGJMP
++#endif
++
++
++/*
++@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
++@* Lua check to set its paths.
++@@ LUA_INIT is the name of the environment variable that Lua
++@* checks for initialization code.
++** CHANGE them if you want different names.
++*/
++#define LUA_PATH "LUA_PATH"
++#define LUA_CPATH "LUA_CPATH"
++#define LUA_INIT "LUA_INIT"
++
++
++/*
++@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
++@* Lua libraries.
++@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
++@* C libraries.
++** CHANGE them if your machine has a non-conventional directory
++** hierarchy or if you want to install your libraries in
++** non-conventional directories.
++*/
++#if defined(_WIN32)
++/*
++** In Windows, any exclamation mark ('!') in the path is replaced by the
++** path of the directory of the executable file of the current process.
++*/
++#define LUA_LDIR "!\\lua\\"
++#define LUA_CDIR "!\\"
++#define LUA_PATH_DEFAULT \
++ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
++ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
++#define LUA_CPATH_DEFAULT \
++ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
++
++#else
++#define LUA_ROOT "/usr/local/"
++#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
++#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
++#define LUA_PATH_DEFAULT \
++ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
++#define LUA_CPATH_DEFAULT \
++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
++#endif
++
++
++/*
++@@ LUA_DIRSEP is the directory separator (for submodules).
++** CHANGE it if your machine does not use "/" as the directory separator
++** and is not Windows. (On Windows Lua automatically uses "\".)
++*/
++#if defined(_WIN32)
++#define LUA_DIRSEP "\\"
++#else
++#define LUA_DIRSEP "/"
++#endif
++
++
++/*
++@@ LUA_PATHSEP is the character that separates templates in a path.
++@@ LUA_PATH_MARK is the string that marks the substitution points in a
++@* template.
++@@ LUA_EXECDIR in a Windows path is replaced by the executable's
++@* directory.
++@@ LUA_IGMARK is a mark to ignore all before it when bulding the
++@* luaopen_ function name.
++** CHANGE them if for some reason your system cannot use those
++** characters. (E.g., if one of those characters is a common character
++** in file/directory names.) Probably you do not need to change them.
++*/
++#define LUA_PATHSEP ";"
++#define LUA_PATH_MARK "?"
++#define LUA_EXECDIR "!"
++#define LUA_IGMARK "-"
++
++
++/*
++@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
++** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
++** machines, ptrdiff_t gives a good choice between int or long.)
++*/
++#define LUA_INTEGER ptrdiff_t
++
++
++/*
++@@ LUA_API is a mark for all core API functions.
++@@ LUALIB_API is a mark for all standard library functions.
++** CHANGE them if you need to define those functions in some special way.
++** For instance, if you want to create one Windows DLL with the core and
++** the libraries, you may want to use the following definition (define
++** LUA_BUILD_AS_DLL to get it).
++*/
++#if defined(LUA_BUILD_AS_DLL)
++
++#if defined(LUA_CORE) || defined(LUA_LIB)
++#define LUA_API __declspec(dllexport)
++#else
++#define LUA_API __declspec(dllimport)
++#endif
++
++#else
++
++#define LUA_API extern
++
++#endif
++
++/* more often than not the libs go together with the core */
++#define LUALIB_API LUA_API
++
++
++/*
++@@ LUAI_FUNC is a mark for all extern functions that are not to be
++@* exported to outside modules.
++@@ LUAI_DATA is a mark for all extern (const) variables that are not to
++@* be exported to outside modules.
++** CHANGE them if you need to mark them in some special way. Elf/gcc
++** (versions 3.2 and later) mark them as "hidden" to optimize access
++** when Lua is compiled as a shared library.
++*/
++#if defined(luaall_c)
++#define LUAI_FUNC static
++#define LUAI_DATA /* empty */
++
++#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
++ defined(__ELF__)
++#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
++#define LUAI_DATA LUAI_FUNC
++
++#else
++#define LUAI_FUNC extern
++#define LUAI_DATA extern
++#endif
++
++
++
++/*
++@@ LUA_QL describes how error messages quote program elements.
++** CHANGE it if you want a different appearance.
++*/
++#define LUA_QL(x) "'" x "'"
++#define LUA_QS LUA_QL("%s")
++
++
++/*
++@@ LUA_IDSIZE gives the maximum size for the description of the source
++@* of a function in debug information.
++** CHANGE it if you want a different size.
++*/
++#define LUA_IDSIZE 60
++
++
++/*
++** {==================================================================
++** Stand-alone configuration
++** ===================================================================
++*/
++
++#if defined(lua_c) || defined(luaall_c)
++
++/*
++@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
++@* is, whether we're running lua interactively).
++** CHANGE it if you have a better definition for non-POSIX/non-Windows
++** systems.
++*/
++#if defined(LUA_USE_ISATTY)
++#include
++#define lua_stdin_is_tty() isatty(0)
++#elif defined(LUA_WIN)
++#include
++#include
++#define lua_stdin_is_tty() _isatty(_fileno(stdin))
++#else
++#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
++#endif
++
++
++/*
++@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
++@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
++** CHANGE them if you want different prompts. (You can also change the
++** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
++*/
++#define LUA_PROMPT "> "
++#define LUA_PROMPT2 ">> "
++
++
++/*
++@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
++** CHANGE it if your stand-alone interpreter has a different name and
++** your system is not able to detect that name automatically.
++*/
++#define LUA_PROGNAME "lua"
++
++
++/*
++@@ LUA_MAXINPUT is the maximum length for an input line in the
++@* stand-alone interpreter.
++** CHANGE it if you need longer lines.
++*/
++#define LUA_MAXINPUT 512
++
++
++/*
++@@ lua_readline defines how to show a prompt and then read a line from
++@* the standard input.
++@@ lua_saveline defines how to "save" a read line in a "history".
++@@ lua_freeline defines how to free a line read by lua_readline.
++** CHANGE them if you want to improve this functionality (e.g., by using
++** GNU readline and history facilities).
++*/
++#if defined(LUA_USE_READLINE)
++#include
++#include
++#include
++#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
++#define lua_saveline(L,idx) \
++ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
++ add_history(lua_tostring(L, idx)); /* add it to history */
++#define lua_freeline(L,b) ((void)L, free(b))
++#else
++#define lua_readline(L,b,p) \
++ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
++ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
++#define lua_saveline(L,idx) { (void)L; (void)idx; }
++#define lua_freeline(L,b) { (void)L; (void)b; }
++#endif
++
++#endif
++
++/* }================================================================== */
++
++
++/*
++@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles
++@* as a percentage.
++** CHANGE it if you want the GC to run faster or slower (higher values
++** mean larger pauses which mean slower collection.) You can also change
++** this value dynamically.
++*/
++#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
++
++
++/*
++@@ LUAI_GCMUL defines the default speed of garbage collection relative to
++@* memory allocation as a percentage.
++** CHANGE it if you want to change the granularity of the garbage
++** collection. (Higher values mean coarser collections. 0 represents
++** infinity, where each step performs a full collection.) You can also
++** change this value dynamically.
++*/
++#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
++
++
++
++/*
++@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.
++** CHANGE it (define it) if you want exact compatibility with the
++** behavior of setn/getn in Lua 5.0.
++*/
++#undef LUA_COMPAT_GETN
++
++/*
++@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.
++** CHANGE it to undefined as soon as you do not need a global 'loadlib'
++** function (the function is still available as 'package.loadlib').
++*/
++#undef LUA_COMPAT_LOADLIB
++
++/*
++@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
++** CHANGE it to undefined as soon as your programs use only '...' to
++** access vararg parameters (instead of the old 'arg' table).
++*/
++#define LUA_COMPAT_VARARG
++
++/*
++@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.
++** CHANGE it to undefined as soon as your programs use 'math.fmod' or
++** the new '%' operator instead of 'math.mod'.
++*/
++#define LUA_COMPAT_MOD
++
++/*
++@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting
++@* facility.
++** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
++** off the advisory error when nesting [[...]].
++*/
++#define LUA_COMPAT_LSTR 1
++
++/*
++@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
++** CHANGE it to undefined as soon as you rename 'string.gfind' to
++** 'string.gmatch'.
++*/
++#define LUA_COMPAT_GFIND
++
++/*
++@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
++@* behavior.
++** CHANGE it to undefined as soon as you replace to 'luaL_register'
++** your uses of 'luaL_openlib'
++*/
++#define LUA_COMPAT_OPENLIB
++
++
++
++/*
++@@ luai_apicheck is the assert macro used by the Lua-C API.
++** CHANGE luai_apicheck if you want Lua to perform some checks in the
++** parameters it gets from API calls. This may slow down the interpreter
++** a bit, but may be quite useful when debugging C code that interfaces
++** with Lua. A useful redefinition is to use assert.h.
++*/
++#if defined(LUA_USE_APICHECK)
++#include
++#define luai_apicheck(L,o) { (void)L; assert(o); }
++#else
++#define luai_apicheck(L,o) { (void)L; }
++#endif
++
++
++/*
++@@ LUAI_BITSINT defines the number of bits in an int.
++** CHANGE here if Lua cannot automatically detect the number of bits of
++** your machine. Probably you do not need to change this.
++*/
++/* avoid overflows in comparison */
++#if !defined(__KERNEL__)
++#include
++#define LUA_INT_MAX INT_MAX
++#else
++#define LUA_INT_MAX (~0U>>1)
++#endif
++
++#if LUA_INT_MAX-20 < 32760
++#define LUAI_BITSINT 16
++#elif LUA_INT_MAX > 2147483640L
++/* int has at least 32 bits */
++#define LUAI_BITSINT 32
++#else
++#error "you must define LUA_BITSINT with number of bits in an integer"
++#endif
++
++
++/*
++@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
++@@ LUAI_INT32 is an signed integer with at least 32 bits.
++@@ LUAI_UMEM is an unsigned integer big enough to count the total
++@* memory used by Lua.
++@@ LUAI_MEM is a signed integer big enough to count the total memory
++@* used by Lua.
++** CHANGE here if for some weird reason the default definitions are not
++** good enough for your machine. (The definitions in the 'else'
++** part always works, but may waste space on machines with 64-bit
++** longs.) Probably you do not need to change this.
++*/
++#if LUAI_BITSINT >= 32
++#define LUAI_UINT32 unsigned int
++#define LUAI_INT32 int
++#define LUAI_MAXINT32 INT_MAX
++#define LUAI_UMEM size_t
++#define LUAI_MEM ptrdiff_t
++#else
++/* 16-bit ints */
++#define LUAI_UINT32 unsigned long
++#define LUAI_INT32 long
++#define LUAI_MAXINT32 LONG_MAX
++#define LUAI_UMEM unsigned long
++#define LUAI_MEM long
++#endif
++
++
++/*
++@@ LUAI_MAXCALLS limits the number of nested calls.
++** CHANGE it if you need really deep recursive calls. This limit is
++** arbitrary; its only purpose is to stop infinite recursion before
++** exhausting memory.
++*/
++#define LUAI_MAXCALLS 20000
++
++
++/*
++@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
++@* can use.
++** CHANGE it if you need lots of (Lua) stack space for your C
++** functions. This limit is arbitrary; its only purpose is to stop C
++** functions to consume unlimited stack space. (must be smaller than
++** -LUA_REGISTRYINDEX)
++*/
++#define LUAI_MAXCSTACK 8000
++
++
++
++/*
++** {==================================================================
++** CHANGE (to smaller values) the following definitions if your system
++** has a small C stack. (Or you may want to change them to larger
++** values if your system has a large C stack and these limits are
++** too rigid for you.) Some of these constants control the size of
++** stack-allocated arrays used by the compiler or the interpreter, while
++** others limit the maximum number of recursive calls that the compiler
++** or the interpreter can perform. Values too large may cause a C stack
++** overflow for some forms of deep constructs.
++** ===================================================================
++*/
++
++
++/*
++@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
++@* syntactical nested non-terminals in a program.
++*/
++#define LUAI_MAXCCALLS 200
++
++
++/*
++@@ LUAI_MAXVARS is the maximum number of local variables per function
++@* (must be smaller than 250).
++*/
++#define LUAI_MAXVARS 200
++
++
++/*
++@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
++@* (must be smaller than 250).
++*/
++#define LUAI_MAXUPVALUES 60
++
++
++/*
++@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
++*/
++#define LUAL_BUFFERSIZE BUFSIZ
++
++/* }================================================================== */
++
++
++
++
++/*
++** {==================================================================
++@@ LUA_NUMBER is the type of numbers in Lua.
++** CHANGE the following definitions only if you want to build Lua
++** with a number type different from double. You may also need to
++** change lua_number2int & lua_number2integer.
++** ===================================================================
++*/
++#if !defined(NO_FPU)
++#define LUA_NUMBER_DOUBLE
++#define LUA_NUMBER double
++#else
++#define LUA_NUMBER long
++#endif
++
++/*
++@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
++@* over a number.
++*/
++#define LUAI_UACNUMBER LUA_NUMBER
++
++
++/*
++@@ LUA_NUMBER_SCAN is the format for reading numbers.
++@@ LUA_NUMBER_FMT is the format for writing numbers.
++@@ lua_number2str converts a number to a string.
++@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
++@@ lua_str2number converts a string to a number.
++*/
++#if !defined(NO_FPU)
++#define LUA_NUMBER_SCAN "%lf"
++#define LUA_NUMBER_FMT "%.14g"
++#define lua_str2number(s,p) strtod((s), (p))
++#else
++#define LUA_NUMBER_SCAN "%ld"
++#define LUA_NUMBER_FMT "%ld"
++#if !defined(__KERNEL__)
++#define lua_str2number(s,p) strtol((s), (p), 10)
++#else
++#define lua_str2number(s,p) simple_strtol((s), (p), 10)
++#endif
++#endif
++
++#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
++#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++@@ The luai_num* macros define the primitive operations over numbers.
++*/
++#if defined(LUA_CORE)
++#define luai_numadd(a,b) ((a)+(b))
++#define luai_numsub(a,b) ((a)-(b))
++#define luai_nummul(a,b) ((a)*(b))
++#define luai_numdiv(a,b) ((a)/(b))
++#define luai_numunm(a) (-(a))
++#define luai_numeq(a,b) ((a)==(b))
++#define luai_numlt(a,b) ((a)<(b))
++#define luai_numle(a,b) ((a)<=(b))
++#define luai_numisnan(a) (!luai_numeq((a), (a)))
++#if !defined(NO_FPU)
++#include
++#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
++#define luai_numpow(a,b) (pow(a,b))
++#else
++#define luai_nummod(a,b) ((a)%(b))
++#define luai_numpow(a,b) luai_nummul(a,b)
++#endif
++#endif
++
++
++/*
++@@ lua_number2int is a macro to convert lua_Number to int.
++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
++** CHANGE them if you know a faster way to convert a lua_Number to
++** int (with any rounding method and without throwing errors) in your
++** system. In Pentium machines, a naive typecast from double to int
++** in C is extremely slow, so any alternative is worth trying.
++*/
++
++/* On a Pentium, resort to a trick */
++#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
++ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
++
++/* On a Microsoft compiler, use assembler */
++#if defined(_MSC_VER)
++
++#define lua_number2int(i,d) __asm fld d __asm fistp i
++#define lua_number2integer(i,n) lua_number2int(i, n)
++
++/* the next trick should work on any Pentium, but sometimes clashes
++ with a DirectX idiosyncrasy */
++#else
++
++union luai_Cast { double l_d; long l_l; };
++#define lua_number2int(i,d) \
++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
++#define lua_number2integer(i,n) lua_number2int(i, n)
++
++#endif
++
++
++/* this option always works, but may be slow */
++#else
++#define lua_number2int(i,d) ((i)=(int)(d))
++#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
++
++#endif
++
++/* }================================================================== */
++
++
++/*
++@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
++** CHANGE it if your system requires alignments larger than double. (For
++** instance, if your system supports long doubles and they must be
++** aligned in 16-byte boundaries, then you should add long double in the
++** union.) Probably you do not need to change this.
++*/
++#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
++
++
++/*
++@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.
++** CHANGE them if you prefer to use longjmp/setjmp even with C++
++** or if want/don't to use _longjmp/_setjmp instead of regular
++** longjmp/setjmp. By default, Lua handles errors with exceptions when
++** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
++** and with longjmp/setjmp otherwise.
++*/
++#if defined(__KERNEL__)
++#undef LUA_USE_ULONGJMP
++#endif
++
++#if defined(__cplusplus)
++/* C++ exceptions */
++#define LUAI_THROW(L,c) throw(c)
++#define LUAI_TRY(L,c,a) try { a } catch(...) \
++ { if ((c)->status == 0) (c)->status = -1; }
++#define luai_jmpbuf int /* dummy variable */
++
++#elif defined(LUA_USE_ULONGJMP)
++/* in Unix, try _longjmp/_setjmp (more efficient) */
++#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
++#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
++#define luai_jmpbuf jmp_buf
++
++#else
++/* default handling with long jumps */
++#define LUAI_THROW(L,c) longjmp((c)->b, 1)
++#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
++#define luai_jmpbuf jmp_buf
++
++#endif
++
++
++/*
++@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
++@* can do during pattern-matching.
++** CHANGE it if you need more captures. This limit is arbitrary.
++*/
++#define LUA_MAXCAPTURES 32
++
++
++/*
++@@ lua_tmpnam is the function that the OS library uses to create a
++@* temporary name.
++@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
++** CHANGE them if you have an alternative to tmpnam (which is considered
++** insecure) or if you want the original tmpnam anyway. By default, Lua
++** uses tmpnam except when POSIX is available, where it uses mkstemp.
++*/
++#if defined(loslib_c) || defined(luaall_c)
++
++#if defined(LUA_USE_MKSTEMP)
++#include
++#define LUA_TMPNAMBUFSIZE 32
++#define lua_tmpnam(b,e) { \
++ strcpy(b, "/tmp/lua_XXXXXX"); \
++ e = mkstemp(b); \
++ if (e != -1) close(e); \
++ e = (e == -1); }
++
++#else
++#define LUA_TMPNAMBUFSIZE L_tmpnam
++#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
++#endif
++
++#endif
++
++
++/*
++@@ lua_popen spawns a new process connected to the current one through
++@* the file streams.
++** CHANGE it if you have a way to implement it in your system.
++*/
++#if defined(LUA_USE_POPEN)
++
++#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
++#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
++
++#elif defined(LUA_WIN)
++
++#define lua_popen(L,c,m) ((void)L, _popen(c,m))
++#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
++
++#else
++
++#define lua_popen(L,c,m) ((void)((void)c, m), \
++ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
++#define lua_pclose(L,file) ((void)((void)L, file), 0)
++
++#endif
++
++/*
++@@ LUA_DL_* define which dynamic-library system Lua should use.
++** CHANGE here if Lua has problems choosing the appropriate
++** dynamic-library system for your platform (either Windows' DLL, Mac's
++** dyld, or Unix's dlopen). If your system is some kind of Unix, there
++** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
++** it. To use dlopen you also need to adapt the src/Makefile (probably
++** adding -ldl to the linker options), so Lua does not select it
++** automatically. (When you change the makefile to add -ldl, you must
++** also add -DLUA_USE_DLOPEN.)
++** If you do not want any kind of dynamic library, undefine all these
++** options.
++** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
++*/
++#if defined(LUA_USE_DLOPEN)
++#define LUA_DL_DLOPEN
++#endif
++
++#if defined(LUA_WIN)
++#define LUA_DL_DLL
++#endif
++
++
++/*
++@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
++@* (the data goes just *before* the lua_State pointer).
++** CHANGE (define) this if you really need that. This value must be
++** a multiple of the maximum alignment required for your machine.
++*/
++#define LUAI_EXTRASPACE 0
++
++
++/*
++@@ luai_userstate* allow user-specific actions on threads.
++** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
++** extra when a thread is created/deleted/resumed/yielded.
++*/
++#define luai_userstateopen(L) ((void)L)
++#define luai_userstateclose(L) ((void)L)
++#define luai_userstatethread(L,L1) ((void)L)
++#define luai_userstatefree(L) ((void)L)
++#define luai_userstateresume(L,n) ((void)L)
++#define luai_userstateyield(L,n) ((void)L)
++
++
++/*
++@@ LUA_INTFRMLEN is the length modifier for integer conversions
++@* in 'string.format'.
++@@ LUA_INTFRM_T is the integer type correspoding to the previous length
++@* modifier.
++** CHANGE them if your system supports long long or does not support long.
++*/
++
++#if defined(LUA_USELONGLONG)
++
++#define LUA_INTFRMLEN "ll"
++#define LUA_INTFRM_T long long
++
++#else
++
++#define LUA_INTFRMLEN "l"
++#define LUA_INTFRM_T long
++
++#endif
++
++/* =================================================================== */
++
++/*
++** Local configuration. You can use this space to add your redefinitions
++** without modifying the main part of the file.
++*/
++
++
++
++#endif
++
+--- /dev/null
++++ b/extensions/LUA/lua/lua.h
+@@ -0,0 +1,387 @@
++/*
++** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
++** Lua - An Extensible Extension Language
++** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
++** See Copyright Notice at the end of this file
++*/
++
++
++#ifndef lua_h
++#define lua_h
++
++#include
++#include
++
++#include "luaconf.h"
++
++
++#define LUA_VERSION "Lua 5.1"
++#define LUA_RELEASE "Lua 5.1.4"
++#define LUA_VERSION_NUM 501
++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
++#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
++
++
++/* mark for precompiled code (`Lua') */
++#define LUA_SIGNATURE "\033Lua"
++
++/* option for multiple returns in `lua_pcall' and `lua_call' */
++#define LUA_MULTRET (-1)
++
++
++/*
++** pseudo-indices
++*/
++#define LUA_REGISTRYINDEX (-10000)
++#define LUA_ENVIRONINDEX (-10001)
++#define LUA_GLOBALSINDEX (-10002)
++#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
++
++
++/* thread status; 0 is OK */
++#define LUA_YIELD 1
++#define LUA_ERRRUN 2
++#define LUA_ERRSYNTAX 3
++#define LUA_ERRMEM 4
++#define LUA_ERRERR 5
++
++
++typedef struct lua_State lua_State;
++
++typedef int (*lua_CFunction) (lua_State *L);
++
++
++/*
++** functions that read/write blocks when loading/dumping Lua chunks
++*/
++typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
++
++typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
++
++
++/*
++** prototype for memory-allocation functions
++*/
++typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
++
++
++/*
++** basic types
++*/
++#define LUA_TNONE (-1)
++
++#define LUA_TNIL 0
++#define LUA_TBOOLEAN 1
++#define LUA_TLIGHTUSERDATA 2
++#define LUA_TNUMBER 3
++#define LUA_TSTRING 4
++#define LUA_TTABLE 5
++#define LUA_TFUNCTION 6
++#define LUA_TUSERDATA 7
++#define LUA_TTHREAD 8
++
++
++
++/* minimum Lua stack available to a C function */
++#define LUA_MINSTACK 20
++
++
++/*
++** generic extra include file
++*/
++#if defined(LUA_USER_H)
++#include LUA_USER_H
++#endif
++
++
++/* type of numbers in Lua */
++typedef LUA_NUMBER lua_Number;
++
++
++/* type for integer functions */
++typedef LUA_INTEGER lua_Integer;
++
++
++
++/*
++** state manipulation
++*/
++LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
++LUA_API void (lua_close) (lua_State *L);
++LUA_API lua_State *(lua_newthread) (lua_State *L);
++
++LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
++
++
++/*
++** basic stack manipulation
++*/
++LUA_API int (lua_gettop) (lua_State *L);
++LUA_API void (lua_settop) (lua_State *L, int idx);
++LUA_API void (lua_pushvalue) (lua_State *L, int idx);
++LUA_API void (lua_remove) (lua_State *L, int idx);
++LUA_API void (lua_insert) (lua_State *L, int idx);
++LUA_API void (lua_replace) (lua_State *L, int idx);
++LUA_API int (lua_checkstack) (lua_State *L, int sz);
++
++LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
++
++
++/*
++** access functions (stack -> C)
++*/
++
++LUA_API int (lua_isnumber) (lua_State *L, int idx);
++LUA_API int (lua_isstring) (lua_State *L, int idx);
++LUA_API int (lua_iscfunction) (lua_State *L, int idx);
++LUA_API int (lua_isuserdata) (lua_State *L, int idx);
++LUA_API int (lua_type) (lua_State *L, int idx);
++LUA_API const char *(lua_typename) (lua_State *L, int tp);
++
++LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
++LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
++LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
++
++LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
++LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
++LUA_API int (lua_toboolean) (lua_State *L, int idx);
++LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
++LUA_API size_t (lua_objlen) (lua_State *L, int idx);
++LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
++LUA_API void *(lua_touserdata) (lua_State *L, int idx);
++LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
++LUA_API const void *(lua_topointer) (lua_State *L, int idx);
++
++
++/*
++** push functions (C -> stack)
++*/
++LUA_API void (lua_pushnil) (lua_State *L);
++LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
++LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
++LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
++LUA_API void (lua_pushstring) (lua_State *L, const char *s);
++LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
++ va_list argp);
++LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
++LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
++LUA_API void (lua_pushboolean) (lua_State *L, int b);
++LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
++LUA_API int (lua_pushthread) (lua_State *L);
++
++
++/*
++** get functions (Lua -> stack)
++*/
++LUA_API void (lua_gettable) (lua_State *L, int idx);
++LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
++LUA_API void (lua_rawget) (lua_State *L, int idx);
++LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
++LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
++LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
++LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
++LUA_API void (lua_getfenv) (lua_State *L, int idx);
++
++
++/*
++** set functions (stack -> Lua)
++*/
++LUA_API void (lua_settable) (lua_State *L, int idx);
++LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
++LUA_API void (lua_rawset) (lua_State *L, int idx);
++LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
++LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
++LUA_API int (lua_setfenv) (lua_State *L, int idx);
++
++
++/*
++** `load' and `call' functions (load and run Lua code)
++*/
++LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
++LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
++LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
++LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
++ const char *chunkname);
++
++LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
++
++
++/*
++** coroutine functions
++*/
++LUA_API int (lua_yield) (lua_State *L, int nresults);
++LUA_API int (lua_resume) (lua_State *L, int narg);
++LUA_API int (lua_status) (lua_State *L);
++
++/*
++** garbage-collection function and options
++*/
++
++#define LUA_GCSTOP 0
++#define LUA_GCRESTART 1
++#define LUA_GCCOLLECT 2
++#define LUA_GCCOUNT 3
++#define LUA_GCCOUNTB 4
++#define LUA_GCSTEP 5
++#define LUA_GCSETPAUSE 6
++#define LUA_GCSETSTEPMUL 7
++
++LUA_API int (lua_gc) (lua_State *L, int what, int data);
++
++
++/*
++** miscellaneous functions
++*/
++
++LUA_API int (lua_error) (lua_State *L);
++
++LUA_API int (lua_next) (lua_State *L, int idx);
++
++LUA_API void (lua_concat) (lua_State *L, int n);
++
++LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
++
++
++
++/*
++** ===============================================================
++** some useful macros
++** ===============================================================
++*/
++
++#define lua_pop(L,n) lua_settop(L, -(n)-1)
++
++#define lua_newtable(L) lua_createtable(L, 0, 0)
++
++#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
++
++#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
++
++#define lua_strlen(L,i) lua_objlen(L, (i))
++
++#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
++#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
++#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
++#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
++#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
++#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
++#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
++#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++
++#define lua_pushliteral(L, s) \
++ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
++
++#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
++#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
++
++#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
++
++
++
++/*
++** compatibility macros and functions
++*/
++
++#define lua_open() luaL_newstate()
++
++#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
++
++#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
++
++#define lua_Chunkreader lua_Reader
++#define lua_Chunkwriter lua_Writer
++
++
++/* hack */
++LUA_API void lua_setlevel (lua_State *from, lua_State *to);
++
++
++/*
++** {======================================================================
++** Debug API
++** =======================================================================
++*/
++
++
++/*
++** Event codes
++*/
++#define LUA_HOOKCALL 0
++#define LUA_HOOKRET 1
++#define LUA_HOOKLINE 2
++#define LUA_HOOKCOUNT 3
++#define LUA_HOOKTAILRET 4
++
++
++/*
++** Event masks
++*/
++#define LUA_MASKCALL (1 << LUA_HOOKCALL)
++#define LUA_MASKRET (1 << LUA_HOOKRET)
++#define LUA_MASKLINE (1 << LUA_HOOKLINE)
++#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
++
++typedef struct lua_Debug lua_Debug; /* activation record */
++
++
++/* Functions to be called by the debuger in specific events */
++typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
++
++
++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
++
++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
++LUA_API lua_Hook lua_gethook (lua_State *L);
++LUA_API int lua_gethookmask (lua_State *L);
++LUA_API int lua_gethookcount (lua_State *L);
++
++
++struct lua_Debug {
++ int event;
++ const char *name; /* (n) */
++ const char *namewhat; /* (n) `global', `local', `field', `method' */
++ const char *what; /* (S) `Lua', `C', `main', `tail' */
++ const char *source; /* (S) */
++ int currentline; /* (l) */
++ int nups; /* (u) number of upvalues */
++ int linedefined; /* (S) */
++ int lastlinedefined; /* (S) */
++ char short_src[LUA_IDSIZE]; /* (S) */
++ /* private part */
++ int i_ci; /* active function */
++};
++
++/* }====================================================================== */
++
++
++/******************************************************************************
++* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
++*
++* Permission is hereby granted, free of charge, to any person obtaining
++* a copy of this software and associated documentation files (the
++* "Software"), to deal in the Software without restriction, including
++* without limitation the rights to use, copy, modify, merge, publish,
++* distribute, sublicense, and/or sell copies of the Software, and to
++* permit persons to whom the Software is furnished to do so, subject to
++* the following conditions:
++*
++* The above copyright notice and this permission notice shall be
++* included in all copies or substantial portions of the Software.
++*
++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
++* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++******************************************************************************/
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lualib.h
+@@ -0,0 +1,55 @@
++/*
++** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
++** Lua standard libraries
++** See Copyright Notice in lua.h
++*/
++
++
++#ifndef lualib_h
++#define lualib_h
++
++#include "lua.h"
++
++
++/* Key to file-handle type */
++#define LUA_FILEHANDLE "FILE*"
++
++
++#define LUA_COLIBNAME "coroutine"
++LUALIB_API int (luaopen_base) (lua_State *L);
++
++#define LUA_TABLIBNAME "table"
++LUALIB_API int (luaopen_table) (lua_State *L);
++/*
++#define LUA_IOLIBNAME "io"
++LUALIB_API int (luaopen_io) (lua_State *L);
++
++#define LUA_OSLIBNAME "os"
++LUALIB_API int (luaopen_os) (lua_State *L);
++*/
++
++#define LUA_STRLIBNAME "string"
++LUALIB_API int (luaopen_string) (lua_State *L);
++
++/*
++#define LUA_MATHLIBNAME "math"
++LUALIB_API int (luaopen_math) (lua_State *L);
++
++#define LUA_DBLIBNAME "debug"
++LUALIB_API int (luaopen_debug) (lua_State *L);
++
++#define LUA_LOADLIBNAME "package"
++LUALIB_API int (luaopen_package) (lua_State *L);
++*/
++
++/* open all previous libraries */
++LUALIB_API void (luaL_openlibs) (lua_State *L);
++
++
++
++#ifndef lua_assert
++#define lua_assert(x) ((void)0)
++#endif
++
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lundump.c
+@@ -0,0 +1,227 @@
++/*
++** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
++** load precompiled Lua chunks
++** See Copyright Notice in lua.h
++*/
++
++#include
++
++#define lundump_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "ldebug.h"
++#include "ldo.h"
++#include "lfunc.h"
++#include "lmem.h"
++#include "lobject.h"
++#include "lstring.h"
++#include "lundump.h"
++#include "lzio.h"
++
++typedef struct {
++ lua_State* L;
++ ZIO* Z;
++ Mbuffer* b;
++ const char* name;
++} LoadState;
++
++#ifdef LUAC_TRUST_BINARIES
++#define IF(c,s)
++#define error(S,s)
++#else
++#define IF(c,s) if (c) error(S,s)
++
++static void error(LoadState* S, const char* why)
++{
++ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
++ luaD_throw(S->L,LUA_ERRSYNTAX);
++}
++#endif
++
++#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
++#define LoadByte(S) (lu_byte)LoadChar(S)
++#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
++#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
++
++static void LoadBlock(LoadState* S, void* b, size_t size)
++{
++ size_t r=luaZ_read(S->Z,b,size);
++ IF (r!=0, "unexpected end");
++}
++
++static int LoadChar(LoadState* S)
++{
++ char x;
++ LoadVar(S,x);
++ return x;
++}
++
++static int LoadInt(LoadState* S)
++{
++ int x;
++ LoadVar(S,x);
++ IF (x<0, "bad integer");
++ return x;
++}
++
++static lua_Number LoadNumber(LoadState* S)
++{
++ lua_Number x;
++ LoadVar(S,x);
++ return x;
++}
++
++static TString* LoadString(LoadState* S)
++{
++ size_t size;
++ LoadVar(S,size);
++ if (size==0)
++ return NULL;
++ else
++ {
++ char* s=luaZ_openspace(S->L,S->b,size);
++ LoadBlock(S,s,size);
++ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
++ }
++}
++
++static void LoadCode(LoadState* S, Proto* f)
++{
++ int n=LoadInt(S);
++ f->code=luaM_newvector(S->L,n,Instruction);
++ f->sizecode=n;
++ LoadVector(S,f->code,n,sizeof(Instruction));
++}
++
++static Proto* LoadFunction(LoadState* S, TString* p);
++
++static void LoadConstants(LoadState* S, Proto* f)
++{
++ int i,n;
++ n=LoadInt(S);
++ f->k=luaM_newvector(S->L,n,TValue);
++ f->sizek=n;
++ for (i=0; ik[i]);
++ for (i=0; ik[i];
++ int t=LoadChar(S);
++ switch (t)
++ {
++ case LUA_TNIL:
++ setnilvalue(o);
++ break;
++ case LUA_TBOOLEAN:
++ setbvalue(o,LoadChar(S)!=0);
++ break;
++ case LUA_TNUMBER:
++ setnvalue(o,LoadNumber(S));
++ break;
++ case LUA_TSTRING:
++ setsvalue2n(S->L,o,LoadString(S));
++ break;
++ default:
++ error(S,"bad constant");
++ break;
++ }
++ }
++ n=LoadInt(S);
++ f->p=luaM_newvector(S->L,n,Proto*);
++ f->sizep=n;
++ for (i=0; ip[i]=NULL;
++ for (i=0; ip[i]=LoadFunction(S,f->source);
++}
++
++static void LoadDebug(LoadState* S, Proto* f)
++{
++ int i,n;
++ n=LoadInt(S);
++ f->lineinfo=luaM_newvector(S->L,n,int);
++ f->sizelineinfo=n;
++ LoadVector(S,f->lineinfo,n,sizeof(int));
++ n=LoadInt(S);
++ f->locvars=luaM_newvector(S->L,n,LocVar);
++ f->sizelocvars=n;
++ for (i=0; ilocvars[i].varname=NULL;
++ for (i=0; ilocvars[i].varname=LoadString(S);
++ f->locvars[i].startpc=LoadInt(S);
++ f->locvars[i].endpc=LoadInt(S);
++ }
++ n=LoadInt(S);
++ f->upvalues=luaM_newvector(S->L,n,TString*);
++ f->sizeupvalues=n;
++ for (i=0; iupvalues[i]=NULL;
++ for (i=0; iupvalues[i]=LoadString(S);
++}
++
++static Proto* LoadFunction(LoadState* S, TString* p)
++{
++ Proto* f;
++ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
++ f=luaF_newproto(S->L);
++ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
++ f->source=LoadString(S); if (f->source==NULL) f->source=p;
++ f->linedefined=LoadInt(S);
++ f->lastlinedefined=LoadInt(S);
++ f->nups=LoadByte(S);
++ f->numparams=LoadByte(S);
++ f->is_vararg=LoadByte(S);
++ f->maxstacksize=LoadByte(S);
++ LoadCode(S,f);
++ LoadConstants(S,f);
++ LoadDebug(S,f);
++ IF (!luaG_checkcode(f), "bad code");
++ S->L->top--;
++ S->L->nCcalls--;
++ return f;
++}
++
++static void LoadHeader(LoadState* S)
++{
++ char h[LUAC_HEADERSIZE];
++ char s[LUAC_HEADERSIZE];
++ luaU_header(h);
++ LoadBlock(S,s,LUAC_HEADERSIZE);
++ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
++}
++
++/*
++** load precompiled chunk
++*/
++Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
++{
++ LoadState S;
++ if (*name=='@' || *name=='=')
++ S.name=name+1;
++ else if (*name==LUA_SIGNATURE[0])
++ S.name="binary string";
++ else
++ S.name=name;
++ S.L=L;
++ S.Z=Z;
++ S.b=buff;
++ LoadHeader(&S);
++ return LoadFunction(&S,luaS_newliteral(L,"=?"));
++}
++
++/*
++* make header
++*/
++void luaU_header (char* h)
++{
++ int x=1;
++ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
++ h+=sizeof(LUA_SIGNATURE)-1;
++ *h++=(char)LUAC_VERSION;
++ *h++=(char)LUAC_FORMAT;
++ *h++=(char)*(char*)&x; /* endianness */
++ *h++=(char)sizeof(int);
++ *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(Instruction);
++ *h++=(char)sizeof(lua_Number);
++ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
++}
+--- /dev/null
++++ b/extensions/LUA/lua/lundump.h
+@@ -0,0 +1,36 @@
++/*
++** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
++** load precompiled Lua chunks
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lundump_h
++#define lundump_h
++
++#include "lobject.h"
++#include "lzio.h"
++
++/* load one chunk; from lundump.c */
++LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
++
++/* make header; from lundump.c */
++LUAI_FUNC void luaU_header (char* h);
++
++/* dump one chunk; from ldump.c */
++LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
++
++#ifdef luac_c
++/* print one chunk; from print.c */
++LUAI_FUNC void luaU_print (const Proto* f, int full);
++#endif
++
++/* for header of binary files -- this is Lua 5.1 */
++#define LUAC_VERSION 0x51
++
++/* for header of binary files -- this is the official format */
++#define LUAC_FORMAT 0
++
++/* size of header of binary files */
++#define LUAC_HEADERSIZE 12
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lvm.c
+@@ -0,0 +1,762 @@
++/*
++** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $
++** Lua virtual machine
++** See Copyright Notice in lua.h
++*/
++
++#include
++#include
++#include
++
++#define lvm_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "ldebug.h"
++#include "ldo.h"
++#include "lfunc.h"
++#include "lgc.h"
++#include "lobject.h"
++#include "lopcodes.h"
++#include "lstate.h"
++#include "lstring.h"
++#include "ltable.h"
++#include "ltm.h"
++#include "lvm.h"
++
++
++
++/* limit for table tag-method chains (to avoid loops) */
++#define MAXTAGLOOP 100
++
++
++const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
++ lua_Number num;
++ if (ttisnumber(obj)) return obj;
++ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
++ setnvalue(n, num);
++ return n;
++ }
++ else
++ return NULL;
++}
++
++
++int luaV_tostring (lua_State *L, StkId obj) {
++ if (!ttisnumber(obj))
++ return 0;
++ else {
++ char s[LUAI_MAXNUMBER2STR];
++ lua_Number n = nvalue(obj);
++ lua_number2str(s, n);
++ setsvalue2s(L, obj, luaS_new(L, s));
++ return 1;
++ }
++}
++
++
++static void traceexec (lua_State *L, const Instruction *pc) {
++ lu_byte mask = L->hookmask;
++ const Instruction *oldpc = L->savedpc;
++ L->savedpc = pc;
++ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
++ resethookcount(L);
++ luaD_callhook(L, LUA_HOOKCOUNT, -1);
++ }
++ if (mask & LUA_MASKLINE) {
++ Proto *p = ci_func(L->ci)->l.p;
++ int npc = pcRel(pc, p);
++ int newline = getline(p, npc);
++ /* call linehook when enter a new function, when jump back (loop),
++ or when enter a new line */
++ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
++ luaD_callhook(L, LUA_HOOKLINE, newline);
++ }
++}
++
++
++static void callTMres (lua_State *L, StkId res, const TValue *f,
++ const TValue *p1, const TValue *p2) {
++ ptrdiff_t result = savestack(L, res);
++ setobj2s(L, L->top, f); /* push function */
++ setobj2s(L, L->top+1, p1); /* 1st argument */
++ setobj2s(L, L->top+2, p2); /* 2nd argument */
++ luaD_checkstack(L, 3);
++ L->top += 3;
++ luaD_call(L, L->top - 3, 1);
++ res = restorestack(L, result);
++ L->top--;
++ setobjs2s(L, res, L->top);
++}
++
++
++
++static void callTM (lua_State *L, const TValue *f, const TValue *p1,
++ const TValue *p2, const TValue *p3) {
++ setobj2s(L, L->top, f); /* push function */
++ setobj2s(L, L->top+1, p1); /* 1st argument */
++ setobj2s(L, L->top+2, p2); /* 2nd argument */
++ setobj2s(L, L->top+3, p3); /* 3th argument */
++ luaD_checkstack(L, 4);
++ L->top += 4;
++ luaD_call(L, L->top - 4, 0);
++}
++
++
++void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
++ int loop;
++ for (loop = 0; loop < MAXTAGLOOP; loop++) {
++ const TValue *tm;
++ if (ttistable(t)) { /* `t' is a table? */
++ Table *h = hvalue(t);
++ const TValue *res = luaH_get(h, key); /* do a primitive get */
++ if (!ttisnil(res) || /* result is no nil? */
++ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
++ setobj2s(L, val, res);
++ return;
++ }
++ /* else will try the tag method */
++ }
++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
++ luaG_typeerror(L, t, "index");
++ if (ttisfunction(tm)) {
++ callTMres(L, val, tm, t, key);
++ return;
++ }
++ t = tm; /* else repeat with `tm' */
++ }
++ luaG_runerror(L, "loop in gettable");
++}
++
++
++void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
++ int loop;
++ for (loop = 0; loop < MAXTAGLOOP; loop++) {
++ const TValue *tm;
++ if (ttistable(t)) { /* `t' is a table? */
++ Table *h = hvalue(t);
++ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
++ if (!ttisnil(oldval) || /* result is no nil? */
++ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
++ setobj2t(L, oldval, val);
++ luaC_barriert(L, h, val);
++ return;
++ }
++ /* else will try the tag method */
++ }
++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
++ luaG_typeerror(L, t, "index");
++ if (ttisfunction(tm)) {
++ callTM(L, tm, t, key, val);
++ return;
++ }
++ t = tm; /* else repeat with `tm' */
++ }
++ luaG_runerror(L, "loop in settable");
++}
++
++
++static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
++ StkId res, TMS event) {
++ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
++ if (ttisnil(tm))
++ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
++ if (ttisnil(tm)) return 0;
++ callTMres(L, res, tm, p1, p2);
++ return 1;
++}
++
++
++static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
++ TMS event) {
++ const TValue *tm1 = fasttm(L, mt1, event);
++ const TValue *tm2;
++ if (tm1 == NULL) return NULL; /* no metamethod */
++ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
++ tm2 = fasttm(L, mt2, event);
++ if (tm2 == NULL) return NULL; /* no metamethod */
++ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */
++ return tm1;
++ return NULL;
++}
++
++
++static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
++ TMS event) {
++ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
++ const TValue *tm2;
++ if (ttisnil(tm1)) return -1; /* no metamethod? */
++ tm2 = luaT_gettmbyobj(L, p2, event);
++ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
++ return -1;
++ callTMres(L, L->top, tm1, p1, p2);
++ return !l_isfalse(L->top);
++}
++
++
++static int l_strcmp (const TString *ls, const TString *rs) {
++ const char *l = getstr(ls);
++ size_t ll = ls->tsv.len;
++ const char *r = getstr(rs);
++ size_t lr = rs->tsv.len;
++ for (;;) {
++ int temp = strcoll(l, r);
++ if (temp != 0) return temp;
++ else { /* strings are equal up to a `\0' */
++ size_t len = strlen(l); /* index of first `\0' in both strings */
++ if (len == lr) /* r is finished? */
++ return (len == ll) ? 0 : 1;
++ else if (len == ll) /* l is finished? */
++ return -1; /* l is smaller than r (because r is not finished) */
++ /* both strings longer than `len'; go on comparing (after the `\0') */
++ len++;
++ l += len; ll -= len; r += len; lr -= len;
++ }
++ }
++}
++
++
++int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
++ int res;
++ if (ttype(l) != ttype(r))
++ return luaG_ordererror(L, l, r);
++ else if (ttisnumber(l))
++ return luai_numlt(nvalue(l), nvalue(r));
++ else if (ttisstring(l))
++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++ return res;
++ return luaG_ordererror(L, l, r);
++}
++
++
++static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
++ int res;
++ if (ttype(l) != ttype(r))
++ return luaG_ordererror(L, l, r);
++ else if (ttisnumber(l))
++ return luai_numle(nvalue(l), nvalue(r));
++ else if (ttisstring(l))
++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
++ return res;
++ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
++ return !res;
++ return luaG_ordererror(L, l, r);
++}
++
++
++int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
++ const TValue *tm;
++ lua_assert(ttype(t1) == ttype(t2));
++ switch (ttype(t1)) {
++ case LUA_TNIL: return 1;
++ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
++ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
++ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
++ case LUA_TUSERDATA: {
++ if (uvalue(t1) == uvalue(t2)) return 1;
++ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
++ TM_EQ);
++ break; /* will try TM */
++ }
++ case LUA_TTABLE: {
++ if (hvalue(t1) == hvalue(t2)) return 1;
++ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
++ break; /* will try TM */
++ }
++ default: return gcvalue(t1) == gcvalue(t2);
++ }
++ if (tm == NULL) return 0; /* no TM? */
++ callTMres(L, L->top, tm, t1, t2); /* call TM */
++ return !l_isfalse(L->top);
++}
++
++
++void luaV_concat (lua_State *L, int total, int last) {
++ do {
++ StkId top = L->base + last + 1;
++ int n = 2; /* number of elements handled in this pass (at least 2) */
++ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
++ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
++ luaG_concaterror(L, top-2, top-1);
++ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
++ (void)tostring(L, top - 2); /* result is first op (as string) */
++ else {
++ /* at least two string values; get as many as possible */
++ size_t tl = tsvalue(top-1)->len;
++ char *buffer;
++ int i;
++ /* collect total length */
++ for (n = 1; n < total && tostring(L, top-n-1); n++) {
++ size_t l = tsvalue(top-n-1)->len;
++ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
++ tl += l;
++ }
++ buffer = luaZ_openspace(L, &G(L)->buff, tl);
++ tl = 0;
++ for (i=n; i>0; i--) { /* concat all strings */
++ size_t l = tsvalue(top-i)->len;
++ memcpy(buffer+tl, svalue(top-i), l);
++ tl += l;
++ }
++ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
++ }
++ total -= n-1; /* got `n' strings to create 1 new */
++ last -= n-1;
++ } while (total > 1); /* repeat until only 1 result left */
++}
++
++
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++ const TValue *rc, TMS op) {
++ TValue tempb, tempc;
++ const TValue *b, *c;
++ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++ (c = luaV_tonumber(rc, &tempc)) != NULL) {
++ lua_Number nb = nvalue(b), nc = nvalue(c);
++ switch (op) {
++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
++ default: lua_assert(0); break;
++ }
++ }
++ else if (!call_binTM(L, rb, rc, ra, op))
++ luaG_aritherror(L, rb, rc);
++}
++
++
++
++/*
++** some macros for common tasks in `luaV_execute'
++*/
++
++#define runtime_check(L, c) { if (!(c)) break; }
++
++#define RA(i) (base+GETARG_A(i))
++/* to be used after possible stack reallocation */
++#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
++#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
++#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
++ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
++#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
++ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
++#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
++
++
++#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);}
++
++
++#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
++
++
++#define arith_op(op,tm) { \
++ TValue *rb = RKB(i); \
++ TValue *rc = RKC(i); \
++ if (ttisnumber(rb) && ttisnumber(rc)) { \
++ lua_Number nb = nvalue(rb), nc = nvalue(rc); \
++ setnvalue(ra, op(nb, nc)); \
++ } \
++ else \
++ Protect(Arith(L, ra, rb, rc, tm)); \
++ }
++
++
++
++void luaV_execute (lua_State *L, int nexeccalls) {
++ LClosure *cl;
++ StkId base;
++ TValue *k;
++ const Instruction *pc;
++ reentry: /* entry point */
++ lua_assert(isLua(L->ci));
++ pc = L->savedpc;
++ cl = &clvalue(L->ci->func)->l;
++ base = L->base;
++ k = cl->p->k;
++ /* main loop of interpreter */
++ for (;;) {
++ const Instruction i = *pc++;
++ StkId ra;
++ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
++ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
++ traceexec(L, pc);
++ if (L->status == LUA_YIELD) { /* did hook yield? */
++ L->savedpc = pc - 1;
++ return;
++ }
++ base = L->base;
++ }
++ /* warning!! several calls may realloc the stack and invalidate `ra' */
++ ra = RA(i);
++ lua_assert(base == L->base && L->base == L->ci->base);
++ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
++ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
++ switch (GET_OPCODE(i)) {
++ case OP_MOVE: {
++ setobjs2s(L, ra, RB(i));
++ continue;
++ }
++ case OP_LOADK: {
++ setobj2s(L, ra, KBx(i));
++ continue;
++ }
++ case OP_LOADBOOL: {
++ setbvalue(ra, GETARG_B(i));
++ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
++ continue;
++ }
++ case OP_LOADNIL: {
++ TValue *rb = RB(i);
++ do {
++ setnilvalue(rb--);
++ } while (rb >= ra);
++ continue;
++ }
++ case OP_GETUPVAL: {
++ int b = GETARG_B(i);
++ setobj2s(L, ra, cl->upvals[b]->v);
++ continue;
++ }
++ case OP_GETGLOBAL: {
++ TValue g;
++ TValue *rb = KBx(i);
++ sethvalue(L, &g, cl->env);
++ lua_assert(ttisstring(rb));
++ Protect(luaV_gettable(L, &g, rb, ra));
++ continue;
++ }
++ case OP_GETTABLE: {
++ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
++ continue;
++ }
++ case OP_SETGLOBAL: {
++ TValue g;
++ sethvalue(L, &g, cl->env);
++ lua_assert(ttisstring(KBx(i)));
++ Protect(luaV_settable(L, &g, KBx(i), ra));
++ continue;
++ }
++ case OP_SETUPVAL: {
++ UpVal *uv = cl->upvals[GETARG_B(i)];
++ setobj(L, uv->v, ra);
++ luaC_barrier(L, uv, ra);
++ continue;
++ }
++ case OP_SETTABLE: {
++ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
++ continue;
++ }
++ case OP_NEWTABLE: {
++ int b = GETARG_B(i);
++ int c = GETARG_C(i);
++ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
++ Protect(luaC_checkGC(L));
++ continue;
++ }
++ case OP_SELF: {
++ StkId rb = RB(i);
++ setobjs2s(L, ra+1, rb);
++ Protect(luaV_gettable(L, rb, RKC(i), ra));
++ continue;
++ }
++ case OP_ADD: {
++ arith_op(luai_numadd, TM_ADD);
++ continue;
++ }
++ case OP_SUB: {
++ arith_op(luai_numsub, TM_SUB);
++ continue;
++ }
++ case OP_MUL: {
++ arith_op(luai_nummul, TM_MUL);
++ continue;
++ }
++ case OP_DIV: {
++ arith_op(luai_numdiv, TM_DIV);
++ continue;
++ }
++ case OP_MOD: {
++ arith_op(luai_nummod, TM_MOD);
++ continue;
++ }
++ case OP_POW: {
++ arith_op(luai_numpow, TM_POW);
++ continue;
++ }
++ case OP_UNM: {
++ TValue *rb = RB(i);
++ if (ttisnumber(rb)) {
++ lua_Number nb = nvalue(rb);
++ setnvalue(ra, luai_numunm(nb));
++ }
++ else {
++ Protect(Arith(L, ra, rb, rb, TM_UNM));
++ }
++ continue;
++ }
++ case OP_NOT: {
++ int res = l_isfalse(RB(i)); /* next assignment may change this value */
++ setbvalue(ra, res);
++ continue;
++ }
++ case OP_LEN: {
++ const TValue *rb = RB(i);
++ switch (ttype(rb)) {
++ case LUA_TTABLE: {
++ setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++ break;
++ }
++ case LUA_TSTRING: {
++ setnvalue(ra, cast_num(tsvalue(rb)->len));
++ break;
++ }
++ default: { /* try metamethod */
++ Protect(
++ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
++ luaG_typeerror(L, rb, "get length of");
++ )
++ }
++ }
++ continue;
++ }
++ case OP_CONCAT: {
++ int b = GETARG_B(i);
++ int c = GETARG_C(i);
++ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
++ setobjs2s(L, RA(i), base+b);
++ continue;
++ }
++ case OP_JMP: {
++ dojump(L, pc, GETARG_sBx(i));
++ continue;
++ }
++ case OP_EQ: {
++ TValue *rb = RKB(i);
++ TValue *rc = RKC(i);
++ Protect(
++ if (equalobj(L, rb, rc) == GETARG_A(i))
++ dojump(L, pc, GETARG_sBx(*pc));
++ )
++ pc++;
++ continue;
++ }
++ case OP_LT: {
++ Protect(
++ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
++ dojump(L, pc, GETARG_sBx(*pc));
++ )
++ pc++;
++ continue;
++ }
++ case OP_LE: {
++ Protect(
++ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
++ dojump(L, pc, GETARG_sBx(*pc));
++ )
++ pc++;
++ continue;
++ }
++ case OP_TEST: {
++ if (l_isfalse(ra) != GETARG_C(i))
++ dojump(L, pc, GETARG_sBx(*pc));
++ pc++;
++ continue;
++ }
++ case OP_TESTSET: {
++ TValue *rb = RB(i);
++ if (l_isfalse(rb) != GETARG_C(i)) {
++ setobjs2s(L, ra, rb);
++ dojump(L, pc, GETARG_sBx(*pc));
++ }
++ pc++;
++ continue;
++ }
++ case OP_CALL: {
++ int b = GETARG_B(i);
++ int nresults = GETARG_C(i) - 1;
++ if (b != 0) L->top = ra+b; /* else previous instruction set top */
++ L->savedpc = pc;
++ switch (luaD_precall(L, ra, nresults)) {
++ case PCRLUA: {
++ nexeccalls++;
++ goto reentry; /* restart luaV_execute over new Lua function */
++ }
++ case PCRC: {
++ /* it was a C function (`precall' called it); adjust results */
++ if (nresults >= 0) L->top = L->ci->top;
++ base = L->base;
++ continue;
++ }
++ default: {
++ return; /* yield */
++ }
++ }
++ }
++ case OP_TAILCALL: {
++ int b = GETARG_B(i);
++ if (b != 0) L->top = ra+b; /* else previous instruction set top */
++ L->savedpc = pc;
++ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
++ switch (luaD_precall(L, ra, LUA_MULTRET)) {
++ case PCRLUA: {
++ /* tail call: put new frame in place of previous one */
++ CallInfo *ci = L->ci - 1; /* previous frame */
++ int aux;
++ StkId func = ci->func;
++ StkId pfunc = (ci+1)->func; /* previous function index */
++ if (L->openupval) luaF_close(L, ci->base);
++ L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
++ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
++ setobjs2s(L, func+aux, pfunc+aux);
++ ci->top = L->top = func+aux; /* correct top */
++ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
++ ci->savedpc = L->savedpc;
++ ci->tailcalls++; /* one more call lost */
++ L->ci--; /* remove new frame */
++ goto reentry;
++ }
++ case PCRC: { /* it was a C function (`precall' called it) */
++ base = L->base;
++ continue;
++ }
++ default: {
++ return; /* yield */
++ }
++ }
++ }
++ case OP_RETURN: {
++ int b = GETARG_B(i);
++ if (b != 0) L->top = ra+b-1;
++ if (L->openupval) luaF_close(L, base);
++ L->savedpc = pc;
++ b = luaD_poscall(L, ra);
++ if (--nexeccalls == 0) /* was previous function running `here'? */
++ return; /* no: return */
++ else { /* yes: continue its execution */
++ if (b) L->top = L->ci->top;
++ lua_assert(isLua(L->ci));
++ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
++ goto reentry;
++ }
++ }
++ case OP_FORLOOP: {
++ lua_Number step = nvalue(ra+2);
++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
++ lua_Number limit = nvalue(ra+1);
++ if (luai_numlt(0, step) ? luai_numle(idx, limit)
++ : luai_numle(limit, idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setnvalue(ra, idx); /* update internal index... */
++ setnvalue(ra+3, idx); /* ...and external index */
++ }
++ continue;
++ }
++ case OP_FORPREP: {
++ const TValue *init = ra;
++ const TValue *plimit = ra+1;
++ const TValue *pstep = ra+2;
++ L->savedpc = pc; /* next steps may throw errors */
++ if (!tonumber(init, ra))
++ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
++ else if (!tonumber(plimit, ra+1))
++ luaG_runerror(L, LUA_QL("for") " limit must be a number");
++ else if (!tonumber(pstep, ra+2))
++ luaG_runerror(L, LUA_QL("for") " step must be a number");
++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ dojump(L, pc, GETARG_sBx(i));
++ continue;
++ }
++ case OP_TFORLOOP: {
++ StkId cb = ra + 3; /* call base */
++ setobjs2s(L, cb+2, ra+2);
++ setobjs2s(L, cb+1, ra+1);
++ setobjs2s(L, cb, ra);
++ L->top = cb+3; /* func. + 2 args (state and index) */
++ Protect(luaD_call(L, cb, GETARG_C(i)));
++ L->top = L->ci->top;
++ cb = RA(i) + 3; /* previous call may change the stack */
++ if (!ttisnil(cb)) { /* continue loop? */
++ setobjs2s(L, cb-1, cb); /* save control variable */
++ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
++ }
++ pc++;
++ continue;
++ }
++ case OP_SETLIST: {
++ int n = GETARG_B(i);
++ int c = GETARG_C(i);
++ int last;
++ Table *h;
++ if (n == 0) {
++ n = cast_int(L->top - ra) - 1;
++ L->top = L->ci->top;
++ }
++ if (c == 0) c = cast_int(*pc++);
++ runtime_check(L, ttistable(ra));
++ h = hvalue(ra);
++ last = ((c-1)*LFIELDS_PER_FLUSH) + n;
++ if (last > h->sizearray) /* needs more space? */
++ luaH_resizearray(L, h, last); /* pre-alloc it at once */
++ for (; n > 0; n--) {
++ TValue *val = ra+n;
++ setobj2t(L, luaH_setnum(L, h, last--), val);
++ luaC_barriert(L, h, val);
++ }
++ continue;
++ }
++ case OP_CLOSE: {
++ luaF_close(L, ra);
++ continue;
++ }
++ case OP_CLOSURE: {
++ Proto *p;
++ Closure *ncl;
++ int nup, j;
++ p = cl->p->p[GETARG_Bx(i)];
++ nup = p->nups;
++ ncl = luaF_newLclosure(L, nup, cl->env);
++ ncl->l.p = p;
++ for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)];
++ else {
++ lua_assert(GET_OPCODE(*pc) == OP_MOVE);
++ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
++ }
++ }
++ setclvalue(L, ra, ncl);
++ Protect(luaC_checkGC(L));
++ continue;
++ }
++ case OP_VARARG: {
++ int b = GETARG_B(i) - 1;
++ int j;
++ CallInfo *ci = L->ci;
++ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
++ if (b == LUA_MULTRET) {
++ Protect(luaD_checkstack(L, n));
++ ra = RA(i); /* previous call may change the stack */
++ b = n;
++ L->top = ra + n;
++ }
++ for (j = 0; j < b; j++) {
++ if (j < n) {
++ setobjs2s(L, ra + j, ci->base - n + j);
++ }
++ else {
++ setnilvalue(ra + j);
++ }
++ }
++ continue;
++ }
++ }
++ }
++}
++
+--- /dev/null
++++ b/extensions/LUA/lua/lvm.h
+@@ -0,0 +1,36 @@
++/*
++** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $
++** Lua virtual machine
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lvm_h
++#define lvm_h
++
++
++#include "ldo.h"
++#include "lobject.h"
++#include "ltm.h"
++
++
++#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
++
++#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
++ (((o) = luaV_tonumber(o,n)) != NULL))
++
++#define equalobj(L,o1,o2) \
++ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++
++
++LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
++LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
++LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
++LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
++LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
++ StkId val);
++LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
++ StkId val);
++LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
++LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/lua/lzio.c
+@@ -0,0 +1,81 @@
++/*
++** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
++** a generic input stream interface
++** See Copyright Notice in lua.h
++*/
++
++#include
++
++#define lzio_c
++#define LUA_CORE
++
++#include "lua.h"
++
++#include "llimits.h"
++#include "lmem.h"
++#include "lstate.h"
++#include "lzio.h"
++
++
++int luaZ_fill (ZIO *z) {
++ size_t size;
++ lua_State *L = z->L;
++ const char *buff;
++ lua_unlock(L);
++ buff = z->reader(L, z->data, &size);
++ lua_lock(L);
++ if (buff == NULL || size == 0) return EOZ;
++ z->n = size - 1;
++ z->p = buff;
++ return char2int(*(z->p++));
++}
++
++
++int luaZ_lookahead (ZIO *z) {
++ if (z->n == 0) {
++ if (luaZ_fill(z) == EOZ)
++ return EOZ;
++ else {
++ z->n++; /* luaZ_fill removed first byte; put back it */
++ z->p--;
++ }
++ }
++ return char2int(*z->p);
++}
++
++
++void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
++ z->L = L;
++ z->reader = reader;
++ z->data = data;
++ z->n = 0;
++ z->p = NULL;
++}
++
++
++/* --------------------------------------------------------------- read --- */
++size_t luaZ_read (ZIO *z, void *b, size_t n) {
++ while (n) {
++ size_t m;
++ if (luaZ_lookahead(z) == EOZ)
++ return n; /* return number of missing bytes */
++ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
++ memcpy(b, z->p, m);
++ z->n -= m;
++ z->p += m;
++ b = (char *)b + m;
++ n -= m;
++ }
++ return 0;
++}
++
++/* ------------------------------------------------------------------------ */
++char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
++ if (n > buff->buffsize) {
++ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
++ luaZ_resizebuffer(L, buff, n);
++ }
++ return buff->buffer;
++}
++
++
+--- /dev/null
++++ b/extensions/LUA/lua/lzio.h
+@@ -0,0 +1,67 @@
++/*
++** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
++** Buffered streams
++** See Copyright Notice in lua.h
++*/
++
++
++#ifndef lzio_h
++#define lzio_h
++
++#include "lua.h"
++
++#include "lmem.h"
++
++
++#define EOZ (-1) /* end of stream */
++
++typedef struct Zio ZIO;
++
++#define char2int(c) cast(int, cast(unsigned char, (c)))
++
++#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
++
++typedef struct Mbuffer {
++ char *buffer;
++ size_t n;
++ size_t buffsize;
++} Mbuffer;
++
++#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
++
++#define luaZ_buffer(buff) ((buff)->buffer)
++#define luaZ_sizebuffer(buff) ((buff)->buffsize)
++#define luaZ_bufflen(buff) ((buff)->n)
++
++#define luaZ_resetbuffer(buff) ((buff)->n = 0)
++
++
++#define luaZ_resizebuffer(L, buff, size) \
++ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
++ (buff)->buffsize = size)
++
++#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
++
++
++LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
++LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
++ void *data);
++LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
++LUAI_FUNC int luaZ_lookahead (ZIO *z);
++
++
++
++/* --------- Private Part ------------------ */
++
++struct Zio {
++ size_t n; /* bytes still unread */
++ const char *p; /* current position in buffer */
++ lua_Reader reader;
++ void* data; /* additional data */
++ lua_State *L; /* Lua state (for reader) */
++};
++
++
++LUAI_FUNC int luaZ_fill (ZIO *z);
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/Makefile
+@@ -0,0 +1,389 @@
++# Makefile.in generated by automake 1.11.1 from Makefile.am.
++# extensions/LUA/Makefile. Generated from Makefile.in by configure.
++
++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
++# Inc.
++# This Makefile.in is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++
++
++# -*- Makefile -*-
++# AUTOMAKE
++
++pkgdatadir = $(datadir)/xtables-addons
++pkgincludedir = $(includedir)/xtables-addons
++pkglibdir = $(libdir)/xtables-addons
++pkglibexecdir = $(libexecdir)/xtables-addons
++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
++install_sh_DATA = $(install_sh) -c -m 644
++install_sh_PROGRAM = $(install_sh) -c
++install_sh_SCRIPT = $(install_sh) -c
++INSTALL_HEADER = $(INSTALL_DATA)
++transform = $(program_transform_name)
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++build_triplet = i686-pc-linux-gnu
++host_triplet = i686-pc-linux-gnu
++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \
++ $(srcdir)/Makefile.in
++subdir = extensions/LUA
++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
++ $(top_srcdir)/configure.ac
++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
++ $(ACLOCAL_M4)
++mkinstalldirs = $(install_sh) -d
++CONFIG_HEADER = $(top_builddir)/config.h
++CONFIG_CLEAN_FILES =
++CONFIG_CLEAN_VPATH_FILES =
++SOURCES =
++DIST_SOURCES =
++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
++ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11
++AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar
++AR = ar
++AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf
++AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader
++AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11
++AWK = mawk
++CC = gcc
++CCDEPMODE = depmode=gcc3
++CFLAGS = -g -O2
++CPP = gcc -E
++CPPFLAGS =
++CYGPATH_W = echo
++DEFS = -DHAVE_CONFIG_H
++DEPDIR = .deps
++DSYMUTIL =
++DUMPBIN =
++ECHO_C =
++ECHO_N = -n
++ECHO_T =
++EGREP = /bin/grep -E
++EXEEXT =
++FGREP = /bin/grep -F
++GREP = /bin/grep
++INSTALL = /usr/bin/install -c
++INSTALL_DATA = ${INSTALL} -m 644
++INSTALL_PROGRAM = ${INSTALL}
++INSTALL_SCRIPT = ${INSTALL}
++INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
++LD = /usr/bin/ld
++LDFLAGS =
++LIBOBJS =
++LIBS =
++LIBTOOL = $(SHELL) $(top_builddir)/libtool
++LIPO =
++LN_S = ln -s
++LTLIBOBJS =
++MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo
++MKDIR_P = /bin/mkdir -p
++NM = /usr/bin/nm -B
++NMEDIT =
++OBJDUMP = objdump
++OBJEXT = o
++OTOOL =
++OTOOL64 =
++PACKAGE = xtables-addons
++PACKAGE_BUGREPORT =
++PACKAGE_NAME = xtables-addons
++PACKAGE_STRING = xtables-addons 1.21
++PACKAGE_TARNAME = xtables-addons
++PACKAGE_URL =
++PACKAGE_VERSION = 1.21
++PATH_SEPARATOR = :
++PKG_CONFIG = /usr/bin/pkg-config
++RANLIB = ranlib
++SED = /bin/sed
++SET_MAKE =
++SHELL = /bin/bash
++STRIP = strip
++VERSION = 1.21
++abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA
++abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA
++abs_top_builddir = /home/andre/Dropbox/xtables-addons
++abs_top_srcdir = /home/andre/Dropbox/xtables-addons
++ac_ct_CC = gcc
++ac_ct_DUMPBIN =
++am__include = include
++am__leading_dot = .
++am__quote =
++am__tar = ${AMTAR} chof - "$$tardir"
++am__untar = ${AMTAR} xf -
++bindir = ${exec_prefix}/bin
++build = i686-pc-linux-gnu
++build_alias =
++build_cpu = i686
++build_os = linux-gnu
++build_vendor = pc
++builddir = .
++datadir = ${datarootdir}
++datarootdir = ${prefix}/share
++docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
++dvidir = ${docdir}
++exec_prefix = ${prefix}
++host = i686-pc-linux-gnu
++host_alias =
++host_cpu = i686
++host_os = linux-gnu
++host_vendor = pc
++htmldir = ${docdir}
++includedir = ${prefix}/include
++infodir = ${datarootdir}/info
++install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh
++kbuilddir = /lib/modules/2.6.33-020633-generic/build
++kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include
++ksourcedir =
++libdir = ${exec_prefix}/lib
++libexecdir = ${exec_prefix}/libexec
++libxtables_CFLAGS =
++libxtables_LIBS = -L/lib -lxtables
++localedir = ${datarootdir}/locale
++localstatedir = ${prefix}/var
++lt_ECHO = echo
++mandir = ${datarootdir}/man
++mkdir_p = /bin/mkdir -p
++oldincludedir = /usr/include
++pdfdir = ${docdir}
++prefix = /usr/local
++program_transform_name = s,x,x,
++psdir = ${docdir}
++regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\"
++sbindir = ${exec_prefix}/sbin
++sharedstatedir = ${prefix}/com
++srcdir = .
++sysconfdir = ${prefix}/etc
++target_alias =
++top_build_prefix = ../../
++top_builddir = ../..
++top_srcdir = ../..
++xtlibdir = ${libexecdir}/xtables
++XA_SRCDIR = ${srcdir}
++XA_TOPSRCDIR = ${top_srcdir}
++XA_ABSTOPSRCDIR = ${abs_top_srcdir}
++_mcall = -f ${top_builddir}/Makefile.iptrules
++all: all-am
++
++.SUFFIXES:
++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps)
++ @for dep in $?; do \
++ case '$(am__configure_deps)' in \
++ *$$dep*) \
++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
++ && { if test -f $@; then exit 0; else break; fi; }; \
++ exit 1;; \
++ esac; \
++ done; \
++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \
++ $(am__cd) $(top_srcdir) && \
++ $(AUTOMAKE) --foreign extensions/LUA/Makefile
++.PRECIOUS: Makefile
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++ @case '$?' in \
++ *config.status*) \
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
++ *) \
++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
++ esac;
++
++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++
++$(top_srcdir)/configure: $(am__configure_deps)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++$(ACLOCAL_M4): $(am__aclocal_m4_deps)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++$(am__aclocal_m4_deps):
++
++mostlyclean-libtool:
++ -rm -f *.lo
++
++clean-libtool:
++ -rm -rf .libs _libs
++tags: TAGS
++TAGS:
++
++ctags: CTAGS
++CTAGS:
++
++
++distdir: $(DISTFILES)
++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
++ list='$(DISTFILES)'; \
++ dist_files=`for file in $$list; do echo $$file; done | \
++ sed -e "s|^$$srcdirstrip/||;t" \
++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
++ case $$dist_files in \
++ */*) $(MKDIR_P) `echo "$$dist_files" | \
++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
++ sort -u` ;; \
++ esac; \
++ for file in $$dist_files; do \
++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
++ if test -d $$d/$$file; then \
++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
++ if test -d "$(distdir)/$$file"; then \
++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
++ fi; \
++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
++ fi; \
++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
++ else \
++ test -f "$(distdir)/$$file" \
++ || cp -p $$d/$$file "$(distdir)/$$file" \
++ || exit 1; \
++ fi; \
++ done
++check-am: all-am
++check: check-am
++all-am: Makefile all-local
++installdirs:
++install: install-am
++install-exec: install-exec-am
++install-data: install-data-am
++uninstall: uninstall-am
++
++install-am: all-am
++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++
++installcheck: installcheck-am
++install-strip:
++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++ `test -z '$(STRIP)' || \
++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
++mostlyclean-generic:
++
++clean-generic:
++
++distclean-generic:
++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
++
++maintainer-clean-generic:
++ @echo "This command is intended for maintainers to use"
++ @echo "it deletes files that may require special tools to rebuild."
++clean: clean-am
++
++clean-am: clean-generic clean-libtool clean-local mostlyclean-am
++
++distclean: distclean-am
++ -rm -f Makefile
++distclean-am: clean-am distclean-generic
++
++dvi: dvi-am
++
++dvi-am:
++
++html: html-am
++
++html-am:
++
++info: info-am
++
++info-am:
++
++install-data-am:
++
++install-dvi: install-dvi-am
++
++install-dvi-am:
++
++install-exec-am: install-exec-local
++
++install-html: install-html-am
++
++install-html-am:
++
++install-info: install-info-am
++
++install-info-am:
++
++install-man:
++
++install-pdf: install-pdf-am
++
++install-pdf-am:
++
++install-ps: install-ps-am
++
++install-ps-am:
++
++installcheck-am:
++
++maintainer-clean: maintainer-clean-am
++ -rm -f Makefile
++maintainer-clean-am: distclean-am maintainer-clean-generic
++
++mostlyclean: mostlyclean-am
++
++mostlyclean-am: mostlyclean-generic mostlyclean-libtool
++
++pdf: pdf-am
++
++pdf-am:
++
++ps: ps-am
++
++ps-am:
++
++uninstall-am:
++
++.MAKE: install-am install-strip
++
++.PHONY: all all-am all-local check check-am clean clean-generic \
++ clean-libtool clean-local distclean distclean-generic \
++ distclean-libtool distdir dvi dvi-am html html-am info info-am \
++ install install-am install-data install-data-am install-dvi \
++ install-dvi-am install-exec install-exec-am install-exec-local \
++ install-html install-html-am install-info install-info-am \
++ install-man install-pdf install-pdf-am install-ps \
++ install-ps-am install-strip installcheck installcheck-am \
++ installdirs maintainer-clean maintainer-clean-generic \
++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
++ ps ps-am uninstall uninstall-am
++
++export XA_SRCDIR
++export XA_TOPSRCDIR
++export XA_ABSTOPSRCDIR
++
++all-local: user-all-local
++
++install-exec-local: user-install-local
++
++clean-local: user-clean-local
++
++user-all-local:
++ ${MAKE} ${_mcall} all;
++
++# Have no user-install-data-local ATM
++user-install-local: user-install-exec-local
++
++user-install-exec-local:
++ ${MAKE} ${_mcall} install;
++
++user-clean-local:
++ ${MAKE} ${_mcall} clean;
++
++# Tell versions [3.59,3.63) of GNU make to not export all variables.
++# Otherwise a system limit (for SysV at least) may be exceeded.
++.NOEXPORT:
++
+--- /dev/null
++++ b/extensions/LUA/Makefile.am
+@@ -0,0 +1 @@
++include ../../Makefile.extra
+--- /dev/null
++++ b/extensions/LUA/Makefile.in
+@@ -0,0 +1,389 @@
++# Makefile.in generated by automake 1.11.1 from Makefile.am.
++# @configure_input@
++
++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
++# Inc.
++# This Makefile.in is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++@SET_MAKE@
++
++# -*- Makefile -*-
++# AUTOMAKE
++VPATH = @srcdir@
++pkgdatadir = $(datadir)/@PACKAGE@
++pkgincludedir = $(includedir)/@PACKAGE@
++pkglibdir = $(libdir)/@PACKAGE@
++pkglibexecdir = $(libexecdir)/@PACKAGE@
++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
++install_sh_DATA = $(install_sh) -c -m 644
++install_sh_PROGRAM = $(install_sh) -c
++install_sh_SCRIPT = $(install_sh) -c
++INSTALL_HEADER = $(INSTALL_DATA)
++transform = $(program_transform_name)
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++build_triplet = @build@
++host_triplet = @host@
++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \
++ $(srcdir)/Makefile.in
++subdir = extensions/LUA
++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
++ $(top_srcdir)/configure.ac
++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
++ $(ACLOCAL_M4)
++mkinstalldirs = $(install_sh) -d
++CONFIG_HEADER = $(top_builddir)/config.h
++CONFIG_CLEAN_FILES =
++CONFIG_CLEAN_VPATH_FILES =
++SOURCES =
++DIST_SOURCES =
++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
++ACLOCAL = @ACLOCAL@
++AMTAR = @AMTAR@
++AR = @AR@
++AUTOCONF = @AUTOCONF@
++AUTOHEADER = @AUTOHEADER@
++AUTOMAKE = @AUTOMAKE@
++AWK = @AWK@
++CC = @CC@
++CCDEPMODE = @CCDEPMODE@
++CFLAGS = @CFLAGS@
++CPP = @CPP@
++CPPFLAGS = @CPPFLAGS@
++CYGPATH_W = @CYGPATH_W@
++DEFS = @DEFS@
++DEPDIR = @DEPDIR@
++DSYMUTIL = @DSYMUTIL@
++DUMPBIN = @DUMPBIN@
++ECHO_C = @ECHO_C@
++ECHO_N = @ECHO_N@
++ECHO_T = @ECHO_T@
++EGREP = @EGREP@
++EXEEXT = @EXEEXT@
++FGREP = @FGREP@
++GREP = @GREP@
++INSTALL = @INSTALL@
++INSTALL_DATA = @INSTALL_DATA@
++INSTALL_PROGRAM = @INSTALL_PROGRAM@
++INSTALL_SCRIPT = @INSTALL_SCRIPT@
++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
++LD = @LD@
++LDFLAGS = @LDFLAGS@
++LIBOBJS = @LIBOBJS@
++LIBS = @LIBS@
++LIBTOOL = @LIBTOOL@
++LIPO = @LIPO@
++LN_S = @LN_S@
++LTLIBOBJS = @LTLIBOBJS@
++MAKEINFO = @MAKEINFO@
++MKDIR_P = @MKDIR_P@
++NM = @NM@
++NMEDIT = @NMEDIT@
++OBJDUMP = @OBJDUMP@
++OBJEXT = @OBJEXT@
++OTOOL = @OTOOL@
++OTOOL64 = @OTOOL64@
++PACKAGE = @PACKAGE@
++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
++PACKAGE_NAME = @PACKAGE_NAME@
++PACKAGE_STRING = @PACKAGE_STRING@
++PACKAGE_TARNAME = @PACKAGE_TARNAME@
++PACKAGE_URL = @PACKAGE_URL@
++PACKAGE_VERSION = @PACKAGE_VERSION@
++PATH_SEPARATOR = @PATH_SEPARATOR@
++PKG_CONFIG = @PKG_CONFIG@
++RANLIB = @RANLIB@
++SED = @SED@
++SET_MAKE = @SET_MAKE@
++SHELL = @SHELL@
++STRIP = @STRIP@
++VERSION = @VERSION@
++abs_builddir = @abs_builddir@
++abs_srcdir = @abs_srcdir@
++abs_top_builddir = @abs_top_builddir@
++abs_top_srcdir = @abs_top_srcdir@
++ac_ct_CC = @ac_ct_CC@
++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
++am__include = @am__include@
++am__leading_dot = @am__leading_dot@
++am__quote = @am__quote@
++am__tar = @am__tar@
++am__untar = @am__untar@
++bindir = @bindir@
++build = @build@
++build_alias = @build_alias@
++build_cpu = @build_cpu@
++build_os = @build_os@
++build_vendor = @build_vendor@
++builddir = @builddir@
++datadir = @datadir@
++datarootdir = @datarootdir@
++docdir = @docdir@
++dvidir = @dvidir@
++exec_prefix = @exec_prefix@
++host = @host@
++host_alias = @host_alias@
++host_cpu = @host_cpu@
++host_os = @host_os@
++host_vendor = @host_vendor@
++htmldir = @htmldir@
++includedir = @includedir@
++infodir = @infodir@
++install_sh = @install_sh@
++kbuilddir = @kbuilddir@
++kinclude_CFLAGS = @kinclude_CFLAGS@
++ksourcedir = @ksourcedir@
++libdir = @libdir@
++libexecdir = @libexecdir@
++libxtables_CFLAGS = @libxtables_CFLAGS@
++libxtables_LIBS = @libxtables_LIBS@
++localedir = @localedir@
++localstatedir = @localstatedir@
++lt_ECHO = @lt_ECHO@
++mandir = @mandir@
++mkdir_p = @mkdir_p@
++oldincludedir = @oldincludedir@
++pdfdir = @pdfdir@
++prefix = @prefix@
++program_transform_name = @program_transform_name@
++psdir = @psdir@
++regular_CFLAGS = @regular_CFLAGS@
++sbindir = @sbindir@
++sharedstatedir = @sharedstatedir@
++srcdir = @srcdir@
++sysconfdir = @sysconfdir@
++target_alias = @target_alias@
++top_build_prefix = @top_build_prefix@
++top_builddir = @top_builddir@
++top_srcdir = @top_srcdir@
++xtlibdir = @xtlibdir@
++XA_SRCDIR = ${srcdir}
++XA_TOPSRCDIR = ${top_srcdir}
++XA_ABSTOPSRCDIR = ${abs_top_srcdir}
++_mcall = -f ${top_builddir}/Makefile.iptrules
++all: all-am
++
++.SUFFIXES:
++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps)
++ @for dep in $?; do \
++ case '$(am__configure_deps)' in \
++ *$$dep*) \
++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
++ && { if test -f $@; then exit 0; else break; fi; }; \
++ exit 1;; \
++ esac; \
++ done; \
++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \
++ $(am__cd) $(top_srcdir) && \
++ $(AUTOMAKE) --foreign extensions/LUA/Makefile
++.PRECIOUS: Makefile
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++ @case '$?' in \
++ *config.status*) \
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
++ *) \
++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
++ esac;
++
++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++
++$(top_srcdir)/configure: $(am__configure_deps)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++$(ACLOCAL_M4): $(am__aclocal_m4_deps)
++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
++$(am__aclocal_m4_deps):
++
++mostlyclean-libtool:
++ -rm -f *.lo
++
++clean-libtool:
++ -rm -rf .libs _libs
++tags: TAGS
++TAGS:
++
++ctags: CTAGS
++CTAGS:
++
++
++distdir: $(DISTFILES)
++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
++ list='$(DISTFILES)'; \
++ dist_files=`for file in $$list; do echo $$file; done | \
++ sed -e "s|^$$srcdirstrip/||;t" \
++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
++ case $$dist_files in \
++ */*) $(MKDIR_P) `echo "$$dist_files" | \
++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
++ sort -u` ;; \
++ esac; \
++ for file in $$dist_files; do \
++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
++ if test -d $$d/$$file; then \
++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
++ if test -d "$(distdir)/$$file"; then \
++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
++ fi; \
++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
++ fi; \
++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
++ else \
++ test -f "$(distdir)/$$file" \
++ || cp -p $$d/$$file "$(distdir)/$$file" \
++ || exit 1; \
++ fi; \
++ done
++check-am: all-am
++check: check-am
++all-am: Makefile all-local
++installdirs:
++install: install-am
++install-exec: install-exec-am
++install-data: install-data-am
++uninstall: uninstall-am
++
++install-am: all-am
++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++
++installcheck: installcheck-am
++install-strip:
++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++ `test -z '$(STRIP)' || \
++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
++mostlyclean-generic:
++
++clean-generic:
++
++distclean-generic:
++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
++
++maintainer-clean-generic:
++ @echo "This command is intended for maintainers to use"
++ @echo "it deletes files that may require special tools to rebuild."
++clean: clean-am
++
++clean-am: clean-generic clean-libtool clean-local mostlyclean-am
++
++distclean: distclean-am
++ -rm -f Makefile
++distclean-am: clean-am distclean-generic
++
++dvi: dvi-am
++
++dvi-am:
++
++html: html-am
++
++html-am:
++
++info: info-am
++
++info-am:
++
++install-data-am:
++
++install-dvi: install-dvi-am
++
++install-dvi-am:
++
++install-exec-am: install-exec-local
++
++install-html: install-html-am
++
++install-html-am:
++
++install-info: install-info-am
++
++install-info-am:
++
++install-man:
++
++install-pdf: install-pdf-am
++
++install-pdf-am:
++
++install-ps: install-ps-am
++
++install-ps-am:
++
++installcheck-am:
++
++maintainer-clean: maintainer-clean-am
++ -rm -f Makefile
++maintainer-clean-am: distclean-am maintainer-clean-generic
++
++mostlyclean: mostlyclean-am
++
++mostlyclean-am: mostlyclean-generic mostlyclean-libtool
++
++pdf: pdf-am
++
++pdf-am:
++
++ps: ps-am
++
++ps-am:
++
++uninstall-am:
++
++.MAKE: install-am install-strip
++
++.PHONY: all all-am all-local check check-am clean clean-generic \
++ clean-libtool clean-local distclean distclean-generic \
++ distclean-libtool distdir dvi dvi-am html html-am info info-am \
++ install install-am install-data install-data-am install-dvi \
++ install-dvi-am install-exec install-exec-am install-exec-local \
++ install-html install-html-am install-info install-info-am \
++ install-man install-pdf install-pdf-am install-ps \
++ install-ps-am install-strip installcheck installcheck-am \
++ installdirs maintainer-clean maintainer-clean-generic \
++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
++ ps ps-am uninstall uninstall-am
++
++export XA_SRCDIR
++export XA_TOPSRCDIR
++export XA_ABSTOPSRCDIR
++
++all-local: user-all-local
++
++install-exec-local: user-install-local
++
++clean-local: user-clean-local
++
++user-all-local:
++ ${MAKE} ${_mcall} all;
++
++# Have no user-install-data-local ATM
++user-install-local: user-install-exec-local
++
++user-install-exec-local:
++ ${MAKE} ${_mcall} install;
++
++user-clean-local:
++ ${MAKE} ${_mcall} clean;
++
++# Tell versions [3.59,3.63) of GNU make to not export all variables.
++# Otherwise a system limit (for SysV at least) may be exceeded.
++.NOEXPORT:
++
+--- /dev/null
++++ b/extensions/LUA/Mbuild
+@@ -0,0 +1,3 @@
++# -*- Makefile -*-
++
++obj-${build_LUA} += libxt_LUA.so
+--- /dev/null
++++ b/extensions/LUA/nf_lua.c
+@@ -0,0 +1,64 @@
++#if defined(__KERNEL__)
++
++#include
++#include
++#include
++#include
++#include
++#include
++
++#endif
++
++#include "lua.h"
++#include "lobject.h" /*sizeof(udata) */
++#include "lauxlib.h"
++#include "controller.h"
++
++#if defined(__KERNEL__) /* reachs until luaopen_nflib */
++
++
++static int32_t nf_get_random(lua_State *L)
++{
++ uint32_t rand = 0;
++
++ get_random_bytes(&rand, sizeof(uint32_t ));
++ lua_pushnumber(L, rand);
++ return 1;
++}
++
++static int32_t nf_get_time(lua_State *L)
++{
++ lua_pushnumber(L, jiffies_to_msecs(jiffies_64));
++ return 1;
++}
++
++static const struct luaL_Reg nf_lua_lib_f [] = {
++ { "get_random", nf_get_random },
++ { "get_time", nf_get_time },
++ { NULL, NULL }
++};
++
++void luaopen_nflib(lua_State *L)
++{
++ int32_t top;
++
++ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f);
++ lua_pop(L, 1);
++
++ /* registering verdicts inside the _G */
++ lua_getglobal(L, "_G");
++ top = lua_gettop(L);
++
++ lua_pushinteger(L, XT_CONTINUE);
++ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */
++
++ lua_pushinteger(L, NF_DROP);
++ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */
++
++ lua_pushinteger(L, NF_ACCEPT);
++ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */
++
++ lua_pop(L, 1); /* pop _G */
++}
++
++#endif
+--- /dev/null
++++ b/extensions/LUA/prot_buf_dynamic.c
+@@ -0,0 +1,486 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#include "controller.h"
++
++
++
++struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL };
++
++
++/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around
++ * a given Lua field setter function of a dynamic protocol buffer. The
++ * string containing the lua function name was piggybacked in the 'set'
++ * member of the protocol_field. We call this function passing the actual
++ * segment as byte array and the set value.
++ *
++ * Paramters:
++ * 1. lua_packet_segment (implicit)
++ * 2. some lua value
++ *
++ * Upvalues:
++ * 1. pointer to the protocol buffer
++ * 2. field index
++ *
++ * Returns:
++ * 1. true or false if the 'set' was successful
++ */
++int32_t field_dynamic_setter(lua_State *L)
++{
++ size_t nbytes;
++ lua_packet_segment * array;
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2));
++
++ /* the function name is piggybacked as a string */
++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set);
++ if (!lua_isfunction(L, -1)) {
++ lua_pushboolean(L, 0);
++ return 1;
++ }
++
++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t);
++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes);
++ array->length = seg->length;
++ array->start = seg->start + seg->offset;
++ array->changes = NULL;
++
++ luaL_getmetatable(L, LUA_BYTE_ARRAY);
++ lua_setmetatable(L, -2);
++ lua_pushvalue(L, 2); /* push value to set */
++ if (lua_pcall(L, 2, 1, 0) != 0) {
++ pr_debug("Error: %s \n", lua_tostring(L, -1));
++ lua_pop(L, 1);
++ lua_pushboolean(L, 0);
++ }
++ return 1;
++}
++
++/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around
++ * a given Lua field getter function of a dynamic protocol buffer. The
++ * string containing the lua function name was piggybacked in the 'get'
++ * member of the protocol_field. We call this function passing the actual
++ * segment as byte array.
++ *
++ * Paramters:
++ * 1. lua_packet_segment (implicit)
++ *
++ * Upvalues:
++ * 1. pointer to the protocol buffer
++ * 2. field index
++ *
++ * Returns:
++ * 1. true or false if the 'get' was successful
++ */
++int32_t field_dynamic_getter(lua_State *L)
++{
++ size_t nbytes;
++ lua_packet_segment * array;
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2));
++
++ /* the function name is piggybacked as a string */
++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get);
++ if (!lua_isfunction(L, -1)) {
++ lua_pushboolean(L, 0);
++ return 1;
++ }
++
++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t);
++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes);
++ array->length = seg->length;
++ array->start = seg->start + seg->offset;
++ array->changes = NULL;
++
++ luaL_getmetatable(L, LUA_BYTE_ARRAY);
++ lua_setmetatable(L, -2);
++ if (lua_pcall(L, 1, 1, 0) != 0) {
++ pr_debug("Error: %s \n", luaL_checkstring(L, -1));
++ lua_pop(L, 1);
++ lua_pushboolean(L, 0);
++ }
++ return 1;
++}
++
++/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around
++ * a given lua has_protocol function of a dynamic protocol buffer. The
++ * string containing the lua function name was piggybacked in the 'has_protocol'
++ * member of the protocol_buffer. We call this function passing the actual
++ * segment.
++ *
++ * Paramters:
++ * 1. lua_packet_segment
++ * 2. protocol type
++ *
++ * Returns:
++ * 1. true or false if the payload field contains the given protocol
++ */
++int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type)
++{
++ lua_packet_segment *seg_new;
++ int32_t res = 0;
++
++ /* the function name is piggybacked as a string */
++ lua_getglobal(L, (char *)prot_buf->has_protocol);
++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment));
++ seg_new->start = seg->start;
++ seg_new->offset = seg->offset;
++ seg_new->length = seg->length;
++ seg_new->changes = NULL;
++ luaL_getmetatable(L, prot_buf->name);
++ lua_setmetatable(L, -2);
++ lua_pushinteger(L, type); /* push the protocol type */
++ if (lua_pcall(L, 2, 1, 0) != 0) {
++ pr_debug("Error: %s \n", luaL_checkstring(L, -1));
++ lua_pop(L, 1);
++ return 0;
++ }
++ res = lua_toboolean(L, -1);
++ lua_pop(L, 1);
++
++ return res;
++}
++
++/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around
++ * a given lua get_field_changes function of a dynamic protocol buffer. The
++ * string containing the lua function name was piggybacked in the 'get_field_changes'
++ * member of the protocol_buffer. We call this function passing the actual
++ * segment. The lua function must return two lua table containing the offset
++ * and length changes (in bits).
++ *
++ * Paramters:
++ * 1. lua_packet_segment
++ *
++ * Returns:
++ * 1. new allocated field_changes struct
++ */
++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg)
++{
++ lua_packet_segment *seg_new;
++ struct field_changes * changes;
++ int32_t nr_of_changes, i;
++
++ lua_getglobal(L, (char *)prot_buf->get_field_changes);
++
++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment));
++ seg_new->start = seg->start;
++ seg_new->offset = seg->offset;
++ seg_new->length = seg->length;
++ seg_new->changes = NULL;
++ luaL_getmetatable(L, prot_buf->name);
++ lua_setmetatable(L, -2);
++
++ if (lua_pcall(L, 1, 2, 0) != 0)
++ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1));
++
++ /* the function call must return a table containing length changes */
++ luaL_checktype(L, -1, LUA_TTABLE);
++ /* the function call must return a table containing offset changes */
++ luaL_checktype(L, -2, LUA_TTABLE);
++ /* both tables have to be of same size */
++ if (lua_objlen(L, -1) != lua_objlen(L, -2))
++ luaL_error(L, "the provided tables are not of equal size");
++
++ nr_of_changes = lua_objlen(L, -1);
++ changes = get_allocated_field_changes(L, nr_of_changes);
++
++ /* loop over the tables */
++ for (i = 1; i < nr_of_changes; i++) {
++ lua_rawgeti(L, -1, i); /* push length value of field at index i */
++ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1);
++ lua_pop(L, 1); /* pop offset value */
++
++ lua_rawgeti(L, -2, i); /* push offset value of field at index i */
++ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1);
++ lua_pop(L, 1); /* pop length value */
++ }
++
++ /* pop both tables */
++ lua_pop(L, 2);
++
++ return changes;
++}
++
++/* C_INT: 'get_free_protocol_index' is only used internally. This function
++ * gets a free slot inside the array holding all the protocol buffers.
++ * There are several ways to get to this information. In this case I take
++ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the
++ * Lua state. Since this function is called at laodtime, we do not have
++ * to care about performance.
++ */
++static int32_t get_free_protocol_index(lua_State *L)
++{
++ int32_t protocol_index;
++
++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE);
++ protocol_index = lua_objlen(L, -1) + 1;
++ lua_pop(L, 1);
++ return protocol_index;
++}
++
++/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given
++ * dynamic protocol buffer. this function is normally called inside a
++ * cleanup routine. Be aware, before running this function you must be
++ * sure that no references to the dynamic protocol buffers were available.
++ * It's recomended to close the Lua state before calling the function. */
++void free_dynamic_prot_buf(struct protocol_buf * prot_buf)
++{
++ struct protocol_field * field = prot_buf->protocol_fields;
++
++ for (; field->name != NULL; field++) {
++ if (field->get) kfree(field->get);
++ if (field->set) kfree(field->set);
++ if (field->name) kfree((char *)field->name);
++ }
++
++ if (prot_buf->payload_field) kfree(prot_buf->payload_field);
++ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol);
++
++ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes);
++ kfree((char *)prot_buf->name);
++ kfree(prot_buf);
++ return;
++}
++
++void cleanup_dynamic_prot_bufs(void)
++{
++ int32_t i;
++
++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) {
++ if (dyn_prot_buf_array[i]) {
++ free_dynamic_prot_buf(dyn_prot_buf_array[i]);
++ dyn_prot_buf_array[i] = NULL;
++ }
++ }
++ return;
++}
++
++
++/* C_INT: 'free_protocol_fields' is used internally as a helper function for
++ * 'register_dynamic_protbuf'. It is used when durin registration an error
++ * occurs and the afore allocated fields needed to be freed. */
++static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i)
++{
++ struct protocol_field * f;
++
++ while (i >= 0) {
++ f = &prot_fields[i];
++ if (f->name) kfree((void *)f->name);
++ if (f->get) kfree((void *)f->get);
++ if (f->set) kfree((void *)f->set);
++ kfree((void *)f);
++ i--;
++ }
++}
++
++/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script.
++ * it takes a Lua table representing the dynamic protocol buffer as parameter.
++ * e.g.:
++ * eth_prot_buf = {
++ * name = "packet_eth_dyn",
++ * payload_field = "data",
++ * protocol_fields = {
++ * {"dmac", 0, 48, nil, nil },
++ * {"smac", 48, 48, nil, nil },
++ * {"type", 96, 16, nil, nil },
++ * {"data", 112, 0, nil, nil },
++ * },
++ * has_protocol = "eth_dyn_has_protocol",
++ * get_field_changes = "eth_dyn_get_field_changes"
++ * }
++ * register_dynamic_protbuf(eth_prot_buf)
++ *
++ * the table gets parsed and a new protocol_buf struct is allocated and
++ * initialized using 'register_protbuf', which is also used for the static
++ * protocol buffers. This enables an identical behavior like the static
++ * protocol buffers. The dynamic protocol buffers are not garbage collected,
++ * use 'free_dynamic_protbuf' to free them after closing the Lua state.
++ */
++static int32_t register_dynamic_protbuf(lua_State *L)
++{
++ struct protocol_buf *prot_buf;
++ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL;
++ int32_t nr_of_fields, i;
++
++ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL);
++ prot_buf->is_dynamic = 1;
++
++ /* check if parameter is a table */
++ luaL_checktype(L, 1, LUA_TTABLE);
++
++ /* initialize prot_buf.name */
++ lua_getfield(L, 1, "name");
++ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1));
++ lua_pop(L, 1); /* pop res from lua_getfield */
++
++ /* check if protocol buffer is already registered */
++ lua_getglobal(L, prot_buf->name);
++ if (!lua_isnil(L, -1)) {
++ lua_pop(L, 1); /* pop res from lua_getglobal */
++ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name);
++ goto free_prot_buf;
++ }
++ lua_pop(L, 1); /* pop res from lua_getglobal */
++
++ /* initialize payload field */
++ lua_getfield(L, 1, "payload_field");
++ if (lua_isstring(L, -1)) {
++ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy(prot_buf->payload_field, lua_tostring(L, -1));
++ }else
++ prot_buf->payload_field = NULL;
++ lua_pop(L, 1); /* pop res from lua_getfield */
++
++ /* initialize protocol_fields field*/
++ lua_getfield(L, 1, "protocol_fields");
++ if (!lua_istable(L, -1)) {
++ pr_debug("invalid protocol_fields table.\n");
++ goto err2;
++
++ }
++
++ nr_of_fields = lua_objlen(L, -1);
++ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL);
++
++ for (i = 1; i <= nr_of_fields; i++) {
++ field = &prot_buf->protocol_fields[i - 1];
++ /* initialize protocol field */
++ lua_rawgeti(L, -1, i); /* push field-table */
++ if (!lua_istable(L, -1)) {
++ free_protocol_fields(prot_buf->protocol_fields, i);
++ pr_debug("invalid protocol_field at %i.\n", i);
++ goto err;
++ }
++
++ /* initialize protocol field name */
++ lua_rawgeti(L, -1, 1);
++ if (!lua_isstring(L, -1)) {
++ free_protocol_fields(prot_buf->protocol_fields, i);
++ pr_debug("invalid protocol_field name at %i.\n", i);
++ goto err;
++ }
++
++ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char*)field->name, lua_tostring(L, -1));
++ lua_pop(L, 1); /* pop field name */
++
++ /* initialize protocol field offset */
++ lua_rawgeti(L, -1, 2);
++ if (!lua_isnumber(L, -1)) {
++ free_protocol_fields(prot_buf->protocol_fields, i);
++ pr_debug("invalid protocol_field offset at %i.\n", i);
++ goto err;
++ }
++ field->offset = lua_tointeger(L, -1);
++ lua_pop(L, 1); /* pop field offset */
++
++ /* initialize protocol field length */
++ lua_rawgeti(L, -1, 3);
++ if (!lua_isnumber(L, -1)) {
++ free_protocol_fields(prot_buf->protocol_fields, i);
++ pr_debug("invalid protocol_field length at %i.\n", i);
++ goto err;
++ }
++ field->length = lua_tointeger(L, -1);
++ lua_pop(L, 1); /* pop field length */
++
++ /* initialize protocol field getter */
++ lua_rawgeti(L, -1, 4);
++ if (lua_isstring(L, -1)) {
++ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */
++ }else
++ field->get = NULL;
++ lua_pop(L, 1); /* pop field getter */
++
++ /* initialize protocol field setter */
++ lua_rawgeti(L, -1, 5);
++ if (lua_isstring(L, -1)) {
++ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */
++ }else
++ field->set = NULL;
++ lua_pop(L, 1); /* pop field setter */
++
++ /* field initialization completed */
++ lua_pop(L, 1); /* pop field-table */
++ }
++
++ /* put sentinel at the end of protocol_fields */
++ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel));
++ lua_pop(L, 1); /* pop protocol-fields-table */
++
++ /* initialize has_protocol field */
++ lua_getfield(L, 1, "has_protocol");
++ if (lua_isstring(L, -1)) {
++ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */
++ }else
++ prot_buf->has_protocol = NULL;
++ lua_pop(L, 1); /* pop has_protocol */
++
++ /* initialize get_field_changes field */
++ lua_getfield(L, 1, "get_field_changes");
++ if (lua_isstring(L, -1)) {
++ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL);
++ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */
++ }else
++ prot_buf->get_field_changes = NULL;
++ lua_pop(L, 1); /* pop get_field_changes */
++
++ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */
++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) {
++ if (!dyn_prot_buf_array[i]) {
++ dyn_prot_buf_array[i] = prot_buf;
++ break;
++ }else
++ goto err;
++ }
++
++ /* call the "common" register_protbuf */
++ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */
++
++ return 0;
++
++err:
++ kfree(prot_buf->protocol_fields);
++err2:
++ if (prot_buf->payload_field) kfree(prot_buf->payload_field);
++free_prot_buf:
++ kfree((void *)prot_buf->name);
++ kfree(prot_buf);
++
++ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log");
++
++ return 0;
++
++}
++
++void luaopen_protbuf_dynamic(lua_State *L)
++{
++ lua_getglobal(L, "_G");
++ lua_pushcclosure(L, register_dynamic_protbuf, 0);
++ lua_setfield(L, -2, "register_dynamic_protbuf");
++ lua_pop(L, 1); /* pop _G */
++ return;
++}
+--- /dev/null
++++ b/extensions/LUA/prot_buf_ethernet.c
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#include "controller.h"
++
++
++static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/;
++ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT));
++
++ switch (res) {
++ case 0x0800: /* 1: Internet Protocol (IP) */
++ if (protocol_type == PACKET_IP) return 1;
++ break;
++ default:
++ return 0;
++ }
++
++ return 0;
++}
++
++static const struct protocol_field eth_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "dmac", 0, 48, NULL, NULL },
++ { "smac", 48, 48, NULL, NULL },
++ { "type", 96, 16, NULL, NULL },
++ { "data", 112, 0, NULL, NULL },
++ PROT_FIELD_SENTINEL,
++};
++
++static const struct protocol_buf eth_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_ETH,
++ .payload_field = "data",
++ .protocol_fields = (struct protocol_field *)ð_protocol_fields,
++ .has_protocol = ð_has_protocol,
++ .get_field_changes = NULL,
++};
++
++
++void luaopen_protbuf_eth(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH);
++}
+--- /dev/null
++++ b/extensions/LUA/prot_buf_helpers.c
+@@ -0,0 +1,216 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#if defined(__KERNEL__)
++#include
++#include /* kmalloc */
++#endif
++
++#include "controller.h"
++
++int32_t get_header_size(struct protocol_buf * prot_buf)
++{
++ int32_t bit_counter = 0;
++ struct protocol_field * field = prot_buf->protocol_fields;
++
++ for (; field->name; field++)
++ bit_counter += field->length;
++
++ return bit_counter >> 3;
++}
++
++
++int32_t set_32_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2));
++ return 0;
++}
++int32_t get_32_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset))));
++ return 1;
++}
++
++int32_t set_16_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2));
++ return 0;
++}
++int32_t get_16_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset))));
++ return 1;
++}
++
++int32_t set_lower_4_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4;
++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset);
++
++ *pos &= 0x0F; /* reset lower 4 bits*/
++ *pos |= b;
++
++ return 0;
++}
++
++int32_t get_lower_4_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4);
++ return 1;
++}
++
++int32_t set_upper_4_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4;
++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset);
++
++ *pos &= 0xF0; /* reset upper 4 bits*/
++ *pos |= (b >> 4);
++
++ return 0;
++}
++
++int32_t get_upper_4_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F);
++ return 1;
++}
++
++
++int32_t set_8_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2);
++ return 0;
++}
++
++int32_t get_8_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset));
++ return 1;
++}
++
++int32_t set_1_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++ unsigned long l = 0;
++
++ memcpy(&l, (seg->start + seg->offset), seg->length);
++ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2)));
++ memcpy((seg->start + seg->offset), &l, seg->length);
++
++ return 0;
++}
++
++int32_t get_1_bit_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++ unsigned long l = 0;
++ uint32_t bit = 0;
++
++ memcpy(&l, (seg->start + seg->offset), seg->length);
++ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2)));
++
++ lua_pushboolean(L, bit);
++ return 1;
++}
++
++int32_t get_string_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++ /* Warning we cast from uchar to char */
++ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length);
++ return 1;
++}
++
++int32_t set_data_generic(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++ lua_packet_segment * data = checkbytearray(L, 2);
++
++ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length);
++
++ if (seg->length >= data->length)
++ memcpy((seg->start + seg->offset), data->start, data->length);
++ else
++ luaL_error(L, "provided byte array too big for given packet segment");
++ return 0;
++}
++
++struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields)
++{
++ struct field_changes * changes;
++
++ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC);
++
++ if (!changes)
++ goto failure;
++
++ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC);
++ if (!changes->field_length_changes)
++ goto free1;
++
++ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC);
++ if (!changes->field_offset_changes)
++ goto free2;
++
++ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int));
++ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int));
++
++ changes->ref_count = 1;
++
++ return changes;
++
++free2: kfree(changes->field_length_changes);
++free1: kfree(changes);
++failure:
++ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'");
++ return NULL; /* only to omit warnings */
++}
+\ No newline at end of file
+--- /dev/null
++++ b/extensions/LUA/prot_buf_icmp.c
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#include "controller.h"
++
++static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ return 0;
++}
++
++static const struct protocol_field icmp_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "type", 0, 8, NULL, NULL },
++ { "code", 8, 8, NULL, NULL },
++ { "checksum", 16, 16, NULL, NULL },
++ { "id", 32, 16, NULL, NULL },
++ { "sequence", 48, 16, NULL, NULL },
++ PROT_FIELD_SENTINEL,
++};
++
++static const struct protocol_buf icmp_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_ICMP,
++ .payload_field = NULL,
++ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields,
++ .has_protocol = &icmp_has_protocol,
++ .get_field_changes = NULL,
++};
++
++void luaopen_protbuf_icmp(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP);
++}
++
+--- /dev/null
++++ b/extensions/LUA/prot_buf_ip.c
+@@ -0,0 +1,209 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#if defined(__KERNEL__)
++ #include
++ #include
++#endif
++
++#include "controller.h"
++
++
++#define IP_FMT "%u.%u.%u.%u"
++#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3]
++
++
++static int32_t ip_version_set(lua_State *L)
++{
++ uint8_t version_checked;
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *version_seg = seg->start + seg->offset;
++ int32_t version = luaL_checkinteger(L, 2);
++
++ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid");
++
++ version_checked = (uint8_t)version;
++
++ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */
++ version_seg[0] |= version_checked << 4;
++
++ return 0;
++}
++static int32_t ip_version_get(lua_State *L)
++{
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *version_seg = seg->start + seg->offset;
++ uint8_t v = version_seg[0] & 0xF0;
++
++ v >>= 4;
++
++ lua_pushinteger(L, v);
++ return 1;
++}
++
++static int32_t ip_ihl_set(lua_State *L)
++{
++ uint8_t ihl_checked;
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *ihl_seg = seg->start + seg->offset;
++ int32_t ihl = luaL_checkinteger(L, 2);
++
++ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits
++
++ ihl_checked = (uint8_t)ihl;
++
++ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */
++ ihl_seg[0] |= ihl_checked;
++
++ return 0;
++}
++static int32_t ip_ihl_get(lua_State *L)
++{
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *ihl_seg = seg->start + seg->offset;
++ uint8_t v = ihl_seg[0] & 0x0F;
++
++ lua_pushinteger(L, v);
++ return 1;
++}
++
++static int32_t ip_addr_set(lua_State *L)
++{
++ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2));
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *addr_seg = seg->start + seg->offset;
++ uint32_t old_addr;
++ char *ip = (char *)luaL_checkstring(L, 2);
++ uint32_t a, b, c, d;
++ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3);
++
++ /* for tcp / udp checksumming*/
++ uint32_t prot_offset;
++ uint8_t *check, *protocol_seg;
++
++ /* end */
++
++ sscanf(ip, IP_FMT, &a, &b, &c, &d);
++
++ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr");
++
++ old_addr = *((uint32_t *)addr_seg);
++ addr_seg[0] = (uint8_t)a;
++ addr_seg[1] = (uint8_t)b;
++ addr_seg[2] = (uint8_t)c;
++ addr_seg[3] = (uint8_t)d;
++
++#if defined(__KERNEL__)
++ if (old_addr != *(uint32_t *)addr_seg) {
++ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */
++
++ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg);
++
++ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */
++ protocol_seg = seg->start + seg->offset + prot_offset;
++
++ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */
++
++ check = seg->start + seg->offset; /* tmp res */
++ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */
++ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */
++
++ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1);
++
++ lua_pop(L, 1);
++ }
++ }
++#endif
++ return 0;
++}
++
++
++
++
++
++static int32_t ip_addr_get(lua_State *L)
++{
++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP);
++ uint8_t *addr_seg = seg->start + seg->offset;
++
++ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */
++
++ sprintf(buf, IP_FMT, IP_ACC(addr_seg));
++ lua_pushstring(L, buf);
++ return 1;
++}
++
++static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/;
++
++ switch (embedded_protocol[0]) {
++ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */
++ if (protocol_type == PACKET_ICMP) return 1;
++ break;
++ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */
++ break;
++ case 0x06: /* 6: Transmission Control Protocol (TCP) */
++ if (protocol_type == PACKET_TCP) return 1;
++ break;
++ case 0x11: /* 17: User Datagram Protocol (UDP) */
++ if (protocol_type == PACKET_UDP) return 1;
++ break;
++ case 0x59: /* 89: Open Shortest Path First (OSPF) */
++ break;
++ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++static const struct protocol_field ip_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "version", 0, 4, ip_version_get, ip_version_set },
++ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set },
++ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic },
++ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic },
++ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic },
++ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic },
++ { "frag_off", 51, 13, NULL, NULL },
++ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic },
++ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic },
++ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic },
++ { "saddr", 96, 32, ip_addr_get, ip_addr_set },
++ { "daddr", 128, 32, ip_addr_get, ip_addr_set },
++ { "data", 160, 0, NULL, set_data_generic },
++ PROT_FIELD_SENTINEL,
++};
++
++static const struct protocol_buf ip_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_IP,
++ .payload_field = "data",
++ .protocol_fields = (struct protocol_field *)&ip_protocol_fields,
++ .has_protocol = &ip_has_protocol,
++ .get_field_changes = NULL,
++};
++
++void luaopen_protbuf_ip(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP);
++}
++
+--- /dev/null
++++ b/extensions/LUA/prot_buf_raw.c
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#include "controller.h"
++static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ return 1;
++}
++
++static const struct protocol_field raw_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "data", 0, 0, NULL, NULL },
++ PROT_FIELD_SENTINEL,
++};
++
++static const struct protocol_buf raw_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_RAW,
++ .payload_field = "data",
++ .protocol_fields = (struct protocol_field *)&raw_protocol_fields,
++ .has_protocol = &raw_has_protocol,
++ .get_field_changes = NULL,
++};
++
++void luaopen_protbuf_raw(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW);
++}
+--- /dev/null
++++ b/extensions/LUA/prot_buf_tcp.c
+@@ -0,0 +1,188 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#if defined(__KERNEL__)
++ #include
++ #include
++#endif
++#include "controller.h"
++
++
++static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ return 1;
++}
++
++static int32_t tcp_set_checksum(lua_State *L)
++{
++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1));
++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name);
++
++#if defined(__KERNEL__)
++ uint8_t * check_seg = seg->start + seg->offset;
++ uint8_t * tcp_hdr = check_seg - 16;
++ uint8_t * saddr = tcp_hdr - 8;
++ uint8_t * daddr = saddr + 4;
++ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8);
++ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr,
++ csum_partial(tcp_hdr, len, 0));
++
++ memcpy(check_seg, &checksum, sizeof(unsigned short));
++#endif
++ return 0;
++}
++
++
++static const struct protocol_field tcp_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic },
++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic },
++ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic },
++ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic },
++ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic },
++ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic },
++ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic },
++ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic },
++ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum },
++ { "urgent", 144, 16, NULL, NULL },
++ { "options", 160, 0, NULL, set_data_generic },
++ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */
++ PROT_FIELD_SENTINEL,
++};
++
++
++static const struct protocol_field tcp_options_and_data[] = {
++ /* field name offset length getter setter */
++ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic },
++ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic },
++ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic },
++ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic },
++ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic },
++ PROT_FIELD_SENTINEL,
++};
++
++
++static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg);
++
++static const struct protocol_buf tcp_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_TCP,
++ .payload_field = "data",
++ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields,
++ .has_protocol = &tcp_has_protocol,
++ .get_field_changes = &tcp_get_field_changes,
++};
++
++
++static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg);
++
++static const struct protocol_buf tcp_options_and_data_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_TCP_OPT,
++ .payload_field = NULL,
++ .protocol_fields = (struct protocol_field *)&tcp_options_and_data,
++ .has_protocol = NULL,
++ .get_field_changes = &tcp_options_get_field_changes,
++};
++
++struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg)
++{
++ /* depending on the value stored inside the 'data_off'-field, the length of
++ * the 'options' field has to be changed, as well as the length and offset
++ * of the 'data' field */
++ uint8_t *tcp_hdr = seg->start + seg->offset;
++
++ /* get the pointer to the 'data_off' field */
++ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */
++ /* extract the stored header length in bits */
++ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32;
++
++ /* get an allocated 'field_changes' structure */
++ struct field_changes * changes = get_allocated_field_changes(L, 12);
++
++ /* depending on the tcp header length, change the length of the options*/
++ changes->field_length_changes[10] = tcp_hdr_len - 160;
++ /* depending on the options length, change the offset of the data */
++ changes->field_offset_changes[11] = changes->field_length_changes[10];
++ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len;
++
++ return changes;
++
++}
++
++struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg)
++{
++ /* depending on the value stored inside the 'data_off'-field, the length of
++ * the 'options' field has to be changed, as well as the length and offset
++ * of the 'data' field */
++ uint8_t *tcp_opt_hdr = seg->start + seg->offset;
++
++ /* get an allocated 'field_changes' structure */
++ struct field_changes * changes = get_allocated_field_changes(L, 5);
++
++ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i;
++
++ uint8_t b1, b2;
++
++ for (i = 0; i < seg->length; i++) {
++ b1 = tcp_opt_hdr[i];
++ b2 = tcp_opt_hdr[i + 1];
++
++ if (b1 == 0x00)
++ break;
++
++ /* test for MSS */
++ if (!MSS && (b1 == 0x02 && b2 == 0x04)) {
++ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT;
++ MSS = 1;
++ }
++
++ /* test for WS --- yet buggy somehow */
++ if (!WS && (b1 == 0x03 && b2 == 0x03)) {
++ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT;
++ WS = 1;
++ }
++
++ /* test for SACK*/
++ if (!SACK && (b1 == 0x04 && b2 == 0x02)) {
++ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */
++ SACK = 1;
++ }
++
++ /* test for TS */
++ if (!TS && (b1 == 0x08 && b2 == 0x0A)) {
++ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT;
++ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT;
++ TS = 1;
++ }
++ }
++
++ return changes;
++
++}
++
++void luaopen_protbuf_tcp(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP);
++}
++void luaopen_protbuf_tcp_options(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS);
++}
++
++
+--- /dev/null
++++ b/extensions/LUA/prot_buf_tftp.c
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++#include "controller.h"
++
++static const struct protocol_field tftp_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "opcode", 0, 16, get_16_bit_generic, NULL},
++ { "filename", 0, 0, get_string_generic, NULL},
++ { "mode", 0, 0, get_string_generic, NULL},
++ { "block_nr", 0, 16, get_16_bit_generic, NULL},
++ { "data", 0, 0, NULL, NULL},
++ PROT_FIELD_SENTINEL,
++};
++
++struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg)
++{
++ /* depending on the value stored inside the 'opcode'-field we have to change
++ * offsets and lengths */
++ uint8_t *tftp_hdr = seg->start + seg->offset;
++ short opcode = ntohs(*((uint16_t *)tftp_hdr));
++ /* get an allocated 'field_changes' structure */
++ struct field_changes * changes = get_allocated_field_changes(L, 5);
++ switch (opcode) {
++ case 1: /* Read Request (RRQ) */
++ /* setting offset and length of field 'filename' */
++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3;
++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3;
++ /* setting offset and length of field 'mode' */
++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1];
++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3));
++ break;
++ case 2: /* Write Request (WRQ) */
++ /* setting offset and length of field 'filename' */
++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3;
++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3;
++ /* setting offset and length of field 'mode' */
++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1];
++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3));
++ break;
++ case 3: /* Data (DATA) */
++ /* setting offset of field 'block_nr' */
++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3;
++ /* setting offset of field 'data' */
++ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3);
++ break;
++ case 4: /* Acknowledgment (ACK) */
++ /* setting offset of field 'block_nr' */
++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3;
++ break;
++ case 5: /* Error (ERROR) */
++ /* we don't care ... yet */
++ break;
++ default:
++ break;
++ }
++
++ return changes;
++}
++
++static const struct protocol_buf tftp_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_TFTP,
++ .payload_field = NULL,
++ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields,
++ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */
++ .get_field_changes = tftp_get_field_changes,
++};
++
++void luaopen_protbuf_tftp(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP);
++}
+--- /dev/null
++++ b/extensions/LUA/prot_buf_udp.c
+@@ -0,0 +1,53 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#if defined(__KERNEL__)
++ #include
++#endif
++
++#include "controller.h"
++
++
++static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type)
++{
++ return 1;
++}
++
++static const struct protocol_field udp_protocol_fields[] = {
++ /* field name offset length getter setter */
++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic },
++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic },
++ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic },
++ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic },
++ { "data", 64, 0, NULL, NULL },
++ PROT_FIELD_SENTINEL,
++};
++
++static const struct protocol_buf udp_protocol_buf = {
++ .is_dynamic = 0,
++ .name = LUA_PACKET_SEG_UDP,
++ .payload_field = "data",
++ .protocol_fields = (struct protocol_field *)&udp_protocol_fields,
++ .has_protocol = &udp_has_protocol,
++ .get_field_changes = NULL,
++};
++
++void luaopen_protbuf_udp(lua_State *L)
++{
++ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP);
++}
+--- /dev/null
++++ b/extensions/LUA/xt_LUA.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#ifndef XT_LUA_H_
++#define XT_LUA_H_
++
++#define MAX_FILENAME_SIZE 256
++#define MAX_FUNCTION_SIZE 256
++#define MAX_SCRIPT_SIZE 32768
++#define LUA_STATE_ARRAY_SIZE 128
++
++/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/
++struct xt_lua_tginfo {
++ char buf[MAX_SCRIPT_SIZE];
++ char filename[MAX_FILENAME_SIZE];
++ char function[MAX_FUNCTION_SIZE];
++ __u64 script_size;
++ __u32 state_id;
++};
++
++#endif /* XT_LUA_H_ */
+--- /dev/null
++++ b/extensions/LUA/xt_LUA_target.c
+@@ -0,0 +1,286 @@
++/*
++ * Copyright (C) 2010 University of Basel
++ * by Andre Graf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see .
++ */
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include "xt_LUA.h"
++
++#include "controller.h"
++
++/*::*
++ * lua_envs
++ * ----------
++ * This array holds a defined number of `lua_envs`_ structures.
++ * The used array index is also used as the Lua state identifier.
++ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_.
++ */
++struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE];
++
++/*::*
++ * lua_state_refs
++ * --------------
++ * This array holds the reference counts of the several `lua_nf_state`_s
++ * which are stored inside the array `lua_states`_.
++ */
++uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 };
++
++/*::*
++ * lua_tg
++ * ------
++ * This function is called whenever a packet matches all matching conditions
++ * inside a rule. It is the target. It extracts the state identifier comming
++ * inside the *xt_target_param* structure and uses it to access the proper
++ * Lua state inside the `lua_states`_ array.
++ *
++ * It then constructs a new Lua userdata of type *lua_packet_segment* and
++ * initializes it with the lowest network header available. This userdata
++ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts
++ * the userdata to a raw lua packet having all raw functions available.
++ * This raw packet is the single parameter to the Lua function *process_packet*
++ * which must be defined inside the Lua script provided by the user. So far
++ * hardcoded, may be later configured by Lua - subject to change.
++ *
++ * The process_packet function must return an integer value, the verdict. For
++ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and
++ * XT_CONTINUE inside the *register_lua_packet_lib* function.
++ */
++
++spinlock_t lock = SPIN_LOCK_UNLOCKED;
++
++static uint32_t
++lua_tg(struct sk_buff *pskb, const struct xt_target_param *par)
++{
++ uint32_t verdict;
++ lua_packet_segment *p;
++ const struct xt_lua_tginfo *info = par->targinfo;
++ lua_State * L;
++
++ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/
++ spin_lock_irq(&lock);
++
++ L = lua_envs[info->state_id]->L;
++
++ if (!skb_make_writable(pskb, pskb->len))
++ return NF_DROP;
++
++ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */
++ lua_getglobal(L, info->function);
++
++ /* push the lua_packet_segment as a parameter */
++ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment));
++ if (pskb->mac_header)
++ p->start = pskb->mac_header;
++ else if (pskb->network_header)
++ p->start = pskb->network_header;
++ else if (pskb->transport_header)
++ p->start = pskb->transport_header;
++ p->offset = 0;
++ p->length = (unsigned long)pskb->tail - (unsigned long)p->start;
++ p->changes = NULL;
++
++ /* marking userdata 'lua_packet_seg' with the corresponding metatable */
++ luaL_getmetatable(L, LUA_PACKET_SEG_RAW);
++ lua_setmetatable(L, -2);
++
++ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/
++ lua_pushlightuserdata(L, (void *)skb_get(pskb));
++
++ /* do the function call (2 argument, 1 result) */
++ if (lua_pcall(L, 2, 1, 0) != 0) {
++ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1));
++ lua_pop(L, 1);
++ return NF_DROP;
++ }
++
++ if (!lua_isnumber(L, -1)) {
++ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function);
++ lua_pop(L, 1);
++ return NF_DROP;
++ }
++
++ verdict = lua_tonumber(L, -1);
++ lua_pop(L, 1);
++
++ kfree_skb(pskb);
++
++ /* END critical section on SMP */
++ spin_unlock_irq(&lock);
++
++
++ return verdict;
++
++}
++/* Helper for checkentry */
++static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf)
++{
++ char *buf = kmalloc(script_size, GFP_KERNEL);
++ int32_t ret;
++ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL);
++
++ if (!script_size > 0) {
++ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size);
++ return false;
++ }
++
++ env->L = lua_open();
++ luaopen_base(env->L);
++ luaopen_controller(env->L);
++
++ lua_getglobal(env->L, "_G");
++ lua_pushinteger(env->L, state_id);
++ lua_setfield(env->L, -2, "STATE_ID");
++ lua_pop(env->L, 1); /* pop _G */
++
++ strncpy(buf, script_buf, script_size);
++ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") ||
++ lua_pcall(env->L, 0, 1, 0);
++
++ if (ret != 0) {
++ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1));
++ lua_pop(env->L, 1);
++ kfree(buf);
++ kfree(env);
++ return false;
++ }
++
++ lua_envs[state_id] = env;
++
++ kfree(buf);
++
++ return true;
++}
++/*::*
++ * lua_tg_checkentry
++ * -----------------
++ * This function is used as a kernel-side sanity check of the data comming
++ * from the iptables userspace program. Since this is the function which is
++ * called everytime a new rule (with -j xt_LUA) is injected, this function
++ * is used to do the bookkeeping work, such as counting the reference of
++ * several Lua states and the initialization of new states if needed. As an
++ * extra initialization step it loads the provided Lua script into the Lua
++ * state.
++ *
++ * Lua state initialization
++ * ~~~~~~~~~~~~~~~~~~~~~~~~
++ * 1. If a new rule is inserted and there is no existing state for the given
++ * state identifier (default state identifier is 0) a new Lua state is
++ * initialized using *lua_open*.
++ * 2. The Lua base library is registered inside the newly initialized state.
++ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base
++ * library are available inside Lua.
++ * 3. The Lua packet library is registered inside the Lua state using the
++ * function *register_lua_packet_lib*. So far this function only registers
++ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the
++ * global environment of the given Lua state.
++ * 4. All the protocol Buffers, and the functions for accessing the bytes are
++ * registered using *register_protocols*.
++ *
++ * Lua state reference counting
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The
++ * state identifier is mapped to the array index, which holds an integer
++ * counting the several initialized states.
++ *
++ * Loading the Lua script
++ * ~~~~~~~~~~~~~~~~~~~~~~
++ * Copying the buffer which was initialized by the userspace program to a
++ * buffer with the proper size. The script is then loaded by the function
++ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does
++ * some workqueue initialization. So far this is done each time this function
++ * is called, subject to change.
++ */
++static bool
++lua_tg_checkentry(const struct xt_tgchk_param *par)
++{
++ const struct xt_lua_tginfo *info = par->targinfo;
++
++ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) {
++ lua_state_refs[info->state_id]++;
++ return true;
++ }
++ return false;
++}
++
++/*::*
++ * lua_tg_destroy
++ * --------------
++ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is
++ * responsible to free all the resources alocated inside the checkentry process.
++ * To be more specific it frees the Lua state using *lua_close* and kfree on all
++ * the dynamically allocated pointers to the registered dynamic protocol buffers.
++ *
++ * Additionally the function cares about decrementing the reference counters
++ * inside the array `lua_states`_.
++ */
++static void
++lua_tg_destroy(const struct xt_tgdtor_param *par)
++{
++ const struct xt_lua_tginfo *info = par->targinfo;
++ struct lua_env * env = lua_envs[info->state_id];
++
++ if (lua_state_refs[info->state_id] == 1) {
++ lua_close(env->L);
++ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */
++ kfree(env);
++ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id);
++ } else
++ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n",
++ info->state_id, lua_state_refs[info->state_id] - 1);
++
++ lua_state_refs[info->state_id]--;
++}
++
++static struct xt_target lua_tg_reg __read_mostly = {
++ .name = "LUA",
++ .revision = 0,
++ .family = NFPROTO_UNSPEC,
++ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)),
++ .target = lua_tg,
++ .checkentry = lua_tg_checkentry,
++ .destroy = lua_tg_destroy,
++ .me = THIS_MODULE,
++};
++
++
++static int32_t lua_tg_init(void)
++{
++ return xt_register_target(&lua_tg_reg);
++}
++
++static void lua_tg_exit(void)
++{
++ xt_unregister_target(&lua_tg_reg);
++}
++
++module_init(lua_tg_init);
++module_exit(lua_tg_exit);
++
++MODULE_AUTHOR("Andre Graf ");
++MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment");
++MODULE_ALIAS("ipt_LUA");
++MODULE_ALIAS("ipt6t_LUA");
++MODULE_ALIAS("arpt_LUA");
++MODULE_ALIAS("ebt_LUA");
++MODULE_LICENSE("GPL");
++
++
++
+--- a/extensions/Kbuild
++++ b/extensions/Kbuild
+@@ -29,6 +29,7 @@ obj-${build_pknock} += pknock/
+ obj-${build_psd} += xt_psd.o
+ obj-${build_quota2} += xt_quota2.o
+ obj-${build_rtsp} += rtsp/
++obj-${build_LUA} += LUA/
+
+ -include ${M}/*.Kbuild
+ -include ${M}/Kbuild.*
+--- a/extensions/Mbuild
++++ b/extensions/Mbuild
+@@ -22,3 +22,4 @@ obj-${build_pknock} += pknock/
+ obj-${build_psd} += libxt_psd.so
+ obj-${build_quota2} += libxt_quota2.so
+ obj-${build_gradm} += libxt_gradm.so
++obj-${build_LUA} += LUA/
+--- a/mconfig
++++ b/mconfig
+@@ -23,3 +23,4 @@ build_pknock=m
+ build_psd=m
+ build_quota2=m
+ build_rtsp=m
++build_LUA=m
--
cgit v1.2.3