= 16) {
- x = (x+1) >> 1;
- e++;
- }
- if (x < 8) return (int)x;
- else return ((e+1) << 3) | (cast_int(x) - 8);
- }
-
-
- /* converts back */
- public static int luaO_fb2int (int x) {
- int e = (x >> 3) & 31;
- if (e == 0) return x;
- else return ((x & 7)+8) << (e - 1);
- }
-
-
- private readonly static lu_byte[] log_2 = {
- 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- };
-
- [CLSCompliantAttribute(false)]
- public static int luaO_log2 (uint x) {
- int l = -1;
- while (x >= 256) { l += 8; x >>= 8; }
- return l + log_2[x];
-
- }
-
-
- public static int luaO_rawequalObj (TValue t1, TValue t2) {
- if (ttype(t1) != ttype(t2)) return 0;
- else switch (ttype(t1)) {
- case LUA_TNIL:
- return 1;
- case LUA_TNUMBER:
- return luai_numeq(nvalue(t1), nvalue(t2)) ? 1 : 0;
- case LUA_TBOOLEAN:
- return bvalue(t1) == bvalue(t2) ? 1 : 0; /* boolean true must be 1....but not in C# !! */
- case LUA_TLIGHTUSERDATA:
- return pvalue(t1) == pvalue(t2) ? 1 : 0;
- default:
- lua_assert(iscollectable(t1));
- return gcvalue(t1) == gcvalue(t2) ? 1 : 0;
- }
- }
-
- public static int luaO_str2d (CharPtr s, out lua_Number result) {
- CharPtr endptr;
- result = lua_str2number(s, out endptr);
- if (endptr == s) return 0; /* conversion failed */
- if (endptr[0] == 'x' || endptr[0] == 'X') /* maybe an hexadecimal constant? */
- result = cast_num(strtoul(s, out endptr, 16));
- if (endptr[0] == '\0') return 1; /* most common case */
- while (isspace(endptr[0])) endptr = endptr.next();
- if (endptr[0] != '\0') return 0; /* invalid trailing characters? */
- return 1;
- }
-
-
-
- private static void pushstr (lua_State L, CharPtr str) {
- setsvalue2s(L, L.top, luaS_new(L, str));
- incr_top(L);
- }
-
-
- /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
- public static CharPtr luaO_pushvfstring (lua_State L, CharPtr fmt, params object[] argp) {
- int parm_index = 0;
- int n = 1;
- pushstr(L, "");
- for (;;) {
- CharPtr e = strchr(fmt, '%');
- if (e == null) break;
- setsvalue2s(L, L.top, luaS_newlstr(L, fmt, (uint)(e-fmt)));
- incr_top(L);
- switch (e[1]) {
- case 's': {
- object o = argp[parm_index++];
- CharPtr s = o as CharPtr;
- if (s == null)
- s = (string)o;
- if (s == null) s = "(null)";
- pushstr(L, s);
- break;
- }
- case 'c': {
- CharPtr buff = new char[2];
- buff[0] = (char)(int)argp[parm_index++];
- buff[1] = '\0';
- pushstr(L, buff);
- break;
- }
- case 'd': {
- setnvalue(L.top, (int)argp[parm_index++]);
- incr_top(L);
- break;
- }
- case 'f': {
- setnvalue(L.top, (l_uacNumber)argp[parm_index++]);
- incr_top(L);
- break;
- }
- case 'p': {
- //CharPtr buff = new char[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
- CharPtr buff = new char[32];
- sprintf(buff, "0x%08x", argp[parm_index++].GetHashCode());
- pushstr(L, buff);
- break;
- }
- case '%': {
- pushstr(L, "%");
- break;
- }
- default: {
- CharPtr buff = new char[3];
- buff[0] = '%';
- buff[1] = e[1];
- buff[2] = '\0';
- pushstr(L, buff);
- break;
- }
- }
- n += 2;
- fmt = e+2;
- }
- pushstr(L, fmt);
- luaV_concat(L, n+1, cast_int(L.top - L.base_) - 1);
- L.top -= n;
- return svalue(L.top - 1);
- }
-
- public static CharPtr luaO_pushfstring(lua_State L, CharPtr fmt, params object[] args)
- {
- return luaO_pushvfstring(L, fmt, args);
- }
-
- [CLSCompliantAttribute(false)]
- public static void luaO_chunkid (CharPtr out_, CharPtr source, uint bufflen) {
- //out_ = "";
- if (source[0] == '=') {
- strncpy(out_, source+1, (int)bufflen); /* remove first char */
- out_[bufflen-1] = '\0'; /* ensures null termination */
- }
- else { /* out = "source", or "...source" */
- if (source[0] == '@') {
- uint l;
- source = source.next(); /* skip the `@' */
- bufflen -= (uint)(" '...' ".Length + 1);
- l = (uint)strlen(source);
- strcpy(out_, "");
- if (l > bufflen) {
- source += (l-bufflen); /* get last part of file name */
- strcat(out_, "...");
- }
- strcat(out_, source);
- }
- else { /* out = [string "string"] */
- uint len = strcspn(source, "\n\r"); /* stop at first newline */
- bufflen -= (uint)(" [string \"...\"] ".Length + 1);
- if (len > bufflen) len = bufflen;
- strcpy(out_, "[string \"");
- if (source[len] != '\0') { /* must truncate? */
- strncat(out_, source, (int)len);
- strcat(out_, "...");
- }
- else
- strcat(out_, source);
- strcat(out_, "\"]");
- }
- }
- }
-
- }
-}
+/*
+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
+** Some generic functions over Lua objects
+** See Copyright Notice in lua.h
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace KopiLua
+{
+ using TValue = Lua.lua_TValue;
+ using StkId = Lua.lua_TValue;
+ using lu_byte = System.Byte;
+ using lua_Number = System.Double;
+ using l_uacNumber = System.Double;
+ using Instruction = System.UInt32;
+
+ public partial class Lua
+ {
+ /* tags for values visible from Lua */
+ public const int LAST_TAG = LUA_TTHREAD;
+
+ public const int NUM_TAGS = (LAST_TAG+1);
+
+
+ /*
+ ** Extra tags for non-values
+ */
+ public const int LUA_TPROTO = (LAST_TAG+1);
+ public const int LUA_TUPVAL = (LAST_TAG+2);
+ public const int LUA_TDEADKEY = (LAST_TAG+3);
+
+ public interface ArrayElement
+ {
+ void set_index(int index);
+ void set_array(object array);
+ }
+
+
+ /*
+ ** Common Header for all collectable objects (in macro form, to be
+ ** included in other objects)
+ */
+ public class CommonHeader
+ {
+ public GCObject next;
+ public lu_byte tt;
+ public lu_byte marked;
+ }
+
+
+ /*
+ ** Common header in struct form
+ */
+ public class GCheader : CommonHeader {
+ };
+
+
+
+
+ /*
+ ** Union of all Lua values (in c# we use virtual data members and boxing)
+ */
+ public class Value
+ {
+
+ // in the original code Value is a struct, so all assignments in the code
+ // need to be replaced with a call to Copy. as it turns out, there are only
+ // a couple. the vast majority of references to Value are the instance that
+ // appears in the TValue class, so if you make that a virtual data member and
+ // omit the set accessor then you'll get a compiler error if anything tries
+ // to set it.
+ public void Copy(Value copy)
+ {
+ this.p = copy.p;
+ }
+
+ public GCObject gc
+ {
+ get {return (GCObject)this.p;}
+ set {this.p = value;}
+ }
+ public object p;
+ public lua_Number n
+ {
+ get { return (lua_Number)this.p; }
+ set { this.p = (object)value; }
+ }
+ public int b
+ {
+ get { return (int)this.p; }
+ set { this.p = (object)value; }
+ }
+ };
+
+
+ /*
+ ** Tagged Values
+ */
+
+ //#define TValuefields Value value; int tt
+
+ public class lua_TValue : ArrayElement
+ {
+ private lua_TValue[] values = null;
+ private int index = -1;
+
+ public void set_index(int index)
+ {
+ this.index = index;
+ }
+
+ public void set_array(object array)
+ {
+ this.values = (lua_TValue[])array;
+ Debug.Assert(this.values != null);
+ }
+
+ public lua_TValue this[int offset]
+ {
+ get { return this.values[this.index + offset]; }
+ }
+
+ [CLSCompliantAttribute(false)]
+ public lua_TValue this[uint offset]
+ {
+ get { return this.values[this.index + (int)offset]; }
+ }
+
+ public static lua_TValue operator +(lua_TValue value, int offset)
+ {
+ return value.values[value.index + offset];
+ }
+
+ public static lua_TValue operator +(int offset, lua_TValue value)
+ {
+ return value.values[value.index + offset];
+ }
+
+ public static lua_TValue operator -(lua_TValue value, int offset)
+ {
+ return value.values[value.index - offset];
+ }
+
+ public static int operator -(lua_TValue value, lua_TValue[] array)
+ {
+ Debug.Assert(value.values == array);
+ return value.index;
+ }
+
+ public static int operator -(lua_TValue a, lua_TValue b)
+ {
+ Debug.Assert(a.values == b.values);
+ return a.index - b.index;
+ }
+
+ public static bool operator <(lua_TValue a, lua_TValue b)
+ {
+ Debug.Assert(a.values == b.values);
+ return a.index < b.index;
+ }
+
+ public static bool operator <=(lua_TValue a, lua_TValue b)
+ {
+ Debug.Assert(a.values == b.values);
+ return a.index <= b.index;
+ }
+
+ public static bool operator >(lua_TValue a, lua_TValue b)
+ {
+ Debug.Assert(a.values == b.values);
+ return a.index > b.index;
+ }
+
+ public static bool operator >=(lua_TValue a, lua_TValue b)
+ {
+ Debug.Assert(a.values == b.values);
+ return a.index >= b.index;
+ }
+
+ public static lua_TValue inc(ref lua_TValue value)
+ {
+ value = value[1];
+ return value[-1];
+ }
+
+ public static lua_TValue dec(ref lua_TValue value)
+ {
+ value = value[-1];
+ return value[1];
+ }
+
+ public static implicit operator int(lua_TValue value)
+ {
+ return value.index;
+ }
+
+ public lua_TValue()
+ {
+ }
+
+ public lua_TValue(lua_TValue copy)
+ {
+ this.values = copy.values;
+ this.index = copy.index;
+ this.value.Copy(copy.value);
+ this.tt = copy.tt;
+ }
+
+ public lua_TValue(Value value, int tt)
+ {
+ this.values = null;
+ this.index = 0;
+ this.value.Copy(value);
+ this.tt = tt;
+ }
+
+ public Value value = new Value();
+ public int tt;
+
+ public override string ToString()
+ {
+ string typename = null;
+ string val = null;
+ switch (tt)
+ {
+ case LUA_TNIL: typename = "LUA_TNIL"; val = string.Empty; break;
+ case LUA_TNUMBER: typename = "LUA_TNUMBER"; val = value.n.ToString(); break;
+ case LUA_TSTRING: typename = "LUA_TSTRING"; val = value.gc.ts.ToString(); break;
+ case LUA_TTABLE: typename = "LUA_TTABLE"; break;
+ case LUA_TFUNCTION: typename = "LUA_TFUNCTION"; break;
+ case LUA_TBOOLEAN: typename = "LUA_TBOOLEAN"; break;
+ case LUA_TUSERDATA: typename = "LUA_TUSERDATA"; break;
+ case LUA_TTHREAD: typename = "LUA_TTHREAD"; break;
+ case LUA_TLIGHTUSERDATA: typename = "LUA_TLIGHTUSERDATA"; break;
+ default: typename = "unknown"; break;
+ }
+ return string.Format("TValue<{0}>({1})", typename, val);
+ }
+ };
+
+ /* Macros to test type */
+ internal static bool ttisnil(TValue o) { return (ttype(o) == LUA_TNIL); }
+ internal static bool ttisnumber(TValue o) {return (ttype(o) == LUA_TNUMBER);}
+ internal static bool ttisstring(TValue o) {return (ttype(o) == LUA_TSTRING);}
+ internal static bool ttistable(TValue o) {return (ttype(o) == LUA_TTABLE);}
+ internal static bool ttisfunction(TValue o) {return (ttype(o) == LUA_TFUNCTION);}
+ internal static bool ttisboolean(TValue o) { return (ttype(o) == LUA_TBOOLEAN); }
+ internal static bool ttisuserdata(TValue o) { return (ttype(o) == LUA_TUSERDATA); }
+ internal static bool ttisthread(TValue o) {return (ttype(o) == LUA_TTHREAD);}
+ internal static bool ttislightuserdata(TValue o) { return (ttype(o) == LUA_TLIGHTUSERDATA); }
+
+ /* Macros to access values */
+#if DEBUG
+ internal static int ttype(TValue o) { return o.tt; }
+ internal static int ttype(CommonHeader o) { return o.tt; }
+ internal static GCObject gcvalue(TValue o) { return (GCObject)check_exp(iscollectable(o), o.value.gc); }
+ internal static object pvalue(TValue o) { return (object)check_exp(ttislightuserdata(o), o.value.p); }
+ internal static lua_Number nvalue(TValue o) { return (lua_Number)check_exp(ttisnumber(o), o.value.n); }
+ internal static TString rawtsvalue(TValue o) { return (TString)check_exp(ttisstring(o), o.value.gc.ts); }
+ internal static TString_tsv tsvalue(TValue o) { return rawtsvalue(o).tsv; }
+ internal static Udata rawuvalue(TValue o) { return (Udata)check_exp(ttisuserdata(o), o.value.gc.u); }
+ internal static Udata_uv uvalue(TValue o) { return rawuvalue(o).uv; }
+ internal static Closure clvalue(TValue o) { return (Closure)check_exp(ttisfunction(o), o.value.gc.cl); }
+ internal static Table hvalue(TValue o) { return (Table)check_exp(ttistable(o), o.value.gc.h); }
+ internal static int bvalue(TValue o) { return (int)check_exp(ttisboolean(o), o.value.b); }
+ internal static lua_State thvalue(TValue o) { return (lua_State)check_exp(ttisthread(o), o.value.gc.th); }
+#else
+ internal static int ttype(TValue o) { return o.tt; }
+ internal static int ttype(CommonHeader o) { return o.tt; }
+ internal static GCObject gcvalue(TValue o) { return o.value.gc; }
+ internal static object pvalue(TValue o) { return o.value.p; }
+ internal static lua_Number nvalue(TValue o) { return o.value.n; }
+ internal static TString rawtsvalue(TValue o) { return o.value.gc.ts; }
+ internal static TString_tsv tsvalue(TValue o) { return rawtsvalue(o).tsv; }
+ internal static Udata rawuvalue(TValue o) { return o.value.gc.u; }
+ internal static Udata_uv uvalue(TValue o) { return rawuvalue(o).uv; }
+ internal static Closure clvalue(TValue o) { return o.value.gc.cl; }
+ internal static Table hvalue(TValue o) { return o.value.gc.h; }
+ internal static int bvalue(TValue o) { return o.value.b; }
+ internal static lua_State thvalue(TValue o) { return (lua_State)check_exp(ttisthread(o), o.value.gc.th); }
+#endif
+
+ public static int l_isfalse(TValue o) { return ((ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))) ? 1 : 0; }
+
+ /*
+ ** for internal debug only
+ */
+ [Conditional("DEBUG")]
+ internal static void checkconsistency(TValue obj)
+ {
+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj).value.gc.gch.tt));
+ }
+
+ [Conditional("DEBUG")]
+ internal static void checkliveness(global_State g, TValue obj)
+ {
+ lua_assert(!iscollectable(obj) ||
+ ((ttype(obj) == obj.value.gc.gch.tt) && !isdead(g, obj.value.gc)));
+ }
+
+ /* Macros to set values */
+ internal static void setnilvalue(TValue obj) {
+ obj.tt=LUA_TNIL;
+ }
+
+ internal static void setnvalue(TValue obj, lua_Number x) {
+ obj.value.n = x;
+ obj.tt = LUA_TNUMBER;
+ }
+
+ internal static void setpvalue( TValue obj, object x) {
+ obj.value.p = x;
+ obj.tt = LUA_TLIGHTUSERDATA;
+ }
+
+ internal static void setbvalue(TValue obj, int x) {
+ obj.value.b = x;
+ obj.tt = LUA_TBOOLEAN;
+ }
+
+ internal static void setsvalue(lua_State L, TValue obj, GCObject x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TSTRING;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void setuvalue(lua_State L, TValue obj, GCObject x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TUSERDATA;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void setthvalue(lua_State L, TValue obj, GCObject x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TTHREAD;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void setclvalue(lua_State L, TValue obj, Closure x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TFUNCTION;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void sethvalue(lua_State L, TValue obj, Table x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TTABLE;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void setptvalue(lua_State L, TValue obj, Proto x) {
+ obj.value.gc = x;
+ obj.tt = LUA_TPROTO;
+ checkliveness(G(L), obj);
+ }
+
+ internal static void setobj(lua_State L, TValue obj1, TValue obj2) {
+ obj1.value.Copy(obj2.value);
+ obj1.tt = obj2.tt;
+ checkliveness(G(L), obj1);
+ }
+
+
+ /*
+ ** different types of sets, according to destination
+ */
+
+ /* from stack to (same) stack */
+ //#define setobjs2s setobj
+ internal static void setobjs2s(lua_State L, TValue obj, TValue x) { setobj(L, obj, x); }
+ ///* to stack (not from same stack) */
+
+ //#define setobj2s setobj
+ internal static void setobj2s(lua_State L, TValue obj, TValue x) { setobj(L, obj, x); }
+
+ //#define setsvalue2s setsvalue
+ internal static void setsvalue2s(lua_State L, TValue obj, TString x) { setsvalue(L, obj, x); }
+
+ //#define sethvalue2s sethvalue
+ internal static void sethvalue2s(lua_State L, TValue obj, Table x) { sethvalue(L, obj, x); }
+
+ //#define setptvalue2s setptvalue
+ internal static void setptvalue2s(lua_State L, TValue obj, Proto x) { setptvalue(L, obj, x); }
+
+ ///* from table to same table */
+ //#define setobjt2t setobj
+ internal static void setobjt2t(lua_State L, TValue obj, TValue x) { setobj(L, obj, x); }
+
+ ///* to table */
+ //#define setobj2t setobj
+ internal static void setobj2t(lua_State L, TValue obj, TValue x) { setobj(L, obj, x); }
+
+ ///* to new object */
+ //#define setobj2n setobj
+ internal static void setobj2n(lua_State L, TValue obj, TValue x) { setobj(L, obj, x); }
+
+ //#define setsvalue2n setsvalue
+ internal static void setsvalue2n(lua_State L, TValue obj, TString x) { setsvalue(L, obj, x); }
+
+ internal static void setttype(TValue obj, int tt) { obj.tt = tt; }
+
+
+ internal static bool iscollectable(TValue o) { return (ttype(o) >= LUA_TSTRING); }
+
+
+
+ //typedef TValue *StkId; /* index to stack elements */
+
+ /*
+ ** String headers for string table
+ */
+ public class TString_tsv : GCObject
+ {
+ public lu_byte reserved;
+ [CLSCompliantAttribute(false)]
+ public uint hash;
+ [CLSCompliantAttribute(false)]
+ public uint len;
+ };
+ public class TString : TString_tsv {
+ //public L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ public TString_tsv tsv { get { return this; } }
+
+ public TString()
+ {
+ }
+ public TString(CharPtr str) { this.str = str; }
+
+ public CharPtr str;
+
+ public override string ToString() { return str.ToString(); } // for debugging
+ };
+
+ public static CharPtr getstr(TString ts) { return ts.str; }
+ public static CharPtr svalue(StkId o) { return getstr(rawtsvalue(o)); }
+
+ public class Udata_uv : GCObject
+ {
+ public Table metatable;
+ public Table env;
+ [CLSCompliantAttribute(false)]
+ public uint len;
+ };
+
+ public class Udata : Udata_uv
+ {
+ public Udata() { this.uv = this; }
+
+ public new Udata_uv uv;
+
+ //public L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
+
+ // in the original C code this was allocated alongside the structure memory. it would probably
+ // be possible to still do that by allocating memory and pinning it down, but we can do the
+ // same thing just as easily by allocating a seperate byte array for it instead.
+ public object user_data;
+ };
+
+
+
+
+ /*
+ ** Function Prototypes
+ */
+ public class Proto : GCObject {
+
+ public Proto[] protos = null;
+ public int index = 0;
+ public Proto this[int offset] {get { return this.protos[this.index + offset]; }}
+
+ public TValue[] k; /* constants used by the function */
+ [CLSCompliantAttribute(false)]
+ public Instruction[] code;
+ public new Proto[] p; /* functions defined inside the function */
+ public int[] lineinfo; /* map from opcodes to source lines */
+ public LocVar[] locvars; /* information about local variables */
+ public TString[] upvalues; /* upvalue names */
+ public TString source;
+ public int sizeupvalues;
+ public int sizek; /* size of `k' */
+ public int sizecode;
+ public int sizelineinfo;
+ public int sizep; /* size of `p' */
+ public int sizelocvars;
+ public int linedefined;
+ public int lastlinedefined;
+ public GCObject gclist;
+ public lu_byte nups; /* number of upvalues */
+ public lu_byte numparams;
+ public lu_byte is_vararg;
+ public lu_byte maxstacksize;
+ };
+
+
+ /* masks for new-style vararg */
+ public const int VARARG_HASARG = 1;
+ public const int VARARG_ISVARARG = 2;
+ public const int VARARG_NEEDSARG = 4;
+
+ public class LocVar {
+ public TString varname;
+ public int startpc; /* first point where variable is active */
+ public int endpc; /* first point where variable is dead */
+ };
+
+
+
+ /*
+ ** Upvalues
+ */
+
+ public class UpVal : GCObject {
+ public TValue v; /* points to stack or to its own value */
+ [CLSCompliantAttribute(false)]
+ public class _u {
+ public TValue value = new TValue(); /* the value (when closed) */
+ [CLSCompliantAttribute(false)]
+ public class _l { /* double linked list (when open) */
+ public UpVal prev;
+ public UpVal next;
+ };
+
+ public _l l = new _l();
+ }
+ [CLSCompliantAttribute(false)]
+ public new _u u = new _u();
+ };
+
+
+ /*
+ ** Closures
+ */
+
+ public class ClosureHeader : GCObject {
+ public lu_byte isC;
+ public lu_byte nupvalues;
+ public GCObject gclist;
+ public Table env;
+ };
+
+ public class ClosureType {
+
+ ClosureHeader header;
+
+ public static implicit operator ClosureHeader(ClosureType ctype) {return ctype.header;}
+ public ClosureType(ClosureHeader header) {this.header = header;}
+
+ public lu_byte isC { get { return header.isC; } set { header.isC = value; } }
+ public lu_byte nupvalues { get { return header.nupvalues; } set { header.nupvalues = value; } }
+ public GCObject gclist { get { return header.gclist; } set { header.gclist = value; } }
+ public Table env { get { return header.env; } set { header.env = value; } }
+ }
+
+ public class CClosure : ClosureType {
+ public CClosure(ClosureHeader header) : base(header) { }
+ public lua_CFunction f;
+ public TValue[] upvalue;
+ };
+
+
+ public class LClosure : ClosureType {
+ public LClosure(ClosureHeader header) : base(header) { }
+ public Proto p;
+ public UpVal[] upvals;
+ };
+
+ public class Closure : ClosureHeader
+ {
+ public Closure()
+ {
+ c = new CClosure(this);
+ l = new LClosure(this);
+ }
+
+ public CClosure c;
+ public LClosure l;
+ };
+
+
+ public static bool iscfunction(TValue o) { return ((ttype(o) == LUA_TFUNCTION) && (clvalue(o).c.isC != 0)); }
+ public static bool isLfunction(TValue o) { return ((ttype(o) == LUA_TFUNCTION) && (clvalue(o).c.isC==0)); }
+
+
+ /*
+ ** Tables
+ */
+
+ public class TKey_nk : TValue
+ {
+ public TKey_nk() { }
+ public TKey_nk(Value value, int tt, Node next) : base(value, tt)
+ {
+ this.next = next;
+ }
+ public Node next; /* for chaining */
+ };
+
+ public class TKey {
+ public TKey()
+ {
+ this.nk = new TKey_nk();
+ }
+ public TKey(TKey copy)
+ {
+ this.nk = new TKey_nk(copy.nk.value, copy.nk.tt, copy.nk.next);
+ }
+ public TKey(Value value, int tt, Node next)
+ {
+ this.nk = new TKey_nk(value, tt, next);
+ }
+
+ public TKey_nk nk = new TKey_nk();
+ public TValue tvk { get { return this.nk; } }
+ };
+
+
+ public class Node : ArrayElement
+ {
+ private Node[] values = null;
+ private int index = -1;
+
+ public void set_index(int index)
+ {
+ this.index = index;
+ }
+
+ public void set_array(object array)
+ {
+ this.values = (Node[])array;
+ Debug.Assert(this.values != null);
+ }
+
+ public Node()
+ {
+ this.i_val = new TValue();
+ this.i_key = new TKey();
+ }
+
+ public Node(Node copy)
+ {
+ this.values = copy.values;
+ this.index = copy.index;
+ this.i_val = new TValue(copy.i_val);
+ this.i_key = new TKey(copy.i_key);
+ }
+
+ public Node(TValue i_val, TKey i_key)
+ {
+ this.values = new Node[] { this };
+ this.index = 0;
+ this.i_val = i_val;
+ this.i_key = i_key;
+ }
+
+ public TValue i_val;
+ public TKey i_key;
+
+ [CLSCompliantAttribute(false)]
+ public Node this[uint offset]
+ {
+ get { return this.values[this.index + (int)offset]; }
+ }
+
+ public Node this[int offset]
+ {
+ get { return this.values[this.index + offset]; }
+ }
+
+ public static int operator -(Node n1, Node n2)
+ {
+ Debug.Assert(n1.values == n2.values);
+ return n1.index - n2.index;
+ }
+
+ public static Node inc(ref Node node)
+ {
+ node = node[1];
+ return node[-1];
+ }
+
+ public static Node dec(ref Node node)
+ {
+ node = node[-1];
+ return node[1];
+ }
+
+ public static bool operator >(Node n1, Node n2) { Debug.Assert(n1.values == n2.values); return n1.index > n2.index; }
+ public static bool operator >=(Node n1, Node n2) { Debug.Assert(n1.values == n2.values); return n1.index >= n2.index; }
+ public static bool operator <(Node n1, Node n2) { Debug.Assert(n1.values == n2.values); return n1.index < n2.index; }
+ public static bool operator <=(Node n1, Node n2) { Debug.Assert(n1.values == n2.values); return n1.index <= n2.index; }
+ public static bool operator ==(Node n1, Node n2)
+ {
+ object o1 = n1 as Node;
+ object o2 = n2 as Node;
+ if ((o1 == null) && (o2 == null)) return true;
+ if (o1 == null) return false;
+ if (o2 == null) return false;
+ if (n1.values != n2.values) return false;
+ return n1.index == n2.index;
+ }
+ public static bool operator !=(Node n1, Node n2) { return !(n1==n2); }
+
+ public override bool Equals(object o) {return this == (Node)o;}
+ public override int GetHashCode() {return 0;}
+ };
+
+
+ public class Table : GCObject {
+ public lu_byte flags; /* 1<
= 16) {
+ x = (x+1) >> 1;
+ e++;
+ }
+ if (x < 8) return (int)x;
+ else return ((e+1) << 3) | (cast_int(x) - 8);
+ }
+
+
+ /* converts back */
+ public static int luaO_fb2int (int x) {
+ int e = (x >> 3) & 31;
+ if (e == 0) return x;
+ else return ((x & 7)+8) << (e - 1);
+ }
+
+
+ private readonly static lu_byte[] log_2 = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+
+ [CLSCompliantAttribute(false)]
+ public static int luaO_log2 (uint x) {
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
+ }
+
+
+ public static int luaO_rawequalObj (TValue t1, TValue t2) {
+ if (ttype(t1) != ttype(t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
+ case LUA_TNUMBER:
+ return luai_numeq(nvalue(t1), nvalue(t2)) ? 1 : 0;
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2) ? 1 : 0; /* boolean true must be 1....but not in C# !! */
+ case LUA_TLIGHTUSERDATA:
+ return pvalue(t1) == pvalue(t2) ? 1 : 0;
+ default:
+ lua_assert(iscollectable(t1));
+ return gcvalue(t1) == gcvalue(t2) ? 1 : 0;
+ }
+ }
+
+ public static int luaO_str2d (CharPtr s, out lua_Number result) {
+ CharPtr endptr;
+ result = lua_str2number(s, out endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ if (endptr[0] == 'x' || endptr[0] == 'X') /* maybe an hexadecimal constant? */
+ result = cast_num(strtoul(s, out endptr, 16));
+ if (endptr[0] == '\0') return 1; /* most common case */
+ while (isspace(endptr[0])) endptr = endptr.next();
+ if (endptr[0] != '\0') return 0; /* invalid trailing characters? */
+ return 1;
+ }
+
+
+
+ private static void pushstr (lua_State L, CharPtr str) {
+ setsvalue2s(L, L.top, luaS_new(L, str));
+ incr_top(L);
+ }
+
+
+ /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+ public static CharPtr luaO_pushvfstring (lua_State L, CharPtr fmt, params object[] argp) {
+ int parm_index = 0;
+ int n = 1;
+ pushstr(L, "");
+ for (;;) {
+ CharPtr e = strchr(fmt, '%');
+ if (e == null) break;
+ setsvalue2s(L, L.top, luaS_newlstr(L, fmt, (uint)(e-fmt)));
+ incr_top(L);
+ switch (e[1]) {
+ case 's': {
+ object o = argp[parm_index++];
+ CharPtr s = o as CharPtr;
+ if (s == null)
+ s = (string)o;
+ if (s == null) s = "(null)";
+ pushstr(L, s);
+ break;
+ }
+ case 'c': {
+ CharPtr buff = new char[2];
+ buff[0] = (char)(int)argp[parm_index++];
+ buff[1] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ case 'd': {
+ setnvalue(L.top, (int)argp[parm_index++]);
+ incr_top(L);
+ break;
+ }
+ case 'f': {
+ setnvalue(L.top, (l_uacNumber)argp[parm_index++]);
+ incr_top(L);
+ break;
+ }
+ case 'p': {
+ //CharPtr buff = new char[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ CharPtr buff = new char[32];
+ sprintf(buff, "0x%08x", argp[parm_index++].GetHashCode());
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
+ pushstr(L, "%");
+ break;
+ }
+ default: {
+ CharPtr buff = new char[3];
+ buff[0] = '%';
+ buff[1] = e[1];
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ }
+ n += 2;
+ fmt = e+2;
+ }
+ pushstr(L, fmt);
+ luaV_concat(L, n+1, cast_int(L.top - L.base_) - 1);
+ L.top -= n;
+ return svalue(L.top - 1);
+ }
+
+ public static CharPtr luaO_pushfstring(lua_State L, CharPtr fmt, params object[] args)
+ {
+ return luaO_pushvfstring(L, fmt, args);
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static void luaO_chunkid (CharPtr out_, CharPtr source, uint bufflen) {
+ //out_ = "";
+ if (source[0] == '=') {
+ strncpy(out_, source+1, (int)bufflen); /* remove first char */
+ out_[bufflen-1] = '\0'; /* ensures null termination */
+ }
+ else { /* out = "source", or "...source" */
+ if (source[0] == '@') {
+ uint l;
+ source = source.next(); /* skip the `@' */
+ bufflen -= (uint)(" '...' ".Length + 1);
+ l = (uint)strlen(source);
+ strcpy(out_, "");
+ if (l > bufflen) {
+ source += (l-bufflen); /* get last part of file name */
+ strcat(out_, "...");
+ }
+ strcat(out_, source);
+ }
+ else { /* out = [string "string"] */
+ uint len = strcspn(source, "\n\r"); /* stop at first newline */
+ bufflen -= (uint)(" [string \"...\"] ".Length + 1);
+ if (len > bufflen) len = bufflen;
+ strcpy(out_, "[string \"");
+ if (source[len] != '\0') { /* must truncate? */
+ strncat(out_, source, (int)len);
+ strcat(out_, "...");
+ }
+ else
+ strcat(out_, source);
+ strcat(out_, "\"]");
+ }
+ }
+ }
+
+ }
+}
diff --git a/Core/KopiLua/lopcodes.cs b/Core/KopiLua/lopcodes.cs
index 96f96415685d9292114998b69394a7d4e7046e04..0f240141bc5cdc21d4e1548127eea7e3f7d733e3 100644
--- a/Core/KopiLua/lopcodes.cs
+++ b/Core/KopiLua/lopcodes.cs
@@ -1,412 +1,412 @@
-/*
-** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
-** See Copyright Notice in lua.h
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace KopiLua
-{
- using lu_byte = System.Byte;
- using Instruction = System.UInt32;
-
- public partial class Lua
- {
- /*===========================================================================
- 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.
- ===========================================================================*/
-
-
- public enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
-
-
- /*
- ** size and position of opcode arguments.
- */
- public const int SIZE_C = 9;
- public const int SIZE_B = 9;
- public const int SIZE_Bx = (SIZE_C + SIZE_B);
- public const int SIZE_A = 8;
-
- public const int SIZE_OP = 6;
-
- public const int POS_OP = 0;
- public const int POS_A = (POS_OP + SIZE_OP);
- public const int POS_C = (POS_A + SIZE_A);
- public const int POS_B = (POS_C + SIZE_C);
- public const int 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
- public const int MAXARG_Bx = ((1<>1); /* `sBx' is signed */
- //#else
- //public const int MAXARG_Bx = System.Int32.MaxValue;
- //public const int MAXARG_sBx = System.Int32.MaxValue;
- //#endif
-
- [CLSCompliantAttribute(false)]
- public const uint MAXARG_A = (uint)((1 << (int)SIZE_A) -1);
- [CLSCompliantAttribute(false)]
- public const uint MAXARG_B = (uint)((1 << (int)SIZE_B) -1);
- [CLSCompliantAttribute(false)]
- public const uint MAXARG_C = (uint)((1 << (int)SIZE_C) -1);
-
-
- /* creates a mask with `n' 1 bits at position `p' */
- //public static int MASK1(int n, int p) { return ((~((~(Instruction)0) << n)) << p); }
- internal static uint MASK1(int n, int p) { return (uint)((~((~0) << n)) << p); }
-
- /* creates a mask with `n' 0 bits at position `p' */
- internal static uint MASK0(int n, int p) { return (uint)(~MASK1(n, p)); }
-
- /*
- ** the following macros help to manipulate instructions
- */
-
- internal static OpCode GET_OPCODE(Instruction i)
- {
- return (OpCode)((i >> POS_OP) & MASK1(SIZE_OP, 0));
- }
- internal static OpCode GET_OPCODE(InstructionPtr i) { return GET_OPCODE(i[0]); }
-
- internal static void SET_OPCODE(ref Instruction i, Instruction o)
- {
- i = (Instruction)(i & MASK0(SIZE_OP, POS_OP)) | ((o << POS_OP) & MASK1(SIZE_OP, POS_OP));
- }
- internal static void SET_OPCODE(ref Instruction i, OpCode opcode)
- {
- i = (Instruction)(i & MASK0(SIZE_OP, POS_OP)) | (((uint)opcode << POS_OP) & MASK1(SIZE_OP, POS_OP));
- }
- internal static void SET_OPCODE(InstructionPtr i, OpCode opcode) { SET_OPCODE(ref i.codes[i.pc], opcode); }
-
- internal static int GETARG_A(Instruction i)
- {
- return (int)((i >> POS_A) & MASK1(SIZE_A, 0));
- }
- internal static int GETARG_A(InstructionPtr i) { return GETARG_A(i[0]); }
-
- internal static void SETARG_A(InstructionPtr i, int u)
- {
- i[0] = (Instruction)((i[0] & MASK0(SIZE_A, POS_A)) | ((u << POS_A) & MASK1(SIZE_A, POS_A)));
- }
-
- internal static int GETARG_B(Instruction i)
- {
- return (int)((i>>POS_B) & MASK1(SIZE_B,0));
- }
- internal static int GETARG_B(InstructionPtr i) { return GETARG_B(i[0]); }
-
- internal static void SETARG_B(InstructionPtr i, int b)
- {
- i[0] = (Instruction)((i[0] & MASK0(SIZE_B, POS_B)) | ((b << POS_B) & MASK1(SIZE_B, POS_B)));
- }
-
- internal static int GETARG_C(Instruction i)
- {
- return (int)((i>>POS_C) & MASK1(SIZE_C,0));
- }
- internal static int GETARG_C(InstructionPtr i) { return GETARG_C(i[0]); }
-
- internal static void SETARG_C(InstructionPtr i, int b)
- {
- i[0] = (Instruction)((i[0] & MASK0(SIZE_C, POS_C)) | ((b << POS_C) & MASK1(SIZE_C, POS_C)));
- }
-
- internal static int GETARG_Bx(Instruction i)
- {
- return (int)((i>>POS_Bx) & MASK1(SIZE_Bx,0));
- }
- internal static int GETARG_Bx(InstructionPtr i) { return GETARG_Bx(i[0]); }
-
- internal static void SETARG_Bx(InstructionPtr i, int b)
- {
- i[0] = (Instruction)((i[0] & MASK0(SIZE_Bx, POS_Bx)) | ((b << POS_Bx) & MASK1(SIZE_Bx, POS_Bx)));
- }
-
- internal static int GETARG_sBx(Instruction i)
- {
- return (GETARG_Bx(i) - MAXARG_sBx);
- }
- internal static int GETARG_sBx(InstructionPtr i) { return GETARG_sBx(i[0]); }
-
- internal static void SETARG_sBx(InstructionPtr i, int b)
- {
- SETARG_Bx(i, b + MAXARG_sBx);
- }
-
- internal static int CREATE_ABC(OpCode o, int a, int b, int c)
- {
- return (int)(((int)o << POS_OP) | (a << POS_A) | (b << POS_B) | (c << POS_C));
- }
-
- internal static int CREATE_ABx(OpCode o, int a, int bc)
- {
- int result = (int)(((int)o << POS_OP) | (a << POS_A) | (bc << POS_Bx));
- return result;
- }
-
-
- /*
- ** Macros to operate RK indices
- */
-
- /* this bit 1 means constant (0 means register) */
- internal readonly static int BITRK = (1 << (SIZE_B - 1));
-
- /* test whether value is a constant */
- internal static int ISK(int x) { return x & BITRK; }
-
- /* gets the index of the constant */
- internal static int INDEXK(int r) { return r & (~BITRK); }
-
- internal static readonly int MAXINDEXRK = BITRK - 1;
-
- /* code a constant index as a RK value */
- internal static int RKASK(int x) { return x | BITRK; }
-
-
- /*
- ** invalid register that fits in 8 bits
- */
- internal static readonly int NO_REG = (int)MAXARG_A;
-
-
- /*
- ** R(x) - register
- ** Kst(x) - constant (in constant table)
- ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
- */
-
-
- /*
- ** grep "ORDER OP" if you change these enums
- */
-
- public enum OpCode {
- /*----------------------------------------------------------------------
- name args description
- ------------------------------------------------------------------------*/
- OP_MOVE,/* A B R(A) := R(B) */
- OP_LOADK,/* A Bx R(A) := Kst(Bx) */
- OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
- OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
- OP_GETUPVAL,/* A B R(A) := UpValue[B] */
-
- OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
- OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
-
- OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
- OP_SETUPVAL,/* A B UpValue[B] := R(A) */
- OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
-
- OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
-
- OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
-
- OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
- OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
- OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
- OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
- OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
- OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
- OP_UNM,/* A B R(A) := -R(B) */
- OP_NOT,/* A B R(A) := not R(B) */
- OP_LEN,/* A B R(A) := length of R(B) */
-
- OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
-
- OP_JMP,/* sBx pc+=sBx */
-
- OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
- OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
- OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
-
- OP_TEST,/* A C if not (R(A) <=> 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 */
- };
-
-
- public const int NUM_OPCODES = (int)OpCode.OP_VARARG;
-
-
-
- /*===========================================================================
- 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
- */
-
- public 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 */
- };
-
- public static OpMode getOpMode(OpCode m) {return (OpMode)(luaP_opmodes[(int)m] & 3);}
- public static OpArgMask getBMode(OpCode m) { return (OpArgMask)((luaP_opmodes[(int)m] >> 4) & 3); }
- public static OpArgMask getCMode(OpCode m) { return (OpArgMask)((luaP_opmodes[(int)m] >> 2) & 3); }
- public static int testAMode(OpCode m) { return luaP_opmodes[(int)m] & (1 << 6); }
- public static int testTMode(OpCode m) { return luaP_opmodes[(int)m] & (1 << 7); }
-
-
- /* number of list items to accumulate before a SETLIST instruction */
- public const int LFIELDS_PER_FLUSH = 50;
-
-
-
- /* ORDER OP */
-
- private readonly static CharPtr[] luaP_opnames = {
- "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",
- };
-
-
- private static lu_byte opmode(lu_byte t, lu_byte a, OpArgMask b, OpArgMask c, OpMode m)
- {
- return (lu_byte)(((t) << 7) | ((a) << 6) | (((lu_byte)b) << 4) | (((lu_byte)c) << 2) | ((lu_byte)m));
- }
-
- private readonly static lu_byte[] luaP_opmodes = {
- /* T A B C mode opcode */
- opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_MOVE */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_LOADK */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_LOADBOOL */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_LOADNIL */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_GETUPVAL */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_GETGLOBAL */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgK, OpMode.iABC) /* OP_GETTABLE */
- ,opmode(0, 0, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_SETGLOBAL */
- ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_SETUPVAL */
- ,opmode(0, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_SETTABLE */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_NEWTABLE */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgK, OpMode.iABC) /* OP_SELF */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_ADD */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_SUB */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_MUL */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_DIV */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_MOD */
- ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_POW */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_UNM */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_NOT */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_LEN */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgR, OpMode.iABC) /* OP_CONCAT */
- ,opmode(0, 0, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_JMP */
- ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_EQ */
- ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_LT */
- ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_LE */
- ,opmode(1, 1, OpArgMask.OpArgR, OpArgMask.OpArgU, OpMode.iABC) /* OP_TEST */
- ,opmode(1, 1, OpArgMask.OpArgR, OpArgMask.OpArgU, OpMode.iABC) /* OP_TESTSET */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_CALL */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_TAILCALL */
- ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_RETURN */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_FORLOOP */
- ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_FORPREP */
- ,opmode(1, 0, OpArgMask.OpArgN, OpArgMask.OpArgU, OpMode.iABC) /* OP_TFORLOOP */
- ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_SETLIST */
- ,opmode(0, 0, OpArgMask.OpArgN, OpArgMask.OpArgN, OpMode.iABC) /* OP_CLOSE */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABx) /* OP_CLOSURE */
- ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_VARARG */
- };
-
- }
-}
+/*
+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
+** See Copyright Notice in lua.h
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace KopiLua
+{
+ using lu_byte = System.Byte;
+ using Instruction = System.UInt32;
+
+ public partial class Lua
+ {
+ /*===========================================================================
+ 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.
+ ===========================================================================*/
+
+
+ public enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
+
+
+ /*
+ ** size and position of opcode arguments.
+ */
+ public const int SIZE_C = 9;
+ public const int SIZE_B = 9;
+ public const int SIZE_Bx = (SIZE_C + SIZE_B);
+ public const int SIZE_A = 8;
+
+ public const int SIZE_OP = 6;
+
+ public const int POS_OP = 0;
+ public const int POS_A = (POS_OP + SIZE_OP);
+ public const int POS_C = (POS_A + SIZE_A);
+ public const int POS_B = (POS_C + SIZE_C);
+ public const int 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
+ public const int MAXARG_Bx = ((1<>1); /* `sBx' is signed */
+ //#else
+ //public const int MAXARG_Bx = System.Int32.MaxValue;
+ //public const int MAXARG_sBx = System.Int32.MaxValue;
+ //#endif
+
+ [CLSCompliantAttribute(false)]
+ public const uint MAXARG_A = (uint)((1 << (int)SIZE_A) -1);
+ [CLSCompliantAttribute(false)]
+ public const uint MAXARG_B = (uint)((1 << (int)SIZE_B) -1);
+ [CLSCompliantAttribute(false)]
+ public const uint MAXARG_C = (uint)((1 << (int)SIZE_C) -1);
+
+
+ /* creates a mask with `n' 1 bits at position `p' */
+ //public static int MASK1(int n, int p) { return ((~((~(Instruction)0) << n)) << p); }
+ internal static uint MASK1(int n, int p) { return (uint)((~((~0) << n)) << p); }
+
+ /* creates a mask with `n' 0 bits at position `p' */
+ internal static uint MASK0(int n, int p) { return (uint)(~MASK1(n, p)); }
+
+ /*
+ ** the following macros help to manipulate instructions
+ */
+
+ internal static OpCode GET_OPCODE(Instruction i)
+ {
+ return (OpCode)((i >> POS_OP) & MASK1(SIZE_OP, 0));
+ }
+ internal static OpCode GET_OPCODE(InstructionPtr i) { return GET_OPCODE(i[0]); }
+
+ internal static void SET_OPCODE(ref Instruction i, Instruction o)
+ {
+ i = (Instruction)(i & MASK0(SIZE_OP, POS_OP)) | ((o << POS_OP) & MASK1(SIZE_OP, POS_OP));
+ }
+ internal static void SET_OPCODE(ref Instruction i, OpCode opcode)
+ {
+ i = (Instruction)(i & MASK0(SIZE_OP, POS_OP)) | (((uint)opcode << POS_OP) & MASK1(SIZE_OP, POS_OP));
+ }
+ internal static void SET_OPCODE(InstructionPtr i, OpCode opcode) { SET_OPCODE(ref i.codes[i.pc], opcode); }
+
+ internal static int GETARG_A(Instruction i)
+ {
+ return (int)((i >> POS_A) & MASK1(SIZE_A, 0));
+ }
+ internal static int GETARG_A(InstructionPtr i) { return GETARG_A(i[0]); }
+
+ internal static void SETARG_A(InstructionPtr i, int u)
+ {
+ i[0] = (Instruction)((i[0] & MASK0(SIZE_A, POS_A)) | ((u << POS_A) & MASK1(SIZE_A, POS_A)));
+ }
+
+ internal static int GETARG_B(Instruction i)
+ {
+ return (int)((i>>POS_B) & MASK1(SIZE_B,0));
+ }
+ internal static int GETARG_B(InstructionPtr i) { return GETARG_B(i[0]); }
+
+ internal static void SETARG_B(InstructionPtr i, int b)
+ {
+ i[0] = (Instruction)((i[0] & MASK0(SIZE_B, POS_B)) | ((b << POS_B) & MASK1(SIZE_B, POS_B)));
+ }
+
+ internal static int GETARG_C(Instruction i)
+ {
+ return (int)((i>>POS_C) & MASK1(SIZE_C,0));
+ }
+ internal static int GETARG_C(InstructionPtr i) { return GETARG_C(i[0]); }
+
+ internal static void SETARG_C(InstructionPtr i, int b)
+ {
+ i[0] = (Instruction)((i[0] & MASK0(SIZE_C, POS_C)) | ((b << POS_C) & MASK1(SIZE_C, POS_C)));
+ }
+
+ internal static int GETARG_Bx(Instruction i)
+ {
+ return (int)((i>>POS_Bx) & MASK1(SIZE_Bx,0));
+ }
+ internal static int GETARG_Bx(InstructionPtr i) { return GETARG_Bx(i[0]); }
+
+ internal static void SETARG_Bx(InstructionPtr i, int b)
+ {
+ i[0] = (Instruction)((i[0] & MASK0(SIZE_Bx, POS_Bx)) | ((b << POS_Bx) & MASK1(SIZE_Bx, POS_Bx)));
+ }
+
+ internal static int GETARG_sBx(Instruction i)
+ {
+ return (GETARG_Bx(i) - MAXARG_sBx);
+ }
+ internal static int GETARG_sBx(InstructionPtr i) { return GETARG_sBx(i[0]); }
+
+ internal static void SETARG_sBx(InstructionPtr i, int b)
+ {
+ SETARG_Bx(i, b + MAXARG_sBx);
+ }
+
+ internal static int CREATE_ABC(OpCode o, int a, int b, int c)
+ {
+ return (int)(((int)o << POS_OP) | (a << POS_A) | (b << POS_B) | (c << POS_C));
+ }
+
+ internal static int CREATE_ABx(OpCode o, int a, int bc)
+ {
+ int result = (int)(((int)o << POS_OP) | (a << POS_A) | (bc << POS_Bx));
+ return result;
+ }
+
+
+ /*
+ ** Macros to operate RK indices
+ */
+
+ /* this bit 1 means constant (0 means register) */
+ internal readonly static int BITRK = (1 << (SIZE_B - 1));
+
+ /* test whether value is a constant */
+ internal static int ISK(int x) { return x & BITRK; }
+
+ /* gets the index of the constant */
+ internal static int INDEXK(int r) { return r & (~BITRK); }
+
+ internal static readonly int MAXINDEXRK = BITRK - 1;
+
+ /* code a constant index as a RK value */
+ internal static int RKASK(int x) { return x | BITRK; }
+
+
+ /*
+ ** invalid register that fits in 8 bits
+ */
+ internal static readonly int NO_REG = (int)MAXARG_A;
+
+
+ /*
+ ** R(x) - register
+ ** Kst(x) - constant (in constant table)
+ ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+ */
+
+
+ /*
+ ** grep "ORDER OP" if you change these enums
+ */
+
+ public enum OpCode {
+ /*----------------------------------------------------------------------
+ name args description
+ ------------------------------------------------------------------------*/
+ OP_MOVE,/* A B R(A) := R(B) */
+ OP_LOADK,/* A Bx R(A) := Kst(Bx) */
+ OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
+ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
+ OP_GETUPVAL,/* A B R(A) := UpValue[B] */
+
+ OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
+ OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
+
+ OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
+ OP_SETUPVAL,/* A B UpValue[B] := R(A) */
+ OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
+
+ OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
+
+ OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
+
+ OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
+ OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
+ OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
+ OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+ OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
+ OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
+ OP_UNM,/* A B R(A) := -R(B) */
+ OP_NOT,/* A B R(A) := not R(B) */
+ OP_LEN,/* A B R(A) := length of R(B) */
+
+ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
+
+ OP_JMP,/* sBx pc+=sBx */
+
+ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
+ OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+ OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+
+ OP_TEST,/* A C if not (R(A) <=> 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 */
+ };
+
+
+ public const int NUM_OPCODES = (int)OpCode.OP_VARARG;
+
+
+
+ /*===========================================================================
+ 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
+ */
+
+ public 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 */
+ };
+
+ public static OpMode getOpMode(OpCode m) {return (OpMode)(luaP_opmodes[(int)m] & 3);}
+ public static OpArgMask getBMode(OpCode m) { return (OpArgMask)((luaP_opmodes[(int)m] >> 4) & 3); }
+ public static OpArgMask getCMode(OpCode m) { return (OpArgMask)((luaP_opmodes[(int)m] >> 2) & 3); }
+ public static int testAMode(OpCode m) { return luaP_opmodes[(int)m] & (1 << 6); }
+ public static int testTMode(OpCode m) { return luaP_opmodes[(int)m] & (1 << 7); }
+
+
+ /* number of list items to accumulate before a SETLIST instruction */
+ public const int LFIELDS_PER_FLUSH = 50;
+
+
+
+ /* ORDER OP */
+
+ private readonly static CharPtr[] luaP_opnames = {
+ "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",
+ };
+
+
+ private static lu_byte opmode(lu_byte t, lu_byte a, OpArgMask b, OpArgMask c, OpMode m)
+ {
+ return (lu_byte)(((t) << 7) | ((a) << 6) | (((lu_byte)b) << 4) | (((lu_byte)c) << 2) | ((lu_byte)m));
+ }
+
+ private readonly static lu_byte[] luaP_opmodes = {
+ /* T A B C mode opcode */
+ opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgK, OpMode.iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgMask.OpArgK, OpArgMask.OpArgN, OpMode.iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgK, OpMode.iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_MOD */
+ ,opmode(0, 1, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iABC) /* OP_LEN */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgR, OpMode.iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgMask.OpArgK, OpArgMask.OpArgK, OpMode.iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgMask.OpArgR, OpArgMask.OpArgU, OpMode.iABC) /* OP_TEST */
+ ,opmode(1, 1, OpArgMask.OpArgR, OpArgMask.OpArgU, OpMode.iABC) /* OP_TESTSET */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgMask.OpArgR, OpArgMask.OpArgN, OpMode.iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgMask.OpArgN, OpArgMask.OpArgU, OpMode.iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgMask.OpArgU, OpArgMask.OpArgU, OpMode.iABC) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgMask.OpArgN, OpArgMask.OpArgN, OpMode.iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgMask.OpArgU, OpArgMask.OpArgN, OpMode.iABC) /* OP_VARARG */
+ };
+
+ }
+}
diff --git a/Core/KopiLua/loslib.cs b/Core/KopiLua/loslib.cs
index 77a041a6bf43a9a59a6c00f9aa5b365deaf1a2da..888ae3b84016666a3d63e2162fa9c1c2256a1f83 100644
--- a/Core/KopiLua/loslib.cs
+++ b/Core/KopiLua/loslib.cs
@@ -1,277 +1,277 @@
-/*
-** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
-** Standard Operating System library
-** See Copyright Notice in lua.h
-*/
-
-using System;
-using System.Threading;
-using System.IO;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-
-namespace KopiLua
-{
- using TValue = Lua.lua_TValue;
- using StkId = Lua.lua_TValue;
- using lua_Integer = System.Int32;
- using lua_Number = System.Double;
-
- public partial class Lua
- {
- private static int os_pushresult (lua_State L, int i, CharPtr filename) {
- int en = errno(); /* calls to Lua API may change this value */
- if (i != 0) {
- lua_pushboolean(L, 1);
- return 1;
- }
- else {
- lua_pushnil(L);
- lua_pushfstring(L, "%s: %s", filename, strerror(en));
- lua_pushinteger(L, en);
- return 3;
- }
- }
-
-
- private static int os_execute (lua_State L) {
-#if XBOX || SILVERLIGHT
- luaL_error(L, "os_execute not supported on XBox360");
-#else
- CharPtr strCmdLine = "/C regenresx " + luaL_optstring(L, 1, null);
- System.Diagnostics.Process proc = new System.Diagnostics.Process();
- proc.EnableRaisingEvents=false;
- proc.StartInfo.FileName = "CMD.exe";
- proc.StartInfo.Arguments = strCmdLine.ToString();
- proc.Start();
- proc.WaitForExit();
- lua_pushinteger(L, proc.ExitCode);
-#endif
- return 1;
- }
-
-
- private static int os_remove (lua_State L) {
- CharPtr filename = luaL_checkstring(L, 1);
- int result = 1;
- try {File.Delete(filename.ToString());} catch {result = 0;}
- return os_pushresult(L, result, filename);
- }
-
-
- private static int os_rename (lua_State L) {
- CharPtr fromname = luaL_checkstring(L, 1);
- CharPtr toname = luaL_checkstring(L, 2);
- int result;
- try
- {
- File.Move(fromname.ToString(), toname.ToString());
- result = 0;
- }
- catch
- {
- result = 1; // todo: this should be a proper error code
- }
- return os_pushresult(L, result, fromname);
- }
-
-
- private static int os_tmpname (lua_State L) {
-#if XBOX
- luaL_error(L, "os_tmpname not supported on Xbox360");
-#else
- lua_pushstring(L, Path.GetTempFileName());
-#endif
- return 1;
- }
-
-
- private static int os_getenv (lua_State L) {
- lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if null push nil */
- return 1;
- }
-
-
- private static int os_clock (lua_State L) {
- long ticks = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
- lua_pushnumber(L, ((lua_Number)ticks)/(lua_Number)1000);
- return 1;
- }
-
-
- /*
- ** {======================================================
- ** Time/Date operations
- ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
- ** wday=%w+1, yday=%j, isdst=? }
- ** =======================================================
- */
-
- private static void setfield (lua_State L, CharPtr key, int value) {
- lua_pushinteger(L, value);
- lua_setfield(L, -2, key);
- }
-
- private static void setboolfield (lua_State L, CharPtr key, int value) {
- if (value < 0) /* undefined? */
- return; /* does not set field */
- lua_pushboolean(L, value);
- lua_setfield(L, -2, key);
- }
-
- private static int getboolfield (lua_State L, CharPtr key) {
- int res;
- lua_getfield(L, -1, key);
- res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
- lua_pop(L, 1);
- return res;
- }
-
- private static int getfield (lua_State L, CharPtr key, int d) {
- int res;
- lua_getfield(L, -1, key);
- if (lua_isnumber(L, -1) != 0)
- res = (int)lua_tointeger(L, -1);
- else {
- if (d < 0)
- return luaL_error(L, "field " + LUA_QS + " missing in date table", key);
- res = d;
- }
- lua_pop(L, 1);
- return res;
- }
-
-
- private static int os_date (lua_State L) {
- CharPtr s = luaL_optstring(L, 1, "%c");
- DateTime stm;
- if (s[0] == '!') { /* UTC? */
- stm = DateTime.UtcNow;
- s.inc(); /* skip `!' */
- }
- else
- stm = DateTime.Now;
- if (strcmp(s, "*t") == 0) {
- lua_createtable(L, 0, 9); /* 9 = number of fields */
- setfield(L, "sec", stm.Second);
- setfield(L, "min", stm.Minute);
- setfield(L, "hour", stm.Hour);
- setfield(L, "day", stm.Day);
- setfield(L, "month", stm.Month);
- setfield(L, "year", stm.Year);
- setfield(L, "wday", (int)stm.DayOfWeek);
- setfield(L, "yday", stm.DayOfYear);
- setboolfield(L, "isdst", stm.IsDaylightSavingTime() ? 1 : 0);
- }
- else {
- luaL_error(L, "strftime not implemented yet"); // todo: implement this - mjf
-#if false
- CharPtr cc = new char[3];
- luaL_Buffer b;
- cc[0] = '%'; cc[2] = '\0';
- luaL_buffinit(L, b);
- for (; s[0] != 0; s.inc()) {
- if (s[0] != '%' || s[1] == '\0') /* no conversion specifier? */
- luaL_addchar(b, s[0]);
- else {
- uint reslen;
- CharPtr buff = new char[200]; /* should be big enough for any conversion result */
- s.inc();
- cc[1] = s[0];
- reslen = strftime(buff, buff.Length, cc, stm);
- luaL_addlstring(b, buff, reslen);
- }
- }
- luaL_pushresult(b);
-#endif // #if 0
- }
- return 1;
- }
-
-
- private static int os_time (lua_State L) {
- DateTime t;
- if (lua_isnoneornil(L, 1)) /* called without args? */
- t = DateTime.Now; /* get current time */
- else {
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_settop(L, 1); /* make sure table is at the top */
- int sec = getfield(L, "sec", 0);
- int min = getfield(L, "min", 0);
- int hour = getfield(L, "hour", 12);
- int day = getfield(L, "day", -1);
- int month = getfield(L, "month", -1) - 1;
- int year = getfield(L, "year", -1) - 1900;
- /*int isdst = */getboolfield(L, "isdst"); // todo: implement this - mjf
- t = new DateTime(year, month, day, hour, min, sec);
- }
- lua_pushnumber(L, t.Ticks);
- return 1;
- }
-
-
- private static int os_difftime (lua_State L) {
- long ticks = (long)luaL_checknumber(L, 1) - (long)luaL_optnumber(L, 2, 0);
- lua_pushnumber(L, ticks/TimeSpan.TicksPerSecond);
- return 1;
- }
-
- /* }====================================================== */
-
- // locale not supported yet
- private static int os_setlocale (lua_State L) {
- /*
- static string[] cat = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
- LC_NUMERIC, LC_TIME};
- static string[] catnames[] = {"all", "collate", "ctype", "monetary",
- "numeric", "time", null};
- CharPtr l = luaL_optstring(L, 1, null);
- int op = luaL_checkoption(L, 2, "all", catnames);
- lua_pushstring(L, setlocale(cat[op], l));
- */
- CharPtr l = luaL_optstring(L, 1, null);
- lua_pushstring(L, "C");
- return (l.ToString() == "C") ? 1 : 0;
- }
-
-
- private static int os_exit (lua_State L) {
-#if XBOX
- luaL_error(L, "os_exit not supported on XBox360");
-#else
-#if SILVERLIGHT
- throw new SystemException();
-#else
- Environment.Exit(EXIT_SUCCESS);
-#endif
-#endif
- return 0;
- }
-
- private readonly static luaL_Reg[] syslib = {
- new luaL_Reg("clock", os_clock),
- new luaL_Reg("date", os_date),
- new luaL_Reg("difftime", os_difftime),
- new luaL_Reg("execute", os_execute),
- new luaL_Reg("exit", os_exit),
- new luaL_Reg("getenv", os_getenv),
- new luaL_Reg("remove", os_remove),
- new luaL_Reg("rename", os_rename),
- new luaL_Reg("setlocale", os_setlocale),
- new luaL_Reg("time", os_time),
- new luaL_Reg("tmpname", os_tmpname),
- new luaL_Reg(null, null)
- };
-
- /* }====================================================== */
-
-
-
- public static int luaopen_os (lua_State L) {
- luaL_register(L, LUA_OSLIBNAME, syslib);
- return 1;
- }
-
- }
-}
+/*
+** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+using System;
+using System.Threading;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace KopiLua
+{
+ using TValue = Lua.lua_TValue;
+ using StkId = Lua.lua_TValue;
+ using lua_Integer = System.Int32;
+ using lua_Number = System.Double;
+
+ public partial class Lua
+ {
+ private static int os_pushresult (lua_State L, int i, CharPtr filename) {
+ int en = errno(); /* calls to Lua API may change this value */
+ if (i != 0) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+ }
+
+
+ private static int os_execute (lua_State L) {
+#if XBOX || SILVERLIGHT
+ luaL_error(L, "os_execute not supported on XBox360");
+#else
+ CharPtr strCmdLine = "/C regenresx " + luaL_optstring(L, 1, null);
+ System.Diagnostics.Process proc = new System.Diagnostics.Process();
+ proc.EnableRaisingEvents=false;
+ proc.StartInfo.FileName = "CMD.exe";
+ proc.StartInfo.Arguments = strCmdLine.ToString();
+ proc.Start();
+ proc.WaitForExit();
+ lua_pushinteger(L, proc.ExitCode);
+#endif
+ return 1;
+ }
+
+
+ private static int os_remove (lua_State L) {
+ CharPtr filename = luaL_checkstring(L, 1);
+ int result = 1;
+ try {File.Delete(filename.ToString());} catch {result = 0;}
+ return os_pushresult(L, result, filename);
+ }
+
+
+ private static int os_rename (lua_State L) {
+ CharPtr fromname = luaL_checkstring(L, 1);
+ CharPtr toname = luaL_checkstring(L, 2);
+ int result;
+ try
+ {
+ File.Move(fromname.ToString(), toname.ToString());
+ result = 0;
+ }
+ catch
+ {
+ result = 1; // todo: this should be a proper error code
+ }
+ return os_pushresult(L, result, fromname);
+ }
+
+
+ private static int os_tmpname (lua_State L) {
+#if XBOX
+ luaL_error(L, "os_tmpname not supported on Xbox360");
+#else
+ lua_pushstring(L, Path.GetTempFileName());
+#endif
+ return 1;
+ }
+
+
+ private static int os_getenv (lua_State L) {
+ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if null push nil */
+ return 1;
+ }
+
+
+ private static int os_clock (lua_State L) {
+ long ticks = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
+ lua_pushnumber(L, ((lua_Number)ticks)/(lua_Number)1000);
+ return 1;
+ }
+
+
+ /*
+ ** {======================================================
+ ** Time/Date operations
+ ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+ ** wday=%w+1, yday=%j, isdst=? }
+ ** =======================================================
+ */
+
+ private static void setfield (lua_State L, CharPtr key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+ }
+
+ private static void setboolfield (lua_State L, CharPtr key, int value) {
+ if (value < 0) /* undefined? */
+ return; /* does not set field */
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, key);
+ }
+
+ private static int getboolfield (lua_State L, CharPtr key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+ }
+
+ private static int getfield (lua_State L, CharPtr key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1) != 0)
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field " + LUA_QS + " missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+ }
+
+
+ private static int os_date (lua_State L) {
+ CharPtr s = luaL_optstring(L, 1, "%c");
+ DateTime stm;
+ if (s[0] == '!') { /* UTC? */
+ stm = DateTime.UtcNow;
+ s.inc(); /* skip `!' */
+ }
+ else
+ stm = DateTime.Now;
+ if (strcmp(s, "*t") == 0) {
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
+ setfield(L, "sec", stm.Second);
+ setfield(L, "min", stm.Minute);
+ setfield(L, "hour", stm.Hour);
+ setfield(L, "day", stm.Day);
+ setfield(L, "month", stm.Month);
+ setfield(L, "year", stm.Year);
+ setfield(L, "wday", (int)stm.DayOfWeek);
+ setfield(L, "yday", stm.DayOfYear);
+ setboolfield(L, "isdst", stm.IsDaylightSavingTime() ? 1 : 0);
+ }
+ else {
+ luaL_error(L, "strftime not implemented yet"); // todo: implement this - mjf
+#if false
+ CharPtr cc = new char[3];
+ luaL_Buffer b;
+ cc[0] = '%'; cc[2] = '\0';
+ luaL_buffinit(L, b);
+ for (; s[0] != 0; s.inc()) {
+ if (s[0] != '%' || s[1] == '\0') /* no conversion specifier? */
+ luaL_addchar(b, s[0]);
+ else {
+ uint reslen;
+ CharPtr buff = new char[200]; /* should be big enough for any conversion result */
+ s.inc();
+ cc[1] = s[0];
+ reslen = strftime(buff, buff.Length, cc, stm);
+ luaL_addlstring(b, buff, reslen);
+ }
+ }
+ luaL_pushresult(b);
+#endif // #if 0
+ }
+ return 1;
+ }
+
+
+ private static int os_time (lua_State L) {
+ DateTime t;
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = DateTime.Now; /* get current time */
+ else {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1); /* make sure table is at the top */
+ int sec = getfield(L, "sec", 0);
+ int min = getfield(L, "min", 0);
+ int hour = getfield(L, "hour", 12);
+ int day = getfield(L, "day", -1);
+ int month = getfield(L, "month", -1) - 1;
+ int year = getfield(L, "year", -1) - 1900;
+ /*int isdst = */getboolfield(L, "isdst"); // todo: implement this - mjf
+ t = new DateTime(year, month, day, hour, min, sec);
+ }
+ lua_pushnumber(L, t.Ticks);
+ return 1;
+ }
+
+
+ private static int os_difftime (lua_State L) {
+ long ticks = (long)luaL_checknumber(L, 1) - (long)luaL_optnumber(L, 2, 0);
+ lua_pushnumber(L, ticks/TimeSpan.TicksPerSecond);
+ return 1;
+ }
+
+ /* }====================================================== */
+
+ // locale not supported yet
+ private static int os_setlocale (lua_State L) {
+ /*
+ static string[] cat = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+ LC_NUMERIC, LC_TIME};
+ static string[] catnames[] = {"all", "collate", "ctype", "monetary",
+ "numeric", "time", null};
+ CharPtr l = luaL_optstring(L, 1, null);
+ int op = luaL_checkoption(L, 2, "all", catnames);
+ lua_pushstring(L, setlocale(cat[op], l));
+ */
+ CharPtr l = luaL_optstring(L, 1, null);
+ lua_pushstring(L, "C");
+ return (l.ToString() == "C") ? 1 : 0;
+ }
+
+
+ private static int os_exit (lua_State L) {
+#if XBOX
+ luaL_error(L, "os_exit not supported on XBox360");
+#else
+#if SILVERLIGHT
+ throw new SystemException();
+#else
+ Environment.Exit(EXIT_SUCCESS);
+#endif
+#endif
+ return 0;
+ }
+
+ private readonly static luaL_Reg[] syslib = {
+ new luaL_Reg("clock", os_clock),
+ new luaL_Reg("date", os_date),
+ new luaL_Reg("difftime", os_difftime),
+ new luaL_Reg("execute", os_execute),
+ new luaL_Reg("exit", os_exit),
+ new luaL_Reg("getenv", os_getenv),
+ new luaL_Reg("remove", os_remove),
+ new luaL_Reg("rename", os_rename),
+ new luaL_Reg("setlocale", os_setlocale),
+ new luaL_Reg("time", os_time),
+ new luaL_Reg("tmpname", os_tmpname),
+ new luaL_Reg(null, null)
+ };
+
+ /* }====================================================== */
+
+
+
+ public static int luaopen_os (lua_State L) {
+ luaL_register(L, LUA_OSLIBNAME, syslib);
+ return 1;
+ }
+
+ }
+}
diff --git a/Core/KopiLua/lparser.cs b/Core/KopiLua/lparser.cs
index 45bd28a30dfe5deac7bcb13f0a36bf7941de26ee..7e4cd3cab60967027ebd5570c7d5b0b0f1f94ed6 100644
--- a/Core/KopiLua/lparser.cs
+++ b/Core/KopiLua/lparser.cs
@@ -1,1458 +1,1458 @@
-/*
-** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
-** Lua Parser
-** See Copyright Notice in lua.h
-*/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-
-namespace KopiLua
-{
- using lu_byte = System.Byte;
- using lua_Number = System.Double;
- using ZIO = Lua.Zio;
-
- public partial class Lua
- {
- /*
- ** Expression descriptor
- */
-
- public enum expkind {
- 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 */
- };
-
-
-
- public class expdesc {
-
- public void Copy(expdesc e)
- {
- this.k = e.k;
- this.u.Copy(e.u);
- this.t = e.t;
- this.f = e.f;
- }
-
- public expkind k;
-
- [CLSCompliantAttribute(false)]
- public class _u
- {
- public void Copy(_u u)
- {
- this.s.Copy(u.s);
- this.nval = u.nval;
- }
-
- [CLSCompliantAttribute(false)]
- public class _s
- {
- public void Copy(_s s)
- {
- this.info = s.info;
- this.aux = s.aux;
- }
- public int info, aux;
- };
- public _s s = new _s();
- public lua_Number nval;
- };
-
- [CLSCompliantAttribute(false)]
- public _u u = new _u();
-
- public int t; /* patch list of `exit when true' */
- public int f; /* patch list of `exit when false' */
- };
-
-
- public class upvaldesc {
- public lu_byte k;
- public lu_byte info;
- };
-
-
- /* state needed to generate code for a given function */
- public class FuncState {
- public FuncState()
- {
- for (int i=0; i (l)) errorlimit(fs, l, m); }
-
-
- /*
- ** nodes for block list (list of active blocks)
- */
- public class BlockCnt {
- public BlockCnt previous; /* chain */
- public int breaklist; /* list of jumps out of this loop */
- public lu_byte nactvar; /* # active locals outside the breakable structure */
- public lu_byte upval; /* true if some variable in the block is an upvalue */
- public lu_byte isbreakable; /* true if `block' is a loop */
- };
-
-
-
- private static void anchor_token (LexState ls) {
- if (ls.t.token == (int)RESERVED.TK_NAME || ls.t.token == (int)RESERVED.TK_STRING) {
- TString ts = ls.t.seminfo.ts;
- luaX_newstring(ls, getstr(ts), ts.tsv.len);
- }
- }
-
-
- private static void error_expected (LexState ls, int token) {
- luaX_syntaxerror(ls,
- luaO_pushfstring(ls.L, LUA_QS + " expected", luaX_token2str(ls, token)));
- }
-
-
- private static void errorlimit (FuncState fs, int limit, CharPtr what) {
- CharPtr 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);
- }
-
-
- private static int testnext (LexState ls, int c) {
- if (ls.t.token == c) {
- luaX_next(ls);
- return 1;
- }
- else return 0;
- }
-
-
- private static void check (LexState ls, int c) {
- if (ls.t.token != c)
- error_expected(ls, c);
- }
-
- private static void checknext (LexState ls, int c) {
- check(ls, c);
- luaX_next(ls);
- }
-
-
- public static void check_condition(LexState ls, bool c, CharPtr msg) {
- if (!(c)) luaX_syntaxerror(ls, msg);
- }
-
- private static void check_match (LexState ls, int what, int who, int where) {
- if (testnext(ls, what)==0) {
- 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));
- }
- }
- }
-
- private static TString str_checkname (LexState ls) {
- TString ts;
- check(ls, (int)RESERVED.TK_NAME);
- ts = ls.t.seminfo.ts;
- luaX_next(ls);
- return ts;
- }
-
-
- private static void init_exp (expdesc e, expkind k, int i) {
- e.f = e.t = NO_JUMP;
- e.k = k;
- e.u.s.info = i;
- }
-
-
- private static void codestring (LexState ls, expdesc e, TString s) {
- init_exp(e, expkind.VK, luaK_stringK(ls.fs, s));
- }
-
-
- private static void checkname(LexState ls, expdesc e) {
- codestring(ls, e, str_checkname(ls));
- }
-
-
- private static int registerlocalvar (LexState ls, TString varname) {
- FuncState fs = ls.fs;
- Proto f = fs.f;
- int oldsize = f.sizelocvars;
- luaM_growvector(ls.L, ref f.locvars, fs.nlocvars, ref f.sizelocvars,
- (int)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++;
- }
-
-
- public static void new_localvarliteral(LexState ls, CharPtr v, int n) {
- new_localvar(ls, luaX_newstring(ls, "" + v, (uint)(v.chars.Length - 1)), n);
- }
-
-
- private 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] = (ushort)registerlocalvar(ls, name);
- }
-
-
- private static void adjustlocalvars (LexState ls, int nvars) {
- FuncState fs = ls.fs;
- fs.nactvar = cast_byte(fs.nactvar + nvars);
- for (; nvars!=0; nvars--) {
- getlocvar(fs, fs.nactvar - nvars).startpc = fs.pc;
- }
- }
-
-
- private static void removevars (LexState ls, int tolevel) {
- FuncState fs = ls.fs;
- while (fs.nactvar > tolevel)
- getlocvar(fs, --fs.nactvar).endpc = fs.pc;
- }
-
-
- private static int indexupvalue (FuncState fs, TString name, expdesc v) {
- int i;
- Proto f = fs.f;
- int oldsize = f.sizeupvalues;
- for (i=0; i= 0; i--) {
- if (n == getlocvar(fs, i).varname)
- return i;
- }
- return -1; /* not found */
- }
-
-
- private static void markupval (FuncState fs, int level) {
- BlockCnt bl = fs.bl;
- while ((bl!=null) && bl.nactvar > level) bl = bl.previous;
- if (bl != null) bl.upval = 1;
- }
-
-
- private static expkind singlevaraux(FuncState fs, TString n, expdesc var, int base_)
- {
- if (fs == null) { /* no more levels? */
- init_exp(var, expkind.VGLOBAL, NO_REG); /* default is global variable */
- return expkind.VGLOBAL;
- }
- else {
- int v = searchvar(fs, n); /* look up at current level */
- if (v >= 0) {
- init_exp(var, expkind.VLOCAL, v);
- if (base_==0)
- markupval(fs, v); /* local will be used as an upval */
- return expkind.VLOCAL;
- }
- else { /* not found at current level; try upper one */
- if (singlevaraux(fs.prev, n, var, 0) == expkind.VGLOBAL)
- return expkind.VGLOBAL;
- var.u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
- var.k = expkind.VUPVAL; /* upvalue in this level */
- return expkind.VUPVAL;
- }
- }
- }
-
-
- private static void singlevar (LexState ls, expdesc var) {
- TString varname = str_checkname(ls);
- FuncState fs = ls.fs;
- if (singlevaraux(fs, varname, var, 1) == expkind.VGLOBAL)
- var.u.s.info = luaK_stringK(fs, varname); /* info points to global name */
- }
-
-
- private static void adjust_assign (LexState ls, int nvars, int nexps, expdesc e) {
- FuncState fs = ls.fs;
- int extra = nvars - nexps;
- if (hasmultret(e.k) != 0) {
- 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 != expkind.VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
- if (extra > 0) {
- int reg = fs.freereg;
- luaK_reserveregs(fs, extra);
- luaK_nil(fs, reg, extra);
- }
- }
- }
-
-
- private static void enterlevel (LexState ls) {
- if (++ls.L.nCcalls > LUAI_MAXCCALLS)
- luaX_lexerror(ls, "chunk has too many syntax levels", 0);
- }
-
-
- private static void leavelevel(LexState ls) { ls.L.nCcalls--; }
-
-
- private 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);
- }
-
-
- private static void leaveblock (FuncState fs) {
- BlockCnt bl = fs.bl;
- fs.bl = bl.previous;
- removevars(fs.ls, bl.nactvar);
- if (bl.upval != 0)
- luaK_codeABC(fs, OpCode.OP_CLOSE, bl.nactvar, 0, 0);
- /* a block either controls scope or breaks (never both) */
- lua_assert((bl.isbreakable==0) || (bl.upval==0));
- lua_assert(bl.nactvar == fs.nactvar);
- fs.freereg = fs.nactvar; /* free registers */
- luaK_patchtohere(fs, bl.breaklist);
- }
-
-
- private 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, ref f.p, fs.np, ref f.sizep,
- 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, expkind.VRELOCABLE, luaK_codeABx(fs, OpCode.OP_CLOSURE, 0, fs.np - 1));
- for (i=0; i 0);
- if (ls.t.token == '}') break;
- closelistfield(fs, cc);
- switch(ls.t.token) {
- case (int)RESERVED.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, ',')!=0) || (testnext(ls, ';')!=0));
- check_match(ls, '}', '{', line);
- lastlistfield(fs, cc);
- SETARG_B(new InstructionPtr(fs.f.code, pc), luaO_int2fb((uint)cc.na)); /* set initial array size */
- SETARG_C(new InstructionPtr(fs.f.code, pc), luaO_int2fb((uint)cc.nh)); /* set initial table size */
- }
-
- /* }====================================================================== */
-
-
-
- private 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 (int)RESERVED.TK_NAME: { /* param . NAME */
- new_localvar(ls, str_checkname(ls), nparams++);
- break;
- }
- case (int)RESERVED.TK_DOTS: { /* param . `...' */
- luaX_next(ls);
- #if 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"); break;
- }
- } while ((f.is_vararg==0) && (testnext(ls, ',')!=0));
- }
- adjustlocalvars(ls, nparams);
- f.numparams = cast_byte(fs.nactvar - (f.is_vararg & VARARG_HASARG));
- luaK_reserveregs(fs, fs.nactvar); /* reserve register for parameters */
- }
-
-
- private static void body (LexState ls, expdesc e, int needself, int line) {
- /* body . `(' parlist `)' chunk END */
- FuncState new_fs = new FuncState();
- open_func(ls, new_fs);
- new_fs.f.linedefined = line;
- checknext(ls, '(');
- if (needself != 0) {
- new_localvarliteral(ls, "self", 0);
- adjustlocalvars(ls, 1);
- }
- parlist(ls);
- checknext(ls, ')');
- chunk(ls);
- new_fs.f.lastlinedefined = ls.linenumber;
- check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_FUNCTION, line);
- close_func(ls);
- pushclosure(ls, new_fs, e);
- }
-
-
- private static int explist1 (LexState ls, expdesc v) {
- /* explist1 . expr { `,' expr } */
- int n = 1; /* at least one expression */
- expr(ls, v);
- while (testnext(ls, ',') != 0) {
- luaK_exp2nextreg(ls.fs, v);
- expr(ls, v);
- n++;
- }
- return n;
- }
-
-
- private static void funcargs (LexState ls, expdesc f) {
- FuncState fs = ls.fs;
- expdesc args = new expdesc();
- 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 = expkind.VVOID;
- else {
- explist1(ls, args);
- luaK_setmultret(fs, args);
- }
- check_match(ls, ')', '(', line);
- break;
- }
- case '{': { /* funcargs . constructor */
- constructor(ls, args);
- break;
- }
- case (int)RESERVED.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 == expkind.VNONRELOC);
- base_ = f.u.s.info; /* base_ register for call */
- if (hasmultret(args.k) != 0)
- nparams = LUA_MULTRET; /* open call */
- else {
- if (args.k != expkind.VVOID)
- luaK_exp2nextreg(fs, args); /* close last argument */
- nparams = fs.freereg - (base_+1);
- }
- init_exp(f, expkind.VCALL, luaK_codeABC(fs, OpCode.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
- ** =======================================================================
- */
-
-
- private 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 (int)RESERVED.TK_NAME: {
- singlevar(ls, v);
- return;
- }
- default: {
- luaX_syntaxerror(ls, "unexpected symbol");
- return;
- }
- }
- }
-
- private 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 = new expdesc();
- luaK_exp2anyreg(fs, v);
- yindex(ls, key);
- luaK_indexed(fs, v, key);
- break;
- }
- case ':': { /* `:' NAME funcargs */
- expdesc key = new expdesc();
- luaX_next(ls);
- checkname(ls, key);
- luaK_self(fs, v, key);
- funcargs(ls, v);
- break;
- }
- case '(': case (int)RESERVED.TK_STRING: case '{': { /* funcargs */
- luaK_exp2nextreg(fs, v);
- funcargs(ls, v);
- break;
- }
- default: return;
- }
- }
- }
-
-
- private static void simpleexp (LexState ls, expdesc v) {
- /* simpleexp . NUMBER | STRING | NIL | true | false | ... |
- constructor | FUNCTION body | primaryexp */
- switch (ls.t.token) {
- case (int)RESERVED.TK_NUMBER: {
- init_exp(v, expkind.VKNUM, 0);
- v.u.nval = ls.t.seminfo.r;
- break;
- }
- case (int)RESERVED.TK_STRING: {
- codestring(ls, v, ls.t.seminfo.ts);
- break;
- }
- case (int)RESERVED.TK_NIL: {
- init_exp(v, expkind.VNIL, 0);
- break;
- }
- case (int)RESERVED.TK_TRUE: {
- init_exp(v, expkind.VTRUE, 0);
- break;
- }
- case (int)RESERVED.TK_FALSE: {
- init_exp(v, expkind.VFALSE, 0);
- break;
- }
- case (int)RESERVED.TK_DOTS: { /* vararg */
- FuncState fs = ls.fs;
- check_condition(ls, fs.f.is_vararg!=0,
- "cannot use " + LUA_QL("...") + " outside a vararg function");
- fs.f.is_vararg &= unchecked((lu_byte)(~VARARG_NEEDSARG)); /* don't need 'arg' */
- init_exp(v, expkind.VVARARG, luaK_codeABC(fs, OpCode.OP_VARARG, 0, 1, 0));
- break;
- }
- case '{': { /* constructor */
- constructor(ls, v);
- return;
- }
- case (int)RESERVED.TK_FUNCTION: {
- luaX_next(ls);
- body(ls, v, 0, ls.linenumber);
- return;
- }
- default: {
- primaryexp(ls, v);
- return;
- }
- }
- luaX_next(ls);
- }
-
-
- private static UnOpr getunopr (int op) {
- switch (op) {
- case (int)RESERVED.TK_NOT: return UnOpr.OPR_NOT;
- case '-': return UnOpr.OPR_MINUS;
- case '#': return UnOpr.OPR_LEN;
- default: return UnOpr.OPR_NOUNOPR;
- }
- }
-
-
- private static BinOpr getbinopr (int op) {
- switch (op) {
- case '+': return BinOpr.OPR_ADD;
- case '-': return BinOpr.OPR_SUB;
- case '*': return BinOpr.OPR_MUL;
- case '/': return BinOpr.OPR_DIV;
- case '%': return BinOpr.OPR_MOD;
- case '^': return BinOpr.OPR_POW;
- case (int)RESERVED.TK_CONCAT: return BinOpr.OPR_CONCAT;
- case (int)RESERVED.TK_NE: return BinOpr.OPR_NE;
- case (int)RESERVED.TK_EQ: return BinOpr.OPR_EQ;
- case '<': return BinOpr.OPR_LT;
- case (int)RESERVED.TK_LE: return BinOpr.OPR_LE;
- case '>': return BinOpr.OPR_GT;
- case (int)RESERVED.TK_GE: return BinOpr.OPR_GE;
- case (int)RESERVED.TK_AND: return BinOpr.OPR_AND;
- case (int)RESERVED.TK_OR: return BinOpr.OPR_OR;
- default: return BinOpr.OPR_NOBINOPR;
- }
- }
-
-
- private class priority_ {
- public priority_(lu_byte left, lu_byte right)
- {
- this.left = left;
- this.right = right;
- }
-
- public lu_byte left; /* left priority for each binary operator */
- public lu_byte right; /* right priority */
- }
-
- private static priority_[] priority = { /* ORDER OPR */
-
- new priority_(6, 6),
- new priority_(6, 6),
- new priority_(7, 7),
- new priority_(7, 7),
- new priority_(7, 7), /* `+' `-' `/' `%' */
-
- new priority_(10, 9),
- new priority_(5, 4), /* power and concat (right associative) */
-
- new priority_(3, 3),
- new priority_(3, 3), /* equality and inequality */
-
- new priority_(3, 3),
- new priority_(3, 3),
- new priority_(3, 3),
- new priority_(3, 3), /* order */
-
- new priority_(2, 2),
- new priority_(1, 1) /* logical (and/or) */
- };
-
- public const int 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'
- */
- private static BinOpr subexpr (LexState ls, expdesc v, uint limit) {
- BinOpr op = new BinOpr();
- UnOpr uop = new UnOpr();
- enterlevel(ls);
- uop = getunopr(ls.t.token);
- if (uop != UnOpr.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 != BinOpr.OPR_NOBINOPR && priority[(int)op].left > limit)
- {
- expdesc v2 = new expdesc();
- BinOpr nextop;
- luaX_next(ls);
- luaK_infix(ls.fs, op, v);
- /* read sub-expression with higher priority */
- nextop = subexpr(ls, v2, priority[(int)op].right);
- luaK_posfix(ls.fs, op, v, v2);
- op = nextop;
- }
- leavelevel(ls);
- return op; /* return first untreated operator */
- }
-
-
- private static void expr (LexState ls, expdesc v) {
- subexpr(ls, v, 0);
- }
-
- /* }==================================================================== */
-
-
-
- /*
- ** {======================================================================
- ** Rules for Statements
- ** =======================================================================
- */
-
-
- private static int block_follow (int token) {
- switch (token) {
- case (int)RESERVED.TK_ELSE: case (int)RESERVED.TK_ELSEIF: case (int)RESERVED.TK_END:
- case (int)RESERVED.TK_UNTIL: case (int)RESERVED.TK_EOS:
- return 1;
- default: return 0;
- }
- }
-
-
- private static void block (LexState ls) {
- /* block . chunk */
- FuncState fs = ls.fs;
- BlockCnt bl = new BlockCnt();
- 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
- */
- public class LHS_assign {
- public LHS_assign prev;
- public expdesc v = new expdesc(); /* 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.
- */
- private static void check_conflict (LexState ls, LHS_assign lh, expdesc v) {
- FuncState fs = ls.fs;
- int extra = fs.freereg; /* eventual position to save local variable */
- int conflict = 0;
- for (; lh!=null; lh = lh.prev) {
- if (lh.v.k == expkind.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 != 0) {
- luaK_codeABC(fs, OpCode.OP_MOVE, fs.freereg, v.u.s.info, 0); /* make copy */
- luaK_reserveregs(fs, 1);
- }
- }
-
-
- private static void assignment (LexState ls, LHS_assign lh, int nvars) {
- expdesc e = new expdesc();
- check_condition(ls, expkind.VLOCAL <= lh.v.k && lh.v.k <= expkind.VINDEXED,
- "syntax error");
- if (testnext(ls, ',') != 0) { /* assignment . `,' primaryexp assignment */
- LHS_assign nv = new LHS_assign();
- nv.prev = lh;
- primaryexp(ls, nv.v);
- if (nv.v.k == expkind.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, expkind.VNONRELOC, ls.fs.freereg - 1); /* default assignment */
- luaK_storevar(ls.fs, lh.v, e);
- }
-
-
- private static int cond (LexState ls) {
- /* cond . exp */
- expdesc v = new expdesc();
- expr(ls, v); /* read condition */
- if (v.k == expkind.VNIL) v.k = expkind.VFALSE; /* `falses' are all equal here */
- luaK_goiftrue(ls.fs, v);
- return v.f;
- }
-
-
- private static void breakstat (LexState ls) {
- FuncState fs = ls.fs;
- BlockCnt bl = fs.bl;
- int upval = 0;
- while ((bl!=null) && (bl.isbreakable==0)) {
- upval |= bl.upval;
- bl = bl.previous;
- }
- if (bl==null)
- luaX_syntaxerror(ls, "no loop to break");
- if (upval != 0)
- luaK_codeABC(fs, OpCode.OP_CLOSE, bl.nactvar, 0, 0);
- luaK_concat(fs, ref bl.breaklist, luaK_jump(fs));
- }
-
-
- private static void whilestat (LexState ls, int line) {
- /* whilestat . WHILE cond DO block END */
- FuncState fs = ls.fs;
- int whileinit;
- int condexit;
- BlockCnt bl = new BlockCnt();
- luaX_next(ls); /* skip WHILE */
- whileinit = luaK_getlabel(fs);
- condexit = cond(ls);
- enterblock(fs, bl, 1);
- checknext(ls, (int)RESERVED.TK_DO);
- block(ls);
- luaK_patchlist(fs, luaK_jump(fs), whileinit);
- check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_WHILE, line);
- leaveblock(fs);
- luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
- }
-
-
- private 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 = new BlockCnt(), bl2 = new BlockCnt();
- enterblock(fs, bl1, 1); /* loop block */
- enterblock(fs, bl2, 0); /* scope block */
- luaX_next(ls); /* skip REPEAT */
- chunk(ls);
- check_match(ls, (int)RESERVED.TK_UNTIL, (int)RESERVED.TK_REPEAT, line);
- condexit = cond(ls); /* read condition (inside scope block) */
- if (bl2.upval==0) { /* 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 */
- }
-
-
- private static int exp1 (LexState ls) {
- expdesc e = new expdesc();
- int k;
- expr(ls, e);
- k = (int)e.k;
- luaK_exp2nextreg(ls.fs, e);
- return k;
- }
-
-
- private static void forbody (LexState ls, int base_, int line, int nvars, int isnum) {
- /* forbody . DO block */
- BlockCnt bl = new BlockCnt();
- FuncState fs = ls.fs;
- int prep, endfor;
- adjustlocalvars(ls, 3); /* control variables */
- checknext(ls, (int)RESERVED.TK_DO);
- prep = (isnum != 0) ? luaK_codeAsBx(fs, OpCode.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!=0) ? luaK_codeAsBx(fs, OpCode.OP_FORLOOP, base_, NO_JUMP) :
- luaK_codeABC(fs, OpCode.OP_TFORLOOP, base_, 0, nvars);
- luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
- luaK_patchlist(fs, ((isnum!=0) ? endfor : luaK_jump(fs)), prep + 1);
- }
-
-
- private 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, ',') != 0)
- exp1(ls); /* optional step */
- else { /* default step = 1 */
- luaK_codeABx(fs, OpCode.OP_LOADK, fs.freereg, luaK_numberK(fs, 1));
- luaK_reserveregs(fs, 1);
- }
- forbody(ls, base_, line, 1, 1);
- }
-
-
- private static void forlist (LexState ls, TString indexname) {
- /* forlist . NAME {,NAME} IN explist1 forbody */
- FuncState fs = ls.fs;
- expdesc e = new expdesc();
- 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, ',') != 0)
- new_localvar(ls, str_checkname(ls), nvars++);
- checknext(ls, (int)RESERVED.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);
- }
-
-
- private static void forstat (LexState ls, int line) {
- /* forstat . FOR (fornum | forlist) END */
- FuncState fs = ls.fs;
- TString varname;
- BlockCnt bl = new BlockCnt();
- 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 (int)RESERVED.TK_IN:
- forlist(ls, varname);
- break;
- default: luaX_syntaxerror(ls, LUA_QL("=") + " or " + LUA_QL("in") + " expected"); break;
- }
- check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_FOR, line);
- leaveblock(fs); /* loop scope (`break' jumps to this point) */
- }
-
-
- private 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, (int)RESERVED.TK_THEN);
- block(ls); /* `then' part */
- return condexit;
- }
-
-
- private 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 == (int)RESERVED.TK_ELSEIF) {
- luaK_concat(fs, ref escapelist, luaK_jump(fs));
- luaK_patchtohere(fs, flist);
- flist = test_then_block(ls); /* ELSEIF cond THEN block */
- }
- if (ls.t.token == (int)RESERVED.TK_ELSE) {
- luaK_concat(fs, ref 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, ref escapelist, flist);
- luaK_patchtohere(fs, escapelist);
- check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_IF, line);
- }
-
-
- private static void localfunc (LexState ls) {
- expdesc v = new expdesc(), b = new expdesc();
- FuncState fs = ls.fs;
- new_localvar(ls, str_checkname(ls), 0);
- init_exp(v, expkind.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;
- }
-
-
- private static void localstat (LexState ls) {
- /* stat . LOCAL NAME {`,' NAME} [`=' explist1] */
- int nvars = 0;
- int nexps;
- expdesc e = new expdesc();
- do {
- new_localvar(ls, str_checkname(ls), nvars++);
- } while (testnext(ls, ',') != 0);
- if (testnext(ls, '=') != 0)
- nexps = explist1(ls, e);
- else {
- e.k = expkind.VVOID;
- nexps = 0;
- }
- adjust_assign(ls, nvars, nexps, e);
- adjustlocalvars(ls, nvars);
- }
-
-
- private 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;
- }
-
-
- private static void funcstat (LexState ls, int line) {
- /* funcstat . FUNCTION funcname body */
- int needself;
- expdesc v = new expdesc(), b = new expdesc();
- 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 */
- }
-
-
- private static void exprstat (LexState ls) {
- /* stat . func | assignment */
- FuncState fs = ls.fs;
- LHS_assign v = new LHS_assign();
- primaryexp(ls, v.v);
- if (v.v.k == expkind.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);
- }
- }
-
-
- private static void retstat (LexState ls) {
- /* stat . RETURN explist */
- FuncState fs = ls.fs;
- expdesc e = new expdesc();
- int first, nret; /* registers with returned values */
- luaX_next(ls); /* skip RETURN */
- if ((block_follow(ls.t.token)!=0) || ls.t.token == ';')
- first = nret = 0; /* return no values */
- else {
- nret = explist1(ls, e); /* optional return values */
- if (hasmultret(e.k) != 0) {
- luaK_setmultret(fs, e);
- if (e.k == expkind.VCALL && nret == 1) { /* tail call? */
- SET_OPCODE(getcode(fs,e), OpCode.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);
- }
-
-
- private static int statement (LexState ls) {
- int line = ls.linenumber; /* may be needed for error messages */
- switch (ls.t.token) {
- case (int)RESERVED.TK_IF: { /* stat . ifstat */
- ifstat(ls, line);
- return 0;
- }
- case (int)RESERVED.TK_WHILE: { /* stat . whilestat */
- whilestat(ls, line);
- return 0;
- }
- case (int)RESERVED.TK_DO: { /* stat . DO block END */
- luaX_next(ls); /* skip DO */
- block(ls);
- check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_DO, line);
- return 0;
- }
- case (int)RESERVED.TK_FOR: { /* stat . forstat */
- forstat(ls, line);
- return 0;
- }
- case (int)RESERVED.TK_REPEAT: { /* stat . repeatstat */
- repeatstat(ls, line);
- return 0;
- }
- case (int)RESERVED.TK_FUNCTION: {
- funcstat(ls, line); /* stat . funcstat */
- return 0;
- }
- case (int)RESERVED.TK_LOCAL: { /* stat . localstat */
- luaX_next(ls); /* skip LOCAL */
- if (testnext(ls, (int)RESERVED.TK_FUNCTION) != 0) /* local function? */
- localfunc(ls);
- else
- localstat(ls);
- return 0;
- }
- case (int)RESERVED.TK_RETURN: { /* stat . retstat */
- retstat(ls);
- return 1; /* must be last statement */
- }
- case (int)RESERVED.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 */
- }
- }
- }
-
-
- private static void chunk (LexState ls) {
- /* chunk . { stat [`;'] } */
- int islast = 0;
- enterlevel(ls);
- while ((islast==0) && (block_follow(ls.t.token)==0)) {
- 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);
- }
-
- /* }====================================================================== */
-
- }
+/*
+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace KopiLua
+{
+ using lu_byte = System.Byte;
+ using lua_Number = System.Double;
+ using ZIO = Lua.Zio;
+
+ public partial class Lua
+ {
+ /*
+ ** Expression descriptor
+ */
+
+ public enum expkind {
+ 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 */
+ };
+
+
+
+ public class expdesc {
+
+ public void Copy(expdesc e)
+ {
+ this.k = e.k;
+ this.u.Copy(e.u);
+ this.t = e.t;
+ this.f = e.f;
+ }
+
+ public expkind k;
+
+ [CLSCompliantAttribute(false)]
+ public class _u
+ {
+ public void Copy(_u u)
+ {
+ this.s.Copy(u.s);
+ this.nval = u.nval;
+ }
+
+ [CLSCompliantAttribute(false)]
+ public class _s
+ {
+ public void Copy(_s s)
+ {
+ this.info = s.info;
+ this.aux = s.aux;
+ }
+ public int info, aux;
+ };
+ public _s s = new _s();
+ public lua_Number nval;
+ };
+
+ [CLSCompliantAttribute(false)]
+ public _u u = new _u();
+
+ public int t; /* patch list of `exit when true' */
+ public int f; /* patch list of `exit when false' */
+ };
+
+
+ public class upvaldesc {
+ public lu_byte k;
+ public lu_byte info;
+ };
+
+
+ /* state needed to generate code for a given function */
+ public class FuncState {
+ public FuncState()
+ {
+ for (int i=0; i (l)) errorlimit(fs, l, m); }
+
+
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+ public class BlockCnt {
+ public BlockCnt previous; /* chain */
+ public int breaklist; /* list of jumps out of this loop */
+ public lu_byte nactvar; /* # active locals outside the breakable structure */
+ public lu_byte upval; /* true if some variable in the block is an upvalue */
+ public lu_byte isbreakable; /* true if `block' is a loop */
+ };
+
+
+
+ private static void anchor_token (LexState ls) {
+ if (ls.t.token == (int)RESERVED.TK_NAME || ls.t.token == (int)RESERVED.TK_STRING) {
+ TString ts = ls.t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts.tsv.len);
+ }
+ }
+
+
+ private static void error_expected (LexState ls, int token) {
+ luaX_syntaxerror(ls,
+ luaO_pushfstring(ls.L, LUA_QS + " expected", luaX_token2str(ls, token)));
+ }
+
+
+ private static void errorlimit (FuncState fs, int limit, CharPtr what) {
+ CharPtr 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);
+ }
+
+
+ private static int testnext (LexState ls, int c) {
+ if (ls.t.token == c) {
+ luaX_next(ls);
+ return 1;
+ }
+ else return 0;
+ }
+
+
+ private static void check (LexState ls, int c) {
+ if (ls.t.token != c)
+ error_expected(ls, c);
+ }
+
+ private static void checknext (LexState ls, int c) {
+ check(ls, c);
+ luaX_next(ls);
+ }
+
+
+ public static void check_condition(LexState ls, bool c, CharPtr msg) {
+ if (!(c)) luaX_syntaxerror(ls, msg);
+ }
+
+ private static void check_match (LexState ls, int what, int who, int where) {
+ if (testnext(ls, what)==0) {
+ 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));
+ }
+ }
+ }
+
+ private static TString str_checkname (LexState ls) {
+ TString ts;
+ check(ls, (int)RESERVED.TK_NAME);
+ ts = ls.t.seminfo.ts;
+ luaX_next(ls);
+ return ts;
+ }
+
+
+ private static void init_exp (expdesc e, expkind k, int i) {
+ e.f = e.t = NO_JUMP;
+ e.k = k;
+ e.u.s.info = i;
+ }
+
+
+ private static void codestring (LexState ls, expdesc e, TString s) {
+ init_exp(e, expkind.VK, luaK_stringK(ls.fs, s));
+ }
+
+
+ private static void checkname(LexState ls, expdesc e) {
+ codestring(ls, e, str_checkname(ls));
+ }
+
+
+ private static int registerlocalvar (LexState ls, TString varname) {
+ FuncState fs = ls.fs;
+ Proto f = fs.f;
+ int oldsize = f.sizelocvars;
+ luaM_growvector(ls.L, ref f.locvars, fs.nlocvars, ref f.sizelocvars,
+ (int)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++;
+ }
+
+
+ public static void new_localvarliteral(LexState ls, CharPtr v, int n) {
+ new_localvar(ls, luaX_newstring(ls, "" + v, (uint)(v.chars.Length - 1)), n);
+ }
+
+
+ private 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] = (ushort)registerlocalvar(ls, name);
+ }
+
+
+ private static void adjustlocalvars (LexState ls, int nvars) {
+ FuncState fs = ls.fs;
+ fs.nactvar = cast_byte(fs.nactvar + nvars);
+ for (; nvars!=0; nvars--) {
+ getlocvar(fs, fs.nactvar - nvars).startpc = fs.pc;
+ }
+ }
+
+
+ private static void removevars (LexState ls, int tolevel) {
+ FuncState fs = ls.fs;
+ while (fs.nactvar > tolevel)
+ getlocvar(fs, --fs.nactvar).endpc = fs.pc;
+ }
+
+
+ private static int indexupvalue (FuncState fs, TString name, expdesc v) {
+ int i;
+ Proto f = fs.f;
+ int oldsize = f.sizeupvalues;
+ for (i=0; i= 0; i--) {
+ if (n == getlocvar(fs, i).varname)
+ return i;
+ }
+ return -1; /* not found */
+ }
+
+
+ private static void markupval (FuncState fs, int level) {
+ BlockCnt bl = fs.bl;
+ while ((bl!=null) && bl.nactvar > level) bl = bl.previous;
+ if (bl != null) bl.upval = 1;
+ }
+
+
+ private static expkind singlevaraux(FuncState fs, TString n, expdesc var, int base_)
+ {
+ if (fs == null) { /* no more levels? */
+ init_exp(var, expkind.VGLOBAL, NO_REG); /* default is global variable */
+ return expkind.VGLOBAL;
+ }
+ else {
+ int v = searchvar(fs, n); /* look up at current level */
+ if (v >= 0) {
+ init_exp(var, expkind.VLOCAL, v);
+ if (base_==0)
+ markupval(fs, v); /* local will be used as an upval */
+ return expkind.VLOCAL;
+ }
+ else { /* not found at current level; try upper one */
+ if (singlevaraux(fs.prev, n, var, 0) == expkind.VGLOBAL)
+ return expkind.VGLOBAL;
+ var.u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
+ var.k = expkind.VUPVAL; /* upvalue in this level */
+ return expkind.VUPVAL;
+ }
+ }
+ }
+
+
+ private static void singlevar (LexState ls, expdesc var) {
+ TString varname = str_checkname(ls);
+ FuncState fs = ls.fs;
+ if (singlevaraux(fs, varname, var, 1) == expkind.VGLOBAL)
+ var.u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+ }
+
+
+ private static void adjust_assign (LexState ls, int nvars, int nexps, expdesc e) {
+ FuncState fs = ls.fs;
+ int extra = nvars - nexps;
+ if (hasmultret(e.k) != 0) {
+ 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 != expkind.VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
+ if (extra > 0) {
+ int reg = fs.freereg;
+ luaK_reserveregs(fs, extra);
+ luaK_nil(fs, reg, extra);
+ }
+ }
+ }
+
+
+ private static void enterlevel (LexState ls) {
+ if (++ls.L.nCcalls > LUAI_MAXCCALLS)
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
+ }
+
+
+ private static void leavelevel(LexState ls) { ls.L.nCcalls--; }
+
+
+ private 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);
+ }
+
+
+ private static void leaveblock (FuncState fs) {
+ BlockCnt bl = fs.bl;
+ fs.bl = bl.previous;
+ removevars(fs.ls, bl.nactvar);
+ if (bl.upval != 0)
+ luaK_codeABC(fs, OpCode.OP_CLOSE, bl.nactvar, 0, 0);
+ /* a block either controls scope or breaks (never both) */
+ lua_assert((bl.isbreakable==0) || (bl.upval==0));
+ lua_assert(bl.nactvar == fs.nactvar);
+ fs.freereg = fs.nactvar; /* free registers */
+ luaK_patchtohere(fs, bl.breaklist);
+ }
+
+
+ private 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, ref f.p, fs.np, ref f.sizep,
+ 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, expkind.VRELOCABLE, luaK_codeABx(fs, OpCode.OP_CLOSURE, 0, fs.np - 1));
+ for (i=0; i 0);
+ if (ls.t.token == '}') break;
+ closelistfield(fs, cc);
+ switch(ls.t.token) {
+ case (int)RESERVED.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, ',')!=0) || (testnext(ls, ';')!=0));
+ check_match(ls, '}', '{', line);
+ lastlistfield(fs, cc);
+ SETARG_B(new InstructionPtr(fs.f.code, pc), luaO_int2fb((uint)cc.na)); /* set initial array size */
+ SETARG_C(new InstructionPtr(fs.f.code, pc), luaO_int2fb((uint)cc.nh)); /* set initial table size */
+ }
+
+ /* }====================================================================== */
+
+
+
+ private 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 (int)RESERVED.TK_NAME: { /* param . NAME */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ break;
+ }
+ case (int)RESERVED.TK_DOTS: { /* param . `...' */
+ luaX_next(ls);
+ #if 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"); break;
+ }
+ } while ((f.is_vararg==0) && (testnext(ls, ',')!=0));
+ }
+ adjustlocalvars(ls, nparams);
+ f.numparams = cast_byte(fs.nactvar - (f.is_vararg & VARARG_HASARG));
+ luaK_reserveregs(fs, fs.nactvar); /* reserve register for parameters */
+ }
+
+
+ private static void body (LexState ls, expdesc e, int needself, int line) {
+ /* body . `(' parlist `)' chunk END */
+ FuncState new_fs = new FuncState();
+ open_func(ls, new_fs);
+ new_fs.f.linedefined = line;
+ checknext(ls, '(');
+ if (needself != 0) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
+ parlist(ls);
+ checknext(ls, ')');
+ chunk(ls);
+ new_fs.f.lastlinedefined = ls.linenumber;
+ check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_FUNCTION, line);
+ close_func(ls);
+ pushclosure(ls, new_fs, e);
+ }
+
+
+ private static int explist1 (LexState ls, expdesc v) {
+ /* explist1 . expr { `,' expr } */
+ int n = 1; /* at least one expression */
+ expr(ls, v);
+ while (testnext(ls, ',') != 0) {
+ luaK_exp2nextreg(ls.fs, v);
+ expr(ls, v);
+ n++;
+ }
+ return n;
+ }
+
+
+ private static void funcargs (LexState ls, expdesc f) {
+ FuncState fs = ls.fs;
+ expdesc args = new expdesc();
+ 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 = expkind.VVOID;
+ else {
+ explist1(ls, args);
+ luaK_setmultret(fs, args);
+ }
+ check_match(ls, ')', '(', line);
+ break;
+ }
+ case '{': { /* funcargs . constructor */
+ constructor(ls, args);
+ break;
+ }
+ case (int)RESERVED.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 == expkind.VNONRELOC);
+ base_ = f.u.s.info; /* base_ register for call */
+ if (hasmultret(args.k) != 0)
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ if (args.k != expkind.VVOID)
+ luaK_exp2nextreg(fs, args); /* close last argument */
+ nparams = fs.freereg - (base_+1);
+ }
+ init_exp(f, expkind.VCALL, luaK_codeABC(fs, OpCode.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
+ ** =======================================================================
+ */
+
+
+ private 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 (int)RESERVED.TK_NAME: {
+ singlevar(ls, v);
+ return;
+ }
+ default: {
+ luaX_syntaxerror(ls, "unexpected symbol");
+ return;
+ }
+ }
+ }
+
+ private 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 = new expdesc();
+ luaK_exp2anyreg(fs, v);
+ yindex(ls, key);
+ luaK_indexed(fs, v, key);
+ break;
+ }
+ case ':': { /* `:' NAME funcargs */
+ expdesc key = new expdesc();
+ luaX_next(ls);
+ checkname(ls, key);
+ luaK_self(fs, v, key);
+ funcargs(ls, v);
+ break;
+ }
+ case '(': case (int)RESERVED.TK_STRING: case '{': { /* funcargs */
+ luaK_exp2nextreg(fs, v);
+ funcargs(ls, v);
+ break;
+ }
+ default: return;
+ }
+ }
+ }
+
+
+ private static void simpleexp (LexState ls, expdesc v) {
+ /* simpleexp . NUMBER | STRING | NIL | true | false | ... |
+ constructor | FUNCTION body | primaryexp */
+ switch (ls.t.token) {
+ case (int)RESERVED.TK_NUMBER: {
+ init_exp(v, expkind.VKNUM, 0);
+ v.u.nval = ls.t.seminfo.r;
+ break;
+ }
+ case (int)RESERVED.TK_STRING: {
+ codestring(ls, v, ls.t.seminfo.ts);
+ break;
+ }
+ case (int)RESERVED.TK_NIL: {
+ init_exp(v, expkind.VNIL, 0);
+ break;
+ }
+ case (int)RESERVED.TK_TRUE: {
+ init_exp(v, expkind.VTRUE, 0);
+ break;
+ }
+ case (int)RESERVED.TK_FALSE: {
+ init_exp(v, expkind.VFALSE, 0);
+ break;
+ }
+ case (int)RESERVED.TK_DOTS: { /* vararg */
+ FuncState fs = ls.fs;
+ check_condition(ls, fs.f.is_vararg!=0,
+ "cannot use " + LUA_QL("...") + " outside a vararg function");
+ fs.f.is_vararg &= unchecked((lu_byte)(~VARARG_NEEDSARG)); /* don't need 'arg' */
+ init_exp(v, expkind.VVARARG, luaK_codeABC(fs, OpCode.OP_VARARG, 0, 1, 0));
+ break;
+ }
+ case '{': { /* constructor */
+ constructor(ls, v);
+ return;
+ }
+ case (int)RESERVED.TK_FUNCTION: {
+ luaX_next(ls);
+ body(ls, v, 0, ls.linenumber);
+ return;
+ }
+ default: {
+ primaryexp(ls, v);
+ return;
+ }
+ }
+ luaX_next(ls);
+ }
+
+
+ private static UnOpr getunopr (int op) {
+ switch (op) {
+ case (int)RESERVED.TK_NOT: return UnOpr.OPR_NOT;
+ case '-': return UnOpr.OPR_MINUS;
+ case '#': return UnOpr.OPR_LEN;
+ default: return UnOpr.OPR_NOUNOPR;
+ }
+ }
+
+
+ private static BinOpr getbinopr (int op) {
+ switch (op) {
+ case '+': return BinOpr.OPR_ADD;
+ case '-': return BinOpr.OPR_SUB;
+ case '*': return BinOpr.OPR_MUL;
+ case '/': return BinOpr.OPR_DIV;
+ case '%': return BinOpr.OPR_MOD;
+ case '^': return BinOpr.OPR_POW;
+ case (int)RESERVED.TK_CONCAT: return BinOpr.OPR_CONCAT;
+ case (int)RESERVED.TK_NE: return BinOpr.OPR_NE;
+ case (int)RESERVED.TK_EQ: return BinOpr.OPR_EQ;
+ case '<': return BinOpr.OPR_LT;
+ case (int)RESERVED.TK_LE: return BinOpr.OPR_LE;
+ case '>': return BinOpr.OPR_GT;
+ case (int)RESERVED.TK_GE: return BinOpr.OPR_GE;
+ case (int)RESERVED.TK_AND: return BinOpr.OPR_AND;
+ case (int)RESERVED.TK_OR: return BinOpr.OPR_OR;
+ default: return BinOpr.OPR_NOBINOPR;
+ }
+ }
+
+
+ private class priority_ {
+ public priority_(lu_byte left, lu_byte right)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ public lu_byte left; /* left priority for each binary operator */
+ public lu_byte right; /* right priority */
+ }
+
+ private static priority_[] priority = { /* ORDER OPR */
+
+ new priority_(6, 6),
+ new priority_(6, 6),
+ new priority_(7, 7),
+ new priority_(7, 7),
+ new priority_(7, 7), /* `+' `-' `/' `%' */
+
+ new priority_(10, 9),
+ new priority_(5, 4), /* power and concat (right associative) */
+
+ new priority_(3, 3),
+ new priority_(3, 3), /* equality and inequality */
+
+ new priority_(3, 3),
+ new priority_(3, 3),
+ new priority_(3, 3),
+ new priority_(3, 3), /* order */
+
+ new priority_(2, 2),
+ new priority_(1, 1) /* logical (and/or) */
+ };
+
+ public const int 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'
+ */
+ private static BinOpr subexpr (LexState ls, expdesc v, uint limit) {
+ BinOpr op = new BinOpr();
+ UnOpr uop = new UnOpr();
+ enterlevel(ls);
+ uop = getunopr(ls.t.token);
+ if (uop != UnOpr.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 != BinOpr.OPR_NOBINOPR && priority[(int)op].left > limit)
+ {
+ expdesc v2 = new expdesc();
+ BinOpr nextop;
+ luaX_next(ls);
+ luaK_infix(ls.fs, op, v);
+ /* read sub-expression with higher priority */
+ nextop = subexpr(ls, v2, priority[(int)op].right);
+ luaK_posfix(ls.fs, op, v, v2);
+ op = nextop;
+ }
+ leavelevel(ls);
+ return op; /* return first untreated operator */
+ }
+
+
+ private static void expr (LexState ls, expdesc v) {
+ subexpr(ls, v, 0);
+ }
+
+ /* }==================================================================== */
+
+
+
+ /*
+ ** {======================================================================
+ ** Rules for Statements
+ ** =======================================================================
+ */
+
+
+ private static int block_follow (int token) {
+ switch (token) {
+ case (int)RESERVED.TK_ELSE: case (int)RESERVED.TK_ELSEIF: case (int)RESERVED.TK_END:
+ case (int)RESERVED.TK_UNTIL: case (int)RESERVED.TK_EOS:
+ return 1;
+ default: return 0;
+ }
+ }
+
+
+ private static void block (LexState ls) {
+ /* block . chunk */
+ FuncState fs = ls.fs;
+ BlockCnt bl = new BlockCnt();
+ 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
+ */
+ public class LHS_assign {
+ public LHS_assign prev;
+ public expdesc v = new expdesc(); /* 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.
+ */
+ private static void check_conflict (LexState ls, LHS_assign lh, expdesc v) {
+ FuncState fs = ls.fs;
+ int extra = fs.freereg; /* eventual position to save local variable */
+ int conflict = 0;
+ for (; lh!=null; lh = lh.prev) {
+ if (lh.v.k == expkind.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 != 0) {
+ luaK_codeABC(fs, OpCode.OP_MOVE, fs.freereg, v.u.s.info, 0); /* make copy */
+ luaK_reserveregs(fs, 1);
+ }
+ }
+
+
+ private static void assignment (LexState ls, LHS_assign lh, int nvars) {
+ expdesc e = new expdesc();
+ check_condition(ls, expkind.VLOCAL <= lh.v.k && lh.v.k <= expkind.VINDEXED,
+ "syntax error");
+ if (testnext(ls, ',') != 0) { /* assignment . `,' primaryexp assignment */
+ LHS_assign nv = new LHS_assign();
+ nv.prev = lh;
+ primaryexp(ls, nv.v);
+ if (nv.v.k == expkind.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, expkind.VNONRELOC, ls.fs.freereg - 1); /* default assignment */
+ luaK_storevar(ls.fs, lh.v, e);
+ }
+
+
+ private static int cond (LexState ls) {
+ /* cond . exp */
+ expdesc v = new expdesc();
+ expr(ls, v); /* read condition */
+ if (v.k == expkind.VNIL) v.k = expkind.VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls.fs, v);
+ return v.f;
+ }
+
+
+ private static void breakstat (LexState ls) {
+ FuncState fs = ls.fs;
+ BlockCnt bl = fs.bl;
+ int upval = 0;
+ while ((bl!=null) && (bl.isbreakable==0)) {
+ upval |= bl.upval;
+ bl = bl.previous;
+ }
+ if (bl==null)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval != 0)
+ luaK_codeABC(fs, OpCode.OP_CLOSE, bl.nactvar, 0, 0);
+ luaK_concat(fs, ref bl.breaklist, luaK_jump(fs));
+ }
+
+
+ private static void whilestat (LexState ls, int line) {
+ /* whilestat . WHILE cond DO block END */
+ FuncState fs = ls.fs;
+ int whileinit;
+ int condexit;
+ BlockCnt bl = new BlockCnt();
+ luaX_next(ls); /* skip WHILE */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
+ enterblock(fs, bl, 1);
+ checknext(ls, (int)RESERVED.TK_DO);
+ block(ls);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
+ check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_WHILE, line);
+ leaveblock(fs);
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
+ }
+
+
+ private 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 = new BlockCnt(), bl2 = new BlockCnt();
+ enterblock(fs, bl1, 1); /* loop block */
+ enterblock(fs, bl2, 0); /* scope block */
+ luaX_next(ls); /* skip REPEAT */
+ chunk(ls);
+ check_match(ls, (int)RESERVED.TK_UNTIL, (int)RESERVED.TK_REPEAT, line);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (bl2.upval==0) { /* 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 */
+ }
+
+
+ private static int exp1 (LexState ls) {
+ expdesc e = new expdesc();
+ int k;
+ expr(ls, e);
+ k = (int)e.k;
+ luaK_exp2nextreg(ls.fs, e);
+ return k;
+ }
+
+
+ private static void forbody (LexState ls, int base_, int line, int nvars, int isnum) {
+ /* forbody . DO block */
+ BlockCnt bl = new BlockCnt();
+ FuncState fs = ls.fs;
+ int prep, endfor;
+ adjustlocalvars(ls, 3); /* control variables */
+ checknext(ls, (int)RESERVED.TK_DO);
+ prep = (isnum != 0) ? luaK_codeAsBx(fs, OpCode.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!=0) ? luaK_codeAsBx(fs, OpCode.OP_FORLOOP, base_, NO_JUMP) :
+ luaK_codeABC(fs, OpCode.OP_TFORLOOP, base_, 0, nvars);
+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
+ luaK_patchlist(fs, ((isnum!=0) ? endfor : luaK_jump(fs)), prep + 1);
+ }
+
+
+ private 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, ',') != 0)
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+ luaK_codeABx(fs, OpCode.OP_LOADK, fs.freereg, luaK_numberK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base_, line, 1, 1);
+ }
+
+
+ private static void forlist (LexState ls, TString indexname) {
+ /* forlist . NAME {,NAME} IN explist1 forbody */
+ FuncState fs = ls.fs;
+ expdesc e = new expdesc();
+ 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, ',') != 0)
+ new_localvar(ls, str_checkname(ls), nvars++);
+ checknext(ls, (int)RESERVED.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);
+ }
+
+
+ private static void forstat (LexState ls, int line) {
+ /* forstat . FOR (fornum | forlist) END */
+ FuncState fs = ls.fs;
+ TString varname;
+ BlockCnt bl = new BlockCnt();
+ 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 (int)RESERVED.TK_IN:
+ forlist(ls, varname);
+ break;
+ default: luaX_syntaxerror(ls, LUA_QL("=") + " or " + LUA_QL("in") + " expected"); break;
+ }
+ check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_FOR, line);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
+ }
+
+
+ private 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, (int)RESERVED.TK_THEN);
+ block(ls); /* `then' part */
+ return condexit;
+ }
+
+
+ private 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 == (int)RESERVED.TK_ELSEIF) {
+ luaK_concat(fs, ref escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
+ }
+ if (ls.t.token == (int)RESERVED.TK_ELSE) {
+ luaK_concat(fs, ref 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, ref escapelist, flist);
+ luaK_patchtohere(fs, escapelist);
+ check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_IF, line);
+ }
+
+
+ private static void localfunc (LexState ls) {
+ expdesc v = new expdesc(), b = new expdesc();
+ FuncState fs = ls.fs;
+ new_localvar(ls, str_checkname(ls), 0);
+ init_exp(v, expkind.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;
+ }
+
+
+ private static void localstat (LexState ls) {
+ /* stat . LOCAL NAME {`,' NAME} [`=' explist1] */
+ int nvars = 0;
+ int nexps;
+ expdesc e = new expdesc();
+ do {
+ new_localvar(ls, str_checkname(ls), nvars++);
+ } while (testnext(ls, ',') != 0);
+ if (testnext(ls, '=') != 0)
+ nexps = explist1(ls, e);
+ else {
+ e.k = expkind.VVOID;
+ nexps = 0;
+ }
+ adjust_assign(ls, nvars, nexps, e);
+ adjustlocalvars(ls, nvars);
+ }
+
+
+ private 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;
+ }
+
+
+ private static void funcstat (LexState ls, int line) {
+ /* funcstat . FUNCTION funcname body */
+ int needself;
+ expdesc v = new expdesc(), b = new expdesc();
+ 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 */
+ }
+
+
+ private static void exprstat (LexState ls) {
+ /* stat . func | assignment */
+ FuncState fs = ls.fs;
+ LHS_assign v = new LHS_assign();
+ primaryexp(ls, v.v);
+ if (v.v.k == expkind.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);
+ }
+ }
+
+
+ private static void retstat (LexState ls) {
+ /* stat . RETURN explist */
+ FuncState fs = ls.fs;
+ expdesc e = new expdesc();
+ int first, nret; /* registers with returned values */
+ luaX_next(ls); /* skip RETURN */
+ if ((block_follow(ls.t.token)!=0) || ls.t.token == ';')
+ first = nret = 0; /* return no values */
+ else {
+ nret = explist1(ls, e); /* optional return values */
+ if (hasmultret(e.k) != 0) {
+ luaK_setmultret(fs, e);
+ if (e.k == expkind.VCALL && nret == 1) { /* tail call? */
+ SET_OPCODE(getcode(fs,e), OpCode.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);
+ }
+
+
+ private static int statement (LexState ls) {
+ int line = ls.linenumber; /* may be needed for error messages */
+ switch (ls.t.token) {
+ case (int)RESERVED.TK_IF: { /* stat . ifstat */
+ ifstat(ls, line);
+ return 0;
+ }
+ case (int)RESERVED.TK_WHILE: { /* stat . whilestat */
+ whilestat(ls, line);
+ return 0;
+ }
+ case (int)RESERVED.TK_DO: { /* stat . DO block END */
+ luaX_next(ls); /* skip DO */
+ block(ls);
+ check_match(ls, (int)RESERVED.TK_END, (int)RESERVED.TK_DO, line);
+ return 0;
+ }
+ case (int)RESERVED.TK_FOR: { /* stat . forstat */
+ forstat(ls, line);
+ return 0;
+ }
+ case (int)RESERVED.TK_REPEAT: { /* stat . repeatstat */
+ repeatstat(ls, line);
+ return 0;
+ }
+ case (int)RESERVED.TK_FUNCTION: {
+ funcstat(ls, line); /* stat . funcstat */
+ return 0;
+ }
+ case (int)RESERVED.TK_LOCAL: { /* stat . localstat */
+ luaX_next(ls); /* skip LOCAL */
+ if (testnext(ls, (int)RESERVED.TK_FUNCTION) != 0) /* local function? */
+ localfunc(ls);
+ else
+ localstat(ls);
+ return 0;
+ }
+ case (int)RESERVED.TK_RETURN: { /* stat . retstat */
+ retstat(ls);
+ return 1; /* must be last statement */
+ }
+ case (int)RESERVED.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 */
+ }
+ }
+ }
+
+
+ private static void chunk (LexState ls) {
+ /* chunk . { stat [`;'] } */
+ int islast = 0;
+ enterlevel(ls);
+ while ((islast==0) && (block_follow(ls.t.token)==0)) {
+ 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);
+ }
+
+ /* }====================================================================== */
+
+ }
}
\ No newline at end of file
diff --git a/Core/KopiLua/lstate.cs b/Core/KopiLua/lstate.cs
index 492676143a6d3871db4fbcfc9a6c83d49fe7be58..d9cb6acad39663daf219a8b41291d17ee2eb64a9 100644
--- a/Core/KopiLua/lstate.cs
+++ b/Core/KopiLua/lstate.cs
@@ -1,542 +1,542 @@
-/*
-** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
-** Global State
-** See Copyright Notice in lua.h
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.Diagnostics;
-
-namespace KopiLua
-{
- using lu_byte = System.Byte;
- using lu_int32 = System.Int32;
- using lu_mem = System.UInt32;
- using TValue = Lua.lua_TValue;
- using StkId = Lua.lua_TValue;
- using ptrdiff_t = System.Int32;
- using Instruction = System.UInt32;
-
- public partial class Lua
- {
- /* table of globals */
- public static TValue gt(lua_State L) {return L.l_gt;}
-
- /* registry */
- public static TValue registry(lua_State L) {return G(L).l_registry;}
-
-
- /* extra stack space to handle TM calls and some other extras */
- public const int EXTRA_STACK = 5;
-
-
- public const int BASIC_CI_SIZE = 8;
-
- public const int BASIC_STACK_SIZE = (2*LUA_MINSTACK);
-
-
-
- public class stringtable {
- public GCObject[] hash;
- public lu_int32 nuse; /* number of elements */
- public int size;
- };
-
-
- /*
- ** informations about a call
- */
- public class CallInfo : ArrayElement
- {
- private CallInfo[] values = null;
- private int index = -1;
-
- public void set_index(int index)
- {
- this.index = index;
- }
-
- public void set_array(object array)
- {
- this.values = (CallInfo[])array;
- Debug.Assert(this.values != null);
- }
-
- public CallInfo this[int offset]
- {
- get { return values[index+offset]; }
- }
-
- public static CallInfo operator +(CallInfo value, int offset)
- {
- return value.values[value.index + offset];
- }
-
- public static CallInfo operator -(CallInfo value, int offset)
- {
- return value.values[value.index - offset];
- }
-
- public static int operator -(CallInfo ci, CallInfo[] values)
- {
- Debug.Assert(ci.values == values);
- return ci.index;
- }
-
- public static int operator -(CallInfo ci1, CallInfo ci2)
- {
- Debug.Assert(ci1.values == ci2.values);
- return ci1.index - ci2.index;
- }
-
- public static bool operator <(CallInfo ci1, CallInfo ci2)
- {
- Debug.Assert(ci1.values == ci2.values);
- return ci1.index < ci2.index;
- }
-
- public static bool operator <=(CallInfo ci1, CallInfo ci2)
- {
- Debug.Assert(ci1.values == ci2.values);
- return ci1.index <= ci2.index;
- }
-
- public static bool operator >(CallInfo ci1, CallInfo ci2)
- {
- Debug.Assert(ci1.values == ci2.values);
- return ci1.index > ci2.index;
- }
-
- public static bool operator >=(CallInfo ci1, CallInfo ci2)
- {
- Debug.Assert(ci1.values == ci2.values);
- return ci1.index >= ci2.index;
- }
-
- public static CallInfo inc(ref CallInfo value)
- {
- value = value[1];
- return value[-1];
- }
-
- public static CallInfo dec(ref CallInfo value)
- {
- value = value[-1];
- return value[1];
- }
-
- public StkId base_; /* base for this function */
- public StkId func; /* function index in the stack */
- public StkId top; /* top for this function */
- public InstructionPtr savedpc;
- public int nresults; /* expected number of results from this function */
- public int tailcalls; /* number of tail calls lost under this entry */
- };
-
-
-
- public static Closure curr_func(lua_State L) { return (clvalue(L.ci.func)); }
- public static Closure ci_func(CallInfo ci) { return (clvalue(ci.func)); }
- public static bool f_isLua(CallInfo ci) {return ci_func(ci).c.isC==0;}
- public static bool isLua(CallInfo ci) {return (ttisfunction((ci).func) && f_isLua(ci));}
-
-
- /*
- ** `global state', shared by all threads of this state
- */
- public class global_State {
- public stringtable strt = new stringtable(); /* hash table for strings */
- public lua_Alloc frealloc; /* function to reallocate memory */
- public object ud; /* auxiliary data to `frealloc' */
- public lu_byte currentwhite;
- public lu_byte gcstate; /* state of garbage collector */
- public int sweepstrgc; /* position of sweep in `strt' */
- public GCObject rootgc; /* list of all collectable objects */
- public GCObjectRef sweepgc; /* position of sweep in `rootgc' */
- public GCObject gray; /* list of gray objects */
- public GCObject grayagain; /* list of objects to be traversed atomically */
- public GCObject weak; /* list of weak tables (to be cleared) */
- public GCObject tmudata; /* last element of list of userdata to be GC */
- public Mbuffer buff = new Mbuffer(); /* temporary buffer for string concatentation */
- [CLSCompliantAttribute(false)]
- public lu_mem GCthreshold;
- [CLSCompliantAttribute(false)]
- public lu_mem totalbytes; /* number of bytes currently allocated */
- [CLSCompliantAttribute(false)]
- public lu_mem estimate; /* an estimate of number of bytes actually in use */
- [CLSCompliantAttribute(false)]
- public lu_mem gcdept; /* how much GC is `behind schedule' */
- public int gcpause; /* size of pause between successive GCs */
- public int gcstepmul; /* GC `granularity' */
- public lua_CFunction panic; /* to be called in unprotected errors */
- public TValue l_registry = new TValue();
- public lua_State mainthread;
- public UpVal uvhead = new UpVal(); /* head of double-linked list of all open upvalues */
- public Table[] mt = new Table[NUM_TAGS]; /* metatables for basic types */
- public TString[] tmname = new TString[(int)TMS.TM_N]; /* array with tag-method names */
- };
-
-
- /*
- ** `per thread' state
- */
- public class lua_State : GCObject {
-
- public lu_byte status;
- public StkId top; /* first free slot in the stack */
- public StkId base_; /* base of current function */
- public global_State l_G;
- public CallInfo ci; /* call info for current function */
- public InstructionPtr savedpc = new InstructionPtr(); /* `savedpc' of current function */
- public StkId stack_last; /* last free slot in the stack */
- public StkId[] stack; /* stack base */
- public CallInfo end_ci; /* points after end of ci array*/
- public CallInfo[] base_ci; /* array of CallInfo's */
- public int stacksize;
- public int size_ci; /* size of array `base_ci' */
- [CLSCompliantAttribute(false)]
- public ushort nCcalls; /* number of nested C calls */
- [CLSCompliantAttribute(false)]
- public ushort baseCcalls; /* nested C calls when resuming coroutine */
- public lu_byte hookmask;
- public lu_byte allowhook;
- public int basehookcount;
- public int hookcount;
- public lua_Hook hook;
- public TValue l_gt = new TValue(); /* table of globals */
- public TValue env = new TValue(); /* temporary place for environments */
- public GCObject openupval; /* list of open upvalues in this stack */
- public GCObject gclist;
- public lua_longjmp errorJmp; /* current error recover point */
- public ptrdiff_t errfunc; /* current error handling function (stack index) */
- };
-
-
- public static global_State G(lua_State L) {return L.l_G;}
- public static void G_set(lua_State L, global_State s) { L.l_G = s; }
-
-
- /*
- ** Union of all collectable objects (not a union anymore in the C# port)
- */
- public class GCObject : GCheader, ArrayElement
- {
- public void set_index(int index)
- {
- //this.index = index;
- }
-
- public void set_array(object array)
- {
- //this.values = (GCObject[])array;
- //Debug.Assert(this.values != null);
- }
-
- public GCheader gch {get{return (GCheader)this;}}
- public TString ts {get{return (TString)this;}}
- public Udata u {get{return (Udata)this;}}
- public Closure cl {get{return (Closure)this;}}
- public Table h {get{return (Table)this;}}
- public Proto p {get{return (Proto)this;}}
- public UpVal uv {get{return (UpVal)this;}}
- public lua_State th {get{return (lua_State)this;}}
- };
-
- /* this interface and is used for implementing GCObject references,
- it's used to emulate the behaviour of a C-style GCObject **
- */
- public interface GCObjectRef
- {
- void set(GCObject value);
- GCObject get();
- }
-
- public class ArrayRef : GCObjectRef, ArrayElement
- {
- public ArrayRef()
- {
- this.array_elements = null;
- this.array_index = 0;
- this.vals = null;
- this.index = 0;
- }
- public ArrayRef(GCObject[] array_elements, int array_index)
- {
- this.array_elements = array_elements;
- this.array_index = array_index;
- this.vals = null;
- this.index = 0;
- }
- public void set(GCObject value) { array_elements[array_index] = value; }
- public GCObject get() { return array_elements[array_index]; }
-
- public void set_index(int index)
- {
- this.index = index;
- }
- public void set_array(object vals)
- {
- // don't actually need this
- this.vals = (ArrayRef[])vals;
- Debug.Assert(this.vals != null);
- }
-
- // ArrayRef is used to reference GCObject objects in an array, the next two members
- // point to that array and the index of the GCObject element we are referencing
- GCObject[] array_elements;
- int array_index;
-
- // ArrayRef is itself stored in an array and derived from ArrayElement, the next
- // two members refer to itself i.e. the array and index of it's own instance.
- ArrayRef[] vals;
- int index;
- }
-
- public class OpenValRef : GCObjectRef
- {
- public OpenValRef(lua_State L) { this.L = L; }
- public void set(GCObject value) { this.L.openupval = value; }
- public GCObject get() { return this.L.openupval; }
- lua_State L;
- }
-
- public class RootGCRef : GCObjectRef
- {
- public RootGCRef(global_State g) { this.g = g; }
- public void set(GCObject value) { this.g.rootgc = value; }
- public GCObject get() { return this.g.rootgc; }
- global_State g;
- }
-
- public class NextRef : GCObjectRef
- {
- public NextRef(GCheader header) { this.header = header; }
- public void set(GCObject value) { this.header.next = value; }
- public GCObject get() { return this.header.next; }
- GCheader header;
- }
-
-
- /* macros to convert a GCObject into a specific value */
- public static TString rawgco2ts(GCObject o) { return (TString)check_exp(o.gch.tt == LUA_TSTRING, o.ts); }
- public static TString gco2ts(GCObject o) { return (TString)(rawgco2ts(o).tsv); }
- public static Udata rawgco2u(GCObject o) { return (Udata)check_exp(o.gch.tt == LUA_TUSERDATA, o.u); }
- public static Udata gco2u(GCObject o) { return (Udata)(rawgco2u(o).uv); }
- public static Closure gco2cl(GCObject o) { return (Closure)check_exp(o.gch.tt == LUA_TFUNCTION, o.cl); }
- public static Table gco2h(GCObject o) { return (Table)check_exp(o.gch.tt == LUA_TTABLE, o.h); }
- public static Proto gco2p(GCObject o) { return (Proto)check_exp(o.gch.tt == LUA_TPROTO, o.p); }
- public static UpVal gco2uv(GCObject o) { return (UpVal)check_exp(o.gch.tt == LUA_TUPVAL, o.uv); }
- public static UpVal ngcotouv(GCObject o) {return (UpVal)check_exp((o == null) || (o.gch.tt == LUA_TUPVAL), o.uv); }
- public static lua_State gco2th(GCObject o) { return (lua_State)check_exp(o.gch.tt == LUA_TTHREAD, o.th); }
-
- /* macro to convert any Lua object into a GCObject */
- public static GCObject obj2gco(object v) {return (GCObject)v;}
-
-
- public static int state_size(object x) { return Marshal.SizeOf(x) + LUAI_EXTRASPACE; }
- /*
- public static lu_byte fromstate(object l)
- {
- return (lu_byte)(l - LUAI_EXTRASPACE);
- }
- */
- public static lua_State tostate(object l)
- {
- Debug.Assert(LUAI_EXTRASPACE == 0, "LUAI_EXTRASPACE not supported");
- return (lua_State)l;
- }
-
-
- /*
- ** Main thread combines a thread state and the global state
- */
- public class LG : lua_State {
- public lua_State l {get {return this;}}
- public global_State g = new global_State();
- };
-
-
-
- private static void stack_init (lua_State L1, lua_State L) {
- /* initialize CallInfo array */
- L1.base_ci = luaM_newvector(L, BASIC_CI_SIZE);
- L1.ci = L1.base_ci[0];
- 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);
- L1.stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
- L1.top = L1.stack[0];
- L1.stack_last = L1.stack[L1.stacksize - EXTRA_STACK - 1];
- /* initialize first ci */
- L1.ci.func = L1.top;
- setnilvalue(StkId.inc(ref L1.top)); /* `function' entry for this `ci' */
- L1.base_ = L1.ci.base_ = L1.top;
- L1.ci.top = L1.top + LUA_MINSTACK;
- }
-
-
- private static void freestack (lua_State L, lua_State L1) {
- luaM_freearray(L, L1.base_ci);
- luaM_freearray(L, L1.stack);
- }
-
-
- /*
- ** open parts that may cause memory-allocation errors
- */
- private static void f_luaopen (lua_State L, object 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;
- }
-
-
- private static void preinit_state (lua_State L, global_State g) {
- G_set(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 = null;
- L.ci = null;
- L.savedpc = new InstructionPtr();
- L.errfunc = 0;
- setnilvalue(gt(L));
- }
-
-
- private static void close_state (lua_State L) {
- global_State g = G(L);
- luaF_close(L, L.stack[0]); /* 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);
- luaZ_freebuffer(L, g.buff);
- freestack(L, L);
- lua_assert(g.totalbytes == GetUnmanagedSize(typeof(LG)));
- //g.frealloc(g.ud, fromstate(L), (uint)state_size(typeof(LG)), 0);
- }
-
-
- private static lua_State luaE_newthread (lua_State L) {
- //lua_State L1 = tostate(luaM_malloc(L, state_size(typeof(lua_State))));
- lua_State L1 = luaM_new(L);
- 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;
- }
-
-
- private static void luaE_freethread (lua_State L, lua_State L1) {
- luaF_close(L1, L1.stack[0]); /* close all upvalues for this thread */
- lua_assert(L1.openupval == null);
- luai_userstatefree(L1);
- freestack(L, L1);
- //luaM_freemem(L, fromstate(L1));
- }
-
-
- public static lua_State lua_newstate (lua_Alloc f, object ud) {
- int i;
- lua_State L;
- global_State g;
- //object l = f(ud, null, 0, (uint)state_size(typeof(LG)));
- object l = f(typeof(LG));
- if (l == null) return null;
- L = tostate(l);
- g = (L as LG).g;
- L.next = null;
- L.tt = LUA_TTHREAD;
- g.currentwhite = (lu_byte)bit2mask(WHITE0BIT, FIXEDBIT);
- L.marked = luaC_white(g);
- lu_byte marked = L.marked; // can't pass properties in as ref
- set2bits(ref marked, FIXEDBIT, SFIXEDBIT);
- L.marked = marked;
- 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 = new RootGCRef(g);
- g.gray = null;
- g.grayagain = null;
- g.weak = null;
- g.tmudata = null;
- g.totalbytes = (uint)GetUnmanagedSize(typeof(LG));
- g.gcpause = LUAI_GCPAUSE;
- g.gcstepmul = LUAI_GCMUL;
- g.gcdept = 0;
- for (i=0; i(CallInfo ci1, CallInfo ci2)
+ {
+ Debug.Assert(ci1.values == ci2.values);
+ return ci1.index > ci2.index;
+ }
+
+ public static bool operator >=(CallInfo ci1, CallInfo ci2)
+ {
+ Debug.Assert(ci1.values == ci2.values);
+ return ci1.index >= ci2.index;
+ }
+
+ public static CallInfo inc(ref CallInfo value)
+ {
+ value = value[1];
+ return value[-1];
+ }
+
+ public static CallInfo dec(ref CallInfo value)
+ {
+ value = value[-1];
+ return value[1];
+ }
+
+ public StkId base_; /* base for this function */
+ public StkId func; /* function index in the stack */
+ public StkId top; /* top for this function */
+ public InstructionPtr savedpc;
+ public int nresults; /* expected number of results from this function */
+ public int tailcalls; /* number of tail calls lost under this entry */
+ };
+
+
+
+ public static Closure curr_func(lua_State L) { return (clvalue(L.ci.func)); }
+ public static Closure ci_func(CallInfo ci) { return (clvalue(ci.func)); }
+ public static bool f_isLua(CallInfo ci) {return ci_func(ci).c.isC==0;}
+ public static bool isLua(CallInfo ci) {return (ttisfunction((ci).func) && f_isLua(ci));}
+
+
+ /*
+ ** `global state', shared by all threads of this state
+ */
+ public class global_State {
+ public stringtable strt = new stringtable(); /* hash table for strings */
+ public lua_Alloc frealloc; /* function to reallocate memory */
+ public object ud; /* auxiliary data to `frealloc' */
+ public lu_byte currentwhite;
+ public lu_byte gcstate; /* state of garbage collector */
+ public int sweepstrgc; /* position of sweep in `strt' */
+ public GCObject rootgc; /* list of all collectable objects */
+ public GCObjectRef sweepgc; /* position of sweep in `rootgc' */
+ public GCObject gray; /* list of gray objects */
+ public GCObject grayagain; /* list of objects to be traversed atomically */
+ public GCObject weak; /* list of weak tables (to be cleared) */
+ public GCObject tmudata; /* last element of list of userdata to be GC */
+ public Mbuffer buff = new Mbuffer(); /* temporary buffer for string concatentation */
+ [CLSCompliantAttribute(false)]
+ public lu_mem GCthreshold;
+ [CLSCompliantAttribute(false)]
+ public lu_mem totalbytes; /* number of bytes currently allocated */
+ [CLSCompliantAttribute(false)]
+ public lu_mem estimate; /* an estimate of number of bytes actually in use */
+ [CLSCompliantAttribute(false)]
+ public lu_mem gcdept; /* how much GC is `behind schedule' */
+ public int gcpause; /* size of pause between successive GCs */
+ public int gcstepmul; /* GC `granularity' */
+ public lua_CFunction panic; /* to be called in unprotected errors */
+ public TValue l_registry = new TValue();
+ public lua_State mainthread;
+ public UpVal uvhead = new UpVal(); /* head of double-linked list of all open upvalues */
+ public Table[] mt = new Table[NUM_TAGS]; /* metatables for basic types */
+ public TString[] tmname = new TString[(int)TMS.TM_N]; /* array with tag-method names */
+ };
+
+
+ /*
+ ** `per thread' state
+ */
+ public class lua_State : GCObject {
+
+ public lu_byte status;
+ public StkId top; /* first free slot in the stack */
+ public StkId base_; /* base of current function */
+ public global_State l_G;
+ public CallInfo ci; /* call info for current function */
+ public InstructionPtr savedpc = new InstructionPtr(); /* `savedpc' of current function */
+ public StkId stack_last; /* last free slot in the stack */
+ public StkId[] stack; /* stack base */
+ public CallInfo end_ci; /* points after end of ci array*/
+ public CallInfo[] base_ci; /* array of CallInfo's */
+ public int stacksize;
+ public int size_ci; /* size of array `base_ci' */
+ [CLSCompliantAttribute(false)]
+ public ushort nCcalls; /* number of nested C calls */
+ [CLSCompliantAttribute(false)]
+ public ushort baseCcalls; /* nested C calls when resuming coroutine */
+ public lu_byte hookmask;
+ public lu_byte allowhook;
+ public int basehookcount;
+ public int hookcount;
+ public lua_Hook hook;
+ public TValue l_gt = new TValue(); /* table of globals */
+ public TValue env = new TValue(); /* temporary place for environments */
+ public GCObject openupval; /* list of open upvalues in this stack */
+ public GCObject gclist;
+ public lua_longjmp errorJmp; /* current error recover point */
+ public ptrdiff_t errfunc; /* current error handling function (stack index) */
+ };
+
+
+ public static global_State G(lua_State L) {return L.l_G;}
+ public static void G_set(lua_State L, global_State s) { L.l_G = s; }
+
+
+ /*
+ ** Union of all collectable objects (not a union anymore in the C# port)
+ */
+ public class GCObject : GCheader, ArrayElement
+ {
+ public void set_index(int index)
+ {
+ //this.index = index;
+ }
+
+ public void set_array(object array)
+ {
+ //this.values = (GCObject[])array;
+ //Debug.Assert(this.values != null);
+ }
+
+ public GCheader gch {get{return (GCheader)this;}}
+ public TString ts {get{return (TString)this;}}
+ public Udata u {get{return (Udata)this;}}
+ public Closure cl {get{return (Closure)this;}}
+ public Table h {get{return (Table)this;}}
+ public Proto p {get{return (Proto)this;}}
+ public UpVal uv {get{return (UpVal)this;}}
+ public lua_State th {get{return (lua_State)this;}}
+ };
+
+ /* this interface and is used for implementing GCObject references,
+ it's used to emulate the behaviour of a C-style GCObject **
+ */
+ public interface GCObjectRef
+ {
+ void set(GCObject value);
+ GCObject get();
+ }
+
+ public class ArrayRef : GCObjectRef, ArrayElement
+ {
+ public ArrayRef()
+ {
+ this.array_elements = null;
+ this.array_index = 0;
+ this.vals = null;
+ this.index = 0;
+ }
+ public ArrayRef(GCObject[] array_elements, int array_index)
+ {
+ this.array_elements = array_elements;
+ this.array_index = array_index;
+ this.vals = null;
+ this.index = 0;
+ }
+ public void set(GCObject value) { array_elements[array_index] = value; }
+ public GCObject get() { return array_elements[array_index]; }
+
+ public void set_index(int index)
+ {
+ this.index = index;
+ }
+ public void set_array(object vals)
+ {
+ // don't actually need this
+ this.vals = (ArrayRef[])vals;
+ Debug.Assert(this.vals != null);
+ }
+
+ // ArrayRef is used to reference GCObject objects in an array, the next two members
+ // point to that array and the index of the GCObject element we are referencing
+ GCObject[] array_elements;
+ int array_index;
+
+ // ArrayRef is itself stored in an array and derived from ArrayElement, the next
+ // two members refer to itself i.e. the array and index of it's own instance.
+ ArrayRef[] vals;
+ int index;
+ }
+
+ public class OpenValRef : GCObjectRef
+ {
+ public OpenValRef(lua_State L) { this.L = L; }
+ public void set(GCObject value) { this.L.openupval = value; }
+ public GCObject get() { return this.L.openupval; }
+ lua_State L;
+ }
+
+ public class RootGCRef : GCObjectRef
+ {
+ public RootGCRef(global_State g) { this.g = g; }
+ public void set(GCObject value) { this.g.rootgc = value; }
+ public GCObject get() { return this.g.rootgc; }
+ global_State g;
+ }
+
+ public class NextRef : GCObjectRef
+ {
+ public NextRef(GCheader header) { this.header = header; }
+ public void set(GCObject value) { this.header.next = value; }
+ public GCObject get() { return this.header.next; }
+ GCheader header;
+ }
+
+
+ /* macros to convert a GCObject into a specific value */
+ public static TString rawgco2ts(GCObject o) { return (TString)check_exp(o.gch.tt == LUA_TSTRING, o.ts); }
+ public static TString gco2ts(GCObject o) { return (TString)(rawgco2ts(o).tsv); }
+ public static Udata rawgco2u(GCObject o) { return (Udata)check_exp(o.gch.tt == LUA_TUSERDATA, o.u); }
+ public static Udata gco2u(GCObject o) { return (Udata)(rawgco2u(o).uv); }
+ public static Closure gco2cl(GCObject o) { return (Closure)check_exp(o.gch.tt == LUA_TFUNCTION, o.cl); }
+ public static Table gco2h(GCObject o) { return (Table)check_exp(o.gch.tt == LUA_TTABLE, o.h); }
+ public static Proto gco2p(GCObject o) { return (Proto)check_exp(o.gch.tt == LUA_TPROTO, o.p); }
+ public static UpVal gco2uv(GCObject o) { return (UpVal)check_exp(o.gch.tt == LUA_TUPVAL, o.uv); }
+ public static UpVal ngcotouv(GCObject o) {return (UpVal)check_exp((o == null) || (o.gch.tt == LUA_TUPVAL), o.uv); }
+ public static lua_State gco2th(GCObject o) { return (lua_State)check_exp(o.gch.tt == LUA_TTHREAD, o.th); }
+
+ /* macro to convert any Lua object into a GCObject */
+ public static GCObject obj2gco(object v) {return (GCObject)v;}
+
+
+ public static int state_size(object x) { return Marshal.SizeOf(x) + LUAI_EXTRASPACE; }
+ /*
+ public static lu_byte fromstate(object l)
+ {
+ return (lu_byte)(l - LUAI_EXTRASPACE);
+ }
+ */
+ public static lua_State tostate(object l)
+ {
+ Debug.Assert(LUAI_EXTRASPACE == 0, "LUAI_EXTRASPACE not supported");
+ return (lua_State)l;
+ }
+
+
+ /*
+ ** Main thread combines a thread state and the global state
+ */
+ public class LG : lua_State {
+ public lua_State l {get {return this;}}
+ public global_State g = new global_State();
+ };
+
+
+
+ private static void stack_init (lua_State L1, lua_State L) {
+ /* initialize CallInfo array */
+ L1.base_ci = luaM_newvector(L, BASIC_CI_SIZE);
+ L1.ci = L1.base_ci[0];
+ 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);
+ L1.stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
+ L1.top = L1.stack[0];
+ L1.stack_last = L1.stack[L1.stacksize - EXTRA_STACK - 1];
+ /* initialize first ci */
+ L1.ci.func = L1.top;
+ setnilvalue(StkId.inc(ref L1.top)); /* `function' entry for this `ci' */
+ L1.base_ = L1.ci.base_ = L1.top;
+ L1.ci.top = L1.top + LUA_MINSTACK;
+ }
+
+
+ private static void freestack (lua_State L, lua_State L1) {
+ luaM_freearray(L, L1.base_ci);
+ luaM_freearray(L, L1.stack);
+ }
+
+
+ /*
+ ** open parts that may cause memory-allocation errors
+ */
+ private static void f_luaopen (lua_State L, object 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;
+ }
+
+
+ private static void preinit_state (lua_State L, global_State g) {
+ G_set(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 = null;
+ L.ci = null;
+ L.savedpc = new InstructionPtr();
+ L.errfunc = 0;
+ setnilvalue(gt(L));
+ }
+
+
+ private static void close_state (lua_State L) {
+ global_State g = G(L);
+ luaF_close(L, L.stack[0]); /* 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);
+ luaZ_freebuffer(L, g.buff);
+ freestack(L, L);
+ lua_assert(g.totalbytes == GetUnmanagedSize(typeof(LG)));
+ //g.frealloc(g.ud, fromstate(L), (uint)state_size(typeof(LG)), 0);
+ }
+
+
+ private static lua_State luaE_newthread (lua_State L) {
+ //lua_State L1 = tostate(luaM_malloc(L, state_size(typeof(lua_State))));
+ lua_State L1 = luaM_new(L);
+ 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;
+ }
+
+
+ private static void luaE_freethread (lua_State L, lua_State L1) {
+ luaF_close(L1, L1.stack[0]); /* close all upvalues for this thread */
+ lua_assert(L1.openupval == null);
+ luai_userstatefree(L1);
+ freestack(L, L1);
+ //luaM_freemem(L, fromstate(L1));
+ }
+
+
+ public static lua_State lua_newstate (lua_Alloc f, object ud) {
+ int i;
+ lua_State L;
+ global_State g;
+ //object l = f(ud, null, 0, (uint)state_size(typeof(LG)));
+ object l = f(typeof(LG));
+ if (l == null) return null;
+ L = tostate(l);
+ g = (L as LG).g;
+ L.next = null;
+ L.tt = LUA_TTHREAD;
+ g.currentwhite = (lu_byte)bit2mask(WHITE0BIT, FIXEDBIT);
+ L.marked = luaC_white(g);
+ lu_byte marked = L.marked; // can't pass properties in as ref
+ set2bits(ref marked, FIXEDBIT, SFIXEDBIT);
+ L.marked = marked;
+ 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 = new RootGCRef(g);
+ g.gray = null;
+ g.grayagain = null;
+ g.weak = null;
+ g.tmudata = null;
+ g.totalbytes = (uint)GetUnmanagedSize(typeof(LG));
+ g.gcpause = LUAI_GCPAUSE;
+ g.gcstepmul = LUAI_GCMUL;
+ g.gcdept = 0;
+ for (i=0; i MAX_SIZET /GetUnmanagedSize(typeof(char)))
- luaM_toobig(L);
- ts = new TString(new char[l+1]);
- AddTotalBytes(L, (int)(l + 1) * GetUnmanagedSize(typeof(char)) + GetUnmanagedSize(typeof(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*GetUnmanagedSize(typeof(char)));
- memcpy(ts.str.chars, str.chars, str.index, (int)l);
- ts.str[l] = '\0'; /* ending 0 */
- tb = G(L).strt;
- h = (uint)lmod(h, tb.size);
- ts.tsv.next = tb.hash[h]; /* chain new entry */
- tb.hash[h] = obj2gco(ts);
- tb.nuse++;
- if ((tb.nuse > (int)tb.size) && (tb.size <= MAX_INT/2))
- luaS_resize(L, tb.size*2); /* too crowded */
- return ts;
- }
-
- [CLSCompliantAttribute(false)]
- public static TString luaS_newlstr (lua_State L, CharPtr str, uint l) {
- GCObject o;
- uint h = (uint)l; /* seed */
- uint step = (l>>5)+1; /* if string is too long, don't hash all its chars */
- uint l1;
- for (l1=l; l1>=step; l1-=step) /* compute hash */
- h = h ^ ((h<<5)+(h>>2)+(byte)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 */
- TString res = newlstr(L, str, l, h);
- return res;
- }
-
- [CLSCompliantAttribute(false)]
- public static Udata luaS_newudata(lua_State L, uint s, Table e)
- {
- Udata u = new 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;
- u.user_data = new byte[s];
- AddTotalBytes(L, GetUnmanagedSize(typeof(Udata)) + sizeudata(u));
- /* chain it on udata list (after main thread) */
- u.uv.next = G(L).mainthread.next;
- G(L).mainthread.next = obj2gco(u);
- return u;
- }
-
- internal static Udata luaS_newudata(lua_State L, Type t, Table e)
- {
- Udata u = new Udata();
- u.uv.marked = luaC_white(G(L)); /* is not finalized */
- u.uv.tt = LUA_TUSERDATA;
- u.uv.len = 0; /* gfoot: not sizeof(t)? */
- u.uv.metatable = null;
- u.uv.env = e;
- u.user_data = luaM_realloc_(L, t);
- AddTotalBytes(L, GetUnmanagedSize(typeof(Udata)));
- /* chain it on udata list (after main thread) */
- u.uv.next = G(L).mainthread.next;
- G(L).mainthread.next = obj2gco(u);
- return u;
- }
-
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace KopiLua
+{
+ using lu_byte = System.Byte;
+
+ public partial class Lua
+ {
+ public static int sizestring(TString s) {return ((int)s.len + 1) * GetUnmanagedSize(typeof(char)); }
+
+ public static int sizeudata(Udata u) { return (int)u.len; }
+
+ public static TString luaS_new(lua_State L, CharPtr s) { return luaS_newlstr(L, s, (uint)strlen(s)); }
+ public static TString luaS_newliteral(lua_State L, CharPtr s) { return luaS_newlstr(L, s, (uint)strlen(s)); }
+
+ public static void luaS_fix(TString s)
+ {
+ lu_byte marked = s.tsv.marked; // can't pass properties in as ref
+ l_setbit(ref marked, FIXEDBIT);
+ s.tsv.marked = marked;
+ }
+
+ public static 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 = new GCObject[newsize];
+ AddTotalBytes(L, newsize * GetUnmanagedSize(typeof(GCObjectRef)));
+ tb = G(L).strt;
+ for (i=0; i MAX_SIZET /GetUnmanagedSize(typeof(char)))
+ luaM_toobig(L);
+ ts = new TString(new char[l+1]);
+ AddTotalBytes(L, (int)(l + 1) * GetUnmanagedSize(typeof(char)) + GetUnmanagedSize(typeof(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*GetUnmanagedSize(typeof(char)));
+ memcpy(ts.str.chars, str.chars, str.index, (int)l);
+ ts.str[l] = '\0'; /* ending 0 */
+ tb = G(L).strt;
+ h = (uint)lmod(h, tb.size);
+ ts.tsv.next = tb.hash[h]; /* chain new entry */
+ tb.hash[h] = obj2gco(ts);
+ tb.nuse++;
+ if ((tb.nuse > (int)tb.size) && (tb.size <= MAX_INT/2))
+ luaS_resize(L, tb.size*2); /* too crowded */
+ return ts;
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static TString luaS_newlstr (lua_State L, CharPtr str, uint l) {
+ GCObject o;
+ uint h = (uint)l; /* seed */
+ uint step = (l>>5)+1; /* if string is too long, don't hash all its chars */
+ uint l1;
+ for (l1=l; l1>=step; l1-=step) /* compute hash */
+ h = h ^ ((h<<5)+(h>>2)+(byte)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 */
+ TString res = newlstr(L, str, l, h);
+ return res;
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static Udata luaS_newudata(lua_State L, uint s, Table e)
+ {
+ Udata u = new 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;
+ u.user_data = new byte[s];
+ AddTotalBytes(L, GetUnmanagedSize(typeof(Udata)) + sizeudata(u));
+ /* chain it on udata list (after main thread) */
+ u.uv.next = G(L).mainthread.next;
+ G(L).mainthread.next = obj2gco(u);
+ return u;
+ }
+
+ internal static Udata luaS_newudata(lua_State L, Type t, Table e)
+ {
+ Udata u = new Udata();
+ u.uv.marked = luaC_white(G(L)); /* is not finalized */
+ u.uv.tt = LUA_TUSERDATA;
+ u.uv.len = 0; /* gfoot: not sizeof(t)? */
+ u.uv.metatable = null;
+ u.uv.env = e;
+ u.user_data = luaM_realloc_(L, t);
+ AddTotalBytes(L, GetUnmanagedSize(typeof(Udata)));
+ /* chain it on udata list (after main thread) */
+ u.uv.next = G(L).mainthread.next;
+ G(L).mainthread.next = obj2gco(u);
+ return u;
+ }
+
+ }
+}
diff --git a/Core/KopiLua/lstrlib.cs b/Core/KopiLua/lstrlib.cs
index 61389690beb1046b7282aaab6365b8b4a5b45b76..184b8e5a6f8be6a56e8a8c71b9f77ddde30cc1fa 100644
--- a/Core/KopiLua/lstrlib.cs
+++ b/Core/KopiLua/lstrlib.cs
@@ -1,966 +1,966 @@
-/*
-** $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
-*/
-
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-
-namespace KopiLua
-{
- using ptrdiff_t = System.Int32;
- using lua_Integer = System.Int32;
- using LUA_INTFRM_T = System.Int64;
- using UNSIGNED_LUA_INTFRM_T = System.UInt64;
-
- public partial class Lua
- {
- private static int str_len (lua_State L) {
- uint l;
- luaL_checklstring(L, 1, out l);
- lua_pushinteger(L, (int)l);
- return 1;
- }
-
-
- private static ptrdiff_t posrelat (ptrdiff_t pos, uint len) {
- /* relative string position: negative means back from end */
- if (pos < 0) pos += (ptrdiff_t)len + 1;
- return (pos >= 0) ? pos : 0;
- }
-
-
- private static int str_sub (lua_State L) {
- uint l;
- CharPtr s = luaL_checklstring(L, 1, out 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, (uint)(end-start+1));
- else lua_pushliteral(L, "");
- return 1;
- }
-
-
- private static int str_reverse (lua_State L) {
- uint l;
- luaL_Buffer b = new luaL_Buffer();
- CharPtr s = luaL_checklstring(L, 1, out l);
- luaL_buffinit(L, b);
- while ((l--) != 0) luaL_addchar(b, s[l]);
- luaL_pushresult(b);
- return 1;
- }
-
-
- private static int str_lower (lua_State L) {
- uint l;
- uint i;
- luaL_Buffer b = new luaL_Buffer();
- CharPtr s = luaL_checklstring(L, 1, out l);
- luaL_buffinit(L, b);
- for (i=0; i 0)
- luaL_addlstring(b, s, l);
- luaL_pushresult(b);
- return 1;
- }
-
-
- private static int str_byte (lua_State L) {
- uint l;
- CharPtr s = luaL_checklstring(L, 1, out 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 ((uint)pose > l) pose = (int)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;
- }
-
-
- private 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");
- }
-
-
- private static CharPtr classend (MatchState ms, CharPtr p) {
- p = new CharPtr(p);
- char c = p[0];
- p = p.next();
- switch (c) {
- case L_ESC: {
- if (p[0] == '\0')
- luaL_error(ms.L, "malformed pattern (ends with " + LUA_QL("%%") + ")");
- return p+1;
- }
- case '[': {
- if (p[0] == '^') p = p.next();
- do { /* look for a `]' */
- if (p[0] == '\0')
- luaL_error(ms.L, "malformed pattern (missing " + LUA_QL("]") + ")");
- c = p[0];
- p = p.next();
- if (c == L_ESC && p[0] != '\0')
- p = p.next(); /* skip escapes (e.g. `%]') */
- } while (p[0] != ']');
- return p+1;
- }
- default: {
- return p;
- }
- }
- }
-
-
- private static int match_class (int c, int cl) {
- bool 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((char)c); break;
- case 'z' : res = (c == 0); break;
- default: return (cl == c) ? 1 : 0;
- }
- return (islower(cl) ? (res ? 1 : 0) : ((!res) ? 1 : 0));
- }
-
-
- private static int matchbracketclass (int c, CharPtr p, CharPtr ec) {
- int sig = 1;
- if (p[1] == '^') {
- sig = 0;
- p = p.next(); /* skip the `^' */
- }
- while ((p=p.next()) < ec) {
- if (p == L_ESC) {
- p = p.next();
- if (match_class(c, (byte)(p[0])) != 0)
- return sig;
- }
- else if ((p[1] == '-') && (p + 2 < ec)) {
- p+=2;
- if ((byte)((p[-2])) <= c && (c <= (byte)p[0]))
- return sig;
- }
- else if ((byte)(p[0]) == c) return sig;
- }
- return (sig == 0) ? 1 : 0;
- }
-
-
- private static int singlematch (int c, CharPtr p, CharPtr ep) {
- switch (p[0]) {
- case '.': return 1; /* matches any char */
- case L_ESC: return match_class(c, (byte)(p[1]));
- case '[': return matchbracketclass(c, p, ep-1);
- default: return ((byte)(p[0]) == c) ? 1 : 0;
- }
- }
-
-
- private static CharPtr matchbalance (MatchState ms, CharPtr s,
- CharPtr p) {
- if ((p[0] == 0) || (p[1] == 0))
- luaL_error(ms.L, "unbalanced pattern");
- if (s[0] != p[0]) return null;
- else {
- int b = p[0];
- int e = p[1];
- int cont = 1;
- while ((s=s.next()) < ms.src_end) {
- if (s[0] == e) {
- if (--cont == 0) return s+1;
- }
- else if (s[0] == b) cont++;
- }
- }
- return null; /* string ends out of balance */
- }
-
-
- private static CharPtr max_expand (MatchState ms, CharPtr s,
- CharPtr p, CharPtr ep) {
- ptrdiff_t i = 0; /* counts maximum expand for item */
- while ( (s+i < ms.src_end) && (singlematch((byte)(s[i]), p, ep) != 0) )
- i++;
- /* keeps trying to match with the maximum repetitions */
- while (i>=0) {
- CharPtr res = match(ms, (s+i), ep+1);
- if (res != null) return res;
- i--; /* else didn't match; reduce 1 repetition to try again */
- }
- return null;
- }
-
-
- private static CharPtr min_expand (MatchState ms, CharPtr s,
- CharPtr p, CharPtr ep) {
- for (;;) {
- CharPtr res = match(ms, s, ep+1);
- if (res != null)
- return res;
- else if ( (s < ms.src_end) && (singlematch((byte)(s[0]), p, ep) != 0) )
- s = s.next(); /* try with one more repetition */
- else return null;
- }
- }
-
-
- private static CharPtr start_capture (MatchState ms, CharPtr s,
- CharPtr p, int what) {
- CharPtr 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;
- }
-
-
- private static CharPtr end_capture(MatchState ms, CharPtr s,
- CharPtr p) {
- int l = capture_to_close(ms);
- CharPtr 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;
- }
-
-
- private static CharPtr match_capture(MatchState ms, CharPtr s, int l)
- {
- uint len;
- l = check_capture(ms, l);
- len = (uint)ms.capture[l].len;
- if ((uint)(ms.src_end-s) >= len &&
- memcmp(ms.capture[l].init, s, len) == 0)
- return s+len;
- else return null;
- }
-
-
- private static CharPtr match (MatchState ms, CharPtr s, CharPtr p) {
- s = new CharPtr(s);
- p = new CharPtr(p);
- init: /* using goto's to optimize tail recursion */
- switch (p[0]) {
- 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? */
- CharPtr ep; char previous;
- p += 2;
- if (p[0] != '[')
- 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((byte)(previous), p, ep-1)!=0) ||
- (matchbracketclass((byte)(s[0]), p, ep-1)==0)) return null;
- p=ep; goto init; /* else return match(ms, s, ep); */
- }
- default: {
- if (isdigit((byte)(p[1]))) { /* capture results (%0-%9)? */
- s = match_capture(ms, s, (byte)(p[1]));
- if (s == null) return null;
- p+=2; goto init; /* else return match(ms, s, p+2) */
- }
- //ismeretlen hiba miatt lett ide átmásolva
- { /* it is a pattern item */
- CharPtr ep = classend(ms, p); /* points to what is next */
- int m = (s l1) return null; /* avoids a negative `l1' */
- else {
- CharPtr 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 = memchr(s1, s2[0], l1)) != null) {
- init = init.next(); /* 1st char is already checked */
- if (memcmp(init, s2+1, l2) == 0)
- return init-1;
- else { /* correct `l1' and `s1' to try again */
- l1 -= (uint)(init-s1);
- s1 = init;
- }
- }
- return null; /* not found */
- }
- }
-
-
- private static void push_onecapture (MatchState ms, int i, CharPtr s,
- CharPtr e) {
- if (i >= ms.level) {
- if (i == 0) /* ms.level == 0, too */
- lua_pushlstring(ms.L, s, (uint)(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, (uint)l);
- }
- }
-
-
- private static int push_captures (MatchState ms, CharPtr s, CharPtr e) {
- int i;
- int nlevels = ((ms.level == 0) && (s!=null)) ? 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 */
- }
-
-
- private static int str_find_aux (lua_State L, int find) {
- uint l1, l2;
- CharPtr s = luaL_checklstring(L, 1, out l1);
- CharPtr p = luaL_checklstring(L, 2, out l2);
- ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
- if (init < 0) init = 0;
- else if ((uint)(init) > l1) init = (ptrdiff_t)l1;
- if ((find!=0) && ((lua_toboolean(L, 4)!=0) || /* explicit request? */
- strpbrk(p, SPECIALS) == null)) { /* or no special characters? */
- /* do a plain search */
- CharPtr s2 = lmemfind(s+init, (uint)(l1-init), p, (uint)(l2));
- if (s2 != null) {
- lua_pushinteger(L, s2-s+1);
- lua_pushinteger(L, (int)(s2-s+l2));
- return 2;
- }
- }
- else {
- MatchState ms = new MatchState();
- int anchor = 0;
- if (p[0] == '^')
- {
- p = p.next();
- anchor = 1;
- }
- CharPtr s1=s+init;
- ms.L = L;
- ms.src_init = s;
- ms.src_end = s+l1;
- do {
- CharPtr res;
- ms.level = 0;
- if ((res=match(ms, s1, p)) != null) {
- if (find != 0) {
- lua_pushinteger(L, s1-s+1); /* start */
- lua_pushinteger(L, res-s); /* end */
- return push_captures(ms, null, null) + 2;
- }
- else
- return push_captures(ms, s1, res);
- }
- } while (((s1=s1.next()) <= ms.src_end) && (anchor==0));
- }
- lua_pushnil(L); /* not found */
- return 1;
- }
-
-
- private static int str_find (lua_State L) {
- return str_find_aux(L, 1);
- }
-
-
- private static int str_match (lua_State L) {
- return str_find_aux(L, 0);
- }
-
-
- private static int gmatch_aux (lua_State L) {
- MatchState ms = new MatchState();
- uint ls;
- CharPtr s = lua_tolstring(L, lua_upvalueindex(1), out ls);
- CharPtr p = lua_tostring(L, lua_upvalueindex(2));
- CharPtr src;
- ms.L = L;
- ms.src_init = s;
- ms.src_end = s+ls;
- for (src = s + (uint)lua_tointeger(L, lua_upvalueindex(3));
- src <= ms.src_end;
- src = src.next()) {
- CharPtr 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 */
- }
-
-
- private 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;
- }
-
-
- private static int gfind_nodef (lua_State L) {
- return luaL_error(L, LUA_QL("string.gfind") + " was renamed to " +
- LUA_QL("string.gmatch"));
- }
-
-
- private static void add_s (MatchState ms, luaL_Buffer b, CharPtr s,
- CharPtr e) {
- uint l, i;
- CharPtr news = lua_tolstring(ms.L, 3, out l);
- for (i = 0; i < l; i++) {
- if (news[i] != L_ESC)
- luaL_addchar(b, news[i]);
- else {
- i++; /* skip ESC */
- if (!isdigit((byte)(news[i])))
- luaL_addchar(b, news[i]);
- else if (news[i] == '0')
- luaL_addlstring(b, s, (uint)(e - s));
- else {
- push_onecapture(ms, news[i] - '1', s, e);
- luaL_addvalue(b); /* add capture to accumulated result */
- }
- }
- }
- }
-
-
- private static void add_value (MatchState ms, luaL_Buffer b, CharPtr s,
- CharPtr 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_TUSERDATA:
- 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)==0) { /* nil or false? */
- lua_pop(L, 1);
- lua_pushlstring(L, s, (uint)(e - s)); /* keep original text */
- }
- else if (lua_isstring(L, -1)==0)
- luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
- luaL_addvalue(b); /* add result to accumulator */
- }
-
-
- private static int str_gsub (lua_State L) {
- uint srcl;
- CharPtr src = luaL_checklstring(L, 1, out srcl);
- CharPtr p = luaL_checkstring(L, 2);
- int tr = lua_type(L, 3);
- int max_s = luaL_optint(L, 4, (int)(srcl+1));
- int anchor = 0;
- if (p[0] == '^')
- {
- p = p.next();
- anchor = 1;
- }
- int n = 0;
- MatchState ms = new MatchState();
- luaL_Buffer b = new luaL_Buffer();
- luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
- tr == LUA_TFUNCTION || tr == LUA_TTABLE ||
- tr == LUA_TUSERDATA, 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) {
- CharPtr e;
- ms.level = 0;
- e = match(ms, src, p);
- if (e != null) {
- n++;
- add_value(ms, b, src, e);
- }
- if ((e!=null) && e>src) /* non empty match? */
- src = e; /* skip it */
- else if (src < ms.src_end)
- {
- char c = src[0];
- src = src.next();
- luaL_addchar(b, c);
- }
- else break;
- if (anchor != 0) break;
- }
- luaL_addlstring(b, src, (uint)(ms.src_end-src));
- luaL_pushresult(b);
- lua_pushinteger(L, n); /* number of substitutions */
- return 2;
- }
-
- /* }====================================================== */
-
-
- /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
- public const int MAX_ITEM = 512;
- /* valid flags in a format specification */
- public const string FLAGS = "-+ #0";
- /*
- ** maximum size of each format specification (such as '%-099.99d')
- ** (+10 accounts for %99.99x plus margin of error)
- */
- public static readonly int MAX_FORMAT = (FLAGS.Length+1) + (LUA_INTFRMLEN.Length+1) + 10;
-
-
- private static void addquoted (lua_State L, luaL_Buffer b, int arg) {
- uint l;
- CharPtr s = luaL_checklstring(L, arg, out l);
- luaL_addchar(b, '"');
- while ((l--) != 0) {
- switch (s[0]) {
- case '"': case '\\': case '\n': {
- luaL_addchar(b, '\\');
- luaL_addchar(b, s[0]);
- break;
- }
- case '\r': {
- luaL_addlstring(b, "\\r", 2);
- break;
- }
- case '\0': {
- luaL_addlstring(b, "\\000", 4);
- break;
- }
- default: {
- luaL_addchar(b, s[0]);
- break;
- }
- }
- s = s.next();
- }
- luaL_addchar(b, '"');
- }
-
- private static CharPtr scanformat (lua_State L, CharPtr strfrmt, CharPtr form) {
- CharPtr p = strfrmt;
- while (p[0] != '\0' && strchr(FLAGS, p[0]) != null) p = p.next(); /* skip flags */
- if ((uint)(p - strfrmt) >= (FLAGS.Length+1))
- luaL_error(L, "invalid format (repeated flags)");
- if (isdigit((byte)(p[0]))) p = p.next(); /* skip width */
- if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */
- if (p[0] == '.') {
- p = p.next();
- if (isdigit((byte)(p[0]))) p = p.next(); /* skip precision */
- if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */
- }
- if (isdigit((byte)(p[0])))
- luaL_error(L, "invalid format (width or precision too long)");
- form[0] = '%';
- form = form.next();
- strncpy(form, strfrmt, p - strfrmt + 1);
- form += p - strfrmt + 1;
- form[0] = '\0';
- return p;
- }
-
-
- private static void addintlen (CharPtr form) {
- uint l = (uint)strlen(form);
- char spec = form[l - 1];
- strcpy(form + l - 1, LUA_INTFRMLEN);
- form[l + (LUA_INTFRMLEN.Length + 1) - 2] = spec;
- form[l + (LUA_INTFRMLEN.Length + 1) - 1] = '\0';
- }
-
-
- private static int str_format (lua_State L) {
- int arg = 1;
- uint sfl;
- CharPtr strfrmt = luaL_checklstring(L, arg, out sfl);
- CharPtr strfrmt_end = strfrmt+sfl;
- luaL_Buffer b = new luaL_Buffer();
- luaL_buffinit(L, b);
- while (strfrmt < strfrmt_end) {
- if (strfrmt[0] != L_ESC)
- {
- luaL_addchar(b, strfrmt[0]);
- strfrmt = strfrmt.next();
- }
- else if (strfrmt[1] == L_ESC)
- {
- luaL_addchar(b, strfrmt[0]); /* %% */
- strfrmt = strfrmt + 2;
- }
- else
- { /* format item */
- strfrmt = strfrmt.next();
- CharPtr form = new char[MAX_FORMAT]; /* to store the format (`%...') */
- CharPtr buff = new char[MAX_ITEM]; /* to store the formatted item */
- arg++;
- strfrmt = scanformat(L, strfrmt, form);
- char ch = strfrmt[0];
- strfrmt = strfrmt.next();
- switch (ch)
- {
- 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 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- {
- sprintf(buff, form, (double)luaL_checknumber(L, arg));
- break;
- }
- case 'q':
- {
- addquoted(L, b, arg);
- continue; /* skip the 'addsize' at the end */
- }
- case 's':
- {
- uint l;
- CharPtr s = luaL_checklstring(L, arg, out l);
- if ((strchr(form, '.') == null) && 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' */
- return luaL_error(L, "invalid option " + LUA_QL("%%%c") + " to " +
- LUA_QL("format"), strfrmt[-1]);
- }
- }
- luaL_addlstring(b, buff, (uint)strlen(buff));
- }
- }
- luaL_pushresult(b);
- return 1;
- }
-
-
- private readonly static luaL_Reg[] strlib = {
- new luaL_Reg("byte", str_byte),
- new luaL_Reg("char", str_char),
- new luaL_Reg("dump", str_dump),
- new luaL_Reg("find", str_find),
- new luaL_Reg("format", str_format),
- new luaL_Reg("gfind", gfind_nodef),
- new luaL_Reg("gmatch", gmatch),
- new luaL_Reg("gsub", str_gsub),
- new luaL_Reg("len", str_len),
- new luaL_Reg("lower", str_lower),
- new luaL_Reg("match", str_match),
- new luaL_Reg("rep", str_rep),
- new luaL_Reg("reverse", str_reverse),
- new luaL_Reg("sub", str_sub),
- new luaL_Reg("upper", str_upper),
- new luaL_Reg(null, null)
- };
-
-
- private 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
- */
- public static int luaopen_string (lua_State L) {
- luaL_register(L, LUA_STRLIBNAME, strlib);
- #if LUA_COMPAT_GFIND
- lua_getfield(L, -1, "gmatch");
- lua_setfield(L, -2, "gfind");
- #endif
- createmetatable(L);
- return 1;
- }
-
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace KopiLua
+{
+ using ptrdiff_t = System.Int32;
+ using lua_Integer = System.Int32;
+ using LUA_INTFRM_T = System.Int64;
+ using UNSIGNED_LUA_INTFRM_T = System.UInt64;
+
+ public partial class Lua
+ {
+ private static int str_len (lua_State L) {
+ uint l;
+ luaL_checklstring(L, 1, out l);
+ lua_pushinteger(L, (int)l);
+ return 1;
+ }
+
+
+ private static ptrdiff_t posrelat (ptrdiff_t pos, uint len) {
+ /* relative string position: negative means back from end */
+ if (pos < 0) pos += (ptrdiff_t)len + 1;
+ return (pos >= 0) ? pos : 0;
+ }
+
+
+ private static int str_sub (lua_State L) {
+ uint l;
+ CharPtr s = luaL_checklstring(L, 1, out 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, (uint)(end-start+1));
+ else lua_pushliteral(L, "");
+ return 1;
+ }
+
+
+ private static int str_reverse (lua_State L) {
+ uint l;
+ luaL_Buffer b = new luaL_Buffer();
+ CharPtr s = luaL_checklstring(L, 1, out l);
+ luaL_buffinit(L, b);
+ while ((l--) != 0) luaL_addchar(b, s[l]);
+ luaL_pushresult(b);
+ return 1;
+ }
+
+
+ private static int str_lower (lua_State L) {
+ uint l;
+ uint i;
+ luaL_Buffer b = new luaL_Buffer();
+ CharPtr s = luaL_checklstring(L, 1, out l);
+ luaL_buffinit(L, b);
+ for (i=0; i 0)
+ luaL_addlstring(b, s, l);
+ luaL_pushresult(b);
+ return 1;
+ }
+
+
+ private static int str_byte (lua_State L) {
+ uint l;
+ CharPtr s = luaL_checklstring(L, 1, out 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 ((uint)pose > l) pose = (int)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;
+ }
+
+
+ private 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");
+ }
+
+
+ private static CharPtr classend (MatchState ms, CharPtr p) {
+ p = new CharPtr(p);
+ char c = p[0];
+ p = p.next();
+ switch (c) {
+ case L_ESC: {
+ if (p[0] == '\0')
+ luaL_error(ms.L, "malformed pattern (ends with " + LUA_QL("%%") + ")");
+ return p+1;
+ }
+ case '[': {
+ if (p[0] == '^') p = p.next();
+ do { /* look for a `]' */
+ if (p[0] == '\0')
+ luaL_error(ms.L, "malformed pattern (missing " + LUA_QL("]") + ")");
+ c = p[0];
+ p = p.next();
+ if (c == L_ESC && p[0] != '\0')
+ p = p.next(); /* skip escapes (e.g. `%]') */
+ } while (p[0] != ']');
+ return p+1;
+ }
+ default: {
+ return p;
+ }
+ }
+ }
+
+
+ private static int match_class (int c, int cl) {
+ bool 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((char)c); break;
+ case 'z' : res = (c == 0); break;
+ default: return (cl == c) ? 1 : 0;
+ }
+ return (islower(cl) ? (res ? 1 : 0) : ((!res) ? 1 : 0));
+ }
+
+
+ private static int matchbracketclass (int c, CharPtr p, CharPtr ec) {
+ int sig = 1;
+ if (p[1] == '^') {
+ sig = 0;
+ p = p.next(); /* skip the `^' */
+ }
+ while ((p=p.next()) < ec) {
+ if (p == L_ESC) {
+ p = p.next();
+ if (match_class(c, (byte)(p[0])) != 0)
+ return sig;
+ }
+ else if ((p[1] == '-') && (p + 2 < ec)) {
+ p+=2;
+ if ((byte)((p[-2])) <= c && (c <= (byte)p[0]))
+ return sig;
+ }
+ else if ((byte)(p[0]) == c) return sig;
+ }
+ return (sig == 0) ? 1 : 0;
+ }
+
+
+ private static int singlematch (int c, CharPtr p, CharPtr ep) {
+ switch (p[0]) {
+ case '.': return 1; /* matches any char */
+ case L_ESC: return match_class(c, (byte)(p[1]));
+ case '[': return matchbracketclass(c, p, ep-1);
+ default: return ((byte)(p[0]) == c) ? 1 : 0;
+ }
+ }
+
+
+ private static CharPtr matchbalance (MatchState ms, CharPtr s,
+ CharPtr p) {
+ if ((p[0] == 0) || (p[1] == 0))
+ luaL_error(ms.L, "unbalanced pattern");
+ if (s[0] != p[0]) return null;
+ else {
+ int b = p[0];
+ int e = p[1];
+ int cont = 1;
+ while ((s=s.next()) < ms.src_end) {
+ if (s[0] == e) {
+ if (--cont == 0) return s+1;
+ }
+ else if (s[0] == b) cont++;
+ }
+ }
+ return null; /* string ends out of balance */
+ }
+
+
+ private static CharPtr max_expand (MatchState ms, CharPtr s,
+ CharPtr p, CharPtr ep) {
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ( (s+i < ms.src_end) && (singlematch((byte)(s[i]), p, ep) != 0) )
+ i++;
+ /* keeps trying to match with the maximum repetitions */
+ while (i>=0) {
+ CharPtr res = match(ms, (s+i), ep+1);
+ if (res != null) return res;
+ i--; /* else didn't match; reduce 1 repetition to try again */
+ }
+ return null;
+ }
+
+
+ private static CharPtr min_expand (MatchState ms, CharPtr s,
+ CharPtr p, CharPtr ep) {
+ for (;;) {
+ CharPtr res = match(ms, s, ep+1);
+ if (res != null)
+ return res;
+ else if ( (s < ms.src_end) && (singlematch((byte)(s[0]), p, ep) != 0) )
+ s = s.next(); /* try with one more repetition */
+ else return null;
+ }
+ }
+
+
+ private static CharPtr start_capture (MatchState ms, CharPtr s,
+ CharPtr p, int what) {
+ CharPtr 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;
+ }
+
+
+ private static CharPtr end_capture(MatchState ms, CharPtr s,
+ CharPtr p) {
+ int l = capture_to_close(ms);
+ CharPtr 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;
+ }
+
+
+ private static CharPtr match_capture(MatchState ms, CharPtr s, int l)
+ {
+ uint len;
+ l = check_capture(ms, l);
+ len = (uint)ms.capture[l].len;
+ if ((uint)(ms.src_end-s) >= len &&
+ memcmp(ms.capture[l].init, s, len) == 0)
+ return s+len;
+ else return null;
+ }
+
+
+ private static CharPtr match (MatchState ms, CharPtr s, CharPtr p) {
+ s = new CharPtr(s);
+ p = new CharPtr(p);
+ init: /* using goto's to optimize tail recursion */
+ switch (p[0]) {
+ 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? */
+ CharPtr ep; char previous;
+ p += 2;
+ if (p[0] != '[')
+ 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((byte)(previous), p, ep-1)!=0) ||
+ (matchbracketclass((byte)(s[0]), p, ep-1)==0)) return null;
+ p=ep; goto init; /* else return match(ms, s, ep); */
+ }
+ default: {
+ if (isdigit((byte)(p[1]))) { /* capture results (%0-%9)? */
+ s = match_capture(ms, s, (byte)(p[1]));
+ if (s == null) return null;
+ p+=2; goto init; /* else return match(ms, s, p+2) */
+ }
+ //ismeretlen hiba miatt lett ide átmásolva
+ { /* it is a pattern item */
+ CharPtr ep = classend(ms, p); /* points to what is next */
+ int m = (s l1) return null; /* avoids a negative `l1' */
+ else {
+ CharPtr 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 = memchr(s1, s2[0], l1)) != null) {
+ init = init.next(); /* 1st char is already checked */
+ if (memcmp(init, s2+1, l2) == 0)
+ return init-1;
+ else { /* correct `l1' and `s1' to try again */
+ l1 -= (uint)(init-s1);
+ s1 = init;
+ }
+ }
+ return null; /* not found */
+ }
+ }
+
+
+ private static void push_onecapture (MatchState ms, int i, CharPtr s,
+ CharPtr e) {
+ if (i >= ms.level) {
+ if (i == 0) /* ms.level == 0, too */
+ lua_pushlstring(ms.L, s, (uint)(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, (uint)l);
+ }
+ }
+
+
+ private static int push_captures (MatchState ms, CharPtr s, CharPtr e) {
+ int i;
+ int nlevels = ((ms.level == 0) && (s!=null)) ? 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 */
+ }
+
+
+ private static int str_find_aux (lua_State L, int find) {
+ uint l1, l2;
+ CharPtr s = luaL_checklstring(L, 1, out l1);
+ CharPtr p = luaL_checklstring(L, 2, out l2);
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((uint)(init) > l1) init = (ptrdiff_t)l1;
+ if ((find!=0) && ((lua_toboolean(L, 4)!=0) || /* explicit request? */
+ strpbrk(p, SPECIALS) == null)) { /* or no special characters? */
+ /* do a plain search */
+ CharPtr s2 = lmemfind(s+init, (uint)(l1-init), p, (uint)(l2));
+ if (s2 != null) {
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, (int)(s2-s+l2));
+ return 2;
+ }
+ }
+ else {
+ MatchState ms = new MatchState();
+ int anchor = 0;
+ if (p[0] == '^')
+ {
+ p = p.next();
+ anchor = 1;
+ }
+ CharPtr s1=s+init;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+l1;
+ do {
+ CharPtr res;
+ ms.level = 0;
+ if ((res=match(ms, s1, p)) != null) {
+ if (find != 0) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(ms, null, null) + 2;
+ }
+ else
+ return push_captures(ms, s1, res);
+ }
+ } while (((s1=s1.next()) <= ms.src_end) && (anchor==0));
+ }
+ lua_pushnil(L); /* not found */
+ return 1;
+ }
+
+
+ private static int str_find (lua_State L) {
+ return str_find_aux(L, 1);
+ }
+
+
+ private static int str_match (lua_State L) {
+ return str_find_aux(L, 0);
+ }
+
+
+ private static int gmatch_aux (lua_State L) {
+ MatchState ms = new MatchState();
+ uint ls;
+ CharPtr s = lua_tolstring(L, lua_upvalueindex(1), out ls);
+ CharPtr p = lua_tostring(L, lua_upvalueindex(2));
+ CharPtr src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (uint)lua_tointeger(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src = src.next()) {
+ CharPtr 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 */
+ }
+
+
+ private 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;
+ }
+
+
+ private static int gfind_nodef (lua_State L) {
+ return luaL_error(L, LUA_QL("string.gfind") + " was renamed to " +
+ LUA_QL("string.gmatch"));
+ }
+
+
+ private static void add_s (MatchState ms, luaL_Buffer b, CharPtr s,
+ CharPtr e) {
+ uint l, i;
+ CharPtr news = lua_tolstring(ms.L, 3, out l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit((byte)(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, (uint)(e - s));
+ else {
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
+ }
+ }
+ }
+ }
+
+
+ private static void add_value (MatchState ms, luaL_Buffer b, CharPtr s,
+ CharPtr 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_TUSERDATA:
+ 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)==0) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, (uint)(e - s)); /* keep original text */
+ }
+ else if (lua_isstring(L, -1)==0)
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
+ }
+
+
+ private static int str_gsub (lua_State L) {
+ uint srcl;
+ CharPtr src = luaL_checklstring(L, 1, out srcl);
+ CharPtr p = luaL_checkstring(L, 2);
+ int tr = lua_type(L, 3);
+ int max_s = luaL_optint(L, 4, (int)(srcl+1));
+ int anchor = 0;
+ if (p[0] == '^')
+ {
+ p = p.next();
+ anchor = 1;
+ }
+ int n = 0;
+ MatchState ms = new MatchState();
+ luaL_Buffer b = new luaL_Buffer();
+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+ tr == LUA_TFUNCTION || tr == LUA_TTABLE ||
+ tr == LUA_TUSERDATA, 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) {
+ CharPtr e;
+ ms.level = 0;
+ e = match(ms, src, p);
+ if (e != null) {
+ n++;
+ add_value(ms, b, src, e);
+ }
+ if ((e!=null) && e>src) /* non empty match? */
+ src = e; /* skip it */
+ else if (src < ms.src_end)
+ {
+ char c = src[0];
+ src = src.next();
+ luaL_addchar(b, c);
+ }
+ else break;
+ if (anchor != 0) break;
+ }
+ luaL_addlstring(b, src, (uint)(ms.src_end-src));
+ luaL_pushresult(b);
+ lua_pushinteger(L, n); /* number of substitutions */
+ return 2;
+ }
+
+ /* }====================================================== */
+
+
+ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+ public const int MAX_ITEM = 512;
+ /* valid flags in a format specification */
+ public const string FLAGS = "-+ #0";
+ /*
+ ** maximum size of each format specification (such as '%-099.99d')
+ ** (+10 accounts for %99.99x plus margin of error)
+ */
+ public static readonly int MAX_FORMAT = (FLAGS.Length+1) + (LUA_INTFRMLEN.Length+1) + 10;
+
+
+ private static void addquoted (lua_State L, luaL_Buffer b, int arg) {
+ uint l;
+ CharPtr s = luaL_checklstring(L, arg, out l);
+ luaL_addchar(b, '"');
+ while ((l--) != 0) {
+ switch (s[0]) {
+ case '"': case '\\': case '\n': {
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, s[0]);
+ break;
+ }
+ case '\r': {
+ luaL_addlstring(b, "\\r", 2);
+ break;
+ }
+ case '\0': {
+ luaL_addlstring(b, "\\000", 4);
+ break;
+ }
+ default: {
+ luaL_addchar(b, s[0]);
+ break;
+ }
+ }
+ s = s.next();
+ }
+ luaL_addchar(b, '"');
+ }
+
+ private static CharPtr scanformat (lua_State L, CharPtr strfrmt, CharPtr form) {
+ CharPtr p = strfrmt;
+ while (p[0] != '\0' && strchr(FLAGS, p[0]) != null) p = p.next(); /* skip flags */
+ if ((uint)(p - strfrmt) >= (FLAGS.Length+1))
+ luaL_error(L, "invalid format (repeated flags)");
+ if (isdigit((byte)(p[0]))) p = p.next(); /* skip width */
+ if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */
+ if (p[0] == '.') {
+ p = p.next();
+ if (isdigit((byte)(p[0]))) p = p.next(); /* skip precision */
+ if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */
+ }
+ if (isdigit((byte)(p[0])))
+ luaL_error(L, "invalid format (width or precision too long)");
+ form[0] = '%';
+ form = form.next();
+ strncpy(form, strfrmt, p - strfrmt + 1);
+ form += p - strfrmt + 1;
+ form[0] = '\0';
+ return p;
+ }
+
+
+ private static void addintlen (CharPtr form) {
+ uint l = (uint)strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + (LUA_INTFRMLEN.Length + 1) - 2] = spec;
+ form[l + (LUA_INTFRMLEN.Length + 1) - 1] = '\0';
+ }
+
+
+ private static int str_format (lua_State L) {
+ int arg = 1;
+ uint sfl;
+ CharPtr strfrmt = luaL_checklstring(L, arg, out sfl);
+ CharPtr strfrmt_end = strfrmt+sfl;
+ luaL_Buffer b = new luaL_Buffer();
+ luaL_buffinit(L, b);
+ while (strfrmt < strfrmt_end) {
+ if (strfrmt[0] != L_ESC)
+ {
+ luaL_addchar(b, strfrmt[0]);
+ strfrmt = strfrmt.next();
+ }
+ else if (strfrmt[1] == L_ESC)
+ {
+ luaL_addchar(b, strfrmt[0]); /* %% */
+ strfrmt = strfrmt + 2;
+ }
+ else
+ { /* format item */
+ strfrmt = strfrmt.next();
+ CharPtr form = new char[MAX_FORMAT]; /* to store the format (`%...') */
+ CharPtr buff = new char[MAX_ITEM]; /* to store the formatted item */
+ arg++;
+ strfrmt = scanformat(L, strfrmt, form);
+ char ch = strfrmt[0];
+ strfrmt = strfrmt.next();
+ switch (ch)
+ {
+ 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 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ {
+ sprintf(buff, form, (double)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'q':
+ {
+ addquoted(L, b, arg);
+ continue; /* skip the 'addsize' at the end */
+ }
+ case 's':
+ {
+ uint l;
+ CharPtr s = luaL_checklstring(L, arg, out l);
+ if ((strchr(form, '.') == null) && 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' */
+ return luaL_error(L, "invalid option " + LUA_QL("%%%c") + " to " +
+ LUA_QL("format"), strfrmt[-1]);
+ }
+ }
+ luaL_addlstring(b, buff, (uint)strlen(buff));
+ }
+ }
+ luaL_pushresult(b);
+ return 1;
+ }
+
+
+ private readonly static luaL_Reg[] strlib = {
+ new luaL_Reg("byte", str_byte),
+ new luaL_Reg("char", str_char),
+ new luaL_Reg("dump", str_dump),
+ new luaL_Reg("find", str_find),
+ new luaL_Reg("format", str_format),
+ new luaL_Reg("gfind", gfind_nodef),
+ new luaL_Reg("gmatch", gmatch),
+ new luaL_Reg("gsub", str_gsub),
+ new luaL_Reg("len", str_len),
+ new luaL_Reg("lower", str_lower),
+ new luaL_Reg("match", str_match),
+ new luaL_Reg("rep", str_rep),
+ new luaL_Reg("reverse", str_reverse),
+ new luaL_Reg("sub", str_sub),
+ new luaL_Reg("upper", str_upper),
+ new luaL_Reg(null, null)
+ };
+
+
+ private 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
+ */
+ public static int luaopen_string (lua_State L) {
+ luaL_register(L, LUA_STRLIBNAME, strlib);
+ #if LUA_COMPAT_GFIND
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+ #endif
+ createmetatable(L);
+ return 1;
+ }
+
+ }
+}
diff --git a/Core/KopiLua/ltable.cs b/Core/KopiLua/ltable.cs
index ef9369e1384ee330d867bbc315fbd5bf10242d42..18124ef6b8ae8b31a4672887d9c7ad40bb625eca 100644
--- a/Core/KopiLua/ltable.cs
+++ b/Core/KopiLua/ltable.cs
@@ -1,600 +1,600 @@
-/*
-** $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
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace KopiLua
-{
- using TValue = Lua.lua_TValue;
- using StkId = Lua.lua_TValue;
- using lua_Number = System.Double;
-
- public partial class Lua
- {
- /*
- ** 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.
- */
-
- internal static Node gnode(Table t, int i) { return t.node[i]; }
- internal static TKey_nk gkey(Node n) { return n.i_key.nk; }
- internal static TValue gval(Node n) { return n.i_val; }
- internal static Node gnext(Node n) { return n.i_key.nk.next; }
-
- internal static void gnext_set(Node n, Node v) { n.i_key.nk.next = v; }
-
- internal static TValue key2tval(Node n) { return n.i_key.tvk; }
-
-
- /*
- ** max size of array part is 2^MAXBITS
- */
- //#if LUAI_BITSINT > 26
- public const int MAXBITS = 26; /* in the dotnet port LUAI_BITSINT is 32 */
- //#else
- //public const int MAXBITS = (LUAI_BITSINT-2);
- //#endif
-
- public const int MAXASIZE = (1 << MAXBITS);
-
-
- //public static Node gnode(Table t, int i) {return t.node[i];}
- internal static Node hashpow2(Table t, lua_Number n) { return gnode(t, (int)lmod(n, sizenode(t))); }
-
- public static Node hashstr(Table t, TString str) {return hashpow2(t, str.tsv.hash);}
- public static Node hashboolean(Table t, int p) {return hashpow2(t, p);}
-
-
- /*
- ** for some types, it is better to avoid modulus by power of 2, as
- ** they tend to have many 2 factors.
- */
- public static Node hashmod(Table t, int n) { return gnode(t, (int)((uint)n % ((sizenode(t) - 1) | 1))); }
-
- public static Node hashpointer(Table t, object p) { return hashmod(t, p.GetHashCode()); }
-
-
- /*
- ** number of ints inside a lua_Number
- */
- public const int numints = sizeof(lua_Number) / sizeof(int);
-
-
- //static const Node dummynode_ = {
- //{{null}, LUA_TNIL}, /* value */
- //{{{null}, LUA_TNIL, null}} /* key */
- //};
- public static Node dummynode_ = new Node(new TValue(new Value(), LUA_TNIL), new TKey(new Value(), LUA_TNIL, null));
- public static Node dummynode = dummynode_;
-
- /*
- ** hash for lua_Numbers
- */
- private static Node hashnum (Table t, lua_Number n) {
- byte[] a = BitConverter.GetBytes(n);
- for (int i = 1; i < a.Length; i++) a[0] += a[i];
- return hashmod(t, (int)a[0]);
- }
-
-
-
- /*
- ** returns the `main' position of an element in a table (that is, the index
- ** of its hash value)
- */
- private static Node mainposition (Table t, 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.
- */
- private static int arrayindex (TValue key) {
- if (ttisnumber(key)) {
- lua_Number n = nvalue(key);
- int k;
- lua_number2int(out 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.
- */
- private 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) != 0) ||
- (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 != null);
- luaG_runerror(L, "invalid key to " + LUA_QL("next")); /* key not found */
- return 0; /* to avoid warnings */
- }
- }
-
-
- public static 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
- ** ==============================================================
- */
-
-
- private static int computesizes (int[] nums, ref 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;
- }
-
-
- private static int countint (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;
- }
-
-
- private static int numusearray (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;
- }
-
-
- private static int numusehash (Table t, int[] nums, ref int pnasize) {
- int totaluse = 0; /* total number of elements */
- int ause = 0; /* summation of `nums' */
- int i = sizenode(t);
- while ((i--) != 0) {
- Node n = t.node[i];
- if (!ttisnil(gval(n))) {
- ause += countint(key2tval(n), nums);
- totaluse++;
- }
- }
- pnasize += ause;
- return totaluse;
- }
-
-
- private static void setarrayvector (lua_State L, Table t, int size) {
- int i;
- luaM_reallocvector(L, ref t.array, t.sizearray, size/*, TValue*/);
- for (i=t.sizearray; i MAXBITS)
- luaG_runerror(L, "table overflow");
- size = twoto(lsize);
- Node[] nodes = luaM_newvector(L, size);
- t.node = nodes;
- for (i=0; i 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; i(L, ref 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[0] != dummynode)
- luaM_freearray(L, nold); /* free old array */
- }
-
-
- public static void luaH_resizearray (lua_State L, Table t, int nasize) {
- int nsize = (t.node[0] == dummynode) ? 0 : sizenode(t);
- resize(L, t, nasize, nsize);
- }
-
-
- private static void rehash (lua_State L, Table t, TValue ek) {
- int nasize, na;
- int[] nums = new int[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, ref nasize); /* count keys in hash part */
- /* count extra key */
- nasize += countint(ek, nums);
- totaluse++;
- /* compute new size for array part */
- na = computesizes(nums, ref nasize);
- /* resize the table to new computed sizes */
- resize(L, t, nasize, totaluse - na);
- }
-
-
-
- /*
- ** }=============================================================
- */
-
-
- public static Table luaH_new (lua_State L, int narray, int nhash) {
- Table t = luaM_new
(L);
- 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 = new Node[] { dummynode };
- setarrayvector(L, t, narray);
- setnodevector(L, t, nhash);
- return t;
- }
-
-
- public static void luaH_free (lua_State L, Table t) {
- if (t.node[0] != dummynode)
- luaM_freearray(L, t.node);
- luaM_freearray(L, t.array);
- luaM_free(L, t);
- }
-
-
- private static Node getfreepos (Table t) {
- while (t.lastfree-- > 0) {
- if (ttisnil(gkey(t.node[t.lastfree])))
- return t.node[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.
- */
- private static TValue newkey (lua_State L, Table t, 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_set(othern, n); /* redo the chain with `n' in place of `mp' */
- n.i_val = new TValue(mp.i_val); /* copy colliding node into free pos. (mp.next also goes) */
- n.i_key = new TKey(mp.i_key);
- gnext_set(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_set(n, gnext(mp)); /* chain new position */
- gnext_set(mp, n);
- mp = n;
- }
- }
- gkey(mp).value.Copy(key.value); gkey(mp).tt = key.tt;
- luaC_barriert(L, t, key);
- lua_assert(ttisnil(gval(mp)));
- return gval(mp);
- }
-
- /*
- ** search function for integers
- */
- public static TValue luaH_getnum(Table t, int key)
- {
- /* (1 <= key && key <= t.sizearray) */
- if ((uint)(key-1) < (uint)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 != null);
- return luaO_nilobject;
- }
- }
-
-
- /*
- ** search function for strings
- */
- public static 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 != null);
- return luaO_nilobject;
- }
-
-
- /*
- ** main search function
- */
- public static TValue luaH_get (Table t, 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(out k, n);
- if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
- return luaH_getnum(t, k); /* use specialized version */
- /* else go through ... actually on second thoughts don't, because this is C#*/
- Node node = mainposition(t, key);
- do
- { /* check whether `key' is somewhere in the chain */
- if (luaO_rawequalObj(key2tval(node), key) != 0)
- return gval(node); /* that's it */
- else node = gnext(node);
- } while (node != null);
- return luaO_nilobject;
- }
- default: {
- Node node = mainposition(t, key);
- do { /* check whether `key' is somewhere in the chain */
- if (luaO_rawequalObj(key2tval(node), key) != 0)
- return gval(node); /* that's it */
- else node = gnext(node);
- } while (node != null);
- return luaO_nilobject;
- }
- }
- }
-
-
- public static TValue luaH_set (lua_State L, Table t, TValue key) {
- TValue p = luaH_get(t, key);
- t.flags = 0;
- if (p != luaO_nilobject)
- return (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);
- }
- }
-
-
- public static TValue luaH_setnum (lua_State L, Table t, int key) {
- TValue p = luaH_getnum(t, key);
- if (p != luaO_nilobject)
- return (TValue)p;
- else {
- TValue k = new TValue();
- setnvalue(k, cast_num(key));
- return newkey(L, t, k);
- }
- }
-
- public static TValue luaH_setstr (lua_State L, Table t, TString key) {
- TValue p = luaH_getstr(t, key);
- if (p != luaO_nilobject)
- return (TValue)p;
- else {
- TValue k = new TValue();
- setsvalue(L, k, key);
- return newkey(L, t, k);
- }
- }
-
- [CLSCompliantAttribute(false)]
- public static int unbound_search (Table t, uint j) {
- uint 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, (int)j))) {
- i = j;
- j *= 2;
- if (j > (uint)MAX_INT) { /* overflow? */
- /* table was built with bad purposes: resort to linear search */
- i = 1;
- while (!ttisnil(luaH_getnum(t, (int)i))) i++;
- return (int)(i - 1);
- }
- }
- /* now do a binary search between them */
- while (j - i > 1) {
- uint m = (i+j)/2;
- if (ttisnil(luaH_getnum(t, (int)m))) j = m;
- else i = m;
- }
- return (int)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).
- */
- public static int luaH_getn (Table t) {
- uint j = (uint)t.sizearray;
- if (j > 0 && ttisnil(t.array[j - 1])) {
- /* there is a boundary in the array part: (binary) search for it */
- uint i = 0;
- while (j - i > 1) {
- uint m = (i+j)/2;
- if (ttisnil(t.array[m - 1])) j = m;
- else i = m;
- }
- return (int)i;
- }
- /* else must find a boundary in hash part */
- else if (t.node[0] == dummynode) /* hash part is empty? */
- return (int)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
-
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace KopiLua
+{
+ using TValue = Lua.lua_TValue;
+ using StkId = Lua.lua_TValue;
+ using lua_Number = System.Double;
+
+ public partial class Lua
+ {
+ /*
+ ** 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.
+ */
+
+ internal static Node gnode(Table t, int i) { return t.node[i]; }
+ internal static TKey_nk gkey(Node n) { return n.i_key.nk; }
+ internal static TValue gval(Node n) { return n.i_val; }
+ internal static Node gnext(Node n) { return n.i_key.nk.next; }
+
+ internal static void gnext_set(Node n, Node v) { n.i_key.nk.next = v; }
+
+ internal static TValue key2tval(Node n) { return n.i_key.tvk; }
+
+
+ /*
+ ** max size of array part is 2^MAXBITS
+ */
+ //#if LUAI_BITSINT > 26
+ public const int MAXBITS = 26; /* in the dotnet port LUAI_BITSINT is 32 */
+ //#else
+ //public const int MAXBITS = (LUAI_BITSINT-2);
+ //#endif
+
+ public const int MAXASIZE = (1 << MAXBITS);
+
+
+ //public static Node gnode(Table t, int i) {return t.node[i];}
+ internal static Node hashpow2(Table t, lua_Number n) { return gnode(t, (int)lmod(n, sizenode(t))); }
+
+ public static Node hashstr(Table t, TString str) {return hashpow2(t, str.tsv.hash);}
+ public static Node hashboolean(Table t, int p) {return hashpow2(t, p);}
+
+
+ /*
+ ** for some types, it is better to avoid modulus by power of 2, as
+ ** they tend to have many 2 factors.
+ */
+ public static Node hashmod(Table t, int n) { return gnode(t, (int)((uint)n % ((sizenode(t) - 1) | 1))); }
+
+ public static Node hashpointer(Table t, object p) { return hashmod(t, p.GetHashCode()); }
+
+
+ /*
+ ** number of ints inside a lua_Number
+ */
+ public const int numints = sizeof(lua_Number) / sizeof(int);
+
+
+ //static const Node dummynode_ = {
+ //{{null}, LUA_TNIL}, /* value */
+ //{{{null}, LUA_TNIL, null}} /* key */
+ //};
+ public static Node dummynode_ = new Node(new TValue(new Value(), LUA_TNIL), new TKey(new Value(), LUA_TNIL, null));
+ public static Node dummynode = dummynode_;
+
+ /*
+ ** hash for lua_Numbers
+ */
+ private static Node hashnum (Table t, lua_Number n) {
+ byte[] a = BitConverter.GetBytes(n);
+ for (int i = 1; i < a.Length; i++) a[0] += a[i];
+ return hashmod(t, (int)a[0]);
+ }
+
+
+
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
+ */
+ private static Node mainposition (Table t, 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.
+ */
+ private static int arrayindex (TValue key) {
+ if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
+ int k;
+ lua_number2int(out 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.
+ */
+ private 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) != 0) ||
+ (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 != null);
+ luaG_runerror(L, "invalid key to " + LUA_QL("next")); /* key not found */
+ return 0; /* to avoid warnings */
+ }
+ }
+
+
+ public static 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
+ ** ==============================================================
+ */
+
+
+ private static int computesizes (int[] nums, ref 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;
+ }
+
+
+ private static int countint (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;
+ }
+
+
+ private static int numusearray (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;
+ }
+
+
+ private static int numusehash (Table t, int[] nums, ref int pnasize) {
+ int totaluse = 0; /* total number of elements */
+ int ause = 0; /* summation of `nums' */
+ int i = sizenode(t);
+ while ((i--) != 0) {
+ Node n = t.node[i];
+ if (!ttisnil(gval(n))) {
+ ause += countint(key2tval(n), nums);
+ totaluse++;
+ }
+ }
+ pnasize += ause;
+ return totaluse;
+ }
+
+
+ private static void setarrayvector (lua_State L, Table t, int size) {
+ int i;
+ luaM_reallocvector(L, ref t.array, t.sizearray, size/*, TValue*/);
+ for (i=t.sizearray; i MAXBITS)
+ luaG_runerror(L, "table overflow");
+ size = twoto(lsize);
+ Node[] nodes = luaM_newvector(L, size);
+ t.node = nodes;
+ for (i=0; i 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; i(L, ref 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[0] != dummynode)
+ luaM_freearray(L, nold); /* free old array */
+ }
+
+
+ public static void luaH_resizearray (lua_State L, Table t, int nasize) {
+ int nsize = (t.node[0] == dummynode) ? 0 : sizenode(t);
+ resize(L, t, nasize, nsize);
+ }
+
+
+ private static void rehash (lua_State L, Table t, TValue ek) {
+ int nasize, na;
+ int[] nums = new int[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, ref nasize); /* count keys in hash part */
+ /* count extra key */
+ nasize += countint(ek, nums);
+ totaluse++;
+ /* compute new size for array part */
+ na = computesizes(nums, ref nasize);
+ /* resize the table to new computed sizes */
+ resize(L, t, nasize, totaluse - na);
+ }
+
+
+
+ /*
+ ** }=============================================================
+ */
+
+
+ public static Table luaH_new (lua_State L, int narray, int nhash) {
+ Table t = luaM_new
(L);
+ 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 = new Node[] { dummynode };
+ setarrayvector(L, t, narray);
+ setnodevector(L, t, nhash);
+ return t;
+ }
+
+
+ public static void luaH_free (lua_State L, Table t) {
+ if (t.node[0] != dummynode)
+ luaM_freearray(L, t.node);
+ luaM_freearray(L, t.array);
+ luaM_free(L, t);
+ }
+
+
+ private static Node getfreepos (Table t) {
+ while (t.lastfree-- > 0) {
+ if (ttisnil(gkey(t.node[t.lastfree])))
+ return t.node[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.
+ */
+ private static TValue newkey (lua_State L, Table t, 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_set(othern, n); /* redo the chain with `n' in place of `mp' */
+ n.i_val = new TValue(mp.i_val); /* copy colliding node into free pos. (mp.next also goes) */
+ n.i_key = new TKey(mp.i_key);
+ gnext_set(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_set(n, gnext(mp)); /* chain new position */
+ gnext_set(mp, n);
+ mp = n;
+ }
+ }
+ gkey(mp).value.Copy(key.value); gkey(mp).tt = key.tt;
+ luaC_barriert(L, t, key);
+ lua_assert(ttisnil(gval(mp)));
+ return gval(mp);
+ }
+
+ /*
+ ** search function for integers
+ */
+ public static TValue luaH_getnum(Table t, int key)
+ {
+ /* (1 <= key && key <= t.sizearray) */
+ if ((uint)(key-1) < (uint)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 != null);
+ return luaO_nilobject;
+ }
+ }
+
+
+ /*
+ ** search function for strings
+ */
+ public static 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 != null);
+ return luaO_nilobject;
+ }
+
+
+ /*
+ ** main search function
+ */
+ public static TValue luaH_get (Table t, 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(out k, n);
+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+ return luaH_getnum(t, k); /* use specialized version */
+ /* else go through ... actually on second thoughts don't, because this is C#*/
+ Node node = mainposition(t, key);
+ do
+ { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(node), key) != 0)
+ return gval(node); /* that's it */
+ else node = gnext(node);
+ } while (node != null);
+ return luaO_nilobject;
+ }
+ default: {
+ Node node = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(node), key) != 0)
+ return gval(node); /* that's it */
+ else node = gnext(node);
+ } while (node != null);
+ return luaO_nilobject;
+ }
+ }
+ }
+
+
+ public static TValue luaH_set (lua_State L, Table t, TValue key) {
+ TValue p = luaH_get(t, key);
+ t.flags = 0;
+ if (p != luaO_nilobject)
+ return (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);
+ }
+ }
+
+
+ public static TValue luaH_setnum (lua_State L, Table t, int key) {
+ TValue p = luaH_getnum(t, key);
+ if (p != luaO_nilobject)
+ return (TValue)p;
+ else {
+ TValue k = new TValue();
+ setnvalue(k, cast_num(key));
+ return newkey(L, t, k);
+ }
+ }
+
+ public static TValue luaH_setstr (lua_State L, Table t, TString key) {
+ TValue p = luaH_getstr(t, key);
+ if (p != luaO_nilobject)
+ return (TValue)p;
+ else {
+ TValue k = new TValue();
+ setsvalue(L, k, key);
+ return newkey(L, t, k);
+ }
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static int unbound_search (Table t, uint j) {
+ uint 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, (int)j))) {
+ i = j;
+ j *= 2;
+ if (j > (uint)MAX_INT) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+ i = 1;
+ while (!ttisnil(luaH_getnum(t, (int)i))) i++;
+ return (int)(i - 1);
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ uint m = (i+j)/2;
+ if (ttisnil(luaH_getnum(t, (int)m))) j = m;
+ else i = m;
+ }
+ return (int)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).
+ */
+ public static int luaH_getn (Table t) {
+ uint j = (uint)t.sizearray;
+ if (j > 0 && ttisnil(t.array[j - 1])) {
+ /* there is a boundary in the array part: (binary) search for it */
+ uint i = 0;
+ while (j - i > 1) {
+ uint m = (i+j)/2;
+ if (ttisnil(t.array[m - 1])) j = m;
+ else i = m;
+ }
+ return (int)i;
+ }
+ /* else must find a boundary in hash part */
+ else if (t.node[0] == dummynode) /* hash part is empty? */
+ return (int)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
+
+ }
+}
diff --git a/Core/KopiLua/ltablib.cs b/Core/KopiLua/ltablib.cs
index 0f60c77835dca3f80df713e8e2f9e1c5286f92ab..11c9f9fb8ca0bcc3c33725617f0a662702db7227 100644
--- a/Core/KopiLua/ltablib.cs
+++ b/Core/KopiLua/ltablib.cs
@@ -1,298 +1,298 @@
-/*
-** $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
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace KopiLua
-{
- using lua_Number = System.Double;
-
- public partial class Lua
- {
- private static int aux_getn(lua_State L, int n) {luaL_checktype(L, n, LUA_TTABLE); return luaL_getn(L, n);}
-
- private 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;
- }
-
-
- private 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) != 0) {
- 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;
- }
-
-
- private 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) != 0) {
- 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;
- }
-
-
- private static int getn (lua_State L) {
- lua_pushinteger(L, aux_getn(L, 1));
- return 1;
- }
-
-
- private 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;
- }
-
-
- private 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;
- }
-
-
- private 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 (auxsort_loop1(L, ref i) != 0) {
- 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 (auxsort_loop2(L, ref j) != 0) {
- if (j max) max = v;
+ }
+ }
+ lua_pushnumber(L, max);
+ return 1;
+ }
+
+
+ private static int getn (lua_State L) {
+ lua_pushinteger(L, aux_getn(L, 1));
+ return 1;
+ }
+
+
+ private 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;
+ }
+
+
+ private 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;
+ }
+
+
+ private 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 (auxsort_loop1(L, ref i) != 0) {
+ 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 (auxsort_loop2(L, ref j) != 0) {
+ if (jLua') */
- public const string LUA_SIGNATURE = "\x01bLua";
-
- /* option for multiple returns in `lua_pcall' and `lua_call' */
- public const int LUA_MULTRET = (-1);
-
-
- /*
- ** pseudo-indices
- */
- public const int LUA_REGISTRYINDEX = (-10000);
- public const int LUA_ENVIRONINDEX = (-10001);
- public const int LUA_GLOBALSINDEX = (-10002);
- public static int lua_upvalueindex(int i) {return LUA_GLOBALSINDEX-i;}
-
-
- /* thread status; 0 is OK */
- public const int LUA_YIELD = 1;
- public const int LUA_ERRRUN = 2;
- public const int LUA_ERRSYNTAX = 3;
- public const int LUA_ERRMEM = 4;
- public const int LUA_ERRERR = 5;
-
-
- public delegate int lua_CFunction(lua_State L);
-
-
- /*
- ** functions that read/write blocks when loading/dumping Lua chunks
- */
- [CLSCompliantAttribute(false)]
- public delegate CharPtr lua_Reader(lua_State L, object ud, out uint sz);
- [CLSCompliantAttribute(false)]
- public delegate int lua_Writer(lua_State L, CharPtr p, uint sz, object ud);
-
-
- /*
- ** prototype for memory-allocation functions
- */
- //public delegate object lua_Alloc(object ud, object ptr, uint osize, uint nsize);
- public delegate object lua_Alloc(Type t);
-
-
- /*
- ** basic types
- */
- public const int LUA_TNONE = -1;
-
- public const int LUA_TNIL = 0;
- public const int LUA_TBOOLEAN = 1;
- public const int LUA_TLIGHTUSERDATA = 2;
- public const int LUA_TNUMBER = 3;
- public const int LUA_TSTRING = 4;
- public const int LUA_TTABLE = 5;
- public const int LUA_TFUNCTION = 6;
- public const int LUA_TUSERDATA = 7;
- public const int LUA_TTHREAD = 8;
-
-
-
- /* minimum Lua stack available to a C function */
- public const int LUA_MINSTACK = 20;
-
-
- /* type of numbers in Lua */
- //typedef LUA_NUMBER lua_Number;
-
-
- /* type for integer functions */
- //typedef LUA_INTEGER lua_Integer;
-
- /*
- ** garbage-collection function and options
- */
-
- public const int LUA_GCSTOP = 0;
- public const int LUA_GCRESTART = 1;
- public const int LUA_GCCOLLECT = 2;
- public const int LUA_GCCOUNT = 3;
- public const int LUA_GCCOUNTB = 4;
- public const int LUA_GCSTEP = 5;
- public const int LUA_GCSETPAUSE = 6;
- public const int LUA_GCSETSTEPMUL = 7;
-
- /*
- ** ===============================================================
- ** some useful macros
- ** ===============================================================
- */
-
- public static void lua_pop(lua_State L, int n)
- {
- lua_settop(L, -(n) - 1);
- }
-
- public static void lua_newtable(lua_State L)
- {
- lua_createtable(L, 0, 0);
- }
-
- public static void lua_register(lua_State L, CharPtr n, lua_CFunction f)
- {
- lua_pushcfunction(L, f);
- lua_setglobal(L, n);
- }
-
- public static void lua_pushcfunction(lua_State L, lua_CFunction f)
- {
- lua_pushcclosure(L, f, 0);
- }
-
- [CLSCompliantAttribute(false)]
- public static uint lua_strlen(lua_State L, int i)
- {
- return lua_objlen(L, i);
- }
-
- public static bool lua_isfunction(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TFUNCTION;
- }
-
- public static bool lua_istable(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TTABLE;
- }
-
- public static bool lua_islightuserdata(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TLIGHTUSERDATA;
- }
-
- public static bool lua_isnil(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TNIL;
- }
-
- public static bool lua_isboolean(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TBOOLEAN;
- }
-
- public static bool lua_isthread(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TTHREAD;
- }
-
- public static bool lua_isnone(lua_State L, int n)
- {
- return lua_type(L, n) == LUA_TNONE;
- }
-
- public static bool lua_isnoneornil(lua_State L, lua_Number n)
- {
- return lua_type(L, (int)n) <= 0;
- }
-
- public static void lua_pushliteral(lua_State L, CharPtr s)
- {
- //TODO: Implement use using lua_pushlstring instead of lua_pushstring
- //lua_pushlstring(L, "" s, (sizeof(s)/GetUnmanagedSize(typeof(char)))-1)
- lua_pushstring(L, s);
- }
-
- public static void lua_setglobal(lua_State L, CharPtr s)
- {
- lua_setfield(L, LUA_GLOBALSINDEX, s);
- }
-
- public static void lua_getglobal(lua_State L, CharPtr s)
- {
- lua_getfield(L, LUA_GLOBALSINDEX, s);
- }
-
- public static CharPtr lua_tostring(lua_State L, int i)
- {
- uint blah;
- return lua_tolstring(L, i, out blah);
- }
-
- ////#define lua_open() luaL_newstate()
- public static lua_State lua_open()
- {
- return luaL_newstate();
- }
-
- ////#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
- public static void lua_getregistry(lua_State L)
- {
- lua_pushvalue(L, LUA_REGISTRYINDEX);
- }
-
- ////#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
- public static int lua_getgccount(lua_State L)
- {
- return lua_gc(L, LUA_GCCOUNT, 0);
- }
-
- //#define lua_Chunkreader lua_Reader
- //#define lua_Chunkwriter lua_Writer
-
-
- /*
- ** {======================================================================
- ** Debug API
- ** =======================================================================
- */
-
-
- /*
- ** Event codes
- */
- public const int LUA_HOOKCALL = 0;
- public const int LUA_HOOKRET = 1;
- public const int LUA_HOOKLINE = 2;
- public const int LUA_HOOKCOUNT = 3;
- public const int LUA_HOOKTAILRET = 4;
-
-
- /*
- ** Event masks
- */
- public const int LUA_MASKCALL = (1 << LUA_HOOKCALL);
- public const int LUA_MASKRET = (1 << LUA_HOOKRET);
- public const int LUA_MASKLINE = (1 << LUA_HOOKLINE);
- public const int LUA_MASKCOUNT = (1 << LUA_HOOKCOUNT);
-
- /* Functions to be called by the debuger in specific events */
- public delegate void lua_Hook(lua_State L, lua_Debug ar);
-
-
- public class lua_Debug {
- public int event_;
- public CharPtr name; /* (n) */
- public CharPtr namewhat; /* (n) `global', `local', `field', `method' */
- public CharPtr what; /* (S) `Lua', `C', `main', `tail' */
- public CharPtr source; /* (S) */
- public int currentline; /* (l) */
- public int nups; /* (u) number of upvalues */
- public int linedefined; /* (S) */
- public int lastlinedefined; /* (S) */
- public CharPtr short_src = new char[LUA_IDSIZE]; /* (S) */
- /* private part */
- public 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.
- ******************************************************************************/
-
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace KopiLua
+{
+ using lua_Number = Double;
+ using lua_Integer = System.Int32;
+
+ [CLSCompliantAttribute(true)]
+ public partial class Lua
+ {
+
+ public const string LUA_VERSION = "Lua 5.1";
+ public const string LUA_RELEASE = "Lua 5.1.4";
+ public const int LUA_VERSION_NUM = 501;
+ public const string LUA_COPYRIGHT = "Copyright (C) 1994-2008 Lua.org, PUC-Rio";
+ public const string LUA_AUTHORS = "R. Ierusalimschy, L. H. de Figueiredo & W. Celes";
+
+
+ /* mark for precompiled code (`Lua') */
+ public const string LUA_SIGNATURE = "\x01bLua";
+
+ /* option for multiple returns in `lua_pcall' and `lua_call' */
+ public const int LUA_MULTRET = (-1);
+
+
+ /*
+ ** pseudo-indices
+ */
+ public const int LUA_REGISTRYINDEX = (-10000);
+ public const int LUA_ENVIRONINDEX = (-10001);
+ public const int LUA_GLOBALSINDEX = (-10002);
+ public static int lua_upvalueindex(int i) {return LUA_GLOBALSINDEX-i;}
+
+
+ /* thread status; 0 is OK */
+ public const int LUA_YIELD = 1;
+ public const int LUA_ERRRUN = 2;
+ public const int LUA_ERRSYNTAX = 3;
+ public const int LUA_ERRMEM = 4;
+ public const int LUA_ERRERR = 5;
+
+
+ public delegate int lua_CFunction(lua_State L);
+
+
+ /*
+ ** functions that read/write blocks when loading/dumping Lua chunks
+ */
+ [CLSCompliantAttribute(false)]
+ public delegate CharPtr lua_Reader(lua_State L, object ud, out uint sz);
+ [CLSCompliantAttribute(false)]
+ public delegate int lua_Writer(lua_State L, CharPtr p, uint sz, object ud);
+
+
+ /*
+ ** prototype for memory-allocation functions
+ */
+ //public delegate object lua_Alloc(object ud, object ptr, uint osize, uint nsize);
+ public delegate object lua_Alloc(Type t);
+
+
+ /*
+ ** basic types
+ */
+ public const int LUA_TNONE = -1;
+
+ public const int LUA_TNIL = 0;
+ public const int LUA_TBOOLEAN = 1;
+ public const int LUA_TLIGHTUSERDATA = 2;
+ public const int LUA_TNUMBER = 3;
+ public const int LUA_TSTRING = 4;
+ public const int LUA_TTABLE = 5;
+ public const int LUA_TFUNCTION = 6;
+ public const int LUA_TUSERDATA = 7;
+ public const int LUA_TTHREAD = 8;
+
+
+
+ /* minimum Lua stack available to a C function */
+ public const int LUA_MINSTACK = 20;
+
+
+ /* type of numbers in Lua */
+ //typedef LUA_NUMBER lua_Number;
+
+
+ /* type for integer functions */
+ //typedef LUA_INTEGER lua_Integer;
+
+ /*
+ ** garbage-collection function and options
+ */
+
+ public const int LUA_GCSTOP = 0;
+ public const int LUA_GCRESTART = 1;
+ public const int LUA_GCCOLLECT = 2;
+ public const int LUA_GCCOUNT = 3;
+ public const int LUA_GCCOUNTB = 4;
+ public const int LUA_GCSTEP = 5;
+ public const int LUA_GCSETPAUSE = 6;
+ public const int LUA_GCSETSTEPMUL = 7;
+
+ /*
+ ** ===============================================================
+ ** some useful macros
+ ** ===============================================================
+ */
+
+ public static void lua_pop(lua_State L, int n)
+ {
+ lua_settop(L, -(n) - 1);
+ }
+
+ public static void lua_newtable(lua_State L)
+ {
+ lua_createtable(L, 0, 0);
+ }
+
+ public static void lua_register(lua_State L, CharPtr n, lua_CFunction f)
+ {
+ lua_pushcfunction(L, f);
+ lua_setglobal(L, n);
+ }
+
+ public static void lua_pushcfunction(lua_State L, lua_CFunction f)
+ {
+ lua_pushcclosure(L, f, 0);
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static uint lua_strlen(lua_State L, int i)
+ {
+ return lua_objlen(L, i);
+ }
+
+ public static bool lua_isfunction(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TFUNCTION;
+ }
+
+ public static bool lua_istable(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TTABLE;
+ }
+
+ public static bool lua_islightuserdata(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TLIGHTUSERDATA;
+ }
+
+ public static bool lua_isnil(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TNIL;
+ }
+
+ public static bool lua_isboolean(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TBOOLEAN;
+ }
+
+ public static bool lua_isthread(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TTHREAD;
+ }
+
+ public static bool lua_isnone(lua_State L, int n)
+ {
+ return lua_type(L, n) == LUA_TNONE;
+ }
+
+ public static bool lua_isnoneornil(lua_State L, lua_Number n)
+ {
+ return lua_type(L, (int)n) <= 0;
+ }
+
+ public static void lua_pushliteral(lua_State L, CharPtr s)
+ {
+ //TODO: Implement use using lua_pushlstring instead of lua_pushstring
+ //lua_pushlstring(L, "" s, (sizeof(s)/GetUnmanagedSize(typeof(char)))-1)
+ lua_pushstring(L, s);
+ }
+
+ public static void lua_setglobal(lua_State L, CharPtr s)
+ {
+ lua_setfield(L, LUA_GLOBALSINDEX, s);
+ }
+
+ public static void lua_getglobal(lua_State L, CharPtr s)
+ {
+ lua_getfield(L, LUA_GLOBALSINDEX, s);
+ }
+
+ public static CharPtr lua_tostring(lua_State L, int i)
+ {
+ uint blah;
+ return lua_tolstring(L, i, out blah);
+ }
+
+ ////#define lua_open() luaL_newstate()
+ public static lua_State lua_open()
+ {
+ return luaL_newstate();
+ }
+
+ ////#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
+ public static void lua_getregistry(lua_State L)
+ {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ }
+
+ ////#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
+ public static int lua_getgccount(lua_State L)
+ {
+ return lua_gc(L, LUA_GCCOUNT, 0);
+ }
+
+ //#define lua_Chunkreader lua_Reader
+ //#define lua_Chunkwriter lua_Writer
+
+
+ /*
+ ** {======================================================================
+ ** Debug API
+ ** =======================================================================
+ */
+
+
+ /*
+ ** Event codes
+ */
+ public const int LUA_HOOKCALL = 0;
+ public const int LUA_HOOKRET = 1;
+ public const int LUA_HOOKLINE = 2;
+ public const int LUA_HOOKCOUNT = 3;
+ public const int LUA_HOOKTAILRET = 4;
+
+
+ /*
+ ** Event masks
+ */
+ public const int LUA_MASKCALL = (1 << LUA_HOOKCALL);
+ public const int LUA_MASKRET = (1 << LUA_HOOKRET);
+ public const int LUA_MASKLINE = (1 << LUA_HOOKLINE);
+ public const int LUA_MASKCOUNT = (1 << LUA_HOOKCOUNT);
+
+ /* Functions to be called by the debuger in specific events */
+ public delegate void lua_Hook(lua_State L, lua_Debug ar);
+
+
+ public class lua_Debug {
+ public int event_;
+ public CharPtr name; /* (n) */
+ public CharPtr namewhat; /* (n) `global', `local', `field', `method' */
+ public CharPtr what; /* (S) `Lua', `C', `main', `tail' */
+ public CharPtr source; /* (S) */
+ public int currentline; /* (l) */
+ public int nups; /* (u) number of upvalues */
+ public int linedefined; /* (S) */
+ public int lastlinedefined; /* (S) */
+ public CharPtr short_src = new char[LUA_IDSIZE]; /* (S) */
+ /* private part */
+ public 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.
+ ******************************************************************************/
+
+ }
+}
diff --git a/Core/KopiLua/luaconf.cs b/Core/KopiLua/luaconf.cs
index 84f1d78968ee0f920eef1d7b6279b0b4fff7d7f6..ea0a30e19c66631ae6cadd2926fc5704c20723d7 100644
--- a/Core/KopiLua/luaconf.cs
+++ b/Core/KopiLua/luaconf.cs
@@ -1,1683 +1,1683 @@
-/*
-** $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
-*/
-
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-using AT.MIN;
-
-namespace KopiLua
-{
- using LUA_INTEGER = System.Int32;
- using LUA_NUMBER = System.Double;
- using LUAI_UACNUMBER = System.Double;
- using LUA_INTFRM_T = System.Int64;
- using TValue = Lua.lua_TValue;
- using lua_Number = System.Double;
- using System.Globalization;
-
- public partial class Lua
- {
- /*
- ** ==================================================================
- ** 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) && _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.
- */
- public const string LUA_PATH = "LUA_PATH";
- public const string LUA_CPATH = "LUA_CPATH";
- public const string 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 _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.
- */
- public const string LUA_LDIR = "!\\lua\\";
- public const string LUA_CDIR = "!\\";
- public const string LUA_PATH_DEFAULT =
- ".\\?.lua;" + LUA_LDIR + "?.lua;" + LUA_LDIR + "?\\init.lua;"
- + LUA_CDIR + "?.lua;" + LUA_CDIR + "?\\init.lua";
- public const string LUA_CPATH_DEFAULT =
- ".\\?.dll;" + LUA_CDIR + "?.dll;" + LUA_CDIR + "loadall.dll";
-
- #else
- public const string LUA_ROOT = "/usr/local/";
- public const string LUA_LDIR = LUA_ROOT + "share/lua/5.1/";
- public const string LUA_CDIR = LUA_ROOT + "lib/lua/5.1/";
- public const string LUA_PATH_DEFAULT =
- "./?.lua;" + LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
- LUA_CDIR + "?.lua;" + LUA_CDIR + "?/init.lua";
- public const string 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 _WIN32
- public const string LUA_DIRSEP = "\\";
- #else
- public const string 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.
- */
- public const string LUA_PATHSEP = ";";
- public const string LUA_PATH_MARK = "?";
- public const string LUA_EXECDIR = "!";
- public const string 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 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.
- */
- public static CharPtr LUA_QL(string x) {return "'" + x + "'";}
- public static CharPtr LUA_QS {get {return 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.
- */
- public const int LUA_IDSIZE = 60;
-
-
- /*
- ** {==================================================================
- ** Stand-alone configuration
- ** ===================================================================
- */
-
- //#if lua_c || 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 LUA_USE_ISATTY
- //#include
- //#define lua_stdin_is_tty() isatty(0)
- #elif LUA_WIN
- //#include
- //#include
- //#define lua_stdin_is_tty() _isatty(_fileno(stdin))
- #else
- public static int lua_stdin_is_tty() { return 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.)
- */
- public const string LUA_PROMPT = "> ";
- public const string 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.
- */
- public const string 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.
- */
- public const int 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 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
- public static bool lua_readline(lua_State L, CharPtr b, CharPtr p)
- {
- fputs(p, stdout);
- fflush(stdout); /* show prompt */
- return (fgets(b, stdin) != null); /* get line */
- }
- public static void lua_saveline(lua_State L, int idx) {}
- public static void lua_freeline(lua_State L, CharPtr 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.
- */
- public const int 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.
- */
- public const int 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 /* dotnet port doesn't define in the first place */
-
- /*
- @@ 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 /* dotnet port doesn't define in the first place */
-
- /*
- @@ 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 /* defined higher up */
-
- /*
- @@ 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 /* defined higher up */
-
- /*
- @@ 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
- //#define LUA_COMPAT_LSTR /* defined higher up */
-
- /*
- @@ 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 /* defined higher up */
-
- /*
- @@ 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 /* defined higher up */
-
-
-
- /*
- @@ 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 LUA_USE_APICHECK
- public static void luai_apicheck(lua_State L, bool o) {Debug.Assert(o);}
- public static void luai_apicheck(lua_State L, int o) {Debug.Assert(o != 0);}
- #else
- public static void luai_apicheck(lua_State L, bool o) {}
- public static void luai_apicheck(lua_State L, int o) { }
- #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 INT_MAX-20 < 32760
- //public const int LUAI_BITSINT = 16
- //#elif INT_MAX > 2147483640L
- /* int has at least 32 bits */
- public const int 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 uint
- //#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.
- */
- public const int 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)
- */
- public const int 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.
- */
- public const int LUAI_MAXCCALLS = 200;
-
-
- /*
- @@ LUAI_MAXVARS is the maximum number of local variables per function
- @* (must be smaller than 250).
- */
- public const int LUAI_MAXVARS = 200;
-
-
- /*
- @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
- @* (must be smaller than 250).
- */
- public const int LUAI_MAXUPVALUES = 60;
-
-
- /*
- @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
- */
- public const int LUAL_BUFFERSIZE = 1024; // BUFSIZ; todo: check this - mjf
-
- /* }================================================================== */
-
-
-
-
- /*
- ** {==================================================================
- @@ 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.
- ** ===================================================================
- */
-
- //#define LUA_NUMBER_DOUBLE
- //#define LUA_NUMBER double /* declared in dotnet build with using statement */
-
- /*
- @@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
- @* over a number.
- */
- //#define LUAI_UACNUMBER double /* declared in dotnet build with using statement */
-
-
- /*
- @@ 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.
- */
- public const string LUA_NUMBER_SCAN = "%lf";
- public const string LUA_NUMBER_FMT = "%.14g";
- public static CharPtr lua_number2str(double n) { return String.Format("{0}", n); }
- public const int LUAI_MAXNUMBER2STR = 32; /* 16 digits, sign, point, and \0 */
-
- private const string number_chars = "0123456789+-eE.";
- public static double lua_str2number(CharPtr s, out CharPtr end)
- {
- end = new CharPtr(s.chars, s.index);
- string str = "";
- while (end[0] == ' ')
- end = end.next();
- while (number_chars.IndexOf(end[0]) >= 0)
- {
- str += end[0];
- end = end.next();
- }
-
- try
- {
- return Convert.ToDouble(str.ToString(), Culture("en-US"));
- }
- catch (System.OverflowException)
- {
- // this is a hack, fix it - mjf
- if (str[0] == '-')
- return System.Double.NegativeInfinity;
- else
- return System.Double.PositiveInfinity;
- }
- catch
- {
- end = new CharPtr(s.chars, s.index);
- return 0;
- }
- }
-
- private static IFormatProvider Culture(string p)
- {
-#if SILVERLIGHT
- return new CultureInfo(p);
-#else
- return CultureInfo.GetCultureInfo(p);
-#endif
- }
-
- /*
- @@ The luai_num* macros define the primitive operations over numbers.
- */
- #if LUA_CORE
- //#include
- public delegate lua_Number op_delegate(lua_Number a, lua_Number b);
- public static lua_Number luai_numadd(lua_Number a, lua_Number b) { return ((a) + (b)); }
- public static lua_Number luai_numsub(lua_Number a, lua_Number b) { return ((a) - (b)); }
- public static lua_Number luai_nummul(lua_Number a, lua_Number b) { return ((a) * (b)); }
- public static lua_Number luai_numdiv(lua_Number a, lua_Number b) { return ((a) / (b)); }
- public static lua_Number luai_nummod(lua_Number a, lua_Number b) { return ((a) - Math.Floor((a) / (b)) * (b)); }
- public static lua_Number luai_numpow(lua_Number a, lua_Number b) { return (Math.Pow(a, b)); }
- public static lua_Number luai_numunm(lua_Number a) { return (-(a)); }
- public static bool luai_numeq(lua_Number a, lua_Number b) { return ((a) == (b)); }
- public static bool luai_numlt(lua_Number a, lua_Number b) { return ((a) < (b)); }
- public static bool luai_numle(lua_Number a, lua_Number b) { return ((a) <= (b)); }
- public static bool luai_numisnan(lua_Number a) { return lua_Number.IsNaN(a); }
- #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
-
- private static void lua_number2int(out int i,lua_Number d) {i = (int)d;}
- private static void lua_number2integer(out int i, lua_Number n) { i = (int)n; }
-
- /* }================================================================== */
-
-
- /*
- @@ 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; }
-
- public class LuaException : Exception
- {
- public lua_State L;
- public lua_longjmp c;
-
- public LuaException(lua_State L, lua_longjmp c) { this.L = L; this.c = c; }
- }
-
- /*
- @@ 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(__cplusplus)
- ///* C++ exceptions */
- public static void LUAI_THROW(lua_State L, lua_longjmp c) {throw new LuaException(L, c);}
- //#define LUAI_TRY(L,c,a) try { a } catch(...) \
- // { if ((c).status == 0) (c).status = -1; }
- public static void LUAI_TRY(lua_State L, lua_longjmp c, object a) {
- 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 */
- //public static void LUAI_THROW(lua_State L, lua_longjmp c) { 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.
- */
- public const int 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 loslib_c || luaall_c
-
- #if LUA_USE_MKSTEMP
- //#include
- public const int 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
- public const int LUA_TMPNAMBUFSIZE = L_tmpnam;
- public static void lua_tmpnam(CharPtr b, int e) { e = (tmpnam(b) == null) ? 1 : 0; }
- #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 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 LUA_WIN
-
- //#define lua_popen(L,c,m) ((void)L, _popen(c,m))
- //#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
-
- //#else
-
- public static Stream lua_popen(lua_State L, CharPtr c, CharPtr m) { luaL_error(L, LUA_QL("popen") + " not supported"); return null; }
- public static int lua_pclose(lua_State L, Stream file) { return 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 LUA_USE_DLOPEN
- //#define LUA_DL_DLOPEN
- //#endif
-
- //#if 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.
- */
- public const int 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.
- */
- public static void luai_userstateopen(lua_State L) {}
- public static void luai_userstateclose(lua_State L) {}
- public static void luai_userstatethread(lua_State L, lua_State L1) {}
- public static void luai_userstatefree(lua_State L) {}
- public static void luai_userstateresume(lua_State L,int n) {}
- public static void luai_userstateyield(lua_State L,int n) {}
-
-
- /*
- @@ 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 LUA_USELONGLONG
-
- public const string LUA_INTFRMLEN = "ll";
- //#define LUA_INTFRM_T long long
-
- #else
-
- public const string LUA_INTFRMLEN = "l";
- //#define LUA_INTFRM_T long /* declared in dotnet build with using statement */
-
- #endif
-
-
-
- /* =================================================================== */
-
- /*
- ** Local configuration. You can use this space to add your redefinitions
- ** without modifying the main part of the file.
- */
-
- // misc stuff needed for the compile
-
- public static bool isalpha(char c) { return Char.IsLetter(c); }
- public static bool iscntrl(char c) { return Char.IsControl(c); }
- public static bool isdigit(char c) { return Char.IsDigit(c); }
- public static bool islower(char c) { return Char.IsLower(c); }
- public static bool ispunct(char c) { return Char.IsPunctuation(c); }
- public static bool isspace(char c) { return (c==' ') || (c>=(char)0x09 && c<=(char)0x0D); }
- public static bool isupper(char c) { return Char.IsUpper(c); }
- public static bool isalnum(char c) { return Char.IsLetterOrDigit(c); }
- public static bool isxdigit(char c) { return "0123456789ABCDEFabcdef".IndexOf(c) >= 0; }
-
- public static bool isalpha(int c) { return Char.IsLetter((char)c); }
- public static bool iscntrl(int c) { return Char.IsControl((char)c); }
- public static bool isdigit(int c) { return Char.IsDigit((char)c); }
- public static bool islower(int c) { return Char.IsLower((char)c); }
- public static bool ispunct(int c) { return ((char)c != ' ') && !isalnum((char)c); } // *not* the same as Char.IsPunctuation
- public static bool isspace(int c) { return ((char)c == ' ') || ((char)c >= (char)0x09 && (char)c <= (char)0x0D); }
- public static bool isupper(int c) { return Char.IsUpper((char)c); }
- public static bool isalnum(int c) { return Char.IsLetterOrDigit((char)c); }
-
- public static char tolower(char c) { return Char.ToLower(c); }
- public static char toupper(char c) { return Char.ToUpper(c); }
- public static char tolower(int c) { return Char.ToLower((char)c); }
- public static char toupper(int c) { return Char.ToUpper((char)c); }
-
- [CLSCompliantAttribute(false)]
- public static ulong strtoul(CharPtr s, out CharPtr end, int base_)
- {
- try
- {
- end = new CharPtr(s.chars, s.index);
-
- // skip over any leading whitespace
- while (end[0] == ' ')
- end = end.next();
-
- // ignore any leading 0x
- if ((end[0] == '0') && (end[1] == 'x'))
- end = end.next().next();
- else if ((end[0] == '0') && (end[1] == 'X'))
- end = end.next().next();
-
- // do we have a leading + or - sign?
- bool negate = false;
- if (end[0] == '+')
- end = end.next();
- else if (end[0] == '-')
- {
- negate = true;
- end = end.next();
- }
-
- // loop through all chars
- bool invalid = false;
- bool had_digits = false;
- ulong result = 0;
- while (true)
- {
- // get this char
- char ch = end[0];
-
- // which digit is this?
- int this_digit = 0;
- if (isdigit(ch))
- this_digit = ch - '0';
- else if (isalpha(ch))
- this_digit = tolower(ch) - 'a' + 10;
- else
- break;
-
- // is this digit valid?
- if (this_digit >= base_)
- invalid = true;
- else
- {
- had_digits = true;
- result = result * (ulong)base_ + (ulong)this_digit;
- }
-
- end = end.next();
- }
-
- // were any of the digits invalid?
- if (invalid || (!had_digits))
- {
- end = s;
- return System.UInt64.MaxValue;
- }
-
- // if the value was a negative then negate it here
- if (negate)
- result = (ulong)-(long)result;
-
- // ok, we're done
- return (ulong)result;
- }
- catch
- {
- end = s;
- return 0;
- }
- }
-
- public static void putchar(char ch)
- {
- Console.Write(ch);
- }
-
- public static void putchar(int ch)
- {
- Console.Write((char)ch);
- }
-
- public static bool isprint(byte c)
- {
- return (c >= (byte)' ') && (c <= (byte)127);
- }
-
- public static int parse_scanf(string str, CharPtr fmt, params object[] argp)
- {
- int parm_index = 0;
- int index = 0;
- while (fmt[index] != 0)
- {
- if (fmt[index++]=='%')
- switch (fmt[index++])
- {
- case 's':
- {
- argp[parm_index++] = str;
- break;
- }
- case 'c':
- {
- argp[parm_index++] = Convert.ToChar(str, Culture("en-US"));
- break;
- }
- case 'd':
- {
- argp[parm_index++] = Convert.ToInt32(str, Culture("en-US"));
- break;
- }
- case 'l':
- {
- argp[parm_index++] = Convert.ToDouble(str, Culture("en-US"));
- break;
- }
- case 'f':
- {
- argp[parm_index++] = Convert.ToDouble(str, Culture("en-US"));
- break;
- }
- //case 'p':
- // {
- // result += "(pointer)";
- // break;
- // }
- }
- }
- return parm_index;
- }
-
- public static void printf(CharPtr str, params object[] argv)
- {
- Tools.printf(str.ToString(), argv);
- }
-
- public static void sprintf(CharPtr buffer, CharPtr str, params object[] argv)
- {
- string temp = Tools.sprintf(str.ToString(), argv);
- strcpy(buffer, temp);
- }
-
- public static int fprintf(Stream stream, CharPtr str, params object[] argv)
- {
- string result = Tools.sprintf(str.ToString(), argv);
- char[] chars = result.ToCharArray();
- byte[] bytes = new byte[chars.Length];
- for (int i=0; i(CharPtr ptr1, CharPtr ptr2) {
- Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index > ptr2.index; }
- public static bool operator >=(CharPtr ptr1, CharPtr ptr2) {
- Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index >= ptr2.index; }
- public static bool operator ==(CharPtr ptr1, CharPtr ptr2) {
- object o1 = ptr1 as CharPtr;
- object o2 = ptr2 as CharPtr;
- if ((o1 == null) && (o2 == null)) return true;
- if (o1 == null) return false;
- if (o2 == null) return false;
- return (ptr1.chars == ptr2.chars) && (ptr1.index == ptr2.index); }
- public static bool operator !=(CharPtr ptr1, CharPtr ptr2) {return !(ptr1 == ptr2); }
-
- public override bool Equals(object o)
- {
- return this == (o as CharPtr);
- }
-
- public override int GetHashCode()
- {
- return 0;
- }
- public override string ToString()
- {
- string result = "";
- for (int i = index; (i 0))
- dst[dst_index++] = src[src_index++];
- return dst;
- }
-
- [CLSCompliantAttribute(false)]
- public static uint strcspn(CharPtr str, CharPtr charset)
- {
- int index = str.ToString().IndexOfAny(charset.ToString().ToCharArray());
- if (index < 0)
- index = str.ToString().Length;
- return (uint)index;
- }
-
- public static CharPtr strncpy(CharPtr dst, CharPtr src, int length)
- {
- int index = 0;
- while ((src[index] != '\0') && (index 0)
- f.Seek(-1, SeekOrigin.Current);
- }
-
-#if XBOX || SILVERLIGHT
- public static Stream stdout;
- public static Stream stdin;
- public static Stream stderr;
-#else
- public static Stream stdout = Console.OpenStandardOutput();
- public static Stream stdin = Console.OpenStandardInput();
- public static Stream stderr = Console.OpenStandardError();
-#endif
- public static int EOF = -1;
-
- public static void fputs(CharPtr str, Stream stream)
- {
- Console.Write(str.ToString());
- }
-
- public static int feof(Stream s)
- {
- return (s.Position >= s.Length) ? 1 : 0;
- }
-
- public static int fread(CharPtr ptr, int size, int num, Stream stream)
- {
- int num_bytes = num * size;
- byte[] bytes = new byte[num_bytes];
- try
- {
- int result = stream.Read(bytes, 0, num_bytes);
- for (int i = 0; i < result; i++)
- ptr[i] = (char)bytes[i];
- return result/size;
- }
- catch
- {
- return 0;
- }
- }
-
- public static int fwrite(CharPtr ptr, int size, int num, Stream stream)
- {
- int num_bytes = num * size;
- byte[] bytes = new byte[num_bytes];
- for (int i = 0; i < num_bytes; i++)
- bytes[i] = (byte)ptr[i];
- try
- {
- stream.Write(bytes, 0, num_bytes);
- }
- catch
- {
- return 0;
- }
- return num;
- }
-
- public static int strcmp(CharPtr s1, CharPtr s2)
- {
- if (s1 == s2)
- return 0;
- if (s1 == null)
- return -1;
- if (s2 == null)
- return 1;
-
- for (int i = 0; ; i++)
- {
- if (s1[i] != s2[i])
- {
- if (s1[i] < s2[i])
- return -1;
- else
- return 1;
- }
- if (s1[i] == '\0')
- return 0;
- }
- }
-
- public static CharPtr fgets(CharPtr str, Stream stream)
- {
- int index = 0;
- try
- {
- while (true)
- {
- str[index] = (char)stream.ReadByte();
- if (str[index] == '\n')
- break;
- if (index >= str.chars.Length)
- break;
- index++;
- }
- }
- catch
- {
- }
- return str;
- }
-
- public static double frexp(double x, out int expptr)
- {
-#if XBOX
- expptr = (int)(Math.Log(x) / Math.Log(2)) + 1;
-#else
- expptr = (int)Math.Log(x, 2) + 1;
-#endif
- double s = x / Math.Pow(2, expptr);
- return s;
- }
-
- public static double ldexp(double x, int expptr)
- {
- return x * Math.Pow(2, expptr);
- }
-
- public static CharPtr strstr(CharPtr str, CharPtr substr)
- {
- int index = str.ToString().IndexOf(substr.ToString());
- if (index < 0)
- return null;
- return new CharPtr(str + index);
- }
-
- public static CharPtr strrchr(CharPtr str, char ch)
- {
- int index = str.ToString().LastIndexOf(ch);
- if (index < 0)
- return null;
- return str + index;
- }
-
- public static Stream fopen(CharPtr filename, CharPtr mode)
- {
- string str = filename.ToString();
- FileMode filemode = FileMode.Open;
- FileAccess fileaccess = (FileAccess)0;
- for (int i=0; mode[i] != '\0'; i++)
- switch (mode[i])
- {
- case 'r':
- fileaccess = fileaccess | FileAccess.Read;
- if (!File.Exists(str))
- return null;
- break;
-
- case 'w':
- filemode = FileMode.Create;
- fileaccess = fileaccess | FileAccess.Write;
- break;
- }
- try
- {
- return new FileStream(str, filemode, fileaccess);
- }
- catch
- {
- return null;
- }
- }
-
- public static Stream freopen(CharPtr filename, CharPtr mode, Stream stream)
- {
- try
- {
- stream.Flush();
- stream.Close();
- }
- catch { }
-
- return fopen(filename, mode);
- }
-
- public static void fflush(Stream stream)
- {
- stream.Flush();
- }
-
- public static int ferror(Stream stream)
- {
- return 0; // todo: fix this - mjf
- }
-
- public static int fclose(Stream stream)
- {
- stream.Close();
- return 0;
- }
-
-#if !XBOX
- public static Stream tmpfile()
- {
- return new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite);
- }
-#endif
-
- public static int fscanf(Stream f, CharPtr format, params object[] argp)
- {
- string str = Console.ReadLine();
- return parse_scanf(str, format, argp);
- }
-
- public static int fseek(Stream f, long offset, int origin)
- {
- try
- {
- f.Seek(offset, (SeekOrigin)origin);
- return 0;
- }
- catch
- {
- return 1;
- }
- }
-
-
- public static int ftell(Stream f)
- {
- return (int)f.Position;
- }
-
- public static int clearerr(Stream f)
- {
- //Debug.Assert(false, "clearerr not implemented yet - mjf");
- return 0;
- }
-
- [CLSCompliantAttribute(false)]
- public static int setvbuf(Stream stream, CharPtr buffer, int mode, uint size)
- {
- Debug.Assert(false, "setvbuf not implemented yet - mjf");
- return 0;
- }
-
- public static void memcpy(T[] dst, T[] src, int length)
- {
- for (int i = 0; i < length; i++)
- dst[i] = src[i];
- }
-
- public static void memcpy(T[] dst, int offset, T[] src, int length)
- {
- for (int i=0; i(T[] dst, T[] src, int srcofs, int length)
- {
- for (int i = 0; i < length; i++)
- dst[i] = src[srcofs+i];
- }
-
- [CLSCompliantAttribute(false)]
- public static void memcpy(CharPtr ptr1, CharPtr ptr2, uint size) { memcpy(ptr1, ptr2, (int)size); }
- public static void memcpy(CharPtr ptr1, CharPtr ptr2, int size)
- {
- for (int i = 0; i < size; i++)
- ptr1[i] = ptr2[i];
- }
-
- public static object VOID(object f) { return f; }
-
- public const double HUGE_VAL = System.Double.MaxValue;
- [CLSCompliantAttribute(false)]
- public const uint SHRT_MAX = System.UInt16.MaxValue;
-
- [CLSCompliantAttribute(false)]
- public const int _IONBF = 0;
- [CLSCompliantAttribute(false)]
- public const int _IOFBF = 1;
- [CLSCompliantAttribute(false)]
- public const int _IOLBF = 2;
-
- public const int SEEK_SET = 0;
- public const int SEEK_CUR = 1;
- public const int SEEK_END = 2;
-
- // one of the primary objectives of this port is to match the C version of Lua as closely as
- // possible. a key part of this is also matching the behaviour of the garbage collector, as
- // that affects the operation of things such as weak tables. in order for this to occur the
- // size of structures that are allocated must be reported as identical to their C++ equivelents.
- // that this means that variables such as global_State.totalbytes no longer indicate the true
- // amount of memory allocated.
- public static int GetUnmanagedSize(Type t)
- {
- if (t == typeof(global_State))
- return 228;
- else if (t == typeof(LG))
- return 376;
- else if (t == typeof(CallInfo))
- return 24;
- else if (t == typeof(lua_TValue))
- return 16;
- else if (t == typeof(Table))
- return 32;
- else if (t == typeof(Node))
- return 32;
- else if (t == typeof(GCObject))
- return 120;
- else if (t == typeof(GCObjectRef))
- return 4;
- else if (t == typeof(ArrayRef))
- return 4;
- else if (t == typeof(Closure))
- return 0; // handle this one manually in the code
- else if (t == typeof(Proto))
- return 76;
- else if (t == typeof(luaL_Reg))
- return 8;
- else if (t == typeof(luaL_Buffer))
- return 524;
- else if (t == typeof(lua_State))
- return 120;
- else if (t == typeof(lua_Debug))
- return 100;
- else if (t == typeof(CallS))
- return 8;
- else if (t == typeof(LoadF))
- return 520;
- else if (t == typeof(LoadS))
- return 8;
- else if (t == typeof(lua_longjmp))
- return 72;
- else if (t == typeof(SParser))
- return 20;
- else if (t == typeof(Token))
- return 16;
- else if (t == typeof(LexState))
- return 52;
- else if (t == typeof(FuncState))
- return 572;
- else if (t == typeof(GCheader))
- return 8;
- else if (t == typeof(lua_TValue))
- return 16;
- else if (t == typeof(TString))
- return 16;
- else if (t == typeof(LocVar))
- return 12;
- else if (t == typeof(UpVal))
- return 32;
- else if (t == typeof(CClosure))
- return 40;
- else if (t == typeof(LClosure))
- return 24;
- else if (t == typeof(TKey))
- return 16;
- else if (t == typeof(ConsControl))
- return 40;
- else if (t == typeof(LHS_assign))
- return 32;
- else if (t == typeof(expdesc))
- return 24;
- else if (t == typeof(upvaldesc))
- return 2;
- else if (t == typeof(BlockCnt))
- return 12;
- else if (t == typeof(Zio))
- return 20;
- else if (t == typeof(Mbuffer))
- return 12;
- else if (t == typeof(LoadState))
- return 16;
- else if (t == typeof(MatchState))
- return 272;
- else if (t == typeof(stringtable))
- return 12;
- else if (t == typeof(FilePtr))
- return 4;
- else if (t == typeof(Udata))
- return 24;
- else if (t == typeof(Char))
- return 1;
- else if (t == typeof(UInt16))
- return 2;
- else if (t == typeof(Int16))
- return 2;
- else if (t == typeof(UInt32))
- return 4;
- else if (t == typeof(Int32))
- return 4;
- else if (t == typeof(Single))
- return 4;
- Debug.Assert(false, "Trying to get unknown sized of unmanaged type " + t.ToString());
- return 0;
- }
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using AT.MIN;
+
+namespace KopiLua
+{
+ using LUA_INTEGER = System.Int32;
+ using LUA_NUMBER = System.Double;
+ using LUAI_UACNUMBER = System.Double;
+ using LUA_INTFRM_T = System.Int64;
+ using TValue = Lua.lua_TValue;
+ using lua_Number = System.Double;
+ using System.Globalization;
+
+ public partial class Lua
+ {
+ /*
+ ** ==================================================================
+ ** 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) && _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.
+ */
+ public const string LUA_PATH = "LUA_PATH";
+ public const string LUA_CPATH = "LUA_CPATH";
+ public const string 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 _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.
+ */
+ public const string LUA_LDIR = "!\\lua\\";
+ public const string LUA_CDIR = "!\\";
+ public const string LUA_PATH_DEFAULT =
+ ".\\?.lua;" + LUA_LDIR + "?.lua;" + LUA_LDIR + "?\\init.lua;"
+ + LUA_CDIR + "?.lua;" + LUA_CDIR + "?\\init.lua";
+ public const string LUA_CPATH_DEFAULT =
+ ".\\?.dll;" + LUA_CDIR + "?.dll;" + LUA_CDIR + "loadall.dll";
+
+ #else
+ public const string LUA_ROOT = "/usr/local/";
+ public const string LUA_LDIR = LUA_ROOT + "share/lua/5.1/";
+ public const string LUA_CDIR = LUA_ROOT + "lib/lua/5.1/";
+ public const string LUA_PATH_DEFAULT =
+ "./?.lua;" + LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
+ LUA_CDIR + "?.lua;" + LUA_CDIR + "?/init.lua";
+ public const string 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 _WIN32
+ public const string LUA_DIRSEP = "\\";
+ #else
+ public const string 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.
+ */
+ public const string LUA_PATHSEP = ";";
+ public const string LUA_PATH_MARK = "?";
+ public const string LUA_EXECDIR = "!";
+ public const string 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 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.
+ */
+ public static CharPtr LUA_QL(string x) {return "'" + x + "'";}
+ public static CharPtr LUA_QS {get {return 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.
+ */
+ public const int LUA_IDSIZE = 60;
+
+
+ /*
+ ** {==================================================================
+ ** Stand-alone configuration
+ ** ===================================================================
+ */
+
+ //#if lua_c || 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 LUA_USE_ISATTY
+ //#include
+ //#define lua_stdin_is_tty() isatty(0)
+ #elif LUA_WIN
+ //#include
+ //#include
+ //#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+ #else
+ public static int lua_stdin_is_tty() { return 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.)
+ */
+ public const string LUA_PROMPT = "> ";
+ public const string 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.
+ */
+ public const string 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.
+ */
+ public const int 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 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
+ public static bool lua_readline(lua_State L, CharPtr b, CharPtr p)
+ {
+ fputs(p, stdout);
+ fflush(stdout); /* show prompt */
+ return (fgets(b, stdin) != null); /* get line */
+ }
+ public static void lua_saveline(lua_State L, int idx) {}
+ public static void lua_freeline(lua_State L, CharPtr 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.
+ */
+ public const int 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.
+ */
+ public const int 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 /* dotnet port doesn't define in the first place */
+
+ /*
+ @@ 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 /* dotnet port doesn't define in the first place */
+
+ /*
+ @@ 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 /* defined higher up */
+
+ /*
+ @@ 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 /* defined higher up */
+
+ /*
+ @@ 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
+ //#define LUA_COMPAT_LSTR /* defined higher up */
+
+ /*
+ @@ 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 /* defined higher up */
+
+ /*
+ @@ 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 /* defined higher up */
+
+
+
+ /*
+ @@ 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 LUA_USE_APICHECK
+ public static void luai_apicheck(lua_State L, bool o) {Debug.Assert(o);}
+ public static void luai_apicheck(lua_State L, int o) {Debug.Assert(o != 0);}
+ #else
+ public static void luai_apicheck(lua_State L, bool o) {}
+ public static void luai_apicheck(lua_State L, int o) { }
+ #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 INT_MAX-20 < 32760
+ //public const int LUAI_BITSINT = 16
+ //#elif INT_MAX > 2147483640L
+ /* int has at least 32 bits */
+ public const int 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 uint
+ //#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.
+ */
+ public const int 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)
+ */
+ public const int 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.
+ */
+ public const int LUAI_MAXCCALLS = 200;
+
+
+ /*
+ @@ LUAI_MAXVARS is the maximum number of local variables per function
+ @* (must be smaller than 250).
+ */
+ public const int LUAI_MAXVARS = 200;
+
+
+ /*
+ @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
+ @* (must be smaller than 250).
+ */
+ public const int LUAI_MAXUPVALUES = 60;
+
+
+ /*
+ @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+ */
+ public const int LUAL_BUFFERSIZE = 1024; // BUFSIZ; todo: check this - mjf
+
+ /* }================================================================== */
+
+
+
+
+ /*
+ ** {==================================================================
+ @@ 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.
+ ** ===================================================================
+ */
+
+ //#define LUA_NUMBER_DOUBLE
+ //#define LUA_NUMBER double /* declared in dotnet build with using statement */
+
+ /*
+ @@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+ @* over a number.
+ */
+ //#define LUAI_UACNUMBER double /* declared in dotnet build with using statement */
+
+
+ /*
+ @@ 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.
+ */
+ public const string LUA_NUMBER_SCAN = "%lf";
+ public const string LUA_NUMBER_FMT = "%.14g";
+ public static CharPtr lua_number2str(double n) { return String.Format("{0}", n); }
+ public const int LUAI_MAXNUMBER2STR = 32; /* 16 digits, sign, point, and \0 */
+
+ private const string number_chars = "0123456789+-eE.";
+ public static double lua_str2number(CharPtr s, out CharPtr end)
+ {
+ end = new CharPtr(s.chars, s.index);
+ string str = "";
+ while (end[0] == ' ')
+ end = end.next();
+ while (number_chars.IndexOf(end[0]) >= 0)
+ {
+ str += end[0];
+ end = end.next();
+ }
+
+ try
+ {
+ return Convert.ToDouble(str.ToString(), Culture("en-US"));
+ }
+ catch (System.OverflowException)
+ {
+ // this is a hack, fix it - mjf
+ if (str[0] == '-')
+ return System.Double.NegativeInfinity;
+ else
+ return System.Double.PositiveInfinity;
+ }
+ catch
+ {
+ end = new CharPtr(s.chars, s.index);
+ return 0;
+ }
+ }
+
+ private static IFormatProvider Culture(string p)
+ {
+#if SILVERLIGHT
+ return new CultureInfo(p);
+#else
+ return CultureInfo.GetCultureInfo(p);
+#endif
+ }
+
+ /*
+ @@ The luai_num* macros define the primitive operations over numbers.
+ */
+ #if LUA_CORE
+ //#include
+ public delegate lua_Number op_delegate(lua_Number a, lua_Number b);
+ public static lua_Number luai_numadd(lua_Number a, lua_Number b) { return ((a) + (b)); }
+ public static lua_Number luai_numsub(lua_Number a, lua_Number b) { return ((a) - (b)); }
+ public static lua_Number luai_nummul(lua_Number a, lua_Number b) { return ((a) * (b)); }
+ public static lua_Number luai_numdiv(lua_Number a, lua_Number b) { return ((a) / (b)); }
+ public static lua_Number luai_nummod(lua_Number a, lua_Number b) { return ((a) - Math.Floor((a) / (b)) * (b)); }
+ public static lua_Number luai_numpow(lua_Number a, lua_Number b) { return (Math.Pow(a, b)); }
+ public static lua_Number luai_numunm(lua_Number a) { return (-(a)); }
+ public static bool luai_numeq(lua_Number a, lua_Number b) { return ((a) == (b)); }
+ public static bool luai_numlt(lua_Number a, lua_Number b) { return ((a) < (b)); }
+ public static bool luai_numle(lua_Number a, lua_Number b) { return ((a) <= (b)); }
+ public static bool luai_numisnan(lua_Number a) { return lua_Number.IsNaN(a); }
+ #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
+
+ private static void lua_number2int(out int i,lua_Number d) {i = (int)d;}
+ private static void lua_number2integer(out int i, lua_Number n) { i = (int)n; }
+
+ /* }================================================================== */
+
+
+ /*
+ @@ 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; }
+
+ public class LuaException : Exception
+ {
+ public lua_State L;
+ public lua_longjmp c;
+
+ public LuaException(lua_State L, lua_longjmp c) { this.L = L; this.c = c; }
+ }
+
+ /*
+ @@ 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(__cplusplus)
+ ///* C++ exceptions */
+ public static void LUAI_THROW(lua_State L, lua_longjmp c) {throw new LuaException(L, c);}
+ //#define LUAI_TRY(L,c,a) try { a } catch(...) \
+ // { if ((c).status == 0) (c).status = -1; }
+ public static void LUAI_TRY(lua_State L, lua_longjmp c, object a) {
+ 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 */
+ //public static void LUAI_THROW(lua_State L, lua_longjmp c) { 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.
+ */
+ public const int 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 loslib_c || luaall_c
+
+ #if LUA_USE_MKSTEMP
+ //#include
+ public const int 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
+ public const int LUA_TMPNAMBUFSIZE = L_tmpnam;
+ public static void lua_tmpnam(CharPtr b, int e) { e = (tmpnam(b) == null) ? 1 : 0; }
+ #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 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 LUA_WIN
+
+ //#define lua_popen(L,c,m) ((void)L, _popen(c,m))
+ //#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
+
+ //#else
+
+ public static Stream lua_popen(lua_State L, CharPtr c, CharPtr m) { luaL_error(L, LUA_QL("popen") + " not supported"); return null; }
+ public static int lua_pclose(lua_State L, Stream file) { return 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 LUA_USE_DLOPEN
+ //#define LUA_DL_DLOPEN
+ //#endif
+
+ //#if 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.
+ */
+ public const int 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.
+ */
+ public static void luai_userstateopen(lua_State L) {}
+ public static void luai_userstateclose(lua_State L) {}
+ public static void luai_userstatethread(lua_State L, lua_State L1) {}
+ public static void luai_userstatefree(lua_State L) {}
+ public static void luai_userstateresume(lua_State L,int n) {}
+ public static void luai_userstateyield(lua_State L,int n) {}
+
+
+ /*
+ @@ 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 LUA_USELONGLONG
+
+ public const string LUA_INTFRMLEN = "ll";
+ //#define LUA_INTFRM_T long long
+
+ #else
+
+ public const string LUA_INTFRMLEN = "l";
+ //#define LUA_INTFRM_T long /* declared in dotnet build with using statement */
+
+ #endif
+
+
+
+ /* =================================================================== */
+
+ /*
+ ** Local configuration. You can use this space to add your redefinitions
+ ** without modifying the main part of the file.
+ */
+
+ // misc stuff needed for the compile
+
+ public static bool isalpha(char c) { return Char.IsLetter(c); }
+ public static bool iscntrl(char c) { return Char.IsControl(c); }
+ public static bool isdigit(char c) { return Char.IsDigit(c); }
+ public static bool islower(char c) { return Char.IsLower(c); }
+ public static bool ispunct(char c) { return Char.IsPunctuation(c); }
+ public static bool isspace(char c) { return (c==' ') || (c>=(char)0x09 && c<=(char)0x0D); }
+ public static bool isupper(char c) { return Char.IsUpper(c); }
+ public static bool isalnum(char c) { return Char.IsLetterOrDigit(c); }
+ public static bool isxdigit(char c) { return "0123456789ABCDEFabcdef".IndexOf(c) >= 0; }
+
+ public static bool isalpha(int c) { return Char.IsLetter((char)c); }
+ public static bool iscntrl(int c) { return Char.IsControl((char)c); }
+ public static bool isdigit(int c) { return Char.IsDigit((char)c); }
+ public static bool islower(int c) { return Char.IsLower((char)c); }
+ public static bool ispunct(int c) { return ((char)c != ' ') && !isalnum((char)c); } // *not* the same as Char.IsPunctuation
+ public static bool isspace(int c) { return ((char)c == ' ') || ((char)c >= (char)0x09 && (char)c <= (char)0x0D); }
+ public static bool isupper(int c) { return Char.IsUpper((char)c); }
+ public static bool isalnum(int c) { return Char.IsLetterOrDigit((char)c); }
+
+ public static char tolower(char c) { return Char.ToLower(c); }
+ public static char toupper(char c) { return Char.ToUpper(c); }
+ public static char tolower(int c) { return Char.ToLower((char)c); }
+ public static char toupper(int c) { return Char.ToUpper((char)c); }
+
+ [CLSCompliantAttribute(false)]
+ public static ulong strtoul(CharPtr s, out CharPtr end, int base_)
+ {
+ try
+ {
+ end = new CharPtr(s.chars, s.index);
+
+ // skip over any leading whitespace
+ while (end[0] == ' ')
+ end = end.next();
+
+ // ignore any leading 0x
+ if ((end[0] == '0') && (end[1] == 'x'))
+ end = end.next().next();
+ else if ((end[0] == '0') && (end[1] == 'X'))
+ end = end.next().next();
+
+ // do we have a leading + or - sign?
+ bool negate = false;
+ if (end[0] == '+')
+ end = end.next();
+ else if (end[0] == '-')
+ {
+ negate = true;
+ end = end.next();
+ }
+
+ // loop through all chars
+ bool invalid = false;
+ bool had_digits = false;
+ ulong result = 0;
+ while (true)
+ {
+ // get this char
+ char ch = end[0];
+
+ // which digit is this?
+ int this_digit = 0;
+ if (isdigit(ch))
+ this_digit = ch - '0';
+ else if (isalpha(ch))
+ this_digit = tolower(ch) - 'a' + 10;
+ else
+ break;
+
+ // is this digit valid?
+ if (this_digit >= base_)
+ invalid = true;
+ else
+ {
+ had_digits = true;
+ result = result * (ulong)base_ + (ulong)this_digit;
+ }
+
+ end = end.next();
+ }
+
+ // were any of the digits invalid?
+ if (invalid || (!had_digits))
+ {
+ end = s;
+ return System.UInt64.MaxValue;
+ }
+
+ // if the value was a negative then negate it here
+ if (negate)
+ result = (ulong)-(long)result;
+
+ // ok, we're done
+ return (ulong)result;
+ }
+ catch
+ {
+ end = s;
+ return 0;
+ }
+ }
+
+ public static void putchar(char ch)
+ {
+ Console.Write(ch);
+ }
+
+ public static void putchar(int ch)
+ {
+ Console.Write((char)ch);
+ }
+
+ public static bool isprint(byte c)
+ {
+ return (c >= (byte)' ') && (c <= (byte)127);
+ }
+
+ public static int parse_scanf(string str, CharPtr fmt, params object[] argp)
+ {
+ int parm_index = 0;
+ int index = 0;
+ while (fmt[index] != 0)
+ {
+ if (fmt[index++]=='%')
+ switch (fmt[index++])
+ {
+ case 's':
+ {
+ argp[parm_index++] = str;
+ break;
+ }
+ case 'c':
+ {
+ argp[parm_index++] = Convert.ToChar(str, Culture("en-US"));
+ break;
+ }
+ case 'd':
+ {
+ argp[parm_index++] = Convert.ToInt32(str, Culture("en-US"));
+ break;
+ }
+ case 'l':
+ {
+ argp[parm_index++] = Convert.ToDouble(str, Culture("en-US"));
+ break;
+ }
+ case 'f':
+ {
+ argp[parm_index++] = Convert.ToDouble(str, Culture("en-US"));
+ break;
+ }
+ //case 'p':
+ // {
+ // result += "(pointer)";
+ // break;
+ // }
+ }
+ }
+ return parm_index;
+ }
+
+ public static void printf(CharPtr str, params object[] argv)
+ {
+ Tools.printf(str.ToString(), argv);
+ }
+
+ public static void sprintf(CharPtr buffer, CharPtr str, params object[] argv)
+ {
+ string temp = Tools.sprintf(str.ToString(), argv);
+ strcpy(buffer, temp);
+ }
+
+ public static int fprintf(Stream stream, CharPtr str, params object[] argv)
+ {
+ string result = Tools.sprintf(str.ToString(), argv);
+ char[] chars = result.ToCharArray();
+ byte[] bytes = new byte[chars.Length];
+ for (int i=0; i(CharPtr ptr1, CharPtr ptr2) {
+ Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index > ptr2.index; }
+ public static bool operator >=(CharPtr ptr1, CharPtr ptr2) {
+ Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index >= ptr2.index; }
+ public static bool operator ==(CharPtr ptr1, CharPtr ptr2) {
+ object o1 = ptr1 as CharPtr;
+ object o2 = ptr2 as CharPtr;
+ if ((o1 == null) && (o2 == null)) return true;
+ if (o1 == null) return false;
+ if (o2 == null) return false;
+ return (ptr1.chars == ptr2.chars) && (ptr1.index == ptr2.index); }
+ public static bool operator !=(CharPtr ptr1, CharPtr ptr2) {return !(ptr1 == ptr2); }
+
+ public override bool Equals(object o)
+ {
+ return this == (o as CharPtr);
+ }
+
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+ public override string ToString()
+ {
+ string result = "";
+ for (int i = index; (i 0))
+ dst[dst_index++] = src[src_index++];
+ return dst;
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static uint strcspn(CharPtr str, CharPtr charset)
+ {
+ int index = str.ToString().IndexOfAny(charset.ToString().ToCharArray());
+ if (index < 0)
+ index = str.ToString().Length;
+ return (uint)index;
+ }
+
+ public static CharPtr strncpy(CharPtr dst, CharPtr src, int length)
+ {
+ int index = 0;
+ while ((src[index] != '\0') && (index 0)
+ f.Seek(-1, SeekOrigin.Current);
+ }
+
+#if XBOX || SILVERLIGHT
+ public static Stream stdout;
+ public static Stream stdin;
+ public static Stream stderr;
+#else
+ public static Stream stdout = Console.OpenStandardOutput();
+ public static Stream stdin = Console.OpenStandardInput();
+ public static Stream stderr = Console.OpenStandardError();
+#endif
+ public static int EOF = -1;
+
+ public static void fputs(CharPtr str, Stream stream)
+ {
+ Console.Write(str.ToString());
+ }
+
+ public static int feof(Stream s)
+ {
+ return (s.Position >= s.Length) ? 1 : 0;
+ }
+
+ public static int fread(CharPtr ptr, int size, int num, Stream stream)
+ {
+ int num_bytes = num * size;
+ byte[] bytes = new byte[num_bytes];
+ try
+ {
+ int result = stream.Read(bytes, 0, num_bytes);
+ for (int i = 0; i < result; i++)
+ ptr[i] = (char)bytes[i];
+ return result/size;
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+
+ public static int fwrite(CharPtr ptr, int size, int num, Stream stream)
+ {
+ int num_bytes = num * size;
+ byte[] bytes = new byte[num_bytes];
+ for (int i = 0; i < num_bytes; i++)
+ bytes[i] = (byte)ptr[i];
+ try
+ {
+ stream.Write(bytes, 0, num_bytes);
+ }
+ catch
+ {
+ return 0;
+ }
+ return num;
+ }
+
+ public static int strcmp(CharPtr s1, CharPtr s2)
+ {
+ if (s1 == s2)
+ return 0;
+ if (s1 == null)
+ return -1;
+ if (s2 == null)
+ return 1;
+
+ for (int i = 0; ; i++)
+ {
+ if (s1[i] != s2[i])
+ {
+ if (s1[i] < s2[i])
+ return -1;
+ else
+ return 1;
+ }
+ if (s1[i] == '\0')
+ return 0;
+ }
+ }
+
+ public static CharPtr fgets(CharPtr str, Stream stream)
+ {
+ int index = 0;
+ try
+ {
+ while (true)
+ {
+ str[index] = (char)stream.ReadByte();
+ if (str[index] == '\n')
+ break;
+ if (index >= str.chars.Length)
+ break;
+ index++;
+ }
+ }
+ catch
+ {
+ }
+ return str;
+ }
+
+ public static double frexp(double x, out int expptr)
+ {
+#if XBOX
+ expptr = (int)(Math.Log(x) / Math.Log(2)) + 1;
+#else
+ expptr = (int)Math.Log(x, 2) + 1;
+#endif
+ double s = x / Math.Pow(2, expptr);
+ return s;
+ }
+
+ public static double ldexp(double x, int expptr)
+ {
+ return x * Math.Pow(2, expptr);
+ }
+
+ public static CharPtr strstr(CharPtr str, CharPtr substr)
+ {
+ int index = str.ToString().IndexOf(substr.ToString());
+ if (index < 0)
+ return null;
+ return new CharPtr(str + index);
+ }
+
+ public static CharPtr strrchr(CharPtr str, char ch)
+ {
+ int index = str.ToString().LastIndexOf(ch);
+ if (index < 0)
+ return null;
+ return str + index;
+ }
+
+ public static Stream fopen(CharPtr filename, CharPtr mode)
+ {
+ string str = filename.ToString();
+ FileMode filemode = FileMode.Open;
+ FileAccess fileaccess = (FileAccess)0;
+ for (int i=0; mode[i] != '\0'; i++)
+ switch (mode[i])
+ {
+ case 'r':
+ fileaccess = fileaccess | FileAccess.Read;
+ if (!File.Exists(str))
+ return null;
+ break;
+
+ case 'w':
+ filemode = FileMode.Create;
+ fileaccess = fileaccess | FileAccess.Write;
+ break;
+ }
+ try
+ {
+ return new FileStream(str, filemode, fileaccess);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public static Stream freopen(CharPtr filename, CharPtr mode, Stream stream)
+ {
+ try
+ {
+ stream.Flush();
+ stream.Close();
+ }
+ catch { }
+
+ return fopen(filename, mode);
+ }
+
+ public static void fflush(Stream stream)
+ {
+ stream.Flush();
+ }
+
+ public static int ferror(Stream stream)
+ {
+ return 0; // todo: fix this - mjf
+ }
+
+ public static int fclose(Stream stream)
+ {
+ stream.Close();
+ return 0;
+ }
+
+#if !XBOX
+ public static Stream tmpfile()
+ {
+ return new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite);
+ }
+#endif
+
+ public static int fscanf(Stream f, CharPtr format, params object[] argp)
+ {
+ string str = Console.ReadLine();
+ return parse_scanf(str, format, argp);
+ }
+
+ public static int fseek(Stream f, long offset, int origin)
+ {
+ try
+ {
+ f.Seek(offset, (SeekOrigin)origin);
+ return 0;
+ }
+ catch
+ {
+ return 1;
+ }
+ }
+
+
+ public static int ftell(Stream f)
+ {
+ return (int)f.Position;
+ }
+
+ public static int clearerr(Stream f)
+ {
+ //Debug.Assert(false, "clearerr not implemented yet - mjf");
+ return 0;
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static int setvbuf(Stream stream, CharPtr buffer, int mode, uint size)
+ {
+ Debug.Assert(false, "setvbuf not implemented yet - mjf");
+ return 0;
+ }
+
+ public static void memcpy(T[] dst, T[] src, int length)
+ {
+ for (int i = 0; i < length; i++)
+ dst[i] = src[i];
+ }
+
+ public static void memcpy(T[] dst, int offset, T[] src, int length)
+ {
+ for (int i=0; i(T[] dst, T[] src, int srcofs, int length)
+ {
+ for (int i = 0; i < length; i++)
+ dst[i] = src[srcofs+i];
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static void memcpy(CharPtr ptr1, CharPtr ptr2, uint size) { memcpy(ptr1, ptr2, (int)size); }
+ public static void memcpy(CharPtr ptr1, CharPtr ptr2, int size)
+ {
+ for (int i = 0; i < size; i++)
+ ptr1[i] = ptr2[i];
+ }
+
+ public static object VOID(object f) { return f; }
+
+ public const double HUGE_VAL = System.Double.MaxValue;
+ [CLSCompliantAttribute(false)]
+ public const uint SHRT_MAX = System.UInt16.MaxValue;
+
+ [CLSCompliantAttribute(false)]
+ public const int _IONBF = 0;
+ [CLSCompliantAttribute(false)]
+ public const int _IOFBF = 1;
+ [CLSCompliantAttribute(false)]
+ public const int _IOLBF = 2;
+
+ public const int SEEK_SET = 0;
+ public const int SEEK_CUR = 1;
+ public const int SEEK_END = 2;
+
+ // one of the primary objectives of this port is to match the C version of Lua as closely as
+ // possible. a key part of this is also matching the behaviour of the garbage collector, as
+ // that affects the operation of things such as weak tables. in order for this to occur the
+ // size of structures that are allocated must be reported as identical to their C++ equivelents.
+ // that this means that variables such as global_State.totalbytes no longer indicate the true
+ // amount of memory allocated.
+ public static int GetUnmanagedSize(Type t)
+ {
+ if (t == typeof(global_State))
+ return 228;
+ else if (t == typeof(LG))
+ return 376;
+ else if (t == typeof(CallInfo))
+ return 24;
+ else if (t == typeof(lua_TValue))
+ return 16;
+ else if (t == typeof(Table))
+ return 32;
+ else if (t == typeof(Node))
+ return 32;
+ else if (t == typeof(GCObject))
+ return 120;
+ else if (t == typeof(GCObjectRef))
+ return 4;
+ else if (t == typeof(ArrayRef))
+ return 4;
+ else if (t == typeof(Closure))
+ return 0; // handle this one manually in the code
+ else if (t == typeof(Proto))
+ return 76;
+ else if (t == typeof(luaL_Reg))
+ return 8;
+ else if (t == typeof(luaL_Buffer))
+ return 524;
+ else if (t == typeof(lua_State))
+ return 120;
+ else if (t == typeof(lua_Debug))
+ return 100;
+ else if (t == typeof(CallS))
+ return 8;
+ else if (t == typeof(LoadF))
+ return 520;
+ else if (t == typeof(LoadS))
+ return 8;
+ else if (t == typeof(lua_longjmp))
+ return 72;
+ else if (t == typeof(SParser))
+ return 20;
+ else if (t == typeof(Token))
+ return 16;
+ else if (t == typeof(LexState))
+ return 52;
+ else if (t == typeof(FuncState))
+ return 572;
+ else if (t == typeof(GCheader))
+ return 8;
+ else if (t == typeof(lua_TValue))
+ return 16;
+ else if (t == typeof(TString))
+ return 16;
+ else if (t == typeof(LocVar))
+ return 12;
+ else if (t == typeof(UpVal))
+ return 32;
+ else if (t == typeof(CClosure))
+ return 40;
+ else if (t == typeof(LClosure))
+ return 24;
+ else if (t == typeof(TKey))
+ return 16;
+ else if (t == typeof(ConsControl))
+ return 40;
+ else if (t == typeof(LHS_assign))
+ return 32;
+ else if (t == typeof(expdesc))
+ return 24;
+ else if (t == typeof(upvaldesc))
+ return 2;
+ else if (t == typeof(BlockCnt))
+ return 12;
+ else if (t == typeof(Zio))
+ return 20;
+ else if (t == typeof(Mbuffer))
+ return 12;
+ else if (t == typeof(LoadState))
+ return 16;
+ else if (t == typeof(MatchState))
+ return 272;
+ else if (t == typeof(stringtable))
+ return 12;
+ else if (t == typeof(FilePtr))
+ return 4;
+ else if (t == typeof(Udata))
+ return 24;
+ else if (t == typeof(Char))
+ return 1;
+ else if (t == typeof(UInt16))
+ return 2;
+ else if (t == typeof(Int16))
+ return 2;
+ else if (t == typeof(UInt32))
+ return 4;
+ else if (t == typeof(Int32))
+ return 4;
+ else if (t == typeof(Single))
+ return 4;
+ Debug.Assert(false, "Trying to get unknown sized of unmanaged type " + t.ToString());
+ return 0;
+ }
+ }
+}
diff --git a/Core/KopiLua/lualib.cs b/Core/KopiLua/lualib.cs
index 40e9dd6c43300e77cefeaff8a3d7248b53ac6aed..4004c5f8ad55183df14f722b61218cc76274748e 100644
--- a/Core/KopiLua/lualib.cs
+++ b/Core/KopiLua/lualib.cs
@@ -1,28 +1,28 @@
-/*
-** $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
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace KopiLua
-{
- public partial class Lua
- {
- /* Key to file-handle type */
- public const string LUA_FILEHANDLE = "FILE*";
-
- public const string LUA_COLIBNAME = "coroutine";
- public const string LUA_TABLIBNAME = "table";
- public const string LUA_IOLIBNAME = "io";
- public const string LUA_OSLIBNAME = "os";
- public const string LUA_STRLIBNAME = "string";
- public const string LUA_MATHLIBNAME = "math";
- public const string LUA_DBLIBNAME = "debug";
- public const string LUA_LOADLIBNAME = "package";
-
- }
-}
+/*
+** $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
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace KopiLua
+{
+ public partial class Lua
+ {
+ /* Key to file-handle type */
+ public const string LUA_FILEHANDLE = "FILE*";
+
+ public const string LUA_COLIBNAME = "coroutine";
+ public const string LUA_TABLIBNAME = "table";
+ public const string LUA_IOLIBNAME = "io";
+ public const string LUA_OSLIBNAME = "os";
+ public const string LUA_STRLIBNAME = "string";
+ public const string LUA_MATHLIBNAME = "math";
+ public const string LUA_DBLIBNAME = "debug";
+ public const string LUA_LOADLIBNAME = "package";
+
+ }
+}
diff --git a/Core/KopiLua/lundump.cs b/Core/KopiLua/lundump.cs
index ab651df3e28cee12ea927dd223acf820230774b1..97f7df6dae4e3ca874cfd5416da4440399233664 100644
--- a/Core/KopiLua/lundump.cs
+++ b/Core/KopiLua/lundump.cs
@@ -1,275 +1,275 @@
-/*
-** $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
-*/
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-
-namespace KopiLua
-{
- using TValue = Lua.lua_TValue;
- using lua_Number = System.Double;
- using lu_byte = System.Byte;
- using StkId = Lua.lua_TValue;
- using Instruction = System.UInt32;
- using ZIO = Lua.Zio;
-
- public partial class Lua
- {
- /* for header of binary files -- this is Lua 5.1 */
- public const int LUAC_VERSION = 0x51;
-
- /* for header of binary files -- this is the official format */
- public const int LUAC_FORMAT = 0;
-
- /* size of header of binary files */
- public const int LUAC_HEADERSIZE = 12;
-
- public class LoadState{
- public lua_State L;
- public ZIO Z;
- public Mbuffer b;
- public CharPtr name;
- };
-
- //#ifdef LUAC_TRUST_BINARIES
- //#define IF(c,s)
- //#define error(S,s)
- //#else
- //#define IF(c,s) if (c) error(S,s)
-
- public static void IF(int c, string s) { }
- public static void IF(bool c, string s) { }
-
- static void error(LoadState S, CharPtr why)
- {
- luaO_pushfstring(S.L,"%s: %s in precompiled chunk",S.name,why);
- luaD_throw(S.L,LUA_ERRSYNTAX);
- }
- //#endif
-
- public static object LoadMem(LoadState S, Type t)
- {
- int size = Marshal.SizeOf(t);
- CharPtr str = new char[size];
- LoadBlock(S, str, size);
- byte[] bytes = new byte[str.chars.Length];
- for (int i = 0; i < str.chars.Length; i++)
- bytes[i] = (byte)str.chars[i];
- GCHandle pinnedPacket = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- object b = Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), t);
- pinnedPacket.Free();
- return b;
- }
-
- public static object LoadMem(LoadState S, Type t, int n)
- {
-#if SILVERLIGHT
- List