-
-
-#include "llimits.h"
-#include "lua.h"
-
-
-/*
-** Extra types for collectable non-values
-*/
-#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
-#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */
-#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */
-
-
-
-/*
-** number of all possible types (including LUA_TNONE but excluding DEADKEY)
-*/
-#define LUA_TOTALTYPES (LUA_TPROTO + 2)
-
-
-/*
-** tags for Tagged Values have the following use of bits:
-** bits 0-3: actual tag (a LUA_T* constant)
-** bits 4-5: variant bits
-** bit 6: whether value is collectable
-*/
-
-/* add variant bits to a type */
-#define makevariant(t,v) ((t) | ((v) << 4))
-
-
-
-/*
-** Union of all Lua values
-*/
-typedef union Value {
- struct GCObject *gc; /* collectable objects */
- void *p; /* light userdata */
- lua_CFunction f; /* light C functions */
- lua_Integer i; /* integer numbers */
- lua_Number n; /* float numbers */
-} Value;
-
-
-/*
-** Tagged Values. This is the basic representation of values in Lua:
-** an actual value plus a tag with its type.
-*/
-
-#define TValuefields Value value_; lu_byte tt_
-
-typedef struct TValue {
- TValuefields;
-} TValue;
-
-
-#define val_(o) ((o)->value_)
-#define valraw(o) (val_(o))
-
-
-/* raw type tag of a TValue */
-#define rawtt(o) ((o)->tt_)
-
-/* tag with no variants (bits 0-3) */
-#define novariant(t) ((t) & 0x0F)
-
-/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
-#define withvariant(t) ((t) & 0x3F)
-#define ttypetag(o) withvariant(rawtt(o))
-
-/* type of a TValue */
-#define ttype(o) (novariant(rawtt(o)))
-
-
-/* Macros to test type */
-#define checktag(o,t) (rawtt(o) == (t))
-#define checktype(o,t) (ttype(o) == (t))
-
-
-/* Macros for internal tests */
-
-/* collectable object has the same tag as the original value */
-#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt)
-
-/*
-** Any value being manipulated by the program either is non
-** collectable, or the collectable object has the right tag
-** and it is not dead. The option 'L == NULL' allows other
-** macros using this one to be used where L is not available.
-*/
-#define checkliveness(L,obj) \
- ((void)L, lua_longassert(!iscollectable(obj) || \
- (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))))
-
-
-/* Macros to set values */
-
-/* set a value's tag */
-#define settt_(o,t) ((o)->tt_=(t))
-
-
-/* main macro to copy values (from 'obj2' to 'obj1') */
-#define setobj(L,obj1,obj2) \
- { TValue *io1=(obj1); const TValue *io2=(obj2); \
- io1->value_ = io2->value_; settt_(io1, io2->tt_); \
- checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
-
-/*
-** Different types of assignments, according to source and destination.
-** (They are mostly equal now, but may be different in the future.)
-*/
-
-/* from stack to stack */
-#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2))
-/* to stack (not from same stack) */
-#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2)
-/* from table to same table */
-#define setobjt2t setobj
-/* to new object */
-#define setobj2n setobj
-/* to table */
-#define setobj2t setobj
-
-
-/*
-** Entries in a Lua stack. Field 'tbclist' forms a list of all
-** to-be-closed variables active in this stack. Dummy entries are
-** used when the distance between two tbc variables does not fit
-** in an unsigned short. They are represented by delta==0, and
-** their real delta is always the maximum value that fits in
-** that field.
-*/
-typedef union StackValue {
- TValue val;
- struct {
- TValuefields;
- unsigned short delta;
- } tbclist;
-} StackValue;
-
-
-/* index to stack elements */
-typedef StackValue *StkId;
-
-/* convert a 'StackValue' to a 'TValue' */
-#define s2v(o) (&(o)->val)
-
-
-
-/*
-** {==================================================================
-** Nil
-** ===================================================================
-*/
-
-/* Standard nil */
-#define LUA_VNIL makevariant(LUA_TNIL, 0)
-
-/* Empty slot (which might be different from a slot containing nil) */
-#define LUA_VEMPTY makevariant(LUA_TNIL, 1)
-
-/* Value returned for a key not found in a table (absent key) */
-#define LUA_VABSTKEY makevariant(LUA_TNIL, 2)
-
-
-/* macro to test for (any kind of) nil */
-#define ttisnil(v) checktype((v), LUA_TNIL)
-
-
-/* macro to test for a standard nil */
-#define ttisstrictnil(o) checktag((o), LUA_VNIL)
-
-
-#define setnilvalue(obj) settt_(obj, LUA_VNIL)
-
-
-#define isabstkey(v) checktag((v), LUA_VABSTKEY)
-
-
-/*
-** macro to detect non-standard nils (used only in assertions)
-*/
-#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v))
-
-
-/*
-** By default, entries with any kind of nil are considered empty.
-** (In any definition, values associated with absent keys must also
-** be accepted as empty.)
-*/
-#define isempty(v) ttisnil(v)
-
-
-/* macro defining a value corresponding to an absent key */
-#define ABSTKEYCONSTANT {NULL}, LUA_VABSTKEY
-
-
-/* mark an entry as empty */
-#define setempty(v) settt_(v, LUA_VEMPTY)
-
-
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Booleans
-** ===================================================================
-*/
-
-
-#define LUA_VFALSE makevariant(LUA_TBOOLEAN, 0)
-#define LUA_VTRUE makevariant(LUA_TBOOLEAN, 1)
-
-#define ttisboolean(o) checktype((o), LUA_TBOOLEAN)
-#define ttisfalse(o) checktag((o), LUA_VFALSE)
-#define ttistrue(o) checktag((o), LUA_VTRUE)
-
-
-#define l_isfalse(o) (ttisfalse(o) || ttisnil(o))
-
-
-#define setbfvalue(obj) settt_(obj, LUA_VFALSE)
-#define setbtvalue(obj) settt_(obj, LUA_VTRUE)
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Threads
-** ===================================================================
-*/
-
-#define LUA_VTHREAD makevariant(LUA_TTHREAD, 0)
-
-#define ttisthread(o) checktag((o), ctb(LUA_VTHREAD))
-
-#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
-
-#define setthvalue(L,obj,x) \
- { TValue *io = (obj); lua_State *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTHREAD)); \
- checkliveness(L,io); }
-
-#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t)
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Collectable Objects
-** ===================================================================
-*/
-
-/*
-** Common Header for all collectable objects (in macro form, to be
-** included in other objects)
-*/
-#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked
-
-
-/* Common type for all collectable objects */
-typedef struct GCObject {
- CommonHeader;
-} GCObject;
-
-
-/* Bit mark for collectable types */
-#define BIT_ISCOLLECTABLE (1 << 6)
-
-#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE)
-
-/* mark a tag as collectable */
-#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
-
-#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
-
-#define gcvalueraw(v) ((v).gc)
-
-#define setgcovalue(L,obj,x) \
- { TValue *io = (obj); GCObject *i_g=(x); \
- val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Numbers
-** ===================================================================
-*/
-
-/* Variant tags for numbers */
-#define LUA_VNUMINT makevariant(LUA_TNUMBER, 0) /* integer numbers */
-#define LUA_VNUMFLT makevariant(LUA_TNUMBER, 1) /* float numbers */
-
-#define ttisnumber(o) checktype((o), LUA_TNUMBER)
-#define ttisfloat(o) checktag((o), LUA_VNUMFLT)
-#define ttisinteger(o) checktag((o), LUA_VNUMINT)
-
-#define nvalue(o) check_exp(ttisnumber(o), \
- (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
-#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
-#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
-
-#define fltvalueraw(v) ((v).n)
-#define ivalueraw(v) ((v).i)
-
-#define setfltvalue(obj,x) \
- { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_VNUMFLT); }
-
-#define chgfltvalue(obj,x) \
- { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
-
-#define setivalue(obj,x) \
- { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_VNUMINT); }
-
-#define chgivalue(obj,x) \
- { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Strings
-** ===================================================================
-*/
-
-/* Variant tags for strings */
-#define LUA_VSHRSTR makevariant(LUA_TSTRING, 0) /* short strings */
-#define LUA_VLNGSTR makevariant(LUA_TSTRING, 1) /* long strings */
-
-#define ttisstring(o) checktype((o), LUA_TSTRING)
-#define ttisshrstring(o) checktag((o), ctb(LUA_VSHRSTR))
-#define ttislngstring(o) checktag((o), ctb(LUA_VLNGSTR))
-
-#define tsvalueraw(v) (gco2ts((v).gc))
-
-#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
-
-#define setsvalue(L,obj,x) \
- { TValue *io = (obj); TString *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
- checkliveness(L,io); }
-
-/* set a string to the stack */
-#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s)
-
-/* set a string to a new object */
-#define setsvalue2n setsvalue
-
-
-/*
-** Header for a string value.
-*/
-typedef struct TString {
- CommonHeader;
- lu_byte extra; /* reserved words for short strings; "has hash" for longs */
- lu_byte shrlen; /* length for short strings */
- unsigned int hash;
- union {
- size_t lnglen; /* length for long strings */
- struct TString *hnext; /* linked list for hash table */
- } u;
- char contents[1];
-} TString;
-
-
-
-/*
-** Get the actual string (array of bytes) from a 'TString'.
-*/
-#define getstr(ts) ((ts)->contents)
-
-
-/* get the actual string (array of bytes) from a Lua value */
-#define svalue(o) getstr(tsvalue(o))
-
-/* get string length from 'TString *s' */
-#define tsslen(s) ((s)->tt == LUA_VSHRSTR ? (s)->shrlen : (s)->u.lnglen)
-
-/* get string length from 'TValue *o' */
-#define vslen(o) tsslen(tsvalue(o))
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Userdata
-** ===================================================================
-*/
-
-
-/*
-** Light userdata should be a variant of userdata, but for compatibility
-** reasons they are also different types.
-*/
-#define LUA_VLIGHTUSERDATA makevariant(LUA_TLIGHTUSERDATA, 0)
-
-#define LUA_VUSERDATA makevariant(LUA_TUSERDATA, 0)
-
-#define ttislightuserdata(o) checktag((o), LUA_VLIGHTUSERDATA)
-#define ttisfulluserdata(o) checktag((o), ctb(LUA_VUSERDATA))
-
-#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
-#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
-
-#define pvalueraw(v) ((v).p)
-
-#define setpvalue(obj,x) \
- { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_VLIGHTUSERDATA); }
-
-#define setuvalue(L,obj,x) \
- { TValue *io = (obj); Udata *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VUSERDATA)); \
- checkliveness(L,io); }
-
-
-/* Ensures that addresses after this type are always fully aligned. */
-typedef union UValue {
- TValue uv;
- LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */
-} UValue;
-
-
-/*
-** Header for userdata with user values;
-** memory area follows the end of this structure.
-*/
-typedef struct Udata {
- CommonHeader;
- unsigned short nuvalue; /* number of user values */
- size_t len; /* number of bytes */
- struct Table *metatable;
- GCObject *gclist;
- UValue uv[1]; /* user values */
-} Udata;
-
-
-/*
-** Header for userdata with no user values. These userdata do not need
-** to be gray during GC, and therefore do not need a 'gclist' field.
-** To simplify, the code always use 'Udata' for both kinds of userdata,
-** making sure it never accesses 'gclist' on userdata with no user values.
-** This structure here is used only to compute the correct size for
-** this representation. (The 'bindata' field in its end ensures correct
-** alignment for binary data following this header.)
-*/
-typedef struct Udata0 {
- CommonHeader;
- unsigned short nuvalue; /* number of user values */
- size_t len; /* number of bytes */
- struct Table *metatable;
- union {LUAI_MAXALIGN;} bindata;
-} Udata0;
-
-
-/* compute the offset of the memory area of a userdata */
-#define udatamemoffset(nuv) \
- ((nuv) == 0 ? offsetof(Udata0, bindata) \
- : offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
-
-/* get the address of the memory block inside 'Udata' */
-#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))
-
-/* compute the size of a userdata */
-#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb))
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Prototypes
-** ===================================================================
-*/
-
-#define LUA_VPROTO makevariant(LUA_TPROTO, 0)
-
-
-/*
-** Description of an upvalue for function prototypes
-*/
-typedef struct Upvaldesc {
- TString *name; /* upvalue name (for debug information) */
- lu_byte instack; /* whether it is in stack (register) */
- lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
- lu_byte kind; /* kind of corresponding variable */
-} Upvaldesc;
-
-
-/*
-** Description of a local variable for function prototypes
-** (used for debug information)
-*/
-typedef struct LocVar {
- TString *varname;
- int startpc; /* first point where variable is active */
- int endpc; /* first point where variable is dead */
-} LocVar;
-
-
-/*
-** Associates the absolute line source for a given instruction ('pc').
-** The array 'lineinfo' gives, for each instruction, the difference in
-** lines from the previous instruction. When that difference does not
-** fit into a byte, Lua saves the absolute line for that instruction.
-** (Lua also saves the absolute line periodically, to speed up the
-** computation of a line number: we can use binary search in the
-** absolute-line array, but we must traverse the 'lineinfo' array
-** linearly to compute a line.)
-*/
-typedef struct AbsLineInfo {
- int pc;
- int line;
-} AbsLineInfo;
-
-/*
-** Function Prototypes
-*/
-typedef struct Proto {
- CommonHeader;
- lu_byte numparams; /* number of fixed (named) parameters */
- lu_byte is_vararg;
- lu_byte maxstacksize; /* number of registers needed by this function */
- int sizeupvalues; /* size of 'upvalues' */
- int sizek; /* size of 'k' */
- int sizecode;
- int sizelineinfo;
- int sizep; /* size of 'p' */
- int sizelocvars;
- int sizeabslineinfo; /* size of 'abslineinfo' */
- int linedefined; /* debug information */
- int lastlinedefined; /* debug information */
- TValue *k; /* constants used by the function */
- Instruction *code; /* opcodes */
- struct Proto **p; /* functions defined inside the function */
- Upvaldesc *upvalues; /* upvalue information */
- ls_byte *lineinfo; /* information about source lines (debug information) */
- AbsLineInfo *abslineinfo; /* idem */
- LocVar *locvars; /* information about local variables (debug information) */
- TString *source; /* used for debug information */
- GCObject *gclist;
-} Proto;
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Functions
-** ===================================================================
-*/
-
-#define LUA_VUPVAL makevariant(LUA_TUPVAL, 0)
-
-
-/* Variant tags for functions */
-#define LUA_VLCL makevariant(LUA_TFUNCTION, 0) /* Lua closure */
-#define LUA_VLCF makevariant(LUA_TFUNCTION, 1) /* light C function */
-#define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */
-
-#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
-#define ttisLclosure(o) checktag((o), ctb(LUA_VLCL))
-#define ttislcf(o) checktag((o), LUA_VLCF)
-#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL))
-#define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o))
-
-
-#define isLfunction(o) ttisLclosure(o)
-
-#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
-#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
-#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
-#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
-
-#define fvalueraw(v) ((v).f)
-
-#define setclLvalue(L,obj,x) \
- { TValue *io = (obj); LClosure *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VLCL)); \
- checkliveness(L,io); }
-
-#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl)
-
-#define setfvalue(obj,x) \
- { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_VLCF); }
-
-#define setclCvalue(L,obj,x) \
- { TValue *io = (obj); CClosure *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \
- checkliveness(L,io); }
-
-
-/*
-** Upvalues for Lua closures
-*/
-typedef struct UpVal {
- CommonHeader;
- lu_byte tbc; /* true if it represents a to-be-closed variable */
- TValue *v; /* points to stack or to its own value */
- union {
- struct { /* (when open) */
- struct UpVal *next; /* linked list */
- struct UpVal **previous;
- } open;
- TValue value; /* the value (when closed) */
- } u;
-} UpVal;
-
-
-
-#define ClosureHeader \
- CommonHeader; lu_byte nupvalues; GCObject *gclist
-
-typedef struct CClosure {
- ClosureHeader;
- lua_CFunction f;
- TValue upvalue[1]; /* list of upvalues */
-} CClosure;
-
-
-typedef struct LClosure {
- ClosureHeader;
- struct Proto *p;
- UpVal *upvals[1]; /* list of upvalues */
-} LClosure;
-
-
-typedef union Closure {
- CClosure c;
- LClosure l;
-} Closure;
-
-
-#define getproto(o) (clLvalue(o)->p)
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Tables
-** ===================================================================
-*/
-
-#define LUA_VTABLE makevariant(LUA_TTABLE, 0)
-
-#define ttistable(o) checktag((o), ctb(LUA_VTABLE))
-
-#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
-
-#define sethvalue(L,obj,x) \
- { TValue *io = (obj); Table *x_ = (x); \
- val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTABLE)); \
- checkliveness(L,io); }
-
-#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h)
-
-
-/*
-** Nodes for Hash tables: A pack of two TValue's (key-value pairs)
-** plus a 'next' field to link colliding entries. The distribution
-** of the key's fields ('key_tt' and 'key_val') not forming a proper
-** 'TValue' allows for a smaller size for 'Node' both in 4-byte
-** and 8-byte alignments.
-*/
-typedef union Node {
- struct NodeKey {
- TValuefields; /* fields for value */
- lu_byte key_tt; /* key type */
- int next; /* for chaining */
- Value key_val; /* key value */
- } u;
- TValue i_val; /* direct access to node's value as a proper 'TValue' */
-} Node;
-
-
-/* copy a value into a key */
-#define setnodekey(L,node,obj) \
- { Node *n_=(node); const TValue *io_=(obj); \
- n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
- checkliveness(L,io_); }
-
-
-/* copy a value from a key */
-#define getnodekey(L,obj,node) \
- { TValue *io_=(obj); const Node *n_=(node); \
- io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
- checkliveness(L,io_); }
-
-
-/*
-** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
-** real size of 'array'. Otherwise, the real size of 'array' is the
-** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
-** is zero); 'alimit' is then used as a hint for #t.
-*/
-
-#define BITRAS (1 << 7)
-#define isrealasize(t) (!((t)->flags & BITRAS))
-#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS))
-#define setnorealasize(t) ((t)->flags |= BITRAS)
-
-
-typedef struct Table {
- CommonHeader;
- lu_byte flags; /* 1<u.key_tt)
-#define keyval(node) ((node)->u.key_val)
-
-#define keyisnil(node) (keytt(node) == LUA_TNIL)
-#define keyisinteger(node) (keytt(node) == LUA_VNUMINT)
-#define keyival(node) (keyval(node).i)
-#define keyisshrstr(node) (keytt(node) == ctb(LUA_VSHRSTR))
-#define keystrval(node) (gco2ts(keyval(node).gc))
-
-#define setnilkey(node) (keytt(node) = LUA_TNIL)
-
-#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
-
-#define gckey(n) (keyval(n).gc)
-#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
-
-
-/*
-** Dead keys in tables have the tag DEADKEY but keep their original
-** gcvalue. This distinguishes them from regular keys but allows them to
-** be found when searched in a special way. ('next' needs that to find
-** keys removed from a table during a traversal.)
-*/
-#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
-#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
-
-/* }================================================================== */
-
-
-
-/*
-** 'module' operation for hashing (size is always a power of 2)
-*/
-#define lmod(s,size) \
- (check_exp((size&(size-1))==0, (cast_int((s) & ((size)-1)))))
-
-
-#define twoto(x) (1<<(x))
-#define sizenode(t) (twoto((t)->lsizenode))
-
-
-/* size of buffer for 'luaO_utf8esc' function */
-#define UTF8BUFFSZ 8
-
-LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
-LUAI_FUNC int luaO_ceillog2 (unsigned int x);
-LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
- const TValue *p2, TValue *res);
-LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
- const TValue *p2, StkId res);
-LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
-LUAI_FUNC int luaO_hexavalue (int c);
-LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
-LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
- va_list argp);
-LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
-LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
-
-
-#endif
-
diff --git a/lua-5.4.4/library/lopcodes.c b/lua-5.4.4/library/lopcodes.c
deleted file mode 100644
index c67aa227..00000000
--- a/lua-5.4.4/library/lopcodes.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** $Id: lopcodes.c $
-** Opcodes for Lua virtual machine
-** See Copyright Notice in lua.h
-*/
-
-#define lopcodes_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include "lopcodes.h"
-
-
-/* ORDER OP */
-
-LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/* MM OT IT T A mode opcode */
- opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */
- ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */
- ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADFALSE */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LFALSESKIP */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADTRUE */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */
- ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */
- ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/
- ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */
- ,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */
- ,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */
- ,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */
- ,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */
- ,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */
- ,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */
- ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */
- ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */
- ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */
- ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
- ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
- ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
- ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
-};
-
diff --git a/lua-5.4.4/library/lopcodes.h b/lua-5.4.4/library/lopcodes.h
deleted file mode 100644
index 7c274515..00000000
--- a/lua-5.4.4/library/lopcodes.h
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-** $Id: lopcodes.h $
-** Opcodes for Lua virtual machine
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lopcodes_h
-#define lopcodes_h
-
-#include "llimits.h"
-
-
-/*===========================================================================
- We assume that instructions are unsigned 32-bit integers.
- All instructions have an opcode in the first 7 bits.
- Instructions can have the following formats:
-
- 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
- 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-iABC C(8) | B(8) |k| A(8) | Op(7) |
-iABx Bx(17) | A(8) | Op(7) |
-iAsBx sBx (signed)(17) | A(8) | Op(7) |
-iAx Ax(25) | Op(7) |
-isJ sJ(25) | Op(7) |
-
- A signed argument is represented in excess K: the represented value is
- the written unsigned value minus K, where K is half the maximum for the
- corresponding unsigned argument.
-===========================================================================*/
-
-
-enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
-
-
-/*
-** size and position of opcode arguments.
-*/
-#define SIZE_C 8
-#define SIZE_B 8
-#define SIZE_Bx (SIZE_C + SIZE_B + 1)
-#define SIZE_A 8
-#define SIZE_Ax (SIZE_Bx + SIZE_A)
-#define SIZE_sJ (SIZE_Bx + SIZE_A)
-
-#define SIZE_OP 7
-
-#define POS_OP 0
-
-#define POS_A (POS_OP + SIZE_OP)
-#define POS_k (POS_A + SIZE_A)
-#define POS_B (POS_k + 1)
-#define POS_C (POS_B + SIZE_B)
-
-#define POS_Bx POS_k
-
-#define POS_Ax POS_A
-
-#define POS_sJ POS_A
-
-
-/*
-** limits for opcode arguments.
-** we use (signed) 'int' to manipulate most arguments,
-** so they must fit in ints.
-*/
-
-/* Check whether type 'int' has at least 'b' bits ('b' < 32) */
-#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1)
-
-
-#if L_INTHASBITS(SIZE_Bx)
-#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */
-
-
-#if L_INTHASBITS(SIZE_Ax)
-#define MAXARG_Ax ((1<> 1)
-
-
-#define MAXARG_A ((1<> 1)
-
-#define int2sC(i) ((i) + OFFSET_sC)
-#define sC2int(i) ((i) - OFFSET_sC)
-
-
-/* creates a mask with 'n' 1 bits at position 'p' */
-#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p))
-
-/* creates a mask with 'n' 0 bits at position 'p' */
-#define MASK0(n,p) (~MASK1(n,p))
-
-/*
-** the following macros help to manipulate instructions
-*/
-
-#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
-#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
- ((cast(Instruction, o)<>(pos)) & MASK1(size,0)))
-#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
- ((cast(Instruction, v)<> sC */
-OP_SHLI,/* A B sC R[A] := sC << R[B] */
-
-OP_ADD,/* A B C R[A] := R[B] + R[C] */
-OP_SUB,/* A B C R[A] := R[B] - R[C] */
-OP_MUL,/* A B C R[A] := R[B] * R[C] */
-OP_MOD,/* A B C R[A] := R[B] % R[C] */
-OP_POW,/* A B C R[A] := R[B] ^ R[C] */
-OP_DIV,/* A B C R[A] := R[B] / R[C] */
-OP_IDIV,/* A B C R[A] := R[B] // R[C] */
-
-OP_BAND,/* A B C R[A] := R[B] & R[C] */
-OP_BOR,/* A B C R[A] := R[B] | R[C] */
-OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */
-OP_SHL,/* A B C R[A] := R[B] << R[C] */
-OP_SHR,/* A B C R[A] := R[B] >> R[C] */
-
-OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */
-OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
-OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
-
-OP_UNM,/* A B R[A] := -R[B] */
-OP_BNOT,/* A B R[A] := ~R[B] */
-OP_NOT,/* A B R[A] := not R[B] */
-OP_LEN,/* A B R[A] := #R[B] (length operator) */
-
-OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
-
-OP_CLOSE,/* A close all upvalues >= R[A] */
-OP_TBC,/* A mark variable A "to be closed" */
-OP_JMP,/* sJ pc += sJ */
-OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */
-OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */
-OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */
-
-OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */
-OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */
-OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */
-OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */
-OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */
-OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
-
-OP_TEST,/* A k if (not R[A] == k) then pc++ */
-OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */
-
-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 k return R[A](R[A+1], ... ,R[A+B-1]) */
-
-OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */
-OP_RETURN0,/* return */
-OP_RETURN1,/* A return R[A] */
-
-OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */
-OP_FORPREP,/* A Bx ;
- if not to run then pc+=Bx+1; */
-
-OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
-OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
-OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
-
-OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
-
-OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
-
-OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
-
-OP_VARARGPREP,/*A (adjust vararg parameters) */
-
-OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
-} OpCode;
-
-
-#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1)
-
-
-
-/*===========================================================================
- Notes:
-
- (*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean
- value, in a code equivalent to (not cond ? false : true). (It
- produces false and skips the next instruction producing true.)
-
- (*) Opcodes OP_MMBIN and variants follow each arithmetic and
- bitwise opcode. If the operation succeeds, it skips this next
- opcode. Otherwise, this opcode calls the corresponding metamethod.
-
- (*) Opcode OP_TESTSET is used in short-circuit expressions that need
- both to jump and to produce a value, such as (a = b or c).
-
- (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
- 'top' is set to last_result+1, so next open instruction (OP_CALL,
- OP_RETURN*, OP_SETLIST) may use 'top'.
-
- (*) In OP_VARARG, if (C == 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_LOADKX and OP_NEWTABLE, the next instruction is always
- OP_EXTRAARG.
-
- (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then
- real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the
- bits of C).
-
- (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a
- power of 2) plus 1, or zero for size zero. If not k, the array size
- is C. Otherwise, the array size is EXTRAARG _ C.
-
- (*) For comparisons, k specifies what condition the test should accept
- (true or false).
-
- (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped
- (the constant is the first operand).
-
- (*) All 'skips' (pc++) assume that next instruction is a jump.
-
- (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
- function builds upvalues, which may need to be closed. C > 0 means
- the function is vararg, so that its 'func' must be corrected before
- returning; in this case, (C - 1) is its number of fixed parameters.
-
- (*) In comparisons with an immediate operand, C signals whether the
- original operand was a float. (It must be corrected in case of
- metamethods.)
-
-===========================================================================*/
-
-
-/*
-** masks for instruction properties. The format is:
-** bits 0-2: op mode
-** bit 3: instruction set register A
-** bit 4: operator is a test (next instruction must be a jump)
-** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0)
-** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
-** bit 7: instruction is an MM instruction (call a metamethod)
-*/
-
-LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
-
-#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7))
-#define testAMode(m) (luaP_opmodes[m] & (1 << 3))
-#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
-#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
-#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
-#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
-
-/* "out top" (set top for next instruction) */
-#define isOT(i) \
- ((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \
- GET_OPCODE(i) == OP_TAILCALL)
-
-/* "in top" (uses top from previous instruction) */
-#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
-
-#define opmode(mm,ot,it,t,a,m) \
- (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m))
-
-
-/* number of list items to accumulate before a SETLIST instruction */
-#define LFIELDS_PER_FLUSH 50
-
-#endif
diff --git a/lua-5.4.4/library/lopnames.h b/lua-5.4.4/library/lopnames.h
deleted file mode 100644
index 965cec9b..00000000
--- a/lua-5.4.4/library/lopnames.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-** $Id: lopnames.h $
-** Opcode names
-** See Copyright Notice in lua.h
-*/
-
-#if !defined(lopnames_h)
-#define lopnames_h
-
-#include
-
-
-/* ORDER OP */
-
-static const char *const opnames[] = {
- "MOVE",
- "LOADI",
- "LOADF",
- "LOADK",
- "LOADKX",
- "LOADFALSE",
- "LFALSESKIP",
- "LOADTRUE",
- "LOADNIL",
- "GETUPVAL",
- "SETUPVAL",
- "GETTABUP",
- "GETTABLE",
- "GETI",
- "GETFIELD",
- "SETTABUP",
- "SETTABLE",
- "SETI",
- "SETFIELD",
- "NEWTABLE",
- "SELF",
- "ADDI",
- "ADDK",
- "SUBK",
- "MULK",
- "MODK",
- "POWK",
- "DIVK",
- "IDIVK",
- "BANDK",
- "BORK",
- "BXORK",
- "SHRI",
- "SHLI",
- "ADD",
- "SUB",
- "MUL",
- "MOD",
- "POW",
- "DIV",
- "IDIV",
- "BAND",
- "BOR",
- "BXOR",
- "SHL",
- "SHR",
- "MMBIN",
- "MMBINI",
- "MMBINK",
- "UNM",
- "BNOT",
- "NOT",
- "LEN",
- "CONCAT",
- "CLOSE",
- "TBC",
- "JMP",
- "EQ",
- "LT",
- "LE",
- "EQK",
- "EQI",
- "LTI",
- "LEI",
- "GTI",
- "GEI",
- "TEST",
- "TESTSET",
- "CALL",
- "TAILCALL",
- "RETURN",
- "RETURN0",
- "RETURN1",
- "FORLOOP",
- "FORPREP",
- "TFORPREP",
- "TFORCALL",
- "TFORLOOP",
- "SETLIST",
- "CLOSURE",
- "VARARG",
- "VARARGPREP",
- "EXTRAARG",
- NULL
-};
-
-#endif
-
diff --git a/lua-5.4.4/library/loslib.c b/lua-5.4.4/library/loslib.c
deleted file mode 100644
index 3e20d622..00000000
--- a/lua-5.4.4/library/loslib.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
-** $Id: loslib.c $
-** Standard Operating System library
-** See Copyright Notice in lua.h
-*/
-
-#define loslib_c
-#define LUA_LIB
-
-#include "lprefix.h"
-
-
-#include
-#include
-#include
-#include
-#include
-
-#include "lua.h"
-
-#include "lauxlib.h"
-#include "lualib.h"
-
-
-/*
-** {==================================================================
-** List of valid conversion specifiers for the 'strftime' function;
-** options are grouped by length; group of length 2 start with '||'.
-** ===================================================================
-*/
-#if !defined(LUA_STRFTIMEOPTIONS) /* { */
-
-/* options for ANSI C 89 (only 1-char options) */
-#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
-
-/* options for ISO C 99 and POSIX */
-#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
- "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
-
-/* options for Windows */
-#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
- "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
-
-#if defined(LUA_USE_WINDOWS)
-#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
-#elif defined(LUA_USE_C89)
-#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
-#else /* C99 specification */
-#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
-#endif
-
-#endif /* } */
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Configuration for time-related stuff
-** ===================================================================
-*/
-
-/*
-** type to represent time_t in Lua
-*/
-#if !defined(LUA_NUMTIME) /* { */
-
-#define l_timet lua_Integer
-#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
-#define l_gettime(L,arg) luaL_checkinteger(L, arg)
-
-#else /* }{ */
-
-#define l_timet lua_Number
-#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t))
-#define l_gettime(L,arg) luaL_checknumber(L, arg)
-
-#endif /* } */
-
-
-#if !defined(l_gmtime) /* { */
-/*
-** By default, Lua uses gmtime/localtime, except when POSIX is available,
-** where it uses gmtime_r/localtime_r
-*/
-
-#if defined(LUA_USE_POSIX) /* { */
-
-#define l_gmtime(t,r) gmtime_r(t,r)
-#define l_localtime(t,r) localtime_r(t,r)
-
-#else /* }{ */
-
-/* ISO C definitions */
-#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
-#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
-
-#endif /* } */
-
-#endif /* } */
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Configuration for 'tmpnam':
-** By default, Lua uses tmpnam except when POSIX is available, where
-** it uses mkstemp.
-** ===================================================================
-*/
-#if !defined(lua_tmpnam) /* { */
-
-#if defined(LUA_USE_POSIX) /* { */
-
-#include
-
-#define LUA_TMPNAMBUFSIZE 32
-
-#if !defined(LUA_TMPNAMTEMPLATE)
-#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
-#endif
-
-#define lua_tmpnam(b,e) { \
- strcpy(b, LUA_TMPNAMTEMPLATE); \
- e = mkstemp(b); \
- if (e != -1) close(e); \
- e = (e == -1); }
-
-#else /* }{ */
-
-/* ISO C definitions */
-#define LUA_TMPNAMBUFSIZE L_tmpnam
-#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
-
-#endif /* } */
-
-#endif /* } */
-/* }================================================================== */
-
-
-
-static int os_execute (lua_State *L) {
- const char *cmd = luaL_optstring(L, 1, NULL);
- int stat;
- errno = 0;
- stat = system(cmd);
- if (cmd != NULL)
- return luaL_execresult(L, stat);
- else {
- lua_pushboolean(L, stat); /* true if there is a shell */
- return 1;
- }
-}
-
-
-static int os_remove (lua_State *L) {
- const char *filename = luaL_checkstring(L, 1);
- return luaL_fileresult(L, remove(filename) == 0, filename);
-}
-
-
-static int os_rename (lua_State *L) {
- const char *fromname = luaL_checkstring(L, 1);
- const char *toname = luaL_checkstring(L, 2);
- return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
-}
-
-
-static int os_tmpname (lua_State *L) {
- char buff[LUA_TMPNAMBUFSIZE];
- int err;
- lua_tmpnam(buff, err);
- if (l_unlikely(err))
- return luaL_error(L, "unable to generate a unique filename");
- lua_pushstring(L, buff);
- return 1;
-}
-
-
-static int os_getenv (lua_State *L) {
- lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
- return 1;
-}
-
-
-static int os_clock (lua_State *L) {
- lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
- return 1;
-}
-
-
-/*
-** {======================================================
-** Time/Date operations
-** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
-** wday=%w+1, yday=%j, isdst=? }
-** =======================================================
-*/
-
-/*
-** About the overflow check: an overflow cannot occur when time
-** is represented by a lua_Integer, because either lua_Integer is
-** large enough to represent all int fields or it is not large enough
-** to represent a time that cause a field to overflow. However, if
-** times are represented as doubles and lua_Integer is int, then the
-** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900
-** to compute the year.
-*/
-static void setfield (lua_State *L, const char *key, int value, int delta) {
- #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX)
- if (l_unlikely(value > LUA_MAXINTEGER - delta))
- luaL_error(L, "field '%s' is out-of-bound", key);
- #endif
- lua_pushinteger(L, (lua_Integer)value + delta);
- lua_setfield(L, -2, key);
-}
-
-
-static void setboolfield (lua_State *L, const char *key, int value) {
- if (value < 0) /* undefined? */
- return; /* does not set field */
- lua_pushboolean(L, value);
- lua_setfield(L, -2, key);
-}
-
-
-/*
-** Set all fields from structure 'tm' in the table on top of the stack
-*/
-static void setallfields (lua_State *L, struct tm *stm) {
- setfield(L, "year", stm->tm_year, 1900);
- setfield(L, "month", stm->tm_mon, 1);
- setfield(L, "day", stm->tm_mday, 0);
- setfield(L, "hour", stm->tm_hour, 0);
- setfield(L, "min", stm->tm_min, 0);
- setfield(L, "sec", stm->tm_sec, 0);
- setfield(L, "yday", stm->tm_yday, 1);
- setfield(L, "wday", stm->tm_wday, 1);
- setboolfield(L, "isdst", stm->tm_isdst);
-}
-
-
-static int getboolfield (lua_State *L, const char *key) {
- int res;
- res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
- lua_pop(L, 1);
- return res;
-}
-
-
-static int getfield (lua_State *L, const char *key, int d, int delta) {
- int isnum;
- int t = lua_getfield(L, -1, key); /* get field and its type */
- lua_Integer res = lua_tointegerx(L, -1, &isnum);
- if (!isnum) { /* field is not an integer? */
- if (l_unlikely(t != LUA_TNIL)) /* some other value? */
- return luaL_error(L, "field '%s' is not an integer", key);
- else if (l_unlikely(d < 0)) /* absent field; no default? */
- return luaL_error(L, "field '%s' missing in date table", key);
- res = d;
- }
- else {
- /* unsigned avoids overflow when lua_Integer has 32 bits */
- if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta
- : (lua_Integer)INT_MIN + delta <= res))
- return luaL_error(L, "field '%s' is out-of-bound", key);
- res -= delta;
- }
- lua_pop(L, 1);
- return (int)res;
-}
-
-
-static const char *checkoption (lua_State *L, const char *conv,
- ptrdiff_t convlen, char *buff) {
- const char *option = LUA_STRFTIMEOPTIONS;
- int oplen = 1; /* length of options being checked */
- for (; *option != '\0' && oplen <= convlen; option += oplen) {
- if (*option == '|') /* next block? */
- oplen++; /* will check options with next length (+1) */
- else if (memcmp(conv, option, oplen) == 0) { /* match? */
- memcpy(buff, conv, oplen); /* copy valid option to buffer */
- buff[oplen] = '\0';
- return conv + oplen; /* return next item */
- }
- }
- luaL_argerror(L, 1,
- lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
- return conv; /* to avoid warnings */
-}
-
-
-static time_t l_checktime (lua_State *L, int arg) {
- l_timet t = l_gettime(L, arg);
- luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
- return (time_t)t;
-}
-
-
-/* maximum size for an individual 'strftime' item */
-#define SIZETIMEFMT 250
-
-
-static int os_date (lua_State *L) {
- size_t slen;
- const char *s = luaL_optlstring(L, 1, "%c", &slen);
- time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
- const char *se = s + slen; /* 's' end */
- struct tm tmr, *stm;
- if (*s == '!') { /* UTC? */
- stm = l_gmtime(&t, &tmr);
- s++; /* skip '!' */
- }
- else
- stm = l_localtime(&t, &tmr);
- if (stm == NULL) /* invalid date? */
- return luaL_error(L,
- "date result cannot be represented in this installation");
- if (strcmp(s, "*t") == 0) {
- lua_createtable(L, 0, 9); /* 9 = number of fields */
- setallfields(L, stm);
- }
- else {
- char cc[4]; /* buffer for individual conversion specifiers */
- luaL_Buffer b;
- cc[0] = '%';
- luaL_buffinit(L, &b);
- while (s < se) {
- if (*s != '%') /* not a conversion specifier? */
- luaL_addchar(&b, *s++);
- else {
- size_t reslen;
- char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
- s++; /* skip '%' */
- s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */
- reslen = strftime(buff, SIZETIMEFMT, cc, stm);
- luaL_addsize(&b, reslen);
- }
- }
- luaL_pushresult(&b);
- }
- return 1;
-}
-
-
-static int os_time (lua_State *L) {
- time_t t;
- if (lua_isnoneornil(L, 1)) /* called without args? */
- t = time(NULL); /* get current time */
- else {
- struct tm ts;
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_settop(L, 1); /* make sure table is at the top */
- ts.tm_year = getfield(L, "year", -1, 1900);
- ts.tm_mon = getfield(L, "month", -1, 1);
- ts.tm_mday = getfield(L, "day", -1, 0);
- ts.tm_hour = getfield(L, "hour", 12, 0);
- ts.tm_min = getfield(L, "min", 0, 0);
- ts.tm_sec = getfield(L, "sec", 0, 0);
- ts.tm_isdst = getboolfield(L, "isdst");
- t = mktime(&ts);
- setallfields(L, &ts); /* update fields with normalized values */
- }
- if (t != (time_t)(l_timet)t || t == (time_t)(-1))
- return luaL_error(L,
- "time result cannot be represented in this installation");
- l_pushtime(L, t);
- return 1;
-}
-
-
-static int os_difftime (lua_State *L) {
- time_t t1 = l_checktime(L, 1);
- time_t t2 = l_checktime(L, 2);
- lua_pushnumber(L, (lua_Number)difftime(t1, t2));
- return 1;
-}
-
-/* }====================================================== */
-
-
-static int os_setlocale (lua_State *L) {
- static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
- LC_NUMERIC, LC_TIME};
- static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
- "numeric", "time", NULL};
- const char *l = luaL_optstring(L, 1, NULL);
- int op = luaL_checkoption(L, 2, "all", catnames);
- lua_pushstring(L, setlocale(cat[op], l));
- return 1;
-}
-
-
-static int os_exit (lua_State *L) {
- int status;
- if (lua_isboolean(L, 1))
- status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
- else
- status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
- if (lua_toboolean(L, 2))
- lua_close(L);
- if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
- return 0;
-}
-
-
-static const luaL_Reg syslib[] = {
- {"clock", os_clock},
- {"date", os_date},
- {"difftime", os_difftime},
- {"execute", os_execute},
- {"exit", os_exit},
- {"getenv", os_getenv},
- {"remove", os_remove},
- {"rename", os_rename},
- {"setlocale", os_setlocale},
- {"time", os_time},
- {"tmpname", os_tmpname},
- {NULL, NULL}
-};
-
-/* }====================================================== */
-
-
-
-LUAMOD_API int luaopen_os (lua_State *L) {
- luaL_newlib(L, syslib);
- return 1;
-}
-
diff --git a/lua-5.4.4/library/lparser.c b/lua-5.4.4/library/lparser.c
deleted file mode 100644
index 3abe3d75..00000000
--- a/lua-5.4.4/library/lparser.c
+++ /dev/null
@@ -1,1966 +0,0 @@
-/*
-** $Id: lparser.c $
-** Lua Parser
-** See Copyright Notice in lua.h
-*/
-
-#define lparser_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-#include
-
-#include "lua.h"
-
-#include "lcode.h"
-#include "ldebug.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "llex.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lopcodes.h"
-#include "lparser.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-
-
-
-/* maximum number of local variables per function (must be smaller
- than 250, due to the bytecode format) */
-#define MAXVARS 200
-
-
-#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
-
-
-/* because all strings are unified by the scanner, the parser
- can use pointer equality for string equality */
-#define eqstr(a,b) ((a) == (b))
-
-
-/*
-** nodes for block list (list of active blocks)
-*/
-typedef struct BlockCnt {
- struct BlockCnt *previous; /* chain */
- int firstlabel; /* index of first label in this block */
- int firstgoto; /* index of first pending goto in this block */
- lu_byte nactvar; /* # active locals outside the block */
- lu_byte upval; /* true if some variable in the block is an upvalue */
- lu_byte isloop; /* true if 'block' is a loop */
- lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */
-} BlockCnt;
-
-
-
-/*
-** prototypes for recursive non-terminal functions
-*/
-static void statement (LexState *ls);
-static void expr (LexState *ls, expdesc *v);
-
-
-static l_noret error_expected (LexState *ls, int token) {
- luaX_syntaxerror(ls,
- luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token)));
-}
-
-
-static l_noret errorlimit (FuncState *fs, int limit, const char *what) {
- lua_State *L = fs->ls->L;
- const char *msg;
- int line = fs->f->linedefined;
- const char *where = (line == 0)
- ? "main function"
- : luaO_pushfstring(L, "function at line %d", line);
- msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s",
- what, limit, where);
- luaX_syntaxerror(fs->ls, msg);
-}
-
-
-static void checklimit (FuncState *fs, int v, int l, const char *what) {
- if (v > l) errorlimit(fs, l, what);
-}
-
-
-/*
-** Test whether next token is 'c'; if so, skip it.
-*/
-static int testnext (LexState *ls, int c) {
- if (ls->t.token == c) {
- luaX_next(ls);
- return 1;
- }
- else return 0;
-}
-
-
-/*
-** Check that next token is 'c'.
-*/
-static void check (LexState *ls, int c) {
- if (ls->t.token != c)
- error_expected(ls, c);
-}
-
-
-/*
-** Check that next token is 'c' and skip it.
-*/
-static void checknext (LexState *ls, int c) {
- check(ls, c);
- luaX_next(ls);
-}
-
-
-#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
-
-
-/*
-** Check that next token is 'what' and skip it. In case of error,
-** raise an error that the expected 'what' should match a 'who'
-** in line 'where' (if that is not the current line).
-*/
-static void check_match (LexState *ls, int what, int who, int where) {
- if (l_unlikely(!testnext(ls, what))) {
- if (where == ls->linenumber) /* all in the same line? */
- error_expected(ls, what); /* do not need a complex message */
- else {
- luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
- "%s expected (to close %s at line %d)",
- luaX_token2str(ls, what), luaX_token2str(ls, who), where));
- }
- }
-}
-
-
-static TString *str_checkname (LexState *ls) {
- TString *ts;
- check(ls, TK_NAME);
- ts = ls->t.seminfo.ts;
- luaX_next(ls);
- return ts;
-}
-
-
-static void init_exp (expdesc *e, expkind k, int i) {
- e->f = e->t = NO_JUMP;
- e->k = k;
- e->u.info = i;
-}
-
-
-static void codestring (expdesc *e, TString *s) {
- e->f = e->t = NO_JUMP;
- e->k = VKSTR;
- e->u.strval = s;
-}
-
-
-static void codename (LexState *ls, expdesc *e) {
- codestring(e, str_checkname(ls));
-}
-
-
-/*
-** Register a new local variable in the active 'Proto' (for debug
-** information).
-*/
-static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) {
- Proto *f = fs->f;
- int oldsize = f->sizelocvars;
- luaM_growvector(ls->L, f->locvars, fs->ndebugvars, f->sizelocvars,
- LocVar, SHRT_MAX, "local variables");
- while (oldsize < f->sizelocvars)
- f->locvars[oldsize++].varname = NULL;
- f->locvars[fs->ndebugvars].varname = varname;
- f->locvars[fs->ndebugvars].startpc = fs->pc;
- luaC_objbarrier(ls->L, f, varname);
- return fs->ndebugvars++;
-}
-
-
-/*
-** Create a new local variable with the given 'name'. Return its index
-** in the function.
-*/
-static int new_localvar (LexState *ls, TString *name) {
- lua_State *L = ls->L;
- FuncState *fs = ls->fs;
- Dyndata *dyd = ls->dyd;
- Vardesc *var;
- checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
- MAXVARS, "local variables");
- luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
- dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");
- var = &dyd->actvar.arr[dyd->actvar.n++];
- var->vd.kind = VDKREG; /* default */
- var->vd.name = name;
- return dyd->actvar.n - 1 - fs->firstlocal;
-}
-
-#define new_localvarliteral(ls,v) \
- new_localvar(ls, \
- luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
-
-
-
-/*
-** Return the "variable description" (Vardesc) of a given variable.
-** (Unless noted otherwise, all variables are referred to by their
-** compiler indices.)
-*/
-static Vardesc *getlocalvardesc (FuncState *fs, int vidx) {
- return &fs->ls->dyd->actvar.arr[fs->firstlocal + vidx];
-}
-
-
-/*
-** Convert 'nvar', a compiler index level, to its corresponding
-** register. For that, search for the highest variable below that level
-** that is in a register and uses its register index ('ridx') plus one.
-*/
-static int reglevel (FuncState *fs, int nvar) {
- while (nvar-- > 0) {
- Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */
- if (vd->vd.kind != RDKCTC) /* is in a register? */
- return vd->vd.ridx + 1;
- }
- return 0; /* no variables in registers */
-}
-
-
-/*
-** Return the number of variables in the register stack for the given
-** function.
-*/
-int luaY_nvarstack (FuncState *fs) {
- return reglevel(fs, fs->nactvar);
-}
-
-
-/*
-** Get the debug-information entry for current variable 'vidx'.
-*/
-static LocVar *localdebuginfo (FuncState *fs, int vidx) {
- Vardesc *vd = getlocalvardesc(fs, vidx);
- if (vd->vd.kind == RDKCTC)
- return NULL; /* no debug info. for constants */
- else {
- int idx = vd->vd.pidx;
- lua_assert(idx < fs->ndebugvars);
- return &fs->f->locvars[idx];
- }
-}
-
-
-/*
-** Create an expression representing variable 'vidx'
-*/
-static void init_var (FuncState *fs, expdesc *e, int vidx) {
- e->f = e->t = NO_JUMP;
- e->k = VLOCAL;
- e->u.var.vidx = vidx;
- e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx;
-}
-
-
-/*
-** Raises an error if variable described by 'e' is read only
-*/
-static void check_readonly (LexState *ls, expdesc *e) {
- FuncState *fs = ls->fs;
- TString *varname = NULL; /* to be set if variable is const */
- switch (e->k) {
- case VCONST: {
- varname = ls->dyd->actvar.arr[e->u.info].vd.name;
- break;
- }
- case VLOCAL: {
- Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx);
- if (vardesc->vd.kind != VDKREG) /* not a regular variable? */
- varname = vardesc->vd.name;
- break;
- }
- case VUPVAL: {
- Upvaldesc *up = &fs->f->upvalues[e->u.info];
- if (up->kind != VDKREG)
- varname = up->name;
- break;
- }
- default:
- return; /* other cases cannot be read-only */
- }
- if (varname) {
- const char *msg = luaO_pushfstring(ls->L,
- "attempt to assign to const variable '%s'", getstr(varname));
- luaK_semerror(ls, msg); /* error */
- }
-}
-
-
-/*
-** Start the scope for the last 'nvars' created variables.
-*/
-static void adjustlocalvars (LexState *ls, int nvars) {
- FuncState *fs = ls->fs;
- int reglevel = luaY_nvarstack(fs);
- int i;
- for (i = 0; i < nvars; i++) {
- int vidx = fs->nactvar++;
- Vardesc *var = getlocalvardesc(fs, vidx);
- var->vd.ridx = reglevel++;
- var->vd.pidx = registerlocalvar(ls, fs, var->vd.name);
- }
-}
-
-
-/*
-** Close the scope for all variables up to level 'tolevel'.
-** (debug info.)
-*/
-static void removevars (FuncState *fs, int tolevel) {
- fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel);
- while (fs->nactvar > tolevel) {
- LocVar *var = localdebuginfo(fs, --fs->nactvar);
- if (var) /* does it have debug information? */
- var->endpc = fs->pc;
- }
-}
-
-
-/*
-** Search the upvalues of the function 'fs' for one
-** with the given 'name'.
-*/
-static int searchupvalue (FuncState *fs, TString *name) {
- int i;
- Upvaldesc *up = fs->f->upvalues;
- for (i = 0; i < fs->nups; i++) {
- if (eqstr(up[i].name, name)) return i;
- }
- return -1; /* not found */
-}
-
-
-static Upvaldesc *allocupvalue (FuncState *fs) {
- Proto *f = fs->f;
- int oldsize = f->sizeupvalues;
- checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
- luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
- Upvaldesc, MAXUPVAL, "upvalues");
- while (oldsize < f->sizeupvalues)
- f->upvalues[oldsize++].name = NULL;
- return &f->upvalues[fs->nups++];
-}
-
-
-static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
- Upvaldesc *up = allocupvalue(fs);
- FuncState *prev = fs->prev;
- if (v->k == VLOCAL) {
- up->instack = 1;
- up->idx = v->u.var.ridx;
- up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind;
- lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name));
- }
- else {
- up->instack = 0;
- up->idx = cast_byte(v->u.info);
- up->kind = prev->f->upvalues[v->u.info].kind;
- lua_assert(eqstr(name, prev->f->upvalues[v->u.info].name));
- }
- up->name = name;
- luaC_objbarrier(fs->ls->L, fs->f, name);
- return fs->nups - 1;
-}
-
-
-/*
-** Look for an active local variable with the name 'n' in the
-** function 'fs'. If found, initialize 'var' with it and return
-** its expression kind; otherwise return -1.
-*/
-static int searchvar (FuncState *fs, TString *n, expdesc *var) {
- int i;
- for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
- Vardesc *vd = getlocalvardesc(fs, i);
- if (eqstr(n, vd->vd.name)) { /* found? */
- if (vd->vd.kind == RDKCTC) /* compile-time constant? */
- init_exp(var, VCONST, fs->firstlocal + i);
- else /* real variable */
- init_var(fs, var, i);
- return var->k;
- }
- }
- return -1; /* not found */
-}
-
-
-/*
-** Mark block where variable at given level was defined
-** (to emit close instructions later).
-*/
-static void markupval (FuncState *fs, int level) {
- BlockCnt *bl = fs->bl;
- while (bl->nactvar > level)
- bl = bl->previous;
- bl->upval = 1;
- fs->needclose = 1;
-}
-
-
-/*
-** Mark that current block has a to-be-closed variable.
-*/
-static void marktobeclosed (FuncState *fs) {
- BlockCnt *bl = fs->bl;
- bl->upval = 1;
- bl->insidetbc = 1;
- fs->needclose = 1;
-}
-
-
-/*
-** Find a variable with the given name 'n'. If it is an upvalue, add
-** this upvalue into all intermediate functions. If it is a global, set
-** 'var' as 'void' as a flag.
-*/
-static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
- if (fs == NULL) /* no more levels? */
- init_exp(var, VVOID, 0); /* default is global */
- else {
- int v = searchvar(fs, n, var); /* look up locals at current level */
- if (v >= 0) { /* found? */
- if (v == VLOCAL && !base)
- markupval(fs, var->u.var.vidx); /* local will be used as an upval */
- }
- else { /* not found as local at current level; try upvalues */
- int idx = searchupvalue(fs, n); /* try existing upvalues */
- if (idx < 0) { /* not found? */
- singlevaraux(fs->prev, n, var, 0); /* try upper levels */
- if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */
- idx = newupvalue(fs, n, var); /* will be a new upvalue */
- else /* it is a global or a constant */
- return; /* don't need to do anything at this level */
- }
- init_exp(var, VUPVAL, idx); /* new or old upvalue */
- }
- }
-}
-
-
-/*
-** Find a variable with the given name 'n', handling global variables
-** too.
-*/
-static void singlevar (LexState *ls, expdesc *var) {
- TString *varname = str_checkname(ls);
- FuncState *fs = ls->fs;
- singlevaraux(fs, varname, var, 1);
- if (var->k == VVOID) { /* global name? */
- expdesc key;
- singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
- lua_assert(var->k != VVOID); /* this one must exist */
- codestring(&key, varname); /* key is variable name */
- luaK_indexed(fs, var, &key); /* env[varname] */
- }
-}
-
-
-/*
-** Adjust the number of results from an expression list 'e' with 'nexps'
-** expressions to 'nvars' values.
-*/
-static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
- FuncState *fs = ls->fs;
- int needed = nvars - nexps; /* extra values needed */
- if (hasmultret(e->k)) { /* last expression has multiple returns? */
- int extra = needed + 1; /* discount last expression itself */
- if (extra < 0)
- extra = 0;
- luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
- }
- else {
- if (e->k != VVOID) /* at least one expression? */
- luaK_exp2nextreg(fs, e); /* close last expression */
- if (needed > 0) /* missing values? */
- luaK_nil(fs, fs->freereg, needed); /* complete with nils */
- }
- if (needed > 0)
- luaK_reserveregs(fs, needed); /* registers for extra values */
- else /* adding 'needed' is actually a subtraction */
- fs->freereg += needed; /* remove extra values */
-}
-
-
-#define enterlevel(ls) luaE_incCstack(ls->L)
-
-
-#define leavelevel(ls) ((ls)->L->nCcalls--)
-
-
-/*
-** Generates an error that a goto jumps into the scope of some
-** local variable.
-*/
-static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) {
- const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name);
- const char *msg = " at line %d jumps into the scope of local '%s'";
- msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname);
- luaK_semerror(ls, msg); /* raise the error */
-}
-
-
-/*
-** Solves the goto at index 'g' to given 'label' and removes it
-** from the list of pending goto's.
-** If it jumps into the scope of some variable, raises an error.
-*/
-static void solvegoto (LexState *ls, int g, Labeldesc *label) {
- int i;
- Labellist *gl = &ls->dyd->gt; /* list of goto's */
- Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */
- lua_assert(eqstr(gt->name, label->name));
- if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */
- jumpscopeerror(ls, gt);
- luaK_patchlist(ls->fs, gt->pc, label->pc);
- for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */
- gl->arr[i] = gl->arr[i + 1];
- gl->n--;
-}
-
-
-/*
-** Search for an active label with the given name.
-*/
-static Labeldesc *findlabel (LexState *ls, TString *name) {
- int i;
- Dyndata *dyd = ls->dyd;
- /* check labels in current function for a match */
- for (i = ls->fs->firstlabel; i < dyd->label.n; i++) {
- Labeldesc *lb = &dyd->label.arr[i];
- if (eqstr(lb->name, name)) /* correct label? */
- return lb;
- }
- return NULL; /* label not found */
-}
-
-
-/*
-** Adds a new label/goto in the corresponding list.
-*/
-static int newlabelentry (LexState *ls, Labellist *l, TString *name,
- int line, int pc) {
- int n = l->n;
- luaM_growvector(ls->L, l->arr, n, l->size,
- Labeldesc, SHRT_MAX, "labels/gotos");
- l->arr[n].name = name;
- l->arr[n].line = line;
- l->arr[n].nactvar = ls->fs->nactvar;
- l->arr[n].close = 0;
- l->arr[n].pc = pc;
- l->n = n + 1;
- return n;
-}
-
-
-static int newgotoentry (LexState *ls, TString *name, int line, int pc) {
- return newlabelentry(ls, &ls->dyd->gt, name, line, pc);
-}
-
-
-/*
-** Solves forward jumps. Check whether new label 'lb' matches any
-** pending gotos in current block and solves them. Return true
-** if any of the goto's need to close upvalues.
-*/
-static int solvegotos (LexState *ls, Labeldesc *lb) {
- Labellist *gl = &ls->dyd->gt;
- int i = ls->fs->bl->firstgoto;
- int needsclose = 0;
- while (i < gl->n) {
- if (eqstr(gl->arr[i].name, lb->name)) {
- needsclose |= gl->arr[i].close;
- solvegoto(ls, i, lb); /* will remove 'i' from the list */
- }
- else
- i++;
- }
- return needsclose;
-}
-
-
-/*
-** Create a new label with the given 'name' at the given 'line'.
-** 'last' tells whether label is the last non-op statement in its
-** block. Solves all pending goto's to this new label and adds
-** a close instruction if necessary.
-** Returns true iff it added a close instruction.
-*/
-static int createlabel (LexState *ls, TString *name, int line,
- int last) {
- FuncState *fs = ls->fs;
- Labellist *ll = &ls->dyd->label;
- int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs));
- if (last) { /* label is last no-op statement in the block? */
- /* assume that locals are already out of scope */
- ll->arr[l].nactvar = fs->bl->nactvar;
- }
- if (solvegotos(ls, &ll->arr[l])) { /* need close? */
- luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0);
- return 1;
- }
- return 0;
-}
-
-
-/*
-** Adjust pending gotos to outer level of a block.
-*/
-static void movegotosout (FuncState *fs, BlockCnt *bl) {
- int i;
- Labellist *gl = &fs->ls->dyd->gt;
- /* correct pending gotos to current block */
- for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */
- Labeldesc *gt = &gl->arr[i];
- /* leaving a variable scope? */
- if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar))
- gt->close |= bl->upval; /* jump may need a close */
- gt->nactvar = bl->nactvar; /* update goto level */
- }
-}
-
-
-static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
- bl->isloop = isloop;
- bl->nactvar = fs->nactvar;
- bl->firstlabel = fs->ls->dyd->label.n;
- bl->firstgoto = fs->ls->dyd->gt.n;
- bl->upval = 0;
- bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
- bl->previous = fs->bl;
- fs->bl = bl;
- lua_assert(fs->freereg == luaY_nvarstack(fs));
-}
-
-
-/*
-** generates an error for an undefined 'goto'.
-*/
-static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
- const char *msg;
- if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) {
- msg = "break outside loop at line %d";
- msg = luaO_pushfstring(ls->L, msg, gt->line);
- }
- else {
- msg = "no visible label '%s' for at line %d";
- msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
- }
- luaK_semerror(ls, msg);
-}
-
-
-static void leaveblock (FuncState *fs) {
- BlockCnt *bl = fs->bl;
- LexState *ls = fs->ls;
- int hasclose = 0;
- int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */
- if (bl->isloop) /* fix pending breaks? */
- hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
- if (!hasclose && bl->previous && bl->upval)
- luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0);
- fs->bl = bl->previous;
- removevars(fs, bl->nactvar);
- lua_assert(bl->nactvar == fs->nactvar);
- fs->freereg = stklevel; /* free registers */
- ls->dyd->label.n = bl->firstlabel; /* remove local labels */
- if (bl->previous) /* inner block? */
- movegotosout(fs, bl); /* update pending gotos to outer block */
- else {
- if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */
- undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */
- }
-}
-
-
-/*
-** adds a new prototype into list of prototypes
-*/
-static Proto *addprototype (LexState *ls) {
- Proto *clp;
- lua_State *L = ls->L;
- FuncState *fs = ls->fs;
- Proto *f = fs->f; /* prototype of current function */
- if (fs->np >= f->sizep) {
- int oldsize = f->sizep;
- luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
- while (oldsize < f->sizep)
- f->p[oldsize++] = NULL;
- }
- f->p[fs->np++] = clp = luaF_newproto(L);
- luaC_objbarrier(L, f, clp);
- return clp;
-}
-
-
-/*
-** codes instruction to create new closure in parent function.
-** The OP_CLOSURE instruction uses the last available register,
-** so that, if it invokes the GC, the GC knows which registers
-** are in use at that time.
-
-*/
-static void codeclosure (LexState *ls, expdesc *v) {
- FuncState *fs = ls->fs->prev;
- init_exp(v, VRELOC, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
- luaK_exp2nextreg(fs, v); /* fix it at the last register */
-}
-
-
-static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
- Proto *f = fs->f;
- fs->prev = ls->fs; /* linked list of funcstates */
- fs->ls = ls;
- ls->fs = fs;
- fs->pc = 0;
- fs->previousline = f->linedefined;
- fs->iwthabs = 0;
- fs->lasttarget = 0;
- fs->freereg = 0;
- fs->nk = 0;
- fs->nabslineinfo = 0;
- fs->np = 0;
- fs->nups = 0;
- fs->ndebugvars = 0;
- fs->nactvar = 0;
- fs->needclose = 0;
- fs->firstlocal = ls->dyd->actvar.n;
- fs->firstlabel = ls->dyd->label.n;
- fs->bl = NULL;
- f->source = ls->source;
- luaC_objbarrier(ls->L, f, f->source);
- f->maxstacksize = 2; /* registers 0/1 are always valid */
- enterblock(fs, bl, 0);
-}
-
-
-static void close_func (LexState *ls) {
- lua_State *L = ls->L;
- FuncState *fs = ls->fs;
- Proto *f = fs->f;
- luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */
- leaveblock(fs);
- lua_assert(fs->bl == NULL);
- luaK_finish(fs);
- luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction);
- luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte);
- luaM_shrinkvector(L, f->abslineinfo, f->sizeabslineinfo,
- fs->nabslineinfo, AbsLineInfo);
- luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue);
- luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
- luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
- luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
- ls->fs = fs->prev;
- luaC_checkGC(L);
-}
-
-
-
-/*============================================================*/
-/* GRAMMAR RULES */
-/*============================================================*/
-
-
-/*
-** check whether current token is in the follow set of a block.
-** 'until' closes syntactical blocks, but do not close scope,
-** so it is handled in separate.
-*/
-static int block_follow (LexState *ls, int withuntil) {
- switch (ls->t.token) {
- case TK_ELSE: case TK_ELSEIF:
- case TK_END: case TK_EOS:
- return 1;
- case TK_UNTIL: return withuntil;
- default: return 0;
- }
-}
-
-
-static void statlist (LexState *ls) {
- /* statlist -> { stat [';'] } */
- while (!block_follow(ls, 1)) {
- if (ls->t.token == TK_RETURN) {
- statement(ls);
- return; /* 'return' must be last statement */
- }
- statement(ls);
- }
-}
-
-
-static void fieldsel (LexState *ls, expdesc *v) {
- /* fieldsel -> ['.' | ':'] NAME */
- FuncState *fs = ls->fs;
- expdesc key;
- luaK_exp2anyregup(fs, v);
- luaX_next(ls); /* skip the dot or colon */
- codename(ls, &key);
- luaK_indexed(fs, v, &key);
-}
-
-
-static void yindex (LexState *ls, expdesc *v) {
- /* index -> '[' expr ']' */
- luaX_next(ls); /* skip the '[' */
- expr(ls, v);
- luaK_exp2val(ls->fs, v);
- checknext(ls, ']');
-}
-
-
-/*
-** {======================================================================
-** Rules for Constructors
-** =======================================================================
-*/
-
-
-typedef struct ConsControl {
- expdesc v; /* last list item read */
- expdesc *t; /* table descriptor */
- int nh; /* total number of 'record' elements */
- int na; /* number of array elements already stored */
- int tostore; /* number of array elements pending to be stored */
-} ConsControl;
-
-
-static void recfield (LexState *ls, ConsControl *cc) {
- /* recfield -> (NAME | '['exp']') = exp */
- FuncState *fs = ls->fs;
- int reg = ls->fs->freereg;
- expdesc tab, key, val;
- if (ls->t.token == TK_NAME) {
- checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
- codename(ls, &key);
- }
- else /* ls->t.token == '[' */
- yindex(ls, &key);
- cc->nh++;
- checknext(ls, '=');
- tab = *cc->t;
- luaK_indexed(fs, &tab, &key);
- expr(ls, &val);
- luaK_storevar(fs, &tab, &val);
- fs->freereg = reg; /* free registers */
-}
-
-
-static void closelistfield (FuncState *fs, ConsControl *cc) {
- if (cc->v.k == VVOID) return; /* there is no list item */
- luaK_exp2nextreg(fs, &cc->v);
- cc->v.k = VVOID;
- if (cc->tostore == LFIELDS_PER_FLUSH) {
- luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */
- cc->na += cc->tostore;
- cc->tostore = 0; /* no more items pending */
- }
-}
-
-
-static void lastlistfield (FuncState *fs, ConsControl *cc) {
- if (cc->tostore == 0) return;
- if (hasmultret(cc->v.k)) {
- luaK_setmultret(fs, &cc->v);
- luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET);
- cc->na--; /* do not count last expression (unknown number of elements) */
- }
- else {
- if (cc->v.k != VVOID)
- luaK_exp2nextreg(fs, &cc->v);
- luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);
- }
- cc->na += cc->tostore;
-}
-
-
-static void listfield (LexState *ls, ConsControl *cc) {
- /* listfield -> exp */
- expr(ls, &cc->v);
- cc->tostore++;
-}
-
-
-static void field (LexState *ls, ConsControl *cc) {
- /* field -> listfield | recfield */
- switch(ls->t.token) {
- case TK_NAME: { /* may be 'listfield' or 'recfield' */
- if (luaX_lookahead(ls) != '=') /* expression? */
- listfield(ls, cc);
- else
- recfield(ls, cc);
- break;
- }
- case '[': {
- recfield(ls, cc);
- break;
- }
- default: {
- listfield(ls, cc);
- break;
- }
- }
-}
-
-
-static void constructor (LexState *ls, expdesc *t) {
- /* constructor -> '{' [ field { sep field } [sep] ] '}'
- sep -> ',' | ';' */
- FuncState *fs = ls->fs;
- int line = ls->linenumber;
- int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
- ConsControl cc;
- luaK_code(fs, 0); /* space for extra arg. */
- cc.na = cc.nh = cc.tostore = 0;
- cc.t = t;
- init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */
- luaK_reserveregs(fs, 1);
- init_exp(&cc.v, VVOID, 0); /* no value (yet) */
- checknext(ls, '{');
- do {
- lua_assert(cc.v.k == VVOID || cc.tostore > 0);
- if (ls->t.token == '}') break;
- closelistfield(fs, &cc);
- field(ls, &cc);
- } while (testnext(ls, ',') || testnext(ls, ';'));
- check_match(ls, '}', '{', line);
- lastlistfield(fs, &cc);
- luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
-}
-
-/* }====================================================================== */
-
-
-static void setvararg (FuncState *fs, int nparams) {
- fs->f->is_vararg = 1;
- luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0);
-}
-
-
-static void parlist (LexState *ls) {
- /* parlist -> [ {NAME ','} (NAME | '...') ] */
- FuncState *fs = ls->fs;
- Proto *f = fs->f;
- int nparams = 0;
- int isvararg = 0;
- if (ls->t.token != ')') { /* is 'parlist' not empty? */
- do {
- switch (ls->t.token) {
- case TK_NAME: {
- new_localvar(ls, str_checkname(ls));
- nparams++;
- break;
- }
- case TK_DOTS: {
- luaX_next(ls);
- isvararg = 1;
- break;
- }
- default: luaX_syntaxerror(ls, " or '...' expected");
- }
- } while (!isvararg && testnext(ls, ','));
- }
- adjustlocalvars(ls, nparams);
- f->numparams = cast_byte(fs->nactvar);
- if (isvararg)
- setvararg(fs, f->numparams); /* declared vararg */
- luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */
-}
-
-
-static void body (LexState *ls, expdesc *e, int ismethod, int line) {
- /* body -> '(' parlist ')' block END */
- FuncState new_fs;
- BlockCnt bl;
- new_fs.f = addprototype(ls);
- new_fs.f->linedefined = line;
- open_func(ls, &new_fs, &bl);
- checknext(ls, '(');
- if (ismethod) {
- new_localvarliteral(ls, "self"); /* create 'self' parameter */
- adjustlocalvars(ls, 1);
- }
- parlist(ls);
- checknext(ls, ')');
- statlist(ls);
- new_fs.f->lastlinedefined = ls->linenumber;
- check_match(ls, TK_END, TK_FUNCTION, line);
- codeclosure(ls, e);
- close_func(ls);
-}
-
-
-static int explist (LexState *ls, expdesc *v) {
- /* explist -> expr { ',' expr } */
- int n = 1; /* at least one expression */
- expr(ls, v);
- while (testnext(ls, ',')) {
- luaK_exp2nextreg(ls->fs, v);
- expr(ls, v);
- n++;
- }
- return n;
-}
-
-
-static void funcargs (LexState *ls, expdesc *f, int line) {
- FuncState *fs = ls->fs;
- expdesc args;
- int base, nparams;
- switch (ls->t.token) {
- case '(': { /* funcargs -> '(' [ explist ] ')' */
- luaX_next(ls);
- if (ls->t.token == ')') /* arg list is empty? */
- args.k = VVOID;
- else {
- explist(ls, &args);
- if (hasmultret(args.k))
- luaK_setmultret(fs, &args);
- }
- check_match(ls, ')', '(', line);
- break;
- }
- case '{': { /* funcargs -> constructor */
- constructor(ls, &args);
- break;
- }
- case TK_STRING: { /* funcargs -> STRING */
- codestring(&args, ls->t.seminfo.ts);
- luaX_next(ls); /* must use 'seminfo' before 'next' */
- break;
- }
- default: {
- luaX_syntaxerror(ls, "function arguments expected");
- }
- }
- lua_assert(f->k == VNONRELOC);
- base = f->u.info; /* base register for call */
- if (hasmultret(args.k))
- nparams = LUA_MULTRET; /* open call */
- else {
- if (args.k != VVOID)
- luaK_exp2nextreg(fs, &args); /* close last argument */
- nparams = fs->freereg - (base+1);
- }
- init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
- luaK_fixline(fs, line);
- fs->freereg = base+1; /* call remove function and arguments and leaves
- (unless changed) one result */
-}
-
-
-
-
-/*
-** {======================================================================
-** Expression parsing
-** =======================================================================
-*/
-
-
-static void primaryexp (LexState *ls, expdesc *v) {
- /* primaryexp -> NAME | '(' expr ')' */
- switch (ls->t.token) {
- case '(': {
- int line = ls->linenumber;
- luaX_next(ls);
- expr(ls, v);
- check_match(ls, ')', '(', line);
- luaK_dischargevars(ls->fs, v);
- return;
- }
- case TK_NAME: {
- singlevar(ls, v);
- return;
- }
- default: {
- luaX_syntaxerror(ls, "unexpected symbol");
- }
- }
-}
-
-
-static void suffixedexp (LexState *ls, expdesc *v) {
- /* suffixedexp ->
- primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
- FuncState *fs = ls->fs;
- int line = ls->linenumber;
- primaryexp(ls, v);
- for (;;) {
- switch (ls->t.token) {
- case '.': { /* fieldsel */
- fieldsel(ls, v);
- break;
- }
- case '[': { /* '[' exp ']' */
- expdesc key;
- luaK_exp2anyregup(fs, v);
- yindex(ls, &key);
- luaK_indexed(fs, v, &key);
- break;
- }
- case ':': { /* ':' NAME funcargs */
- expdesc key;
- luaX_next(ls);
- codename(ls, &key);
- luaK_self(fs, v, &key);
- funcargs(ls, v, line);
- break;
- }
- case '(': case TK_STRING: case '{': { /* funcargs */
- luaK_exp2nextreg(fs, v);
- funcargs(ls, v, line);
- break;
- }
- default: return;
- }
- }
-}
-
-
-static void simpleexp (LexState *ls, expdesc *v) {
- /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
- constructor | FUNCTION body | suffixedexp */
- switch (ls->t.token) {
- case TK_FLT: {
- init_exp(v, VKFLT, 0);
- v->u.nval = ls->t.seminfo.r;
- break;
- }
- case TK_INT: {
- init_exp(v, VKINT, 0);
- v->u.ival = ls->t.seminfo.i;
- break;
- }
- case TK_STRING: {
- codestring(v, ls->t.seminfo.ts);
- break;
- }
- case TK_NIL: {
- init_exp(v, VNIL, 0);
- break;
- }
- case TK_TRUE: {
- init_exp(v, VTRUE, 0);
- break;
- }
- case TK_FALSE: {
- init_exp(v, VFALSE, 0);
- break;
- }
- case TK_DOTS: { /* vararg */
- FuncState *fs = ls->fs;
- check_condition(ls, fs->f->is_vararg,
- "cannot use '...' outside a vararg function");
- init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1));
- break;
- }
- case '{': { /* constructor */
- constructor(ls, v);
- return;
- }
- case TK_FUNCTION: {
- luaX_next(ls);
- body(ls, v, 0, ls->linenumber);
- return;
- }
- default: {
- suffixedexp(ls, v);
- return;
- }
- }
- luaX_next(ls);
-}
-
-
-static UnOpr getunopr (int op) {
- switch (op) {
- case TK_NOT: return OPR_NOT;
- case '-': return OPR_MINUS;
- case '~': return OPR_BNOT;
- case '#': return OPR_LEN;
- default: return OPR_NOUNOPR;
- }
-}
-
-
-static BinOpr getbinopr (int op) {
- switch (op) {
- case '+': return OPR_ADD;
- case '-': return OPR_SUB;
- case '*': return OPR_MUL;
- case '%': return OPR_MOD;
- case '^': return OPR_POW;
- case '/': return OPR_DIV;
- case TK_IDIV: return OPR_IDIV;
- case '&': return OPR_BAND;
- case '|': return OPR_BOR;
- case '~': return OPR_BXOR;
- case TK_SHL: return OPR_SHL;
- case TK_SHR: return OPR_SHR;
- case TK_CONCAT: return OPR_CONCAT;
- case TK_NE: return OPR_NE;
- case TK_EQ: return OPR_EQ;
- case '<': return OPR_LT;
- case TK_LE: return OPR_LE;
- case '>': return OPR_GT;
- case TK_GE: return OPR_GE;
- case TK_AND: return OPR_AND;
- case TK_OR: return OPR_OR;
- default: return OPR_NOBINOPR;
- }
-}
-
-
-/*
-** Priority table for binary operators.
-*/
-static const struct {
- lu_byte left; /* left priority for each binary operator */
- lu_byte right; /* right priority */
-} priority[] = { /* ORDER OPR */
- {10, 10}, {10, 10}, /* '+' '-' */
- {11, 11}, {11, 11}, /* '*' '%' */
- {14, 13}, /* '^' (right associative) */
- {11, 11}, {11, 11}, /* '/' '//' */
- {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */
- {7, 7}, {7, 7}, /* '<<' '>>' */
- {9, 8}, /* '..' (right associative) */
- {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */
- {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */
- {2, 2}, {1, 1} /* and, or */
-};
-
-#define UNARY_PRIORITY 12 /* priority for unary operators */
-
-
-/*
-** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
-** where 'binop' is any binary operator with a priority higher than 'limit'
-*/
-static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
- BinOpr op;
- UnOpr uop;
- enterlevel(ls);
- uop = getunopr(ls->t.token);
- if (uop != OPR_NOUNOPR) { /* prefix (unary) operator? */
- int line = ls->linenumber;
- luaX_next(ls); /* skip operator */
- subexpr(ls, v, UNARY_PRIORITY);
- luaK_prefix(ls->fs, uop, v, line);
- }
- else simpleexp(ls, v);
- /* expand while operators have priorities higher than 'limit' */
- op = getbinopr(ls->t.token);
- while (op != OPR_NOBINOPR && priority[op].left > limit) {
- expdesc v2;
- BinOpr nextop;
- int line = ls->linenumber;
- luaX_next(ls); /* skip operator */
- luaK_infix(ls->fs, op, v);
- /* read sub-expression with higher priority */
- nextop = subexpr(ls, &v2, priority[op].right);
- luaK_posfix(ls->fs, op, v, &v2, line);
- op = nextop;
- }
- leavelevel(ls);
- return op; /* return first untreated operator */
-}
-
-
-static void expr (LexState *ls, expdesc *v) {
- subexpr(ls, v, 0);
-}
-
-/* }==================================================================== */
-
-
-
-/*
-** {======================================================================
-** Rules for Statements
-** =======================================================================
-*/
-
-
-static void block (LexState *ls) {
- /* block -> statlist */
- FuncState *fs = ls->fs;
- BlockCnt bl;
- enterblock(fs, &bl, 0);
- statlist(ls);
- leaveblock(fs);
-}
-
-
-/*
-** structure to chain all variables in the left-hand side of an
-** assignment
-*/
-struct LHS_assign {
- struct LHS_assign *prev;
- expdesc v; /* variable (global, local, upvalue, or indexed) */
-};
-
-
-/*
-** check whether, in an assignment to an upvalue/local variable, the
-** upvalue/local variable is begin used in a previous assignment to a
-** table. If so, save original upvalue/local value in a safe place and
-** use this safe copy in the previous assignment.
-*/
-static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
- FuncState *fs = ls->fs;
- int extra = fs->freereg; /* eventual position to save local variable */
- int conflict = 0;
- for (; lh; lh = lh->prev) { /* check all previous assignments */
- if (vkisindexed(lh->v.k)) { /* assignment to table field? */
- if (lh->v.k == VINDEXUP) { /* is table an upvalue? */
- if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) {
- conflict = 1; /* table is the upvalue being assigned now */
- lh->v.k = VINDEXSTR;
- lh->v.u.ind.t = extra; /* assignment will use safe copy */
- }
- }
- else { /* table is a register */
- if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) {
- conflict = 1; /* table is the local being assigned now */
- lh->v.u.ind.t = extra; /* assignment will use safe copy */
- }
- /* is index the local being assigned? */
- if (lh->v.k == VINDEXED && v->k == VLOCAL &&
- lh->v.u.ind.idx == v->u.var.ridx) {
- conflict = 1;
- lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
- }
- }
- }
- }
- if (conflict) {
- /* copy upvalue/local value to a temporary (in position 'extra') */
- if (v->k == VLOCAL)
- luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0);
- else
- luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0);
- luaK_reserveregs(fs, 1);
- }
-}
-
-/*
-** Parse and compile a multiple assignment. The first "variable"
-** (a 'suffixedexp') was already read by the caller.
-**
-** assignment -> suffixedexp restassign
-** restassign -> ',' suffixedexp restassign | '=' explist
-*/
-static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) {
- expdesc e;
- check_condition(ls, vkisvar(lh->v.k), "syntax error");
- check_readonly(ls, &lh->v);
- if (testnext(ls, ',')) { /* restassign -> ',' suffixedexp restassign */
- struct LHS_assign nv;
- nv.prev = lh;
- suffixedexp(ls, &nv.v);
- if (!vkisindexed(nv.v.k))
- check_conflict(ls, lh, &nv.v);
- enterlevel(ls); /* control recursion depth */
- restassign(ls, &nv, nvars+1);
- leavelevel(ls);
- }
- else { /* restassign -> '=' explist */
- int nexps;
- checknext(ls, '=');
- nexps = explist(ls, &e);
- if (nexps != nvars)
- adjust_assign(ls, nvars, nexps, &e);
- else {
- luaK_setoneret(ls->fs, &e); /* close last expression */
- luaK_storevar(ls->fs, &lh->v, &e);
- return; /* avoid default */
- }
- }
- init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
- luaK_storevar(ls->fs, &lh->v, &e);
-}
-
-
-static int cond (LexState *ls) {
- /* cond -> exp */
- expdesc v;
- expr(ls, &v); /* read condition */
- if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */
- luaK_goiftrue(ls->fs, &v);
- return v.f;
-}
-
-
-static void gotostat (LexState *ls) {
- FuncState *fs = ls->fs;
- int line = ls->linenumber;
- TString *name = str_checkname(ls); /* label's name */
- Labeldesc *lb = findlabel(ls, name);
- if (lb == NULL) /* no label? */
- /* forward jump; will be resolved when the label is declared */
- newgotoentry(ls, name, line, luaK_jump(fs));
- else { /* found a label */
- /* backward jump; will be resolved here */
- int lblevel = reglevel(fs, lb->nactvar); /* label level */
- if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */
- luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0);
- /* create jump and link it to the label */
- luaK_patchlist(fs, luaK_jump(fs), lb->pc);
- }
-}
-
-
-/*
-** Break statement. Semantically equivalent to "goto break".
-*/
-static void breakstat (LexState *ls) {
- int line = ls->linenumber;
- luaX_next(ls); /* skip break */
- newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs));
-}
-
-
-/*
-** Check whether there is already a label with the given 'name'.
-*/
-static void checkrepeated (LexState *ls, TString *name) {
- Labeldesc *lb = findlabel(ls, name);
- if (l_unlikely(lb != NULL)) { /* already defined? */
- const char *msg = "label '%s' already defined on line %d";
- msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line);
- luaK_semerror(ls, msg); /* error */
- }
-}
-
-
-static void labelstat (LexState *ls, TString *name, int line) {
- /* label -> '::' NAME '::' */
- checknext(ls, TK_DBCOLON); /* skip double colon */
- while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
- statement(ls); /* skip other no-op statements */
- checkrepeated(ls, name); /* check for repeated labels */
- createlabel(ls, name, line, block_follow(ls, 0));
-}
-
-
-static void whilestat (LexState *ls, int line) {
- /* whilestat -> WHILE cond DO block END */
- FuncState *fs = ls->fs;
- int whileinit;
- int condexit;
- BlockCnt bl;
- luaX_next(ls); /* skip WHILE */
- whileinit = luaK_getlabel(fs);
- condexit = cond(ls);
- enterblock(fs, &bl, 1);
- checknext(ls, TK_DO);
- block(ls);
- luaK_jumpto(fs, whileinit);
- check_match(ls, TK_END, TK_WHILE, line);
- leaveblock(fs);
- luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
-}
-
-
-static void repeatstat (LexState *ls, int line) {
- /* repeatstat -> REPEAT block UNTIL cond */
- int condexit;
- FuncState *fs = ls->fs;
- int repeat_init = luaK_getlabel(fs);
- BlockCnt bl1, bl2;
- enterblock(fs, &bl1, 1); /* loop block */
- enterblock(fs, &bl2, 0); /* scope block */
- luaX_next(ls); /* skip REPEAT */
- statlist(ls);
- check_match(ls, TK_UNTIL, TK_REPEAT, line);
- condexit = cond(ls); /* read condition (inside scope block) */
- leaveblock(fs); /* finish scope */
- if (bl2.upval) { /* upvalues? */
- int exit = luaK_jump(fs); /* normal exit must jump over fix */
- luaK_patchtohere(fs, condexit); /* repetition must close upvalues */
- luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0);
- condexit = luaK_jump(fs); /* repeat after closing upvalues */
- luaK_patchtohere(fs, exit); /* normal exit comes to here */
- }
- luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
- leaveblock(fs); /* finish loop */
-}
-
-
-/*
-** Read an expression and generate code to put its results in next
-** stack slot.
-**
-*/
-static void exp1 (LexState *ls) {
- expdesc e;
- expr(ls, &e);
- luaK_exp2nextreg(ls->fs, &e);
- lua_assert(e.k == VNONRELOC);
-}
-
-
-/*
-** Fix for instruction at position 'pc' to jump to 'dest'.
-** (Jump addresses are relative in Lua). 'back' true means
-** a back jump.
-*/
-static void fixforjump (FuncState *fs, int pc, int dest, int back) {
- Instruction *jmp = &fs->f->code[pc];
- int offset = dest - (pc + 1);
- if (back)
- offset = -offset;
- if (l_unlikely(offset > MAXARG_Bx))
- luaX_syntaxerror(fs->ls, "control structure too long");
- SETARG_Bx(*jmp, offset);
-}
-
-
-/*
-** Generate code for a 'for' loop.
-*/
-static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
- /* forbody -> DO block */
- static const OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP};
- static const OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP};
- BlockCnt bl;
- FuncState *fs = ls->fs;
- int prep, endfor;
- checknext(ls, TK_DO);
- prep = luaK_codeABx(fs, forprep[isgen], base, 0);
- 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 */
- fixforjump(fs, prep, luaK_getlabel(fs), 0);
- if (isgen) { /* generic for? */
- luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
- luaK_fixline(fs, line);
- }
- endfor = luaK_codeABx(fs, forloop[isgen], base, 0);
- fixforjump(fs, endfor, prep + 1, 1);
- luaK_fixline(fs, line);
-}
-
-
-static void fornum (LexState *ls, TString *varname, int line) {
- /* fornum -> NAME = exp,exp[,exp] forbody */
- FuncState *fs = ls->fs;
- int base = fs->freereg;
- new_localvarliteral(ls, "(for state)");
- new_localvarliteral(ls, "(for state)");
- new_localvarliteral(ls, "(for state)");
- new_localvar(ls, varname);
- checknext(ls, '=');
- exp1(ls); /* initial value */
- checknext(ls, ',');
- exp1(ls); /* limit */
- if (testnext(ls, ','))
- exp1(ls); /* optional step */
- else { /* default step = 1 */
- luaK_int(fs, fs->freereg, 1);
- luaK_reserveregs(fs, 1);
- }
- adjustlocalvars(ls, 3); /* control variables */
- forbody(ls, base, line, 1, 0);
-}
-
-
-static void forlist (LexState *ls, TString *indexname) {
- /* forlist -> NAME {,NAME} IN explist forbody */
- FuncState *fs = ls->fs;
- expdesc e;
- int nvars = 5; /* gen, state, control, toclose, 'indexname' */
- int line;
- int base = fs->freereg;
- /* create control variables */
- new_localvarliteral(ls, "(for state)");
- new_localvarliteral(ls, "(for state)");
- new_localvarliteral(ls, "(for state)");
- new_localvarliteral(ls, "(for state)");
- /* create declared variables */
- new_localvar(ls, indexname);
- while (testnext(ls, ',')) {
- new_localvar(ls, str_checkname(ls));
- nvars++;
- }
- checknext(ls, TK_IN);
- line = ls->linenumber;
- adjust_assign(ls, 4, explist(ls, &e), &e);
- adjustlocalvars(ls, 4); /* control variables */
- marktobeclosed(fs); /* last control var. must be closed */
- luaK_checkstack(fs, 3); /* extra space to call generator */
- forbody(ls, base, line, nvars - 4, 1);
-}
-
-
-static void forstat (LexState *ls, int line) {
- /* forstat -> FOR (fornum | forlist) END */
- FuncState *fs = ls->fs;
- TString *varname;
- BlockCnt bl;
- enterblock(fs, &bl, 1); /* scope for loop and control variables */
- luaX_next(ls); /* skip 'for' */
- varname = str_checkname(ls); /* first variable name */
- switch (ls->t.token) {
- case '=': fornum(ls, varname, line); break;
- case ',': case TK_IN: forlist(ls, varname); break;
- default: luaX_syntaxerror(ls, "'=' or 'in' expected");
- }
- check_match(ls, TK_END, TK_FOR, line);
- leaveblock(fs); /* loop scope ('break' jumps to this point) */
-}
-
-
-static void test_then_block (LexState *ls, int *escapelist) {
- /* test_then_block -> [IF | ELSEIF] cond THEN block */
- BlockCnt bl;
- FuncState *fs = ls->fs;
- expdesc v;
- int jf; /* instruction to skip 'then' code (if condition is false) */
- luaX_next(ls); /* skip IF or ELSEIF */
- expr(ls, &v); /* read condition */
- checknext(ls, TK_THEN);
- if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
- int line = ls->linenumber;
- luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */
- luaX_next(ls); /* skip 'break' */
- enterblock(fs, &bl, 0); /* must enter block before 'goto' */
- newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
- while (testnext(ls, ';')) {} /* skip semicolons */
- if (block_follow(ls, 0)) { /* jump is the entire block? */
- leaveblock(fs);
- return; /* and that is it */
- }
- else /* must skip over 'then' part if condition is false */
- jf = luaK_jump(fs);
- }
- else { /* regular case (not a break) */
- luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
- enterblock(fs, &bl, 0);
- jf = v.f;
- }
- statlist(ls); /* 'then' part */
- leaveblock(fs);
- if (ls->t.token == TK_ELSE ||
- ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */
- luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */
- luaK_patchtohere(fs, jf);
-}
-
-
-static void ifstat (LexState *ls, int line) {
- /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
- FuncState *fs = ls->fs;
- int escapelist = NO_JUMP; /* exit list for finished parts */
- test_then_block(ls, &escapelist); /* IF cond THEN block */
- while (ls->t.token == TK_ELSEIF)
- test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */
- if (testnext(ls, TK_ELSE))
- block(ls); /* 'else' part */
- check_match(ls, TK_END, TK_IF, line);
- luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */
-}
-
-
-static void localfunc (LexState *ls) {
- expdesc b;
- FuncState *fs = ls->fs;
- int fvar = fs->nactvar; /* function's variable index */
- new_localvar(ls, str_checkname(ls)); /* new local variable */
- adjustlocalvars(ls, 1); /* enter its scope */
- body(ls, &b, 0, ls->linenumber); /* function created in next register */
- /* debug information will only see the variable after this point! */
- localdebuginfo(fs, fvar)->startpc = fs->pc;
-}
-
-
-static int getlocalattribute (LexState *ls) {
- /* ATTRIB -> ['<' Name '>'] */
- if (testnext(ls, '<')) {
- const char *attr = getstr(str_checkname(ls));
- checknext(ls, '>');
- if (strcmp(attr, "const") == 0)
- return RDKCONST; /* read-only variable */
- else if (strcmp(attr, "close") == 0)
- return RDKTOCLOSE; /* to-be-closed variable */
- else
- luaK_semerror(ls,
- luaO_pushfstring(ls->L, "unknown attribute '%s'", attr));
- }
- return VDKREG; /* regular variable */
-}
-
-
-static void checktoclose (FuncState *fs, int level) {
- if (level != -1) { /* is there a to-be-closed variable? */
- marktobeclosed(fs);
- luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
- }
-}
-
-
-static void localstat (LexState *ls) {
- /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
- FuncState *fs = ls->fs;
- int toclose = -1; /* index of to-be-closed variable (if any) */
- Vardesc *var; /* last variable */
- int vidx, kind; /* index and kind of last variable */
- int nvars = 0;
- int nexps;
- expdesc e;
- do {
- vidx = new_localvar(ls, str_checkname(ls));
- kind = getlocalattribute(ls);
- getlocalvardesc(fs, vidx)->vd.kind = kind;
- if (kind == RDKTOCLOSE) { /* to-be-closed? */
- if (toclose != -1) /* one already present? */
- luaK_semerror(ls, "multiple to-be-closed variables in local list");
- toclose = fs->nactvar + nvars;
- }
- nvars++;
- } while (testnext(ls, ','));
- if (testnext(ls, '='))
- nexps = explist(ls, &e);
- else {
- e.k = VVOID;
- nexps = 0;
- }
- var = getlocalvardesc(fs, vidx); /* get last variable */
- if (nvars == nexps && /* no adjustments? */
- var->vd.kind == RDKCONST && /* last variable is const? */
- luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */
- var->vd.kind = RDKCTC; /* variable is a compile-time constant */
- adjustlocalvars(ls, nvars - 1); /* exclude last variable */
- fs->nactvar++; /* but count it */
- }
- else {
- adjust_assign(ls, nvars, nexps, &e);
- adjustlocalvars(ls, nvars);
- }
- checktoclose(fs, toclose);
-}
-
-
-static int funcname (LexState *ls, expdesc *v) {
- /* funcname -> NAME {fieldsel} [':' NAME] */
- int ismethod = 0;
- singlevar(ls, v);
- while (ls->t.token == '.')
- fieldsel(ls, v);
- if (ls->t.token == ':') {
- ismethod = 1;
- fieldsel(ls, v);
- }
- return ismethod;
-}
-
-
-static void funcstat (LexState *ls, int line) {
- /* funcstat -> FUNCTION funcname body */
- int ismethod;
- expdesc v, b;
- luaX_next(ls); /* skip FUNCTION */
- ismethod = funcname(ls, &v);
- body(ls, &b, ismethod, line);
- check_readonly(ls, &v);
- luaK_storevar(ls->fs, &v, &b);
- luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
-}
-
-
-static void exprstat (LexState *ls) {
- /* stat -> func | assignment */
- FuncState *fs = ls->fs;
- struct LHS_assign v;
- suffixedexp(ls, &v.v);
- if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
- v.prev = NULL;
- restassign(ls, &v, 1);
- }
- else { /* stat -> func */
- Instruction *inst;
- check_condition(ls, v.v.k == VCALL, "syntax error");
- inst = &getinstruction(fs, &v.v);
- SETARG_C(*inst, 1); /* call statement uses no results */
- }
-}
-
-
-static void retstat (LexState *ls) {
- /* stat -> RETURN [explist] [';'] */
- FuncState *fs = ls->fs;
- expdesc e;
- int nret; /* number of values being returned */
- int first = luaY_nvarstack(fs); /* first slot to be returned */
- if (block_follow(ls, 1) || ls->t.token == ';')
- nret = 0; /* return no values */
- else {
- nret = explist(ls, &e); /* optional return values */
- if (hasmultret(e.k)) {
- luaK_setmultret(fs, &e);
- if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */
- SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
- lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs));
- }
- nret = LUA_MULTRET; /* return all values */
- }
- else {
- if (nret == 1) /* only one single value? */
- first = luaK_exp2anyreg(fs, &e); /* can use original slot */
- else { /* values must go to the top of the stack */
- luaK_exp2nextreg(fs, &e);
- lua_assert(nret == fs->freereg - first);
- }
- }
- }
- luaK_ret(fs, first, nret);
- testnext(ls, ';'); /* skip optional semicolon */
-}
-
-
-static void statement (LexState *ls) {
- int line = ls->linenumber; /* may be needed for error messages */
- enterlevel(ls);
- switch (ls->t.token) {
- case ';': { /* stat -> ';' (empty statement) */
- luaX_next(ls); /* skip ';' */
- break;
- }
- case TK_IF: { /* stat -> ifstat */
- ifstat(ls, line);
- break;
- }
- case TK_WHILE: { /* stat -> whilestat */
- whilestat(ls, line);
- break;
- }
- case TK_DO: { /* stat -> DO block END */
- luaX_next(ls); /* skip DO */
- block(ls);
- check_match(ls, TK_END, TK_DO, line);
- break;
- }
- case TK_FOR: { /* stat -> forstat */
- forstat(ls, line);
- break;
- }
- case TK_REPEAT: { /* stat -> repeatstat */
- repeatstat(ls, line);
- break;
- }
- case TK_FUNCTION: { /* stat -> funcstat */
- funcstat(ls, line);
- break;
- }
- case TK_LOCAL: { /* stat -> localstat */
- luaX_next(ls); /* skip LOCAL */
- if (testnext(ls, TK_FUNCTION)) /* local function? */
- localfunc(ls);
- else
- localstat(ls);
- break;
- }
- case TK_DBCOLON: { /* stat -> label */
- luaX_next(ls); /* skip double colon */
- labelstat(ls, str_checkname(ls), line);
- break;
- }
- case TK_RETURN: { /* stat -> retstat */
- luaX_next(ls); /* skip RETURN */
- retstat(ls);
- break;
- }
- case TK_BREAK: { /* stat -> breakstat */
- breakstat(ls);
- break;
- }
- case TK_GOTO: { /* stat -> 'goto' NAME */
- luaX_next(ls); /* skip 'goto' */
- gotostat(ls);
- break;
- }
- default: { /* stat -> func | assignment */
- exprstat(ls);
- break;
- }
- }
- lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
- ls->fs->freereg >= luaY_nvarstack(ls->fs));
- ls->fs->freereg = luaY_nvarstack(ls->fs); /* free registers */
- leavelevel(ls);
-}
-
-/* }====================================================================== */
-
-
-/*
-** compiles the main function, which is a regular vararg function with an
-** upvalue named LUA_ENV
-*/
-static void mainfunc (LexState *ls, FuncState *fs) {
- BlockCnt bl;
- Upvaldesc *env;
- open_func(ls, fs, &bl);
- setvararg(fs, 0); /* main function is always declared vararg */
- env = allocupvalue(fs); /* ...set environment upvalue */
- env->instack = 1;
- env->idx = 0;
- env->kind = VDKREG;
- env->name = ls->envn;
- luaC_objbarrier(ls->L, fs->f, env->name);
- luaX_next(ls); /* read first token */
- statlist(ls); /* parse main body */
- check(ls, TK_EOS);
- close_func(ls);
-}
-
-
-LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar) {
- LexState lexstate;
- FuncState funcstate;
- LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */
- setclLvalue2s(L, L->top, cl); /* anchor it (to avoid being collected) */
- luaD_inctop(L);
- lexstate.h = luaH_new(L); /* create table for scanner */
- sethvalue2s(L, L->top, lexstate.h); /* anchor it */
- luaD_inctop(L);
- funcstate.f = cl->p = luaF_newproto(L);
- luaC_objbarrier(L, cl, cl->p);
- funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
- luaC_objbarrier(L, funcstate.f, funcstate.f->source);
- lexstate.buff = buff;
- lexstate.dyd = dyd;
- dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
- luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
- mainfunc(&lexstate, &funcstate);
- lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
- /* all scopes should be correctly finished */
- lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
- L->top--; /* remove scanner's table */
- return cl; /* closure is on the stack, too */
-}
-
diff --git a/lua-5.4.4/library/lparser.h b/lua-5.4.4/library/lparser.h
deleted file mode 100644
index 5e4500f1..00000000
--- a/lua-5.4.4/library/lparser.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-** $Id: lparser.h $
-** Lua Parser
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lparser_h
-#define lparser_h
-
-#include "llimits.h"
-#include "lobject.h"
-#include "lzio.h"
-
-
-/*
-** Expression and variable descriptor.
-** Code generation for variables and expressions can be delayed to allow
-** optimizations; An 'expdesc' structure describes a potentially-delayed
-** variable/expression. It has a description of its "main" value plus a
-** list of conditional jumps that can also produce its value (generated
-** by short-circuit operators 'and'/'or').
-*/
-
-/* kinds of variables/expressions */
-typedef enum {
- VVOID, /* when 'expdesc' describes the last expression of a list,
- this kind means an empty list (so, no expression) */
- VNIL, /* constant nil */
- VTRUE, /* constant true */
- VFALSE, /* constant false */
- VK, /* constant in 'k'; info = index of constant in 'k' */
- VKFLT, /* floating constant; nval = numerical float value */
- VKINT, /* integer constant; ival = numerical integer value */
- VKSTR, /* string constant; strval = TString address;
- (string is fixed by the lexer) */
- VNONRELOC, /* expression has its value in a fixed register;
- info = result register */
- VLOCAL, /* local variable; var.ridx = register index;
- var.vidx = relative index in 'actvar.arr' */
- VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
- VCONST, /* compile-time variable;
- info = absolute index in 'actvar.arr' */
- VINDEXED, /* indexed variable;
- ind.t = table register;
- ind.idx = key's R index */
- VINDEXUP, /* indexed upvalue;
- ind.t = table upvalue;
- ind.idx = key's K index */
- VINDEXI, /* indexed variable with constant integer;
- ind.t = table register;
- ind.idx = key's value */
- VINDEXSTR, /* indexed variable with literal string;
- ind.t = table register;
- ind.idx = key's K index */
- VJMP, /* expression is a test/comparison;
- info = pc of corresponding jump instruction */
- VRELOC, /* expression can put result in any register;
- info = instruction pc */
- VCALL, /* expression is a function call; info = instruction pc */
- VVARARG /* vararg expression; info = instruction pc */
-} expkind;
-
-
-#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
-#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
-
-
-typedef struct expdesc {
- expkind k;
- union {
- lua_Integer ival; /* for VKINT */
- lua_Number nval; /* for VKFLT */
- TString *strval; /* for VKSTR */
- int info; /* for generic use */
- struct { /* for indexed variables */
- short idx; /* index (R or "long" K) */
- lu_byte t; /* table (register or upvalue) */
- } ind;
- struct { /* for local variables */
- lu_byte ridx; /* register holding the variable */
- unsigned short vidx; /* compiler index (in 'actvar.arr') */
- } var;
- } u;
- int t; /* patch list of 'exit when true' */
- int f; /* patch list of 'exit when false' */
-} expdesc;
-
-
-/* kinds of variables */
-#define VDKREG 0 /* regular */
-#define RDKCONST 1 /* constant */
-#define RDKTOCLOSE 2 /* to-be-closed */
-#define RDKCTC 3 /* compile-time constant */
-
-/* description of an active local variable */
-typedef union Vardesc {
- struct {
- TValuefields; /* constant value (if it is a compile-time constant) */
- lu_byte kind;
- lu_byte ridx; /* register holding the variable */
- short pidx; /* index of the variable in the Proto's 'locvars' array */
- TString *name; /* variable name */
- } vd;
- TValue k; /* constant value (if any) */
-} Vardesc;
-
-
-
-/* description of pending goto statements and label statements */
-typedef struct Labeldesc {
- TString *name; /* label identifier */
- int pc; /* position in code */
- int line; /* line where it appeared */
- lu_byte nactvar; /* number of active variables in that position */
- lu_byte close; /* goto that escapes upvalues */
-} Labeldesc;
-
-
-/* list of labels or gotos */
-typedef struct Labellist {
- Labeldesc *arr; /* array */
- int n; /* number of entries in use */
- int size; /* array size */
-} Labellist;
-
-
-/* dynamic structures used by the parser */
-typedef struct Dyndata {
- struct { /* list of all active local variables */
- Vardesc *arr;
- int n;
- int size;
- } actvar;
- Labellist gt; /* list of pending gotos */
- Labellist label; /* list of active labels */
-} Dyndata;
-
-
-/* control of blocks */
-struct BlockCnt; /* defined in lparser.c */
-
-
-/* state needed to generate code for a given function */
-typedef struct FuncState {
- Proto *f; /* current function header */
- struct FuncState *prev; /* enclosing function */
- struct LexState *ls; /* lexical state */
- struct BlockCnt *bl; /* chain of current blocks */
- int pc; /* next position to code (equivalent to 'ncode') */
- int lasttarget; /* 'label' of last 'jump label' */
- int previousline; /* last line that was saved in 'lineinfo' */
- int nk; /* number of elements in 'k' */
- int np; /* number of elements in 'p' */
- int nabslineinfo; /* number of elements in 'abslineinfo' */
- int firstlocal; /* index of first local var (in Dyndata array) */
- int firstlabel; /* index of first label (in 'dyd->label->arr') */
- short ndebugvars; /* number of elements in 'f->locvars' */
- lu_byte nactvar; /* number of active local variables */
- lu_byte nups; /* number of upvalues */
- lu_byte freereg; /* first free register */
- lu_byte iwthabs; /* instructions issued since last absolute line info */
- lu_byte needclose; /* function needs to close upvalues when returning */
-} FuncState;
-
-
-LUAI_FUNC int luaY_nvarstack (FuncState *fs);
-LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar);
-
-
-#endif
diff --git a/lua-5.4.4/library/lprefix.h b/lua-5.4.4/library/lprefix.h
deleted file mode 100644
index 484f2ad6..00000000
--- a/lua-5.4.4/library/lprefix.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-** $Id: lprefix.h $
-** Definitions for Lua code that must come before any other header file
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lprefix_h
-#define lprefix_h
-
-
-/*
-** Allows POSIX/XSI stuff
-*/
-#if !defined(LUA_USE_C89) /* { */
-
-#if !defined(_XOPEN_SOURCE)
-#define _XOPEN_SOURCE 600
-#elif _XOPEN_SOURCE == 0
-#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
-#endif
-
-/*
-** Allows manipulation of large files in gcc and some other compilers
-*/
-#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
-#define _LARGEFILE_SOURCE 1
-#define _FILE_OFFSET_BITS 64
-#endif
-
-#endif /* } */
-
-
-/*
-** Windows stuff
-*/
-#if defined(_WIN32) /* { */
-
-#if !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
-#endif
-
-#endif /* } */
-
-#endif
-
diff --git a/lua-5.4.4/library/lstate.c b/lua-5.4.4/library/lstate.c
deleted file mode 100644
index 1ffe1a0f..00000000
--- a/lua-5.4.4/library/lstate.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
-** $Id: lstate.c $
-** Global State
-** See Copyright Notice in lua.h
-*/
-
-#define lstate_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-#include
-
-#include "lua.h"
-
-#include "lapi.h"
-#include "ldebug.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lgc.h"
-#include "llex.h"
-#include "lmem.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-#include "ltm.h"
-
-
-
-/*
-** thread state + extra space
-*/
-typedef struct LX {
- lu_byte extra_[LUA_EXTRASPACE];
- lua_State l;
-} LX;
-
-
-/*
-** Main thread combines a thread state and the global state
-*/
-typedef struct LG {
- LX l;
- global_State g;
-} LG;
-
-
-
-#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
-
-
-/*
-** A macro to create a "random" seed when a state is created;
-** the seed is used to randomize string hashes.
-*/
-#if !defined(luai_makeseed)
-
-#include
-
-/*
-** Compute an initial seed with some level of randomness.
-** Rely on Address Space Layout Randomization (if present) and
-** current time.
-*/
-#define addbuff(b,p,e) \
- { size_t t = cast_sizet(e); \
- memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
-
-static unsigned int luai_makeseed (lua_State *L) {
- char buff[3 * sizeof(size_t)];
- unsigned int h = cast_uint(time(NULL));
- int p = 0;
- addbuff(buff, p, L); /* heap variable */
- addbuff(buff, p, &h); /* local variable */
- addbuff(buff, p, &lua_newstate); /* public function */
- lua_assert(p == sizeof(buff));
- return luaS_hash(buff, p, h);
-}
-
-#endif
-
-
-/*
-** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
-** invariant (and avoiding underflows in 'totalbytes')
-*/
-void luaE_setdebt (global_State *g, l_mem debt) {
- l_mem tb = gettotalbytes(g);
- lua_assert(tb > 0);
- if (debt < tb - MAX_LMEM)
- debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */
- g->totalbytes = tb - debt;
- g->GCdebt = debt;
-}
-
-
-LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
- UNUSED(L); UNUSED(limit);
- return LUAI_MAXCCALLS; /* warning?? */
-}
-
-
-CallInfo *luaE_extendCI (lua_State *L) {
- CallInfo *ci;
- lua_assert(L->ci->next == NULL);
- ci = luaM_new(L, CallInfo);
- lua_assert(L->ci->next == NULL);
- L->ci->next = ci;
- ci->previous = L->ci;
- ci->next = NULL;
- ci->u.l.trap = 0;
- L->nci++;
- return ci;
-}
-
-
-/*
-** free all CallInfo structures not in use by a thread
-*/
-void luaE_freeCI (lua_State *L) {
- CallInfo *ci = L->ci;
- CallInfo *next = ci->next;
- ci->next = NULL;
- while ((ci = next) != NULL) {
- next = ci->next;
- luaM_free(L, ci);
- L->nci--;
- }
-}
-
-
-/*
-** free half of the CallInfo structures not in use by a thread,
-** keeping the first one.
-*/
-void luaE_shrinkCI (lua_State *L) {
- CallInfo *ci = L->ci->next; /* first free CallInfo */
- CallInfo *next;
- if (ci == NULL)
- return; /* no extra elements */
- while ((next = ci->next) != NULL) { /* two extra elements? */
- CallInfo *next2 = next->next; /* next's next */
- ci->next = next2; /* remove next from the list */
- L->nci--;
- luaM_free(L, next); /* free next */
- if (next2 == NULL)
- break; /* no more elements */
- else {
- next2->previous = ci;
- ci = next2; /* continue */
- }
- }
-}
-
-
-/*
-** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS.
-** If equal, raises an overflow error. If value is larger than
-** LUAI_MAXCCALLS (which means it is handling an overflow) but
-** not much larger, does not report an error (to allow overflow
-** handling to work).
-*/
-void luaE_checkcstack (lua_State *L) {
- if (getCcalls(L) == LUAI_MAXCCALLS)
- luaG_runerror(L, "C stack overflow");
- else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
- luaD_throw(L, LUA_ERRERR); /* error while handling stack error */
-}
-
-
-LUAI_FUNC void luaE_incCstack (lua_State *L) {
- L->nCcalls++;
- if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
- luaE_checkcstack(L);
-}
-
-
-static void stack_init (lua_State *L1, lua_State *L) {
- int i; CallInfo *ci;
- /* initialize stack array */
- L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
- L1->tbclist = L1->stack;
- for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
- setnilvalue(s2v(L1->stack + i)); /* erase new stack */
- L1->top = L1->stack;
- L1->stack_last = L1->stack + BASIC_STACK_SIZE;
- /* initialize first ci */
- ci = &L1->base_ci;
- ci->next = ci->previous = NULL;
- ci->callstatus = CIST_C;
- ci->func = L1->top;
- ci->u.c.k = NULL;
- ci->nresults = 0;
- setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */
- L1->top++;
- ci->top = L1->top + LUA_MINSTACK;
- L1->ci = ci;
-}
-
-
-static void freestack (lua_State *L) {
- if (L->stack == NULL)
- return; /* stack not completely built yet */
- L->ci = &L->base_ci; /* free the entire 'ci' list */
- luaE_freeCI(L);
- lua_assert(L->nci == 0);
- luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */
-}
-
-
-/*
-** Create registry table and its predefined values
-*/
-static void init_registry (lua_State *L, global_State *g) {
- /* create registry */
- Table *registry = luaH_new(L);
- sethvalue(L, &g->l_registry, registry);
- luaH_resize(L, registry, LUA_RIDX_LAST, 0);
- /* registry[LUA_RIDX_MAINTHREAD] = L */
- setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L);
- /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
- sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L));
-}
-
-
-/*
-** open parts of the state that may cause memory-allocation errors.
-*/
-static void f_luaopen (lua_State *L, void *ud) {
- global_State *g = G(L);
- UNUSED(ud);
- stack_init(L, L); /* init stack */
- init_registry(L, g);
- luaS_init(L);
- luaT_init(L);
- luaX_init(L);
- g->gcstp = 0; /* allow gc */
- setnilvalue(&g->nilvalue); /* now state is complete */
- luai_userstateopen(L);
-}
-
-
-/*
-** preinitialize a thread with consistent values without allocating
-** any memory (to avoid errors)
-*/
-static void preinit_thread (lua_State *L, global_State *g) {
- G(L) = g;
- L->stack = NULL;
- L->ci = NULL;
- L->nci = 0;
- L->twups = L; /* thread has no upvalues */
- L->nCcalls = 0;
- L->errorJmp = NULL;
- L->hook = NULL;
- L->hookmask = 0;
- L->basehookcount = 0;
- L->allowhook = 1;
- resethookcount(L);
- L->openupval = NULL;
- L->status = LUA_OK;
- L->errfunc = 0;
- L->oldpc = 0;
-}
-
-
-static void close_state (lua_State *L) {
- global_State *g = G(L);
- if (!completestate(g)) /* closing a partially built state? */
- luaC_freeallobjects(L); /* just collect its objects */
- else { /* closing a fully built state */
- L->ci = &L->base_ci; /* unwind CallInfo list */
- luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
- luaC_freeallobjects(L); /* collect all objects */
- luai_userstateclose(L);
- }
- luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
- freestack(L);
- lua_assert(gettotalbytes(g) == sizeof(LG));
- (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
-}
-
-
-LUA_API lua_State *lua_newthread (lua_State *L) {
- global_State *g;
- lua_State *L1;
- lua_lock(L);
- g = G(L);
- luaC_checkGC(L);
- /* create new thread */
- L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
- L1->marked = luaC_white(g);
- L1->tt = LUA_VTHREAD;
- /* link it on list 'allgc' */
- L1->next = g->allgc;
- g->allgc = obj2gco(L1);
- /* anchor it on L stack */
- setthvalue2s(L, L->top, L1);
- api_incr_top(L);
- preinit_thread(L1, g);
- L1->hookmask = L->hookmask;
- L1->basehookcount = L->basehookcount;
- L1->hook = L->hook;
- resethookcount(L1);
- /* initialize L1 extra space */
- memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
- LUA_EXTRASPACE);
- luai_userstatethread(L, L1);
- stack_init(L1, L); /* init stack */
- lua_unlock(L);
- return L1;
-}
-
-
-void luaE_freethread (lua_State *L, lua_State *L1) {
- LX *l = fromstate(L1);
- luaF_closeupval(L1, L1->stack); /* close all upvalues */
- lua_assert(L1->openupval == NULL);
- luai_userstatefree(L, L1);
- freestack(L1);
- luaM_free(L, l);
-}
-
-
-int luaE_resetthread (lua_State *L, int status) {
- CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */
- setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */
- ci->func = L->stack;
- ci->callstatus = CIST_C;
- if (status == LUA_YIELD)
- status = LUA_OK;
- L->status = LUA_OK; /* so it can run __close metamethods */
- status = luaD_closeprotected(L, 1, status);
- if (status != LUA_OK) /* errors? */
- luaD_seterrorobj(L, status, L->stack + 1);
- else
- L->top = L->stack + 1;
- ci->top = L->top + LUA_MINSTACK;
- luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
- return status;
-}
-
-
-LUA_API int lua_resetthread (lua_State *L) {
- int status;
- lua_lock(L);
- status = luaE_resetthread(L, L->status);
- lua_unlock(L);
- return status;
-}
-
-
-LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
- int i;
- lua_State *L;
- global_State *g;
- LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
- if (l == NULL) return NULL;
- L = &l->l.l;
- g = &l->g;
- L->tt = LUA_VTHREAD;
- g->currentwhite = bitmask(WHITE0BIT);
- L->marked = luaC_white(g);
- preinit_thread(L, g);
- g->allgc = obj2gco(L); /* by now, only object is the main thread */
- L->next = NULL;
- incnny(L); /* main thread is always non yieldable */
- g->frealloc = f;
- g->ud = ud;
- g->warnf = NULL;
- g->ud_warn = NULL;
- g->mainthread = L;
- g->seed = luai_makeseed(L);
- g->gcstp = GCSTPGC; /* no GC while building state */
- g->strt.size = g->strt.nuse = 0;
- g->strt.hash = NULL;
- setnilvalue(&g->l_registry);
- g->panic = NULL;
- g->gcstate = GCSpause;
- g->gckind = KGC_INC;
- g->gcstopem = 0;
- g->gcemergency = 0;
- g->finobj = g->tobefnz = g->fixedgc = NULL;
- g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
- g->finobjsur = g->finobjold1 = g->finobjrold = NULL;
- g->sweepgc = NULL;
- g->gray = g->grayagain = NULL;
- g->weak = g->ephemeron = g->allweak = NULL;
- g->twups = NULL;
- g->totalbytes = sizeof(LG);
- g->GCdebt = 0;
- g->lastatomic = 0;
- setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
- setgcparam(g->gcpause, LUAI_GCPAUSE);
- setgcparam(g->gcstepmul, LUAI_GCMUL);
- g->gcstepsize = LUAI_GCSTEPSIZE;
- setgcparam(g->genmajormul, LUAI_GENMAJORMUL);
- g->genminormul = LUAI_GENMINORMUL;
- for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
- if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
- /* memory allocation error: free partial state */
- close_state(L);
- L = NULL;
- }
- return L;
-}
-
-
-LUA_API void lua_close (lua_State *L) {
- lua_lock(L);
- L = G(L)->mainthread; /* only the main thread can be closed */
- close_state(L);
-}
-
-
-void luaE_warning (lua_State *L, const char *msg, int tocont) {
- lua_WarnFunction wf = G(L)->warnf;
- if (wf != NULL)
- wf(G(L)->ud_warn, msg, tocont);
-}
-
-
-/*
-** Generate a warning from an error message
-*/
-void luaE_warnerror (lua_State *L, const char *where) {
- TValue *errobj = s2v(L->top - 1); /* error object */
- const char *msg = (ttisstring(errobj))
- ? svalue(errobj)
- : "error object is not a string";
- /* produce warning "error in %s (%s)" (where, msg) */
- luaE_warning(L, "error in ", 1);
- luaE_warning(L, where, 1);
- luaE_warning(L, " (", 1);
- luaE_warning(L, msg, 1);
- luaE_warning(L, ")", 0);
-}
-
diff --git a/lua-5.4.4/library/lstate.h b/lua-5.4.4/library/lstate.h
deleted file mode 100644
index 61e82cde..00000000
--- a/lua-5.4.4/library/lstate.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
-** $Id: lstate.h $
-** Global State
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lstate_h
-#define lstate_h
-
-#include "lua.h"
-
-#include "lobject.h"
-#include "ltm.h"
-#include "lzio.h"
-
-
-/*
-** Some notes about garbage-collected objects: All objects in Lua must
-** be kept somehow accessible until being freed, so all objects always
-** belong to one (and only one) of these lists, using field 'next' of
-** the 'CommonHeader' for the link:
-**
-** 'allgc': all objects not marked for finalization;
-** 'finobj': all objects marked for finalization;
-** 'tobefnz': all objects ready to be finalized;
-** 'fixedgc': all objects that are not to be collected (currently
-** only small strings, such as reserved words).
-**
-** For the generational collector, some of these lists have marks for
-** generations. Each mark points to the first element in the list for
-** that particular generation; that generation goes until the next mark.
-**
-** 'allgc' -> 'survival': new objects;
-** 'survival' -> 'old': objects that survived one collection;
-** 'old1' -> 'reallyold': objects that became old in last collection;
-** 'reallyold' -> NULL: objects old for more than one cycle.
-**
-** 'finobj' -> 'finobjsur': new objects marked for finalization;
-** 'finobjsur' -> 'finobjold1': survived """";
-** 'finobjold1' -> 'finobjrold': just old """";
-** 'finobjrold' -> NULL: really old """".
-**
-** All lists can contain elements older than their main ages, due
-** to 'luaC_checkfinalizer' and 'udata2finalize', which move
-** objects between the normal lists and the "marked for finalization"
-** lists. Moreover, barriers can age young objects in young lists as
-** OLD0, which then become OLD1. However, a list never contains
-** elements younger than their main ages.
-**
-** The generational collector also uses a pointer 'firstold1', which
-** points to the first OLD1 object in the list. It is used to optimize
-** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc'
-** and 'reallyold', but often the list has no OLD1 objects or they are
-** after 'old1'.) Note the difference between it and 'old1':
-** 'firstold1': no OLD1 objects before this point; there can be all
-** ages after it.
-** 'old1': no objects younger than OLD1 after this point.
-*/
-
-/*
-** Moreover, there is another set of lists that control gray objects.
-** These lists are linked by fields 'gclist'. (All objects that
-** can become gray have such a field. The field is not the same
-** in all objects, but it always has this name.) Any gray object
-** must belong to one of these lists, and all objects in these lists
-** must be gray (with two exceptions explained below):
-**
-** 'gray': regular gray objects, still waiting to be visited.
-** 'grayagain': objects that must be revisited at the atomic phase.
-** That includes
-** - black objects got in a write barrier;
-** - all kinds of weak tables during propagation phase;
-** - all threads.
-** 'weak': tables with weak values to be cleared;
-** 'ephemeron': ephemeron tables with white->white entries;
-** 'allweak': tables with weak keys and/or weak values to be cleared.
-**
-** The exceptions to that "gray rule" are:
-** - TOUCHED2 objects in generational mode stay in a gray list (because
-** they must be visited again at the end of the cycle), but they are
-** marked black because assignments to them must activate barriers (to
-** move them back to TOUCHED1).
-** - Open upvales are kept gray to avoid barriers, but they stay out
-** of gray lists. (They don't even have a 'gclist' field.)
-*/
-
-
-
-/*
-** About 'nCcalls': This count has two parts: the lower 16 bits counts
-** the number of recursive invocations in the C stack; the higher
-** 16 bits counts the number of non-yieldable calls in the stack.
-** (They are together so that we can change and save both with one
-** instruction.)
-*/
-
-
-/* true if this thread does not have non-yieldable calls in the stack */
-#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
-
-/* real number of C calls */
-#define getCcalls(L) ((L)->nCcalls & 0xffff)
-
-
-/* Increment the number of non-yieldable calls */
-#define incnny(L) ((L)->nCcalls += 0x10000)
-
-/* Decrement the number of non-yieldable calls */
-#define decnny(L) ((L)->nCcalls -= 0x10000)
-
-/* Non-yieldable call increment */
-#define nyci (0x10000 | 1)
-
-
-
-
-struct lua_longjmp; /* defined in ldo.c */
-
-
-/*
-** Atomic type (relative to signals) to better ensure that 'lua_sethook'
-** is thread safe
-*/
-#if !defined(l_signalT)
-#include
-#define l_signalT sig_atomic_t
-#endif
-
-
-/*
-** Extra stack space to handle TM calls and some other extras. This
-** space is not included in 'stack_last'. It is used only to avoid stack
-** checks, either because the element will be promptly popped or because
-** there will be a stack check soon after the push. Function frames
-** never use this extra space, so it does not need to be kept clean.
-*/
-#define EXTRA_STACK 5
-
-
-#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
-
-#define stacksize(th) cast_int((th)->stack_last - (th)->stack)
-
-
-/* kinds of Garbage Collection */
-#define KGC_INC 0 /* incremental gc */
-#define KGC_GEN 1 /* generational gc */
-
-
-typedef struct stringtable {
- TString **hash;
- int nuse; /* number of elements */
- int size;
-} stringtable;
-
-
-/*
-** Information about a call.
-** About union 'u':
-** - field 'l' is used only for Lua functions;
-** - field 'c' is used only for C functions.
-** About union 'u2':
-** - field 'funcidx' is used only by C functions while doing a
-** protected call;
-** - field 'nyield' is used only while a function is "doing" an
-** yield (from the yield until the next resume);
-** - field 'nres' is used only while closing tbc variables when
-** returning from a function;
-** - field 'transferinfo' is used only during call/returnhooks,
-** before the function starts or after it ends.
-*/
-typedef struct CallInfo {
- StkId func; /* function index in the stack */
- StkId top; /* top for this function */
- struct CallInfo *previous, *next; /* dynamic call link */
- union {
- struct { /* only for Lua functions */
- const Instruction *savedpc;
- volatile l_signalT trap;
- int nextraargs; /* # of extra arguments in vararg functions */
- } l;
- struct { /* only for C functions */
- lua_KFunction k; /* continuation in case of yields */
- ptrdiff_t old_errfunc;
- lua_KContext ctx; /* context info. in case of yields */
- } c;
- } u;
- union {
- int funcidx; /* called-function index */
- int nyield; /* number of values yielded */
- int nres; /* number of values returned */
- struct { /* info about transferred values (for call/return hooks) */
- unsigned short ftransfer; /* offset of first value transferred */
- unsigned short ntransfer; /* number of values transferred */
- } transferinfo;
- } u2;
- short nresults; /* expected number of results from this function */
- unsigned short callstatus;
-} CallInfo;
-
-
-/*
-** Bits in CallInfo status
-*/
-#define CIST_OAH (1<<0) /* original value of 'allowhook' */
-#define CIST_C (1<<1) /* call is running a C function */
-#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
-#define CIST_HOOKED (1<<3) /* call is running a debug hook */
-#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
-#define CIST_TAIL (1<<5) /* call was tail called */
-#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
-#define CIST_FIN (1<<7) /* function "called" a finalizer */
-#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
-#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
-/* Bits 10-12 are used for CIST_RECST (see below) */
-#define CIST_RECST 10
-#if defined(LUA_COMPAT_LT_LE)
-#define CIST_LEQ (1<<13) /* using __lt for __le */
-#endif
-
-
-/*
-** Field CIST_RECST stores the "recover status", used to keep the error
-** status while closing to-be-closed variables in coroutines, so that
-** Lua can correctly resume after an yield from a __close method called
-** because of an error. (Three bits are enough for error status.)
-*/
-#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7)
-#define setcistrecst(ci,st) \
- check_exp(((st) & 7) == (st), /* status must fit in three bits */ \
- ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \
- | ((st) << CIST_RECST)))
-
-
-/* active function is a Lua function */
-#define isLua(ci) (!((ci)->callstatus & CIST_C))
-
-/* call is running Lua code (not a hook) */
-#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED)))
-
-/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
-#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v))
-#define getoah(st) ((st) & CIST_OAH)
-
-
-/*
-** 'global state', shared by all threads of this state
-*/
-typedef struct global_State {
- lua_Alloc frealloc; /* function to reallocate memory */
- void *ud; /* auxiliary data to 'frealloc' */
- l_mem totalbytes; /* number of bytes currently allocated - GCdebt */
- l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
- lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
- lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */
- stringtable strt; /* hash table for strings */
- TValue l_registry;
- TValue nilvalue; /* a nil value */
- unsigned int seed; /* randomized seed for hashes */
- lu_byte currentwhite;
- lu_byte gcstate; /* state of garbage collector */
- lu_byte gckind; /* kind of GC running */
- lu_byte gcstopem; /* stops emergency collections */
- lu_byte genminormul; /* control for minor generational collections */
- lu_byte genmajormul; /* control for major generational collections */
- lu_byte gcstp; /* control whether GC is running */
- lu_byte gcemergency; /* true if this is an emergency collection */
- lu_byte gcpause; /* size of pause between successive GCs */
- lu_byte gcstepmul; /* GC "speed" */
- lu_byte gcstepsize; /* (log2 of) GC granularity */
- GCObject *allgc; /* list of all collectable objects */
- GCObject **sweepgc; /* current position of sweep in list */
- GCObject *finobj; /* list of collectable objects with finalizers */
- GCObject *gray; /* list of gray objects */
- GCObject *grayagain; /* list of objects to be traversed atomically */
- GCObject *weak; /* list of tables with weak values */
- GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
- GCObject *allweak; /* list of all-weak tables */
- GCObject *tobefnz; /* list of userdata to be GC */
- GCObject *fixedgc; /* list of objects not to be collected */
- /* fields for generational collector */
- GCObject *survival; /* start of objects that survived one GC cycle */
- GCObject *old1; /* start of old1 objects */
- GCObject *reallyold; /* objects more than one cycle old ("really old") */
- GCObject *firstold1; /* first OLD1 object in the list (if any) */
- GCObject *finobjsur; /* list of survival objects with finalizers */
- GCObject *finobjold1; /* list of old1 objects with finalizers */
- GCObject *finobjrold; /* list of really old objects with finalizers */
- struct lua_State *twups; /* list of threads with open upvalues */
- lua_CFunction panic; /* to be called in unprotected errors */
- struct lua_State *mainthread;
- TString *memerrmsg; /* message for memory-allocation errors */
- TString *tmname[TM_N]; /* array with tag-method names */
- struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
- TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
- lua_WarnFunction warnf; /* warning function */
- void *ud_warn; /* auxiliary data to 'warnf' */
-} global_State;
-
-
-/*
-** 'per thread' state
-*/
-struct lua_State {
- CommonHeader;
- lu_byte status;
- lu_byte allowhook;
- unsigned short nci; /* number of items in 'ci' list */
- StkId top; /* first free slot in the stack */
- global_State *l_G;
- CallInfo *ci; /* call info for current function */
- StkId stack_last; /* end of stack (last element + 1) */
- StkId stack; /* stack base */
- UpVal *openupval; /* list of open upvalues in this stack */
- StkId tbclist; /* list of to-be-closed variables */
- GCObject *gclist;
- struct lua_State *twups; /* list of threads with open upvalues */
- struct lua_longjmp *errorJmp; /* current error recover point */
- CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
- volatile lua_Hook hook;
- ptrdiff_t errfunc; /* current error handling function (stack index) */
- l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */
- int oldpc; /* last pc traced */
- int basehookcount;
- int hookcount;
- volatile l_signalT hookmask;
-};
-
-
-#define G(L) (L->l_G)
-
-/*
-** 'g->nilvalue' being a nil value flags that the state was completely
-** build.
-*/
-#define completestate(g) ttisnil(&g->nilvalue)
-
-
-/*
-** Union of all collectable objects (only for conversions)
-** ISO C99, 6.5.2.3 p.5:
-** "if a union contains several structures that share a common initial
-** sequence [...], and if the union object currently contains one
-** of these structures, it is permitted to inspect the common initial
-** part of any of them anywhere that a declaration of the complete type
-** of the union is visible."
-*/
-union GCUnion {
- GCObject gc; /* common header */
- struct TString ts;
- struct Udata u;
- union Closure cl;
- struct Table h;
- struct Proto p;
- struct lua_State th; /* thread */
- struct UpVal upv;
-};
-
-
-/*
-** ISO C99, 6.7.2.1 p.14:
-** "A pointer to a union object, suitably converted, points to each of
-** its members [...], and vice versa."
-*/
-#define cast_u(o) cast(union GCUnion *, (o))
-
-/* macros to convert a GCObject into a specific value */
-#define gco2ts(o) \
- check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
-#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u))
-#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l))
-#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c))
-#define gco2cl(o) \
- check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
-#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
-#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
-#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
-#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
-
-
-/*
-** macro to convert a Lua object into a GCObject
-** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.)
-*/
-#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc))
-
-
-/* actual number of total bytes allocated */
-#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt)
-
-LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
-LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
-LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
-LUAI_FUNC void luaE_freeCI (lua_State *L);
-LUAI_FUNC void luaE_shrinkCI (lua_State *L);
-LUAI_FUNC void luaE_checkcstack (lua_State *L);
-LUAI_FUNC void luaE_incCstack (lua_State *L);
-LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
-LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
-LUAI_FUNC int luaE_resetthread (lua_State *L, int status);
-
-
-#endif
-
diff --git a/lua-5.4.4/library/lstring.c b/lua-5.4.4/library/lstring.c
deleted file mode 100644
index 13dcaf42..00000000
--- a/lua-5.4.4/library/lstring.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
-** $Id: lstring.c $
-** String table (keeps all strings handled by Lua)
-** See Copyright Notice in lua.h
-*/
-
-#define lstring_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-
-#include "lua.h"
-
-#include "ldebug.h"
-#include "ldo.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lstate.h"
-#include "lstring.h"
-
-
-/*
-** Maximum size for string table.
-*/
-#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*))
-
-
-/*
-** equality for long strings
-*/
-int luaS_eqlngstr (TString *a, TString *b) {
- size_t len = a->u.lnglen;
- lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
- return (a == b) || /* same instance or... */
- ((len == b->u.lnglen) && /* equal length and ... */
- (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
-}
-
-
-unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
- unsigned int h = seed ^ cast_uint(l);
- for (; l > 0; l--)
- h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
- return h;
-}
-
-
-unsigned int luaS_hashlongstr (TString *ts) {
- lua_assert(ts->tt == LUA_VLNGSTR);
- if (ts->extra == 0) { /* no hash? */
- size_t len = ts->u.lnglen;
- ts->hash = luaS_hash(getstr(ts), len, ts->hash);
- ts->extra = 1; /* now it has its hash */
- }
- return ts->hash;
-}
-
-
-static void tablerehash (TString **vect, int osize, int nsize) {
- int i;
- for (i = osize; i < nsize; i++) /* clear new elements */
- vect[i] = NULL;
- for (i = 0; i < osize; i++) { /* rehash old part of the array */
- TString *p = vect[i];
- vect[i] = NULL;
- while (p) { /* for each string in the list */
- TString *hnext = p->u.hnext; /* save next */
- unsigned int h = lmod(p->hash, nsize); /* new position */
- p->u.hnext = vect[h]; /* chain it into array */
- vect[h] = p;
- p = hnext;
- }
- }
-}
-
-
-/*
-** Resize the string table. If allocation fails, keep the current size.
-** (This can degrade performance, but any non-zero size should work
-** correctly.)
-*/
-void luaS_resize (lua_State *L, int nsize) {
- stringtable *tb = &G(L)->strt;
- int osize = tb->size;
- TString **newvect;
- if (nsize < osize) /* shrinking table? */
- tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */
- newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
- if (l_unlikely(newvect == NULL)) { /* reallocation failed? */
- if (nsize < osize) /* was it shrinking table? */
- tablerehash(tb->hash, nsize, osize); /* restore to original size */
- /* leave table as it was */
- }
- else { /* allocation succeeded */
- tb->hash = newvect;
- tb->size = nsize;
- if (nsize > osize)
- tablerehash(newvect, osize, nsize); /* rehash for new size */
- }
-}
-
-
-/*
-** Clear API string cache. (Entries cannot be empty, so fill them with
-** a non-collectable string.)
-*/
-void luaS_clearcache (global_State *g) {
- int i, j;
- for (i = 0; i < STRCACHE_N; i++)
- for (j = 0; j < STRCACHE_M; j++) {
- if (iswhite(g->strcache[i][j])) /* will entry be collected? */
- g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */
- }
-}
-
-
-/*
-** Initialize the string table and the string cache
-*/
-void luaS_init (lua_State *L) {
- global_State *g = G(L);
- int i, j;
- stringtable *tb = &G(L)->strt;
- tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
- tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */
- tb->size = MINSTRTABSIZE;
- /* pre-create memory-error message */
- g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
- luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
- for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */
- for (j = 0; j < STRCACHE_M; j++)
- g->strcache[i][j] = g->memerrmsg;
-}
-
-
-
-/*
-** creates a new string object
-*/
-static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
- TString *ts;
- GCObject *o;
- size_t totalsize; /* total size of TString object */
- totalsize = sizelstring(l);
- o = luaC_newobj(L, tag, totalsize);
- ts = gco2ts(o);
- ts->hash = h;
- ts->extra = 0;
- getstr(ts)[l] = '\0'; /* ending 0 */
- return ts;
-}
-
-
-TString *luaS_createlngstrobj (lua_State *L, size_t l) {
- TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
- ts->u.lnglen = l;
- return ts;
-}
-
-
-void luaS_remove (lua_State *L, TString *ts) {
- stringtable *tb = &G(L)->strt;
- TString **p = &tb->hash[lmod(ts->hash, tb->size)];
- while (*p != ts) /* find previous element */
- p = &(*p)->u.hnext;
- *p = (*p)->u.hnext; /* remove element from its list */
- tb->nuse--;
-}
-
-
-static void growstrtab (lua_State *L, stringtable *tb) {
- if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */
- luaC_fullgc(L, 1); /* try to free some... */
- if (tb->nuse == MAX_INT) /* still too many? */
- luaM_error(L); /* cannot even create a message... */
- }
- if (tb->size <= MAXSTRTB / 2) /* can grow string table? */
- luaS_resize(L, tb->size * 2);
-}
-
-
-/*
-** Checks whether short string exists and reuses it or creates a new one.
-*/
-static TString *internshrstr (lua_State *L, const char *str, size_t l) {
- TString *ts;
- global_State *g = G(L);
- stringtable *tb = &g->strt;
- unsigned int h = luaS_hash(str, l, g->seed);
- TString **list = &tb->hash[lmod(h, tb->size)];
- lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
- for (ts = *list; ts != NULL; ts = ts->u.hnext) {
- if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
- /* found! */
- if (isdead(g, ts)) /* dead (but not collected yet)? */
- changewhite(ts); /* resurrect it */
- return ts;
- }
- }
- /* else must create a new string */
- if (tb->nuse >= tb->size) { /* need to grow string table? */
- growstrtab(L, tb);
- list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
- }
- ts = createstrobj(L, l, LUA_VSHRSTR, h);
- memcpy(getstr(ts), str, l * sizeof(char));
- ts->shrlen = cast_byte(l);
- ts->u.hnext = *list;
- *list = ts;
- tb->nuse++;
- return ts;
-}
-
-
-/*
-** new string (with explicit length)
-*/
-TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
- if (l <= LUAI_MAXSHORTLEN) /* short string? */
- return internshrstr(L, str, l);
- else {
- TString *ts;
- if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
- luaM_toobig(L);
- ts = luaS_createlngstrobj(L, l);
- memcpy(getstr(ts), str, l * sizeof(char));
- return ts;
- }
-}
-
-
-/*
-** Create or reuse a zero-terminated string, first checking in the
-** cache (using the string address as a key). The cache can contain
-** only zero-terminated strings, so it is safe to use 'strcmp' to
-** check hits.
-*/
-TString *luaS_new (lua_State *L, const char *str) {
- unsigned int i = point2uint(str) % STRCACHE_N; /* hash */
- int j;
- TString **p = G(L)->strcache[i];
- for (j = 0; j < STRCACHE_M; j++) {
- if (strcmp(str, getstr(p[j])) == 0) /* hit? */
- return p[j]; /* that is it */
- }
- /* normal route */
- for (j = STRCACHE_M - 1; j > 0; j--)
- p[j] = p[j - 1]; /* move out last element */
- /* new element is first in the list */
- p[0] = luaS_newlstr(L, str, strlen(str));
- return p[0];
-}
-
-
-Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
- Udata *u;
- int i;
- GCObject *o;
- if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
- luaM_toobig(L);
- o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
- u = gco2u(o);
- u->len = s;
- u->nuvalue = nuvalue;
- u->metatable = NULL;
- for (i = 0; i < nuvalue; i++)
- setnilvalue(&u->uv[i].uv);
- return u;
-}
-
diff --git a/lua-5.4.4/library/lstring.h b/lua-5.4.4/library/lstring.h
deleted file mode 100644
index 450c2390..00000000
--- a/lua-5.4.4/library/lstring.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** $Id: lstring.h $
-** String table (keep all strings handled by Lua)
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lstring_h
-#define lstring_h
-
-#include "lgc.h"
-#include "lobject.h"
-#include "lstate.h"
-
-
-/*
-** Memory-allocation error message must be preallocated (it cannot
-** be created after memory is exhausted)
-*/
-#define MEMERRMSG "not enough memory"
-
-
-/*
-** Size of a TString: Size of the header plus space for the string
-** itself (including final '\0').
-*/
-#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
-
-#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
- (sizeof(s)/sizeof(char))-1))
-
-
-/*
-** test whether a string is a reserved word
-*/
-#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0)
-
-
-/*
-** equality for short strings, which are always internalized
-*/
-#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
-
-
-LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
-LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
-LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
-LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
-LUAI_FUNC void luaS_clearcache (global_State *g);
-LUAI_FUNC void luaS_init (lua_State *L);
-LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
-LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue);
-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
-LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
-LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
-
-
-#endif
diff --git a/lua-5.4.4/library/lstrlib.c b/lua-5.4.4/library/lstrlib.c
deleted file mode 100644
index 0b4fdbb7..00000000
--- a/lua-5.4.4/library/lstrlib.c
+++ /dev/null
@@ -1,1874 +0,0 @@
-/*
-** $Id: lstrlib.c $
-** Standard library for string operations and pattern-matching
-** See Copyright Notice in lua.h
-*/
-
-#define lstrlib_c
-#define LUA_LIB
-
-#include "lprefix.h"
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "lua.h"
-
-#include "lauxlib.h"
-#include "lualib.h"
-
-
-/*
-** maximum number of captures that a pattern can do during
-** pattern-matching. This limit is arbitrary, but must fit in
-** an unsigned char.
-*/
-#if !defined(LUA_MAXCAPTURES)
-#define LUA_MAXCAPTURES 32
-#endif
-
-
-/* macro to 'unsign' a character */
-#define uchar(c) ((unsigned char)(c))
-
-
-/*
-** Some sizes are better limited to fit in 'int', but must also fit in
-** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
-*/
-#define MAX_SIZET ((size_t)(~(size_t)0))
-
-#define MAXSIZE \
- (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
-
-
-
-
-static int str_len (lua_State *L) {
- size_t l;
- luaL_checklstring(L, 1, &l);
- lua_pushinteger(L, (lua_Integer)l);
- return 1;
-}
-
-
-/*
-** translate a relative initial string position
-** (negative means back from end): clip result to [1, inf).
-** The length of any string in Lua must fit in a lua_Integer,
-** so there are no overflows in the casts.
-** The inverted comparison avoids a possible overflow
-** computing '-pos'.
-*/
-static size_t posrelatI (lua_Integer pos, size_t len) {
- if (pos > 0)
- return (size_t)pos;
- else if (pos == 0)
- return 1;
- else if (pos < -(lua_Integer)len) /* inverted comparison */
- return 1; /* clip to 1 */
- else return len + (size_t)pos + 1;
-}
-
-
-/*
-** Gets an optional ending string position from argument 'arg',
-** with default value 'def'.
-** Negative means back from end: clip result to [0, len]
-*/
-static size_t getendpos (lua_State *L, int arg, lua_Integer def,
- size_t len) {
- lua_Integer pos = luaL_optinteger(L, arg, def);
- if (pos > (lua_Integer)len)
- return len;
- else if (pos >= 0)
- return (size_t)pos;
- else if (pos < -(lua_Integer)len)
- return 0;
- else return len + (size_t)pos + 1;
-}
-
-
-static int str_sub (lua_State *L) {
- size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- size_t start = posrelatI(luaL_checkinteger(L, 2), l);
- size_t end = getendpos(L, 3, -1, l);
- if (start <= end)
- lua_pushlstring(L, s + start - 1, (end - start) + 1);
- else lua_pushliteral(L, "");
- return 1;
-}
-
-
-static int str_reverse (lua_State *L) {
- size_t l, i;
- luaL_Buffer b;
- const char *s = luaL_checklstring(L, 1, &l);
- char *p = luaL_buffinitsize(L, &b, l);
- for (i = 0; i < l; i++)
- p[i] = s[l - i - 1];
- luaL_pushresultsize(&b, l);
- return 1;
-}
-
-
-static int str_lower (lua_State *L) {
- size_t l;
- size_t i;
- luaL_Buffer b;
- const char *s = luaL_checklstring(L, 1, &l);
- char *p = luaL_buffinitsize(L, &b, l);
- for (i=0; i MAXSIZE / n))
- return luaL_error(L, "resulting string too large");
- else {
- size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
- luaL_Buffer b;
- char *p = luaL_buffinitsize(L, &b, totallen);
- while (n-- > 1) { /* first n-1 copies (followed by separator) */
- memcpy(p, s, l * sizeof(char)); p += l;
- if (lsep > 0) { /* empty 'memcpy' is not that cheap */
- memcpy(p, sep, lsep * sizeof(char));
- p += lsep;
- }
- }
- memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
- luaL_pushresultsize(&b, totallen);
- }
- return 1;
-}
-
-
-static int str_byte (lua_State *L) {
- size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- lua_Integer pi = luaL_optinteger(L, 2, 1);
- size_t posi = posrelatI(pi, l);
- size_t pose = getendpos(L, 3, pi, l);
- int n, i;
- if (posi > pose) return 0; /* empty interval; return no values */
- if (l_unlikely(pose - posi >= (size_t)INT_MAX)) /* arithmetic overflow? */
- return luaL_error(L, "string slice too long");
- n = (int)(pose - posi) + 1;
- luaL_checkstack(L, n, "string slice too long");
- for (i=0; iinit) {
- state->init = 1;
- luaL_buffinit(L, &state->B);
- }
- luaL_addlstring(&state->B, (const char *)b, size);
- return 0;
-}
-
-
-static int str_dump (lua_State *L) {
- struct str_Writer state;
- int strip = lua_toboolean(L, 2);
- luaL_checktype(L, 1, LUA_TFUNCTION);
- lua_settop(L, 1); /* ensure function is on the top of the stack */
- state.init = 0;
- if (l_unlikely(lua_dump(L, writer, &state, strip) != 0))
- return luaL_error(L, "unable to dump given function");
- luaL_pushresult(&state.B);
- return 1;
-}
-
-
-
-/*
-** {======================================================
-** METAMETHODS
-** =======================================================
-*/
-
-#if defined(LUA_NOCVTS2N) /* { */
-
-/* no coercion from strings to numbers */
-
-static const luaL_Reg stringmetamethods[] = {
- {"__index", NULL}, /* placeholder */
- {NULL, NULL}
-};
-
-#else /* }{ */
-
-static int tonum (lua_State *L, int arg) {
- if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */
- lua_pushvalue(L, arg);
- return 1;
- }
- else { /* check whether it is a numerical string */
- size_t len;
- const char *s = lua_tolstring(L, arg, &len);
- return (s != NULL && lua_stringtonumber(L, s) == len + 1);
- }
-}
-
-
-static void trymt (lua_State *L, const char *mtname) {
- lua_settop(L, 2); /* back to the original arguments */
- if (l_unlikely(lua_type(L, 2) == LUA_TSTRING ||
- !luaL_getmetafield(L, 2, mtname)))
- luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
- luaL_typename(L, -2), luaL_typename(L, -1));
- lua_insert(L, -3); /* put metamethod before arguments */
- lua_call(L, 2, 1); /* call metamethod */
-}
-
-
-static int arith (lua_State *L, int op, const char *mtname) {
- if (tonum(L, 1) && tonum(L, 2))
- lua_arith(L, op); /* result will be on the top */
- else
- trymt(L, mtname);
- return 1;
-}
-
-
-static int arith_add (lua_State *L) {
- return arith(L, LUA_OPADD, "__add");
-}
-
-static int arith_sub (lua_State *L) {
- return arith(L, LUA_OPSUB, "__sub");
-}
-
-static int arith_mul (lua_State *L) {
- return arith(L, LUA_OPMUL, "__mul");
-}
-
-static int arith_mod (lua_State *L) {
- return arith(L, LUA_OPMOD, "__mod");
-}
-
-static int arith_pow (lua_State *L) {
- return arith(L, LUA_OPPOW, "__pow");
-}
-
-static int arith_div (lua_State *L) {
- return arith(L, LUA_OPDIV, "__div");
-}
-
-static int arith_idiv (lua_State *L) {
- return arith(L, LUA_OPIDIV, "__idiv");
-}
-
-static int arith_unm (lua_State *L) {
- return arith(L, LUA_OPUNM, "__unm");
-}
-
-
-static const luaL_Reg stringmetamethods[] = {
- {"__add", arith_add},
- {"__sub", arith_sub},
- {"__mul", arith_mul},
- {"__mod", arith_mod},
- {"__pow", arith_pow},
- {"__div", arith_div},
- {"__idiv", arith_idiv},
- {"__unm", arith_unm},
- {"__index", NULL}, /* placeholder */
- {NULL, NULL}
-};
-
-#endif /* } */
-
-/* }====================================================== */
-
-/*
-** {======================================================
-** PATTERN MATCHING
-** =======================================================
-*/
-
-
-#define CAP_UNFINISHED (-1)
-#define CAP_POSITION (-2)
-
-
-typedef struct MatchState {
- const char *src_init; /* init of source string */
- const char *src_end; /* end ('\0') of source string */
- const char *p_end; /* end ('\0') of pattern */
- lua_State *L;
- int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
- unsigned char level; /* total number of captures (finished or unfinished) */
- struct {
- const char *init;
- ptrdiff_t len;
- } capture[LUA_MAXCAPTURES];
-} MatchState;
-
-
-/* recursive function */
-static const char *match (MatchState *ms, const char *s, const char *p);
-
-
-/* maximum recursion depth for 'match' */
-#if !defined(MAXCCALLS)
-#define MAXCCALLS 200
-#endif
-
-
-#define L_ESC '%'
-#define SPECIALS "^$*+?.([%-"
-
-
-static int check_capture (MatchState *ms, int l) {
- l -= '1';
- if (l_unlikely(l < 0 || l >= ms->level ||
- ms->capture[l].len == CAP_UNFINISHED))
- return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
- return l;
-}
-
-
-static int capture_to_close (MatchState *ms) {
- int level = ms->level;
- for (level--; level>=0; level--)
- if (ms->capture[level].len == CAP_UNFINISHED) return level;
- return luaL_error(ms->L, "invalid pattern capture");
-}
-
-
-static const char *classend (MatchState *ms, const char *p) {
- switch (*p++) {
- case L_ESC: {
- if (l_unlikely(p == ms->p_end))
- luaL_error(ms->L, "malformed pattern (ends with '%%')");
- return p+1;
- }
- case '[': {
- if (*p == '^') p++;
- do { /* look for a ']' */
- if (l_unlikely(p == ms->p_end))
- luaL_error(ms->L, "malformed pattern (missing ']')");
- if (*(p++) == L_ESC && p < ms->p_end)
- p++; /* skip escapes (e.g. '%]') */
- } while (*p != ']');
- return p+1;
- }
- default: {
- return p;
- }
- }
-}
-
-
-static int match_class (int c, int cl) {
- int res;
- switch (tolower(cl)) {
- case 'a' : res = isalpha(c); break;
- case 'c' : res = iscntrl(c); break;
- case 'd' : res = isdigit(c); break;
- case 'g' : res = isgraph(c); break;
- case 'l' : res = islower(c); break;
- case 'p' : res = ispunct(c); break;
- case 's' : res = isspace(c); break;
- case 'u' : res = isupper(c); break;
- case 'w' : res = isalnum(c); break;
- case 'x' : res = isxdigit(c); break;
- case 'z' : res = (c == 0); break; /* deprecated option */
- default: return (cl == c);
- }
- return (islower(cl) ? res : !res);
-}
-
-
-static int matchbracketclass (int c, const char *p, const char *ec) {
- int sig = 1;
- if (*(p+1) == '^') {
- sig = 0;
- p++; /* skip the '^' */
- }
- while (++p < ec) {
- if (*p == L_ESC) {
- p++;
- if (match_class(c, uchar(*p)))
- return sig;
- }
- else if ((*(p+1) == '-') && (p+2 < ec)) {
- p+=2;
- if (uchar(*(p-2)) <= c && c <= uchar(*p))
- return sig;
- }
- else if (uchar(*p) == c) return sig;
- }
- return !sig;
-}
-
-
-static int singlematch (MatchState *ms, const char *s, const char *p,
- const char *ep) {
- if (s >= ms->src_end)
- return 0;
- else {
- int c = uchar(*s);
- switch (*p) {
- case '.': return 1; /* matches any char */
- case L_ESC: return match_class(c, uchar(*(p+1)));
- case '[': return matchbracketclass(c, p, ep-1);
- default: return (uchar(*p) == c);
- }
- }
-}
-
-
-static const char *matchbalance (MatchState *ms, const char *s,
- const char *p) {
- if (l_unlikely(p >= ms->p_end - 1))
- luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
- if (*s != *p) return NULL;
- else {
- int b = *p;
- int e = *(p+1);
- int cont = 1;
- while (++s < ms->src_end) {
- if (*s == e) {
- if (--cont == 0) return s+1;
- }
- else if (*s == b) cont++;
- }
- }
- return NULL; /* string ends out of balance */
-}
-
-
-static const char *max_expand (MatchState *ms, const char *s,
- const char *p, const char *ep) {
- ptrdiff_t i = 0; /* counts maximum expand for item */
- while (singlematch(ms, s + i, p, ep))
- i++;
- /* keeps trying to match with the maximum repetitions */
- while (i>=0) {
- const char *res = match(ms, (s+i), ep+1);
- if (res) return res;
- i--; /* else didn't match; reduce 1 repetition to try again */
- }
- return NULL;
-}
-
-
-static const char *min_expand (MatchState *ms, const char *s,
- const char *p, const char *ep) {
- for (;;) {
- const char *res = match(ms, s, ep+1);
- if (res != NULL)
- return res;
- else if (singlematch(ms, s, p, ep))
- s++; /* try with one more repetition */
- else return NULL;
- }
-}
-
-
-static const char *start_capture (MatchState *ms, const char *s,
- const char *p, int what) {
- const char *res;
- int level = ms->level;
- if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
- ms->capture[level].init = s;
- ms->capture[level].len = what;
- ms->level = level+1;
- if ((res=match(ms, s, p)) == NULL) /* match failed? */
- ms->level--; /* undo capture */
- return res;
-}
-
-
-static const char *end_capture (MatchState *ms, const char *s,
- const char *p) {
- int l = capture_to_close(ms);
- const char *res;
- ms->capture[l].len = s - ms->capture[l].init; /* close capture */
- if ((res = match(ms, s, p)) == NULL) /* match failed? */
- ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
- return res;
-}
-
-
-static const char *match_capture (MatchState *ms, const char *s, int l) {
- size_t len;
- l = check_capture(ms, l);
- len = ms->capture[l].len;
- if ((size_t)(ms->src_end-s) >= len &&
- memcmp(ms->capture[l].init, s, len) == 0)
- return s+len;
- else return NULL;
-}
-
-
-static const char *match (MatchState *ms, const char *s, const char *p) {
- if (l_unlikely(ms->matchdepth-- == 0))
- luaL_error(ms->L, "pattern too complex");
- init: /* using goto's to optimize tail recursion */
- if (p != ms->p_end) { /* end of pattern? */
- switch (*p) {
- case '(': { /* start capture */
- if (*(p + 1) == ')') /* position capture? */
- s = start_capture(ms, s, p + 2, CAP_POSITION);
- else
- s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
- break;
- }
- case ')': { /* end capture */
- s = end_capture(ms, s, p + 1);
- break;
- }
- case '$': {
- if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */
- goto dflt; /* no; go to default */
- s = (s == ms->src_end) ? s : NULL; /* check end of string */
- break;
- }
- case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
- switch (*(p + 1)) {
- case 'b': { /* balanced string? */
- s = matchbalance(ms, s, p + 2);
- if (s != NULL) {
- p += 4; goto init; /* return match(ms, s, p + 4); */
- } /* else fail (s == NULL) */
- break;
- }
- case 'f': { /* frontier? */
- const char *ep; char previous;
- p += 2;
- if (l_unlikely(*p != '['))
- luaL_error(ms->L, "missing '[' after '%%f' in pattern");
- ep = classend(ms, p); /* points to what is next */
- previous = (s == ms->src_init) ? '\0' : *(s - 1);
- if (!matchbracketclass(uchar(previous), p, ep - 1) &&
- matchbracketclass(uchar(*s), p, ep - 1)) {
- p = ep; goto init; /* return match(ms, s, ep); */
- }
- s = NULL; /* match failed */
- break;
- }
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9': { /* capture results (%0-%9)? */
- s = match_capture(ms, s, uchar(*(p + 1)));
- if (s != NULL) {
- p += 2; goto init; /* return match(ms, s, p + 2) */
- }
- break;
- }
- default: goto dflt;
- }
- break;
- }
- default: dflt: { /* pattern class plus optional suffix */
- const char *ep = classend(ms, p); /* points to optional suffix */
- /* does not match at least once? */
- if (!singlematch(ms, s, p, ep)) {
- if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
- p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
- }
- else /* '+' or no suffix */
- s = NULL; /* fail */
- }
- else { /* matched once */
- switch (*ep) { /* handle optional suffix */
- case '?': { /* optional */
- const char *res;
- if ((res = match(ms, s + 1, ep + 1)) != NULL)
- s = res;
- else {
- p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
- }
- break;
- }
- case '+': /* 1 or more repetitions */
- s++; /* 1 match already done */
- /* FALLTHROUGH */
- case '*': /* 0 or more repetitions */
- s = max_expand(ms, s, p, ep);
- break;
- case '-': /* 0 or more repetitions (minimum) */
- s = min_expand(ms, s, p, ep);
- break;
- default: /* no suffix */
- s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
- }
- }
- break;
- }
- }
- }
- ms->matchdepth++;
- return s;
-}
-
-
-
-static const char *lmemfind (const char *s1, size_t l1,
- const char *s2, size_t l2) {
- if (l2 == 0) return s1; /* empty strings are everywhere */
- else if (l2 > l1) return NULL; /* avoids a negative 'l1' */
- else {
- const char *init; /* to search for a '*s2' inside 's1' */
- l2--; /* 1st char will be checked by 'memchr' */
- l1 = l1-l2; /* 's2' cannot be found after that */
- while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
- init++; /* 1st char is already checked */
- if (memcmp(init, s2+1, l2) == 0)
- return init-1;
- else { /* correct 'l1' and 's1' to try again */
- l1 -= init-s1;
- s1 = init;
- }
- }
- return NULL; /* not found */
- }
-}
-
-
-/*
-** get information about the i-th capture. If there are no captures
-** and 'i==0', return information about the whole match, which
-** is the range 's'..'e'. If the capture is a string, return
-** its length and put its address in '*cap'. If it is an integer
-** (a position), push it on the stack and return CAP_POSITION.
-*/
-static size_t get_onecapture (MatchState *ms, int i, const char *s,
- const char *e, const char **cap) {
- if (i >= ms->level) {
- if (l_unlikely(i != 0))
- luaL_error(ms->L, "invalid capture index %%%d", i + 1);
- *cap = s;
- return e - s;
- }
- else {
- ptrdiff_t capl = ms->capture[i].len;
- *cap = ms->capture[i].init;
- if (l_unlikely(capl == CAP_UNFINISHED))
- luaL_error(ms->L, "unfinished capture");
- else if (capl == CAP_POSITION)
- lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
- return capl;
- }
-}
-
-
-/*
-** Push the i-th capture on the stack.
-*/
-static void push_onecapture (MatchState *ms, int i, const char *s,
- const char *e) {
- const char *cap;
- ptrdiff_t l = get_onecapture(ms, i, s, e, &cap);
- if (l != CAP_POSITION)
- lua_pushlstring(ms->L, cap, l);
- /* else position was already pushed */
-}
-
-
-static int push_captures (MatchState *ms, const char *s, const char *e) {
- int i;
- int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
- luaL_checkstack(ms->L, nlevels, "too many captures");
- for (i = 0; i < nlevels; i++)
- push_onecapture(ms, i, s, e);
- return nlevels; /* number of strings pushed */
-}
-
-
-/* check whether pattern has no special characters */
-static int nospecials (const char *p, size_t l) {
- size_t upto = 0;
- do {
- if (strpbrk(p + upto, SPECIALS))
- return 0; /* pattern has a special character */
- upto += strlen(p + upto) + 1; /* may have more after \0 */
- } while (upto <= l);
- return 1; /* no special chars found */
-}
-
-
-static void prepstate (MatchState *ms, lua_State *L,
- const char *s, size_t ls, const char *p, size_t lp) {
- ms->L = L;
- ms->matchdepth = MAXCCALLS;
- ms->src_init = s;
- ms->src_end = s + ls;
- ms->p_end = p + lp;
-}
-
-
-static void reprepstate (MatchState *ms) {
- ms->level = 0;
- lua_assert(ms->matchdepth == MAXCCALLS);
-}
-
-
-static int str_find_aux (lua_State *L, int find) {
- size_t ls, lp;
- const char *s = luaL_checklstring(L, 1, &ls);
- const char *p = luaL_checklstring(L, 2, &lp);
- size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
- if (init > ls) { /* start after string's end? */
- luaL_pushfail(L); /* cannot find anything */
- return 1;
- }
- /* explicit request or no special characters? */
- if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
- /* do a plain search */
- const char *s2 = lmemfind(s + init, ls - init, p, lp);
- if (s2) {
- lua_pushinteger(L, (s2 - s) + 1);
- lua_pushinteger(L, (s2 - s) + lp);
- return 2;
- }
- }
- else {
- MatchState ms;
- const char *s1 = s + init;
- int anchor = (*p == '^');
- if (anchor) {
- p++; lp--; /* skip anchor character */
- }
- prepstate(&ms, L, s, ls, p, lp);
- do {
- const char *res;
- reprepstate(&ms);
- if ((res=match(&ms, s1, p)) != NULL) {
- if (find) {
- lua_pushinteger(L, (s1 - s) + 1); /* start */
- lua_pushinteger(L, res - s); /* end */
- return push_captures(&ms, NULL, 0) + 2;
- }
- else
- return push_captures(&ms, s1, res);
- }
- } while (s1++ < ms.src_end && !anchor);
- }
- luaL_pushfail(L); /* not found */
- return 1;
-}
-
-
-static int str_find (lua_State *L) {
- return str_find_aux(L, 1);
-}
-
-
-static int str_match (lua_State *L) {
- return str_find_aux(L, 0);
-}
-
-
-/* state for 'gmatch' */
-typedef struct GMatchState {
- const char *src; /* current position */
- const char *p; /* pattern */
- const char *lastmatch; /* end of last match */
- MatchState ms; /* match state */
-} GMatchState;
-
-
-static int gmatch_aux (lua_State *L) {
- GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
- const char *src;
- gm->ms.L = L;
- for (src = gm->src; src <= gm->ms.src_end; src++) {
- const char *e;
- reprepstate(&gm->ms);
- if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
- gm->src = gm->lastmatch = e;
- return push_captures(&gm->ms, src, e);
- }
- }
- return 0; /* not found */
-}
-
-
-static int gmatch (lua_State *L) {
- size_t ls, lp;
- const char *s = luaL_checklstring(L, 1, &ls);
- const char *p = luaL_checklstring(L, 2, &lp);
- size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
- GMatchState *gm;
- lua_settop(L, 2); /* keep strings on closure to avoid being collected */
- gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0);
- if (init > ls) /* start after string's end? */
- init = ls + 1; /* avoid overflows in 's + init' */
- prepstate(&gm->ms, L, s, ls, p, lp);
- gm->src = s + init; gm->p = p; gm->lastmatch = NULL;
- lua_pushcclosure(L, gmatch_aux, 3);
- return 1;
-}
-
-
-static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
- const char *e) {
- size_t l;
- lua_State *L = ms->L;
- const char *news = lua_tolstring(L, 3, &l);
- const char *p;
- while ((p = (char *)memchr(news, L_ESC, l)) != NULL) {
- luaL_addlstring(b, news, p - news);
- p++; /* skip ESC */
- if (*p == L_ESC) /* '%%' */
- luaL_addchar(b, *p);
- else if (*p == '0') /* '%0' */
- luaL_addlstring(b, s, e - s);
- else if (isdigit(uchar(*p))) { /* '%n' */
- const char *cap;
- ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap);
- if (resl == CAP_POSITION)
- luaL_addvalue(b); /* add position to accumulated result */
- else
- luaL_addlstring(b, cap, resl);
- }
- else
- luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
- l -= p + 1 - news;
- news = p + 1;
- }
- luaL_addlstring(b, news, l);
-}
-
-
-/*
-** Add the replacement value to the string buffer 'b'.
-** Return true if the original string was changed. (Function calls and
-** table indexing resulting in nil or false do not change the subject.)
-*/
-static int add_value (MatchState *ms, luaL_Buffer *b, const char *s,
- const char *e, int tr) {
- lua_State *L = ms->L;
- switch (tr) {
- case LUA_TFUNCTION: { /* call the function */
- int n;
- lua_pushvalue(L, 3); /* push the function */
- n = push_captures(ms, s, e); /* all captures as arguments */
- lua_call(L, n, 1); /* call it */
- break;
- }
- case LUA_TTABLE: { /* index the table */
- push_onecapture(ms, 0, s, e); /* first capture is the index */
- lua_gettable(L, 3);
- break;
- }
- default: { /* LUA_TNUMBER or LUA_TSTRING */
- add_s(ms, b, s, e); /* add value to the buffer */
- return 1; /* something changed */
- }
- }
- if (!lua_toboolean(L, -1)) { /* nil or false? */
- lua_pop(L, 1); /* remove value */
- luaL_addlstring(b, s, e - s); /* keep original text */
- return 0; /* no changes */
- }
- else if (l_unlikely(!lua_isstring(L, -1)))
- return luaL_error(L, "invalid replacement value (a %s)",
- luaL_typename(L, -1));
- else {
- luaL_addvalue(b); /* add result to accumulator */
- return 1; /* something changed */
- }
-}
-
-
-static int str_gsub (lua_State *L) {
- size_t srcl, lp;
- const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
- const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
- const char *lastmatch = NULL; /* end of last match */
- int tr = lua_type(L, 3); /* replacement type */
- lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
- int anchor = (*p == '^');
- lua_Integer n = 0; /* replacement count */
- int changed = 0; /* change flag */
- MatchState ms;
- luaL_Buffer b;
- luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
- tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
- "string/function/table");
- luaL_buffinit(L, &b);
- if (anchor) {
- p++; lp--; /* skip anchor character */
- }
- prepstate(&ms, L, src, srcl, p, lp);
- while (n < max_s) {
- const char *e;
- reprepstate(&ms); /* (re)prepare state for new match */
- if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
- n++;
- changed = add_value(&ms, &b, src, e, tr) | changed;
- src = lastmatch = e;
- }
- else if (src < ms.src_end) /* otherwise, skip one character */
- luaL_addchar(&b, *src++);
- else break; /* end of subject */
- if (anchor) break;
- }
- if (!changed) /* no changes? */
- lua_pushvalue(L, 1); /* return original string */
- else { /* something changed */
- luaL_addlstring(&b, src, ms.src_end-src);
- luaL_pushresult(&b); /* create and return new string */
- }
- lua_pushinteger(L, n); /* number of substitutions */
- return 2;
-}
-
-/* }====================================================== */
-
-
-
-/*
-** {======================================================
-** STRING FORMAT
-** =======================================================
-*/
-
-#if !defined(lua_number2strx) /* { */
-
-/*
-** Hexadecimal floating-point formatter
-*/
-
-#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
-
-
-/*
-** Number of bits that goes into the first digit. It can be any value
-** between 1 and 4; the following definition tries to align the number
-** to nibble boundaries by making what is left after that first digit a
-** multiple of 4.
-*/
-#define L_NBFD ((l_floatatt(MANT_DIG) - 1)%4 + 1)
-
-
-/*
-** Add integer part of 'x' to buffer and return new 'x'
-*/
-static lua_Number adddigit (char *buff, int n, lua_Number x) {
- lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
- int d = (int)dd;
- buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
- return x - dd; /* return what is left */
-}
-
-
-static int num2straux (char *buff, int sz, lua_Number x) {
- /* if 'inf' or 'NaN', format it like '%g' */
- if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL)
- return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x);
- else if (x == 0) { /* can be -0... */
- /* create "0" or "-0" followed by exponent */
- return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x);
- }
- else {
- int e;
- lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
- int n = 0; /* character count */
- if (m < 0) { /* is number negative? */
- buff[n++] = '-'; /* add sign */
- m = -m; /* make it positive */
- }
- buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
- m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
- e -= L_NBFD; /* this digit goes before the radix point */
- if (m > 0) { /* more digits? */
- buff[n++] = lua_getlocaledecpoint(); /* add radix point */
- do { /* add as many digits as needed */
- m = adddigit(buff, n++, m * 16);
- } while (m > 0);
- }
- n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */
- lua_assert(n < sz);
- return n;
- }
-}
-
-
-static int lua_number2strx (lua_State *L, char *buff, int sz,
- const char *fmt, lua_Number x) {
- int n = num2straux(buff, sz, x);
- if (fmt[SIZELENMOD] == 'A') {
- int i;
- for (i = 0; i < n; i++)
- buff[i] = toupper(uchar(buff[i]));
- }
- else if (l_unlikely(fmt[SIZELENMOD] != 'a'))
- return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
- return n;
-}
-
-#endif /* } */
-
-
-/*
-** Maximum size for items formatted with '%f'. This size is produced
-** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
-** and '\0') + number of decimal digits to represent maxfloat (which
-** is maximum exponent + 1). (99+3+1, adding some extra, 110)
-*/
-#define MAX_ITEMF (110 + l_floatatt(MAX_10_EXP))
-
-
-/*
-** All formats except '%f' do not need that large limit. The other
-** float formats use exponents, so that they fit in the 99 limit for
-** significant digits; 's' for large strings and 'q' add items directly
-** to the buffer; all integer formats also fit in the 99 limit. The
-** worst case are floats: they may need 99 significant digits, plus
-** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120.
-*/
-#define MAX_ITEM 120
-
-
-/* valid flags in a format specification */
-#if !defined(L_FMTFLAGSF)
-
-/* valid flags for a, A, e, E, f, F, g, and G conversions */
-#define L_FMTFLAGSF "-+#0 "
-
-/* valid flags for o, x, and X conversions */
-#define L_FMTFLAGSX "-#0"
-
-/* valid flags for d and i conversions */
-#define L_FMTFLAGSI "-+0 "
-
-/* valid flags for u conversions */
-#define L_FMTFLAGSU "-0"
-
-/* valid flags for c, p, and s conversions */
-#define L_FMTFLAGSC "-"
-
-#endif
-
-
-/*
-** Maximum size of each format specification (such as "%-099.99d"):
-** Initial '%', flags (up to 5), width (2), period, precision (2),
-** length modifier (8), conversion specifier, and final '\0', plus some
-** extra.
-*/
-#define MAX_FORMAT 32
-
-
-static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
- luaL_addchar(b, '"');
- while (len--) {
- if (*s == '"' || *s == '\\' || *s == '\n') {
- luaL_addchar(b, '\\');
- luaL_addchar(b, *s);
- }
- else if (iscntrl(uchar(*s))) {
- char buff[10];
- if (!isdigit(uchar(*(s+1))))
- l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
- else
- l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
- luaL_addstring(b, buff);
- }
- else
- luaL_addchar(b, *s);
- s++;
- }
- luaL_addchar(b, '"');
-}
-
-
-/*
-** Serialize a floating-point number in such a way that it can be
-** scanned back by Lua. Use hexadecimal format for "common" numbers
-** (to preserve precision); inf, -inf, and NaN are handled separately.
-** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.)
-*/
-static int quotefloat (lua_State *L, char *buff, lua_Number n) {
- const char *s; /* for the fixed representations */
- if (n == (lua_Number)HUGE_VAL) /* inf? */
- s = "1e9999";
- else if (n == -(lua_Number)HUGE_VAL) /* -inf? */
- s = "-1e9999";
- else if (n != n) /* NaN? */
- s = "(0/0)";
- else { /* format number as hexadecimal */
- int nb = lua_number2strx(L, buff, MAX_ITEM,
- "%" LUA_NUMBER_FRMLEN "a", n);
- /* ensures that 'buff' string uses a dot as the radix character */
- if (memchr(buff, '.', nb) == NULL) { /* no dot? */
- char point = lua_getlocaledecpoint(); /* try locale point */
- char *ppoint = (char *)memchr(buff, point, nb);
- if (ppoint) *ppoint = '.'; /* change it to a dot */
- }
- return nb;
- }
- /* for the fixed representations */
- return l_sprintf(buff, MAX_ITEM, "%s", s);
-}
-
-
-static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
- switch (lua_type(L, arg)) {
- case LUA_TSTRING: {
- size_t len;
- const char *s = lua_tolstring(L, arg, &len);
- addquoted(b, s, len);
- break;
- }
- case LUA_TNUMBER: {
- char *buff = luaL_prepbuffsize(b, MAX_ITEM);
- int nb;
- if (!lua_isinteger(L, arg)) /* float? */
- nb = quotefloat(L, buff, lua_tonumber(L, arg));
- else { /* integers */
- lua_Integer n = lua_tointeger(L, arg);
- const char *format = (n == LUA_MININTEGER) /* corner case? */
- ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hex */
- : LUA_INTEGER_FMT; /* else use default format */
- nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
- }
- luaL_addsize(b, nb);
- break;
- }
- case LUA_TNIL: case LUA_TBOOLEAN: {
- luaL_tolstring(L, arg, NULL);
- luaL_addvalue(b);
- break;
- }
- default: {
- luaL_argerror(L, arg, "value has no literal form");
- }
- }
-}
-
-
-static const char *get2digits (const char *s) {
- if (isdigit(uchar(*s))) {
- s++;
- if (isdigit(uchar(*s))) s++; /* (2 digits at most) */
- }
- return s;
-}
-
-
-/*
-** Check whether a conversion specification is valid. When called,
-** first character in 'form' must be '%' and last character must
-** be a valid conversion specifier. 'flags' are the accepted flags;
-** 'precision' signals whether to accept a precision.
-*/
-static void checkformat (lua_State *L, const char *form, const char *flags,
- int precision) {
- const char *spec = form + 1; /* skip '%' */
- spec += strspn(spec, flags); /* skip flags */
- if (*spec != '0') { /* a width cannot start with '0' */
- spec = get2digits(spec); /* skip width */
- if (*spec == '.' && precision) {
- spec++;
- spec = get2digits(spec); /* skip precision */
- }
- }
- if (!isalpha(uchar(*spec))) /* did not go to the end? */
- luaL_error(L, "invalid conversion specification: '%s'", form);
-}
-
-
-/*
-** Get a conversion specification and copy it to 'form'.
-** Return the address of its last character.
-*/
-static const char *getformat (lua_State *L, const char *strfrmt,
- char *form) {
- /* spans flags, width, and precision ('0' is included as a flag) */
- size_t len = strspn(strfrmt, L_FMTFLAGSF "123456789.");
- len++; /* adds following character (should be the specifier) */
- /* still needs space for '%', '\0', plus a length modifier */
- if (len >= MAX_FORMAT - 10)
- luaL_error(L, "invalid format (too long)");
- *(form++) = '%';
- memcpy(form, strfrmt, len * sizeof(char));
- *(form + len) = '\0';
- return strfrmt + len - 1;
-}
-
-
-/*
-** add length modifier into formats
-*/
-static void addlenmod (char *form, const char *lenmod) {
- size_t l = strlen(form);
- size_t lm = strlen(lenmod);
- char spec = form[l - 1];
- strcpy(form + l - 1, lenmod);
- form[l + lm - 1] = spec;
- form[l + lm] = '\0';
-}
-
-
-static int str_format (lua_State *L) {
- int top = lua_gettop(L);
- int arg = 1;
- size_t sfl;
- const char *strfrmt = luaL_checklstring(L, arg, &sfl);
- const char *strfrmt_end = strfrmt+sfl;
- const char *flags;
- luaL_Buffer b;
- luaL_buffinit(L, &b);
- while (strfrmt < strfrmt_end) {
- if (*strfrmt != L_ESC)
- luaL_addchar(&b, *strfrmt++);
- else if (*++strfrmt == L_ESC)
- luaL_addchar(&b, *strfrmt++); /* %% */
- else { /* format item */
- char form[MAX_FORMAT]; /* to store the format ('%...') */
- int maxitem = MAX_ITEM; /* maximum length for the result */
- char *buff = luaL_prepbuffsize(&b, maxitem); /* to put result */
- int nb = 0; /* number of bytes in result */
- if (++arg > top)
- return luaL_argerror(L, arg, "no value");
- strfrmt = getformat(L, strfrmt, form);
- switch (*strfrmt++) {
- case 'c': {
- checkformat(L, form, L_FMTFLAGSC, 0);
- nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
- break;
- }
- case 'd': case 'i':
- flags = L_FMTFLAGSI;
- goto intcase;
- case 'u':
- flags = L_FMTFLAGSU;
- goto intcase;
- case 'o': case 'x': case 'X':
- flags = L_FMTFLAGSX;
- intcase: {
- lua_Integer n = luaL_checkinteger(L, arg);
- checkformat(L, form, flags, 1);
- addlenmod(form, LUA_INTEGER_FRMLEN);
- nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
- break;
- }
- case 'a': case 'A':
- checkformat(L, form, L_FMTFLAGSF, 1);
- addlenmod(form, LUA_NUMBER_FRMLEN);
- nb = lua_number2strx(L, buff, maxitem, form,
- luaL_checknumber(L, arg));
- break;
- case 'f':
- maxitem = MAX_ITEMF; /* extra space for '%f' */
- buff = luaL_prepbuffsize(&b, maxitem);
- /* FALLTHROUGH */
- case 'e': case 'E': case 'g': case 'G': {
- lua_Number n = luaL_checknumber(L, arg);
- checkformat(L, form, L_FMTFLAGSF, 1);
- addlenmod(form, LUA_NUMBER_FRMLEN);
- nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
- break;
- }
- case 'p': {
- const void *p = lua_topointer(L, arg);
- checkformat(L, form, L_FMTFLAGSC, 0);
- if (p == NULL) { /* avoid calling 'printf' with argument NULL */
- p = "(null)"; /* result */
- form[strlen(form) - 1] = 's'; /* format it as a string */
- }
- nb = l_sprintf(buff, maxitem, form, p);
- break;
- }
- case 'q': {
- if (form[2] != '\0') /* modifiers? */
- return luaL_error(L, "specifier '%%q' cannot have modifiers");
- addliteral(L, &b, arg);
- break;
- }
- case 's': {
- size_t l;
- const char *s = luaL_tolstring(L, arg, &l);
- if (form[2] == '\0') /* no modifiers? */
- luaL_addvalue(&b); /* keep entire string */
- else {
- luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
- checkformat(L, form, L_FMTFLAGSC, 1);
- if (strchr(form, '.') == NULL && l >= 100) {
- /* no precision and string is too long to be formatted */
- luaL_addvalue(&b); /* keep entire string */
- }
- else { /* format the string into 'buff' */
- nb = l_sprintf(buff, maxitem, form, s);
- lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
- }
- }
- break;
- }
- default: { /* also treat cases 'pnLlh' */
- return luaL_error(L, "invalid conversion '%s' to 'format'", form);
- }
- }
- lua_assert(nb < maxitem);
- luaL_addsize(&b, nb);
- }
- }
- luaL_pushresult(&b);
- return 1;
-}
-
-/* }====================================================== */
-
-
-/*
-** {======================================================
-** PACK/UNPACK
-** =======================================================
-*/
-
-
-/* value used for padding */
-#if !defined(LUAL_PACKPADBYTE)
-#define LUAL_PACKPADBYTE 0x00
-#endif
-
-/* maximum size for the binary representation of an integer */
-#define MAXINTSIZE 16
-
-/* number of bits in a character */
-#define NB CHAR_BIT
-
-/* mask for one character (NB 1's) */
-#define MC ((1 << NB) - 1)
-
-/* size of a lua_Integer */
-#define SZINT ((int)sizeof(lua_Integer))
-
-
-/* dummy union to get native endianness */
-static const union {
- int dummy;
- char little; /* true iff machine is little endian */
-} nativeendian = {1};
-
-
-/*
-** information to pack/unpack stuff
-*/
-typedef struct Header {
- lua_State *L;
- int islittle;
- int maxalign;
-} Header;
-
-
-/*
-** options for pack/unpack
-*/
-typedef enum KOption {
- Kint, /* signed integers */
- Kuint, /* unsigned integers */
- Kfloat, /* single-precision floating-point numbers */
- Knumber, /* Lua "native" floating-point numbers */
- Kdouble, /* double-precision floating-point numbers */
- Kchar, /* fixed-length strings */
- Kstring, /* strings with prefixed length */
- Kzstr, /* zero-terminated strings */
- Kpadding, /* padding */
- Kpaddalign, /* padding for alignment */
- Knop /* no-op (configuration or spaces) */
-} KOption;
-
-
-/*
-** Read an integer numeral from string 'fmt' or return 'df' if
-** there is no numeral
-*/
-static int digit (int c) { return '0' <= c && c <= '9'; }
-
-static int getnum (const char **fmt, int df) {
- if (!digit(**fmt)) /* no number? */
- return df; /* return default value */
- else {
- int a = 0;
- do {
- a = a*10 + (*((*fmt)++) - '0');
- } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
- return a;
- }
-}
-
-
-/*
-** Read an integer numeral and raises an error if it is larger
-** than the maximum size for integers.
-*/
-static int getnumlimit (Header *h, const char **fmt, int df) {
- int sz = getnum(fmt, df);
- if (l_unlikely(sz > MAXINTSIZE || sz <= 0))
- return luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
- sz, MAXINTSIZE);
- return sz;
-}
-
-
-/*
-** Initialize Header
-*/
-static void initheader (lua_State *L, Header *h) {
- h->L = L;
- h->islittle = nativeendian.little;
- h->maxalign = 1;
-}
-
-
-/*
-** Read and classify next option. 'size' is filled with option's size.
-*/
-static KOption getoption (Header *h, const char **fmt, int *size) {
- /* dummy structure to get native alignment requirements */
- struct cD { char c; union { LUAI_MAXALIGN; } u; };
- int opt = *((*fmt)++);
- *size = 0; /* default */
- switch (opt) {
- case 'b': *size = sizeof(char); return Kint;
- case 'B': *size = sizeof(char); return Kuint;
- case 'h': *size = sizeof(short); return Kint;
- case 'H': *size = sizeof(short); return Kuint;
- case 'l': *size = sizeof(long); return Kint;
- case 'L': *size = sizeof(long); return Kuint;
- case 'j': *size = sizeof(lua_Integer); return Kint;
- case 'J': *size = sizeof(lua_Integer); return Kuint;
- case 'T': *size = sizeof(size_t); return Kuint;
- case 'f': *size = sizeof(float); return Kfloat;
- case 'n': *size = sizeof(lua_Number); return Knumber;
- case 'd': *size = sizeof(double); return Kdouble;
- case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
- case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
- case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
- case 'c':
- *size = getnum(fmt, -1);
- if (l_unlikely(*size == -1))
- luaL_error(h->L, "missing size for format option 'c'");
- return Kchar;
- case 'z': return Kzstr;
- case 'x': *size = 1; return Kpadding;
- case 'X': return Kpaddalign;
- case ' ': break;
- case '<': h->islittle = 1; break;
- case '>': h->islittle = 0; break;
- case '=': h->islittle = nativeendian.little; break;
- case '!': {
- const int maxalign = offsetof(struct cD, u);
- h->maxalign = getnumlimit(h, fmt, maxalign);
- break;
- }
- default: luaL_error(h->L, "invalid format option '%c'", opt);
- }
- return Knop;
-}
-
-
-/*
-** Read, classify, and fill other details about the next option.
-** 'psize' is filled with option's size, 'notoalign' with its
-** alignment requirements.
-** Local variable 'size' gets the size to be aligned. (Kpadal option
-** always gets its full alignment, other options are limited by
-** the maximum alignment ('maxalign'). Kchar option needs no alignment
-** despite its size.
-*/
-static KOption getdetails (Header *h, size_t totalsize,
- const char **fmt, int *psize, int *ntoalign) {
- KOption opt = getoption(h, fmt, psize);
- int align = *psize; /* usually, alignment follows size */
- if (opt == Kpaddalign) { /* 'X' gets alignment from following option */
- if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
- luaL_argerror(h->L, 1, "invalid next option for option 'X'");
- }
- if (align <= 1 || opt == Kchar) /* need no alignment? */
- *ntoalign = 0;
- else {
- if (align > h->maxalign) /* enforce maximum alignment */
- align = h->maxalign;
- if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */
- luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
- *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
- }
- return opt;
-}
-
-
-/*
-** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
-** The final 'if' handles the case when 'size' is larger than
-** the size of a Lua integer, correcting the extra sign-extension
-** bytes if necessary (by default they would be zeros).
-*/
-static void packint (luaL_Buffer *b, lua_Unsigned n,
- int islittle, int size, int neg) {
- char *buff = luaL_prepbuffsize(b, size);
- int i;
- buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */
- for (i = 1; i < size; i++) {
- n >>= NB;
- buff[islittle ? i : size - 1 - i] = (char)(n & MC);
- }
- if (neg && size > SZINT) { /* negative number need sign extension? */
- for (i = SZINT; i < size; i++) /* correct extra bytes */
- buff[islittle ? i : size - 1 - i] = (char)MC;
- }
- luaL_addsize(b, size); /* add result to buffer */
-}
-
-
-/*
-** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
-** given 'islittle' is different from native endianness.
-*/
-static void copywithendian (char *dest, const char *src,
- int size, int islittle) {
- if (islittle == nativeendian.little)
- memcpy(dest, src, size);
- else {
- dest += size - 1;
- while (size-- != 0)
- *(dest--) = *(src++);
- }
-}
-
-
-static int str_pack (lua_State *L) {
- luaL_Buffer b;
- Header h;
- const char *fmt = luaL_checkstring(L, 1); /* format string */
- int arg = 1; /* current argument to pack */
- size_t totalsize = 0; /* accumulate total size of result */
- initheader(L, &h);
- lua_pushnil(L); /* mark to separate arguments from string buffer */
- luaL_buffinit(L, &b);
- while (*fmt != '\0') {
- int size, ntoalign;
- KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
- totalsize += ntoalign + size;
- while (ntoalign-- > 0)
- luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
- arg++;
- switch (opt) {
- case Kint: { /* signed integers */
- lua_Integer n = luaL_checkinteger(L, arg);
- if (size < SZINT) { /* need overflow check? */
- lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
- luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
- }
- packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
- break;
- }
- case Kuint: { /* unsigned integers */
- lua_Integer n = luaL_checkinteger(L, arg);
- if (size < SZINT) /* need overflow check? */
- luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
- arg, "unsigned overflow");
- packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
- break;
- }
- case Kfloat: { /* C float */
- float f = (float)luaL_checknumber(L, arg); /* get argument */
- char *buff = luaL_prepbuffsize(&b, sizeof(f));
- /* move 'f' to final result, correcting endianness if needed */
- copywithendian(buff, (char *)&f, sizeof(f), h.islittle);
- luaL_addsize(&b, size);
- break;
- }
- case Knumber: { /* Lua float */
- lua_Number f = luaL_checknumber(L, arg); /* get argument */
- char *buff = luaL_prepbuffsize(&b, sizeof(f));
- /* move 'f' to final result, correcting endianness if needed */
- copywithendian(buff, (char *)&f, sizeof(f), h.islittle);
- luaL_addsize(&b, size);
- break;
- }
- case Kdouble: { /* C double */
- double f = (double)luaL_checknumber(L, arg); /* get argument */
- char *buff = luaL_prepbuffsize(&b, sizeof(f));
- /* move 'f' to final result, correcting endianness if needed */
- copywithendian(buff, (char *)&f, sizeof(f), h.islittle);
- luaL_addsize(&b, size);
- break;
- }
- case Kchar: { /* fixed-size string */
- size_t len;
- const char *s = luaL_checklstring(L, arg, &len);
- luaL_argcheck(L, len <= (size_t)size, arg,
- "string longer than given size");
- luaL_addlstring(&b, s, len); /* add string */
- while (len++ < (size_t)size) /* pad extra space */
- luaL_addchar(&b, LUAL_PACKPADBYTE);
- break;
- }
- case Kstring: { /* strings with length count */
- size_t len;
- const char *s = luaL_checklstring(L, arg, &len);
- luaL_argcheck(L, size >= (int)sizeof(size_t) ||
- len < ((size_t)1 << (size * NB)),
- arg, "string length does not fit in given size");
- packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
- luaL_addlstring(&b, s, len);
- totalsize += len;
- break;
- }
- case Kzstr: { /* zero-terminated string */
- size_t len;
- const char *s = luaL_checklstring(L, arg, &len);
- luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
- luaL_addlstring(&b, s, len);
- luaL_addchar(&b, '\0'); /* add zero at the end */
- totalsize += len + 1;
- break;
- }
- case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
- case Kpaddalign: case Knop:
- arg--; /* undo increment */
- break;
- }
- }
- luaL_pushresult(&b);
- return 1;
-}
-
-
-static int str_packsize (lua_State *L) {
- Header h;
- const char *fmt = luaL_checkstring(L, 1); /* format string */
- size_t totalsize = 0; /* accumulate total size of result */
- initheader(L, &h);
- while (*fmt != '\0') {
- int size, ntoalign;
- KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
- luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
- "variable-length format");
- size += ntoalign; /* total space used by option */
- luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
- "format result too large");
- totalsize += size;
- }
- lua_pushinteger(L, (lua_Integer)totalsize);
- return 1;
-}
-
-
-/*
-** Unpack an integer with 'size' bytes and 'islittle' endianness.
-** If size is smaller than the size of a Lua integer and integer
-** is signed, must do sign extension (propagating the sign to the
-** higher bits); if size is larger than the size of a Lua integer,
-** it must check the unread bytes to see whether they do not cause an
-** overflow.
-*/
-static lua_Integer unpackint (lua_State *L, const char *str,
- int islittle, int size, int issigned) {
- lua_Unsigned res = 0;
- int i;
- int limit = (size <= SZINT) ? size : SZINT;
- for (i = limit - 1; i >= 0; i--) {
- res <<= NB;
- res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
- }
- if (size < SZINT) { /* real size smaller than lua_Integer? */
- if (issigned) { /* needs sign extension? */
- lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
- res = ((res ^ mask) - mask); /* do sign extension */
- }
- }
- else if (size > SZINT) { /* must check unread bytes */
- int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
- for (i = limit; i < size; i++) {
- if (l_unlikely((unsigned char)str[islittle ? i : size - 1 - i] != mask))
- luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
- }
- }
- return (lua_Integer)res;
-}
-
-
-static int str_unpack (lua_State *L) {
- Header h;
- const char *fmt = luaL_checkstring(L, 1);
- size_t ld;
- const char *data = luaL_checklstring(L, 2, &ld);
- size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1;
- int n = 0; /* number of results */
- luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
- initheader(L, &h);
- while (*fmt != '\0') {
- int size, ntoalign;
- KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
- luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2,
- "data string too short");
- pos += ntoalign; /* skip alignment */
- /* stack space for item + next position */
- luaL_checkstack(L, 2, "too many results");
- n++;
- switch (opt) {
- case Kint:
- case Kuint: {
- lua_Integer res = unpackint(L, data + pos, h.islittle, size,
- (opt == Kint));
- lua_pushinteger(L, res);
- break;
- }
- case Kfloat: {
- float f;
- copywithendian((char *)&f, data + pos, sizeof(f), h.islittle);
- lua_pushnumber(L, (lua_Number)f);
- break;
- }
- case Knumber: {
- lua_Number f;
- copywithendian((char *)&f, data + pos, sizeof(f), h.islittle);
- lua_pushnumber(L, f);
- break;
- }
- case Kdouble: {
- double f;
- copywithendian((char *)&f, data + pos, sizeof(f), h.islittle);
- lua_pushnumber(L, (lua_Number)f);
- break;
- }
- case Kchar: {
- lua_pushlstring(L, data + pos, size);
- break;
- }
- case Kstring: {
- size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
- luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
- lua_pushlstring(L, data + pos + size, len);
- pos += len; /* skip string */
- break;
- }
- case Kzstr: {
- size_t len = strlen(data + pos);
- luaL_argcheck(L, pos + len < ld, 2,
- "unfinished string for format 'z'");
- lua_pushlstring(L, data + pos, len);
- pos += len + 1; /* skip string plus final '\0' */
- break;
- }
- case Kpaddalign: case Kpadding: case Knop:
- n--; /* undo increment */
- break;
- }
- pos += size;
- }
- lua_pushinteger(L, pos + 1); /* next position */
- return n + 1;
-}
-
-/* }====================================================== */
-
-
-static const luaL_Reg strlib[] = {
- {"byte", str_byte},
- {"char", str_char},
- {"dump", str_dump},
- {"find", str_find},
- {"format", str_format},
- {"gmatch", gmatch},
- {"gsub", str_gsub},
- {"len", str_len},
- {"lower", str_lower},
- {"match", str_match},
- {"rep", str_rep},
- {"reverse", str_reverse},
- {"sub", str_sub},
- {"upper", str_upper},
- {"pack", str_pack},
- {"packsize", str_packsize},
- {"unpack", str_unpack},
- {NULL, NULL}
-};
-
-
-static void createmetatable (lua_State *L) {
- /* table to be metatable for strings */
- luaL_newlibtable(L, stringmetamethods);
- luaL_setfuncs(L, stringmetamethods, 0);
- lua_pushliteral(L, ""); /* dummy string */
- lua_pushvalue(L, -2); /* copy table */
- lua_setmetatable(L, -2); /* set table as metatable for strings */
- lua_pop(L, 1); /* pop dummy string */
- lua_pushvalue(L, -2); /* get string library */
- lua_setfield(L, -2, "__index"); /* metatable.__index = string */
- lua_pop(L, 1); /* pop metatable */
-}
-
-
-/*
-** Open string library
-*/
-LUAMOD_API int luaopen_string (lua_State *L) {
- luaL_newlib(L, strlib);
- createmetatable(L);
- return 1;
-}
-
diff --git a/lua-5.4.4/library/ltable.c b/lua-5.4.4/library/ltable.c
deleted file mode 100644
index 1b1cd241..00000000
--- a/lua-5.4.4/library/ltable.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
-** $Id: ltable.c $
-** Lua tables (hash)
-** See Copyright Notice in lua.h
-*/
-
-#define ltable_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-/*
-** Implementation of tables (aka arrays, objects, or hash tables).
-** Tables keep its elements in two parts: an array part and a hash part.
-** Non-negative integer keys are all candidates to be kept in the array
-** part. The actual size of the array is the largest 'n' such that
-** more than half the slots between 1 and n are in use.
-** Hash uses a mix of chained scatter table with Brent's variation.
-** A main invariant of these tables is that, if an element is not
-** in its main position (i.e. the 'original' position that its hash gives
-** to it), then the colliding element is in its own main position.
-** Hence even when the load factor reaches 100%, performance remains good.
-*/
-
-#include
-#include
-
-#include "lua.h"
-
-#include "ldebug.h"
-#include "ldo.h"
-#include "lgc.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-#include "lvm.h"
-
-
-/*
-** MAXABITS is the largest integer such that MAXASIZE fits in an
-** unsigned int.
-*/
-#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1)
-
-
-/*
-** MAXASIZE is the maximum size of the array part. It is the minimum
-** between 2^MAXABITS and the maximum size that, measured in bytes,
-** fits in a 'size_t'.
-*/
-#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue)
-
-/*
-** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a
-** signed int.
-*/
-#define MAXHBITS (MAXABITS - 1)
-
-
-/*
-** MAXHSIZE is the maximum size of the hash part. It is the minimum
-** between 2^MAXHBITS and the maximum size such that, measured in bytes,
-** it fits in a 'size_t'.
-*/
-#define MAXHSIZE luaM_limitN(1u << MAXHBITS, Node)
-
-
-/*
-** When the original hash value is good, hashing by a power of 2
-** avoids the cost of '%'.
-*/
-#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
-
-/*
-** for other types, it is better to avoid modulo by power of 2, as
-** they can have many 2 factors.
-*/
-#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
-
-
-#define hashstr(t,str) hashpow2(t, (str)->hash)
-#define hashboolean(t,p) hashpow2(t, p)
-
-
-#define hashpointer(t,p) hashmod(t, point2uint(p))
-
-
-#define dummynode (&dummynode_)
-
-static const Node dummynode_ = {
- {{NULL}, LUA_VEMPTY, /* value's value and type */
- LUA_VNIL, 0, {NULL}} /* key type, next, and key value */
-};
-
-
-static const TValue absentkey = {ABSTKEYCONSTANT};
-
-
-/*
-** Hash for integers. To allow a good hash, use the remainder operator
-** ('%'). If integer fits as a non-negative int, compute an int
-** remainder, which is faster. Otherwise, use an unsigned-integer
-** remainder, which uses all bits and ensures a non-negative result.
-*/
-static Node *hashint (const Table *t, lua_Integer i) {
- lua_Unsigned ui = l_castS2U(i);
- if (ui <= (unsigned int)INT_MAX)
- return hashmod(t, cast_int(ui));
- else
- return hashmod(t, ui);
-}
-
-
-/*
-** Hash for floating-point numbers.
-** The main computation should be just
-** n = frexp(n, &i); return (n * INT_MAX) + i
-** but there are some numerical subtleties.
-** In a two-complement representation, INT_MAX does not has an exact
-** representation as a float, but INT_MIN does; because the absolute
-** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
-** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
-** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when
-** adding 'i'; the use of '~u' (instead of '-u') avoids problems with
-** INT_MIN.
-*/
-#if !defined(l_hashfloat)
-static int l_hashfloat (lua_Number n) {
- int i;
- lua_Integer ni;
- n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN);
- if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */
- lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL));
- return 0;
- }
- else { /* normal case */
- unsigned int u = cast_uint(i) + cast_uint(ni);
- return cast_int(u <= cast_uint(INT_MAX) ? u : ~u);
- }
-}
-#endif
-
-
-/*
-** returns the 'main' position of an element in a table (that is,
-** the index of its hash value).
-*/
-static Node *mainpositionTV (const Table *t, const TValue *key) {
- switch (ttypetag(key)) {
- case LUA_VNUMINT: {
- lua_Integer i = ivalue(key);
- return hashint(t, i);
- }
- case LUA_VNUMFLT: {
- lua_Number n = fltvalue(key);
- return hashmod(t, l_hashfloat(n));
- }
- case LUA_VSHRSTR: {
- TString *ts = tsvalue(key);
- return hashstr(t, ts);
- }
- case LUA_VLNGSTR: {
- TString *ts = tsvalue(key);
- return hashpow2(t, luaS_hashlongstr(ts));
- }
- case LUA_VFALSE:
- return hashboolean(t, 0);
- case LUA_VTRUE:
- return hashboolean(t, 1);
- case LUA_VLIGHTUSERDATA: {
- void *p = pvalue(key);
- return hashpointer(t, p);
- }
- case LUA_VLCF: {
- lua_CFunction f = fvalue(key);
- return hashpointer(t, f);
- }
- default: {
- GCObject *o = gcvalue(key);
- return hashpointer(t, o);
- }
- }
-}
-
-
-l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) {
- TValue key;
- getnodekey(cast(lua_State *, NULL), &key, nd);
- return mainpositionTV(t, &key);
-}
-
-
-/*
-** Check whether key 'k1' is equal to the key in node 'n2'. This
-** equality is raw, so there are no metamethods. Floats with integer
-** values have been normalized, so integers cannot be equal to
-** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
-** that short strings are handled in the default case.
-** A true 'deadok' means to accept dead keys as equal to their original
-** values. All dead keys are compared in the default case, by pointer
-** identity. (Only collectable objects can produce dead keys.) Note that
-** dead long strings are also compared by identity.
-** Once a key is dead, its corresponding value may be collected, and
-** then another value can be created with the same address. If this
-** other value is given to 'next', 'equalkey' will signal a false
-** positive. In a regular traversal, this situation should never happen,
-** as all keys given to 'next' came from the table itself, and therefore
-** could not have been collected. Outside a regular traversal, we
-** have garbage in, garbage out. What is relevant is that this false
-** positive does not break anything. (In particular, 'next' will return
-** some other valid item on the table or nil.)
-*/
-static int equalkey (const TValue *k1, const Node *n2, int deadok) {
- if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */
- !(deadok && keyisdead(n2) && iscollectable(k1)))
- return 0; /* cannot be same key */
- switch (keytt(n2)) {
- case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
- return 1;
- case LUA_VNUMINT:
- return (ivalue(k1) == keyival(n2));
- case LUA_VNUMFLT:
- return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
- case LUA_VLIGHTUSERDATA:
- return pvalue(k1) == pvalueraw(keyval(n2));
- case LUA_VLCF:
- return fvalue(k1) == fvalueraw(keyval(n2));
- case ctb(LUA_VLNGSTR):
- return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
- default:
- return gcvalue(k1) == gcvalueraw(keyval(n2));
- }
-}
-
-
-/*
-** True if value of 'alimit' is equal to the real size of the array
-** part of table 't'. (Otherwise, the array part must be larger than
-** 'alimit'.)
-*/
-#define limitequalsasize(t) (isrealasize(t) || ispow2((t)->alimit))
-
-
-/*
-** Returns the real size of the 'array' array
-*/
-LUAI_FUNC unsigned int luaH_realasize (const Table *t) {
- if (limitequalsasize(t))
- return t->alimit; /* this is the size */
- else {
- unsigned int size = t->alimit;
- /* compute the smallest power of 2 not smaller than 'n' */
- size |= (size >> 1);
- size |= (size >> 2);
- size |= (size >> 4);
- size |= (size >> 8);
- size |= (size >> 16);
-#if (UINT_MAX >> 30) > 3
- size |= (size >> 32); /* unsigned int has more than 32 bits */
-#endif
- size++;
- lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size);
- return size;
- }
-}
-
-
-/*
-** Check whether real size of the array is a power of 2.
-** (If it is not, 'alimit' cannot be changed to any other value
-** without changing the real size.)
-*/
-static int ispow2realasize (const Table *t) {
- return (!isrealasize(t) || ispow2(t->alimit));
-}
-
-
-static unsigned int setlimittosize (Table *t) {
- t->alimit = luaH_realasize(t);
- setrealasize(t);
- return t->alimit;
-}
-
-
-#define limitasasize(t) check_exp(isrealasize(t), t->alimit)
-
-
-
-/*
-** "Generic" get version. (Not that generic: not valid for integers,
-** which may be in array part, nor for floats with integral values.)
-** See explanation about 'deadok' in function 'equalkey'.
-*/
-static const TValue *getgeneric (Table *t, const TValue *key, int deadok) {
- Node *n = mainpositionTV(t, key);
- for (;;) { /* check whether 'key' is somewhere in the chain */
- if (equalkey(key, n, deadok))
- return gval(n); /* that's it */
- else {
- int nx = gnext(n);
- if (nx == 0)
- return &absentkey; /* not found */
- n += nx;
- }
- }
-}
-
-
-/*
-** returns the index for 'k' if 'k' is an appropriate key to live in
-** the array part of a table, 0 otherwise.
-*/
-static unsigned int arrayindex (lua_Integer k) {
- if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */
- return cast_uint(k); /* 'key' is an appropriate array index */
- else
- return 0;
-}
-
-
-/*
-** 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 signaled by 0.
-*/
-static unsigned int findindex (lua_State *L, Table *t, TValue *key,
- unsigned int asize) {
- unsigned int i;
- if (ttisnil(key)) return 0; /* first iteration */
- i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
- if (i - 1u < asize) /* is 'key' inside array part? */
- return i; /* yes; that's the index */
- else {
- const TValue *n = getgeneric(t, key, 1);
- if (l_unlikely(isabstkey(n)))
- luaG_runerror(L, "invalid key to 'next'"); /* key not found */
- i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
- /* hash elements are numbered after array ones */
- return (i + 1) + asize;
- }
-}
-
-
-int luaH_next (lua_State *L, Table *t, StkId key) {
- unsigned int asize = luaH_realasize(t);
- unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */
- for (; i < asize; i++) { /* try first array part */
- if (!isempty(&t->array[i])) { /* a non-empty entry? */
- setivalue(s2v(key), i + 1);
- setobj2s(L, key + 1, &t->array[i]);
- return 1;
- }
- }
- for (i -= asize; cast_int(i) < sizenode(t); i++) { /* hash part */
- if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */
- Node *n = gnode(t, i);
- getnodekey(L, s2v(key), n);
- setobj2s(L, key + 1, gval(n));
- return 1;
- }
- }
- return 0; /* no more elements */
-}
-
-
-static void freehash (lua_State *L, Table *t) {
- if (!isdummy(t))
- luaM_freearray(L, t->node, cast_sizet(sizenode(t)));
-}
-
-
-/*
-** {=============================================================
-** Rehash
-** ==============================================================
-*/
-
-/*
-** Compute the optimal size for the array part of table 't'. 'nums' is a
-** "count array" where 'nums[i]' is the number of integers in the table
-** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of
-** integer keys in the table and leaves with the number of keys that
-** will go to the array part; return the optimal size. (The condition
-** 'twotoi > 0' in the for loop stops the loop if 'twotoi' overflows.)
-*/
-static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
- int i;
- unsigned int twotoi; /* 2^i (candidate for optimal size) */
- unsigned int a = 0; /* number of elements smaller than 2^i */
- unsigned int na = 0; /* number of elements to go to array part */
- unsigned int optimal = 0; /* optimal size for array part */
- /* loop while keys can fill more than half of total size */
- for (i = 0, twotoi = 1;
- twotoi > 0 && *pna > twotoi / 2;
- i++, twotoi *= 2) {
- a += nums[i];
- if (a > twotoi/2) { /* more than half elements present? */
- optimal = twotoi; /* optimal size (till now) */
- na = a; /* all elements up to 'optimal' will go to array part */
- }
- }
- lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal);
- *pna = na;
- return optimal;
-}
-
-
-static int countint (lua_Integer key, unsigned int *nums) {
- unsigned int k = arrayindex(key);
- if (k != 0) { /* is 'key' an appropriate array index? */
- nums[luaO_ceillog2(k)]++; /* count as such */
- return 1;
- }
- else
- return 0;
-}
-
-
-/*
-** Count keys in array part of table 't': Fill 'nums[i]' with
-** number of keys that will go into corresponding slice and return
-** total number of non-nil keys.
-*/
-static unsigned int numusearray (const Table *t, unsigned int *nums) {
- int lg;
- unsigned int ttlg; /* 2^lg */
- unsigned int ause = 0; /* summation of 'nums' */
- unsigned int i = 1; /* count to traverse all array keys */
- unsigned int asize = limitasasize(t); /* real array size */
- /* traverse each slice */
- for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) {
- unsigned int lc = 0; /* counter */
- unsigned int lim = ttlg;
- if (lim > asize) {
- lim = asize; /* 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 (!isempty(&t->array[i-1]))
- lc++;
- }
- nums[lg] += lc;
- ause += lc;
- }
- return ause;
-}
-
-
-static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
- int totaluse = 0; /* total number of elements */
- int ause = 0; /* elements added to 'nums' (can go to array part) */
- int i = sizenode(t);
- while (i--) {
- Node *n = &t->node[i];
- if (!isempty(gval(n))) {
- if (keyisinteger(n))
- ause += countint(keyival(n), nums);
- totaluse++;
- }
- }
- *pna += ause;
- return totaluse;
-}
-
-
-/*
-** Creates an array for the hash part of a table with the given
-** size, or reuses the dummy node if size is zero.
-** The computation for size overflow is in two steps: the first
-** comparison ensures that the shift in the second one does not
-** overflow.
-*/
-static void setnodevector (lua_State *L, Table *t, unsigned int size) {
- if (size == 0) { /* no elements to hash part? */
- t->node = cast(Node *, dummynode); /* use common 'dummynode' */
- t->lsizenode = 0;
- t->lastfree = NULL; /* signal that it is using dummy node */
- }
- else {
- int i;
- int lsize = luaO_ceillog2(size);
- if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
- luaG_runerror(L, "table overflow");
- size = twoto(lsize);
- t->node = luaM_newvector(L, size, Node);
- for (i = 0; i < (int)size; i++) {
- Node *n = gnode(t, i);
- gnext(n) = 0;
- setnilkey(n);
- setempty(gval(n));
- }
- t->lsizenode = cast_byte(lsize);
- t->lastfree = gnode(t, size); /* all positions are free */
- }
-}
-
-
-/*
-** (Re)insert all elements from the hash part of 'ot' into table 't'.
-*/
-static void reinsert (lua_State *L, Table *ot, Table *t) {
- int j;
- int size = sizenode(ot);
- for (j = 0; j < size; j++) {
- Node *old = gnode(ot, j);
- if (!isempty(gval(old))) {
- /* doesn't need barrier/invalidate cache, as entry was
- already present in the table */
- TValue k;
- getnodekey(L, &k, old);
- luaH_set(L, t, &k, gval(old));
- }
- }
-}
-
-
-/*
-** Exchange the hash part of 't1' and 't2'.
-*/
-static void exchangehashpart (Table *t1, Table *t2) {
- lu_byte lsizenode = t1->lsizenode;
- Node *node = t1->node;
- Node *lastfree = t1->lastfree;
- t1->lsizenode = t2->lsizenode;
- t1->node = t2->node;
- t1->lastfree = t2->lastfree;
- t2->lsizenode = lsizenode;
- t2->node = node;
- t2->lastfree = lastfree;
-}
-
-
-/*
-** Resize table 't' for the new given sizes. Both allocations (for
-** the hash part and for the array part) can fail, which creates some
-** subtleties. If the first allocation, for the hash part, fails, an
-** error is raised and that is it. Otherwise, it copies the elements from
-** the shrinking part of the array (if it is shrinking) into the new
-** hash. Then it reallocates the array part. If that fails, the table
-** is in its original state; the function frees the new hash part and then
-** raises the allocation error. Otherwise, it sets the new hash part
-** into the table, initializes the new part of the array (if any) with
-** nils and reinserts the elements of the old hash back into the new
-** parts of the table.
-*/
-void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
- unsigned int nhsize) {
- unsigned int i;
- Table newt; /* to keep the new hash part */
- unsigned int oldasize = setlimittosize(t);
- TValue *newarray;
- /* create new hash part with appropriate size into 'newt' */
- setnodevector(L, &newt, nhsize);
- if (newasize < oldasize) { /* will array shrink? */
- t->alimit = newasize; /* pretend array has new size... */
- exchangehashpart(t, &newt); /* and new hash */
- /* re-insert into the new hash the elements from vanishing slice */
- for (i = newasize; i < oldasize; i++) {
- if (!isempty(&t->array[i]))
- luaH_setint(L, t, i + 1, &t->array[i]);
- }
- t->alimit = oldasize; /* restore current size... */
- exchangehashpart(t, &newt); /* and hash (in case of errors) */
- }
- /* allocate new array */
- newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue);
- if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */
- freehash(L, &newt); /* release new hash part */
- luaM_error(L); /* raise error (with array unchanged) */
- }
- /* allocation ok; initialize new part of the array */
- exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */
- t->array = newarray; /* set new array part */
- t->alimit = newasize;
- for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
- setempty(&t->array[i]);
- /* re-insert elements from old hash part into new parts */
- reinsert(L, &newt, t); /* 'newt' now has the old hash */
- freehash(L, &newt); /* free old hash part */
-}
-
-
-void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
- int nsize = allocsizenode(t);
- luaH_resize(L, t, nasize, nsize);
-}
-
-/*
-** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
-*/
-static void rehash (lua_State *L, Table *t, const TValue *ek) {
- unsigned int asize; /* optimal size for array part */
- unsigned int na; /* number of keys in the array part */
- unsigned int nums[MAXABITS + 1];
- int i;
- int totaluse;
- for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
- setlimittosize(t);
- na = numusearray(t, nums); /* count keys in array part */
- totaluse = na; /* all those keys are integer keys */
- totaluse += numusehash(t, nums, &na); /* count keys in hash part */
- /* count extra key */
- if (ttisinteger(ek))
- na += countint(ivalue(ek), nums);
- totaluse++;
- /* compute new size for array part */
- asize = computesizes(nums, &na);
- /* resize the table to new computed sizes */
- luaH_resize(L, t, asize, totaluse - na);
-}
-
-
-
-/*
-** }=============================================================
-*/
-
-
-Table *luaH_new (lua_State *L) {
- GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table));
- Table *t = gco2t(o);
- t->metatable = NULL;
- t->flags = cast_byte(maskflags); /* table has no metamethod fields */
- t->array = NULL;
- t->alimit = 0;
- setnodevector(L, t, 0);
- return t;
-}
-
-
-void luaH_free (lua_State *L, Table *t) {
- freehash(L, t);
- luaM_freearray(L, t->array, luaH_realasize(t));
- luaM_free(L, t);
-}
-
-
-static Node *getfreepos (Table *t) {
- if (!isdummy(t)) {
- while (t->lastfree > t->node) {
- t->lastfree--;
- if (keyisnil(t->lastfree))
- return t->lastfree;
- }
- }
- return NULL; /* could not find a free place */
-}
-
-
-
-/*
-** inserts a new key into a hash table; first, check whether key's main
-** position is free. If not, check whether colliding node is in its main
-** position or not: if it is not, move colliding node to an empty place and
-** put new key in its main position; otherwise (colliding node is in its main
-** position), new key goes to an empty position.
-*/
-void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
- Node *mp;
- TValue aux;
- if (l_unlikely(ttisnil(key)))
- luaG_runerror(L, "table index is nil");
- else if (ttisfloat(key)) {
- lua_Number f = fltvalue(key);
- lua_Integer k;
- if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */
- setivalue(&aux, k);
- key = &aux; /* insert it as an integer */
- }
- else if (l_unlikely(luai_numisnan(f)))
- luaG_runerror(L, "table index is NaN");
- }
- if (ttisnil(value))
- return; /* do not insert nil values */
- mp = mainpositionTV(t, key);
- if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */
- Node *othern;
- Node *f = getfreepos(t); /* get a free place */
- if (f == NULL) { /* cannot find a free place? */
- rehash(L, t, key); /* grow table */
- /* whatever called 'newkey' takes care of TM cache */
- luaH_set(L, t, key, value); /* insert key into grown table */
- return;
- }
- lua_assert(!isdummy(t));
- othern = mainpositionfromnode(t, mp);
- if (othern != mp) { /* is colliding node out of its main position? */
- /* yes; move colliding node into free position */
- while (othern + gnext(othern) != mp) /* find previous */
- othern += gnext(othern);
- gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */
- *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */
- if (gnext(mp) != 0) {
- gnext(f) += cast_int(mp - f); /* correct 'next' */
- gnext(mp) = 0; /* now 'mp' is free */
- }
- setempty(gval(mp));
- }
- else { /* colliding node is in its own main position */
- /* new node will go into free position */
- if (gnext(mp) != 0)
- gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */
- else lua_assert(gnext(f) == 0);
- gnext(mp) = cast_int(f - mp);
- mp = f;
- }
- }
- setnodekey(L, mp, key);
- luaC_barrierback(L, obj2gco(t), key);
- lua_assert(isempty(gval(mp)));
- setobj2t(L, gval(mp), value);
-}
-
-
-/*
-** Search function for integers. If integer is inside 'alimit', get it
-** directly from the array part. Otherwise, if 'alimit' is not equal to
-** the real size of the array, key still can be in the array part. In
-** this case, try to avoid a call to 'luaH_realasize' when key is just
-** one more than the limit (so that it can be incremented without
-** changing the real size of the array).
-*/
-const TValue *luaH_getint (Table *t, lua_Integer key) {
- if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */
- return &t->array[key - 1];
- else if (!limitequalsasize(t) && /* key still may be in the array part? */
- (l_castS2U(key) == t->alimit + 1 ||
- l_castS2U(key) - 1u < luaH_realasize(t))) {
- t->alimit = cast_uint(key); /* probably '#t' is here now */
- return &t->array[key - 1];
- }
- else {
- Node *n = hashint(t, key);
- for (;;) { /* check whether 'key' is somewhere in the chain */
- if (keyisinteger(n) && keyival(n) == key)
- return gval(n); /* that's it */
- else {
- int nx = gnext(n);
- if (nx == 0) break;
- n += nx;
- }
- }
- return &absentkey;
- }
-}
-
-
-/*
-** search function for short strings
-*/
-const TValue *luaH_getshortstr (Table *t, TString *key) {
- Node *n = hashstr(t, key);
- lua_assert(key->tt == LUA_VSHRSTR);
- for (;;) { /* check whether 'key' is somewhere in the chain */
- if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
- return gval(n); /* that's it */
- else {
- int nx = gnext(n);
- if (nx == 0)
- return &absentkey; /* not found */
- n += nx;
- }
- }
-}
-
-
-const TValue *luaH_getstr (Table *t, TString *key) {
- if (key->tt == LUA_VSHRSTR)
- return luaH_getshortstr(t, key);
- else { /* for long strings, use generic case */
- TValue ko;
- setsvalue(cast(lua_State *, NULL), &ko, key);
- return getgeneric(t, &ko, 0);
- }
-}
-
-
-/*
-** main search function
-*/
-const TValue *luaH_get (Table *t, const TValue *key) {
- switch (ttypetag(key)) {
- case LUA_VSHRSTR: return luaH_getshortstr(t, tsvalue(key));
- case LUA_VNUMINT: return luaH_getint(t, ivalue(key));
- case LUA_VNIL: return &absentkey;
- case LUA_VNUMFLT: {
- lua_Integer k;
- if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */
- return luaH_getint(t, k); /* use specialized version */
- /* else... */
- } /* FALLTHROUGH */
- default:
- return getgeneric(t, key, 0);
- }
-}
-
-
-/*
-** Finish a raw "set table" operation, where 'slot' is where the value
-** should have been (the result of a previous "get table").
-** Beware: when using this function you probably need to check a GC
-** barrier and invalidate the TM cache.
-*/
-void luaH_finishset (lua_State *L, Table *t, const TValue *key,
- const TValue *slot, TValue *value) {
- if (isabstkey(slot))
- luaH_newkey(L, t, key, value);
- else
- setobj2t(L, cast(TValue *, slot), value);
-}
-
-
-/*
-** beware: when using this function you probably need to check a GC
-** barrier and invalidate the TM cache.
-*/
-void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) {
- const TValue *slot = luaH_get(t, key);
- luaH_finishset(L, t, key, slot, value);
-}
-
-
-void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
- const TValue *p = luaH_getint(t, key);
- if (isabstkey(p)) {
- TValue k;
- setivalue(&k, key);
- luaH_newkey(L, t, &k, value);
- }
- else
- setobj2t(L, cast(TValue *, p), value);
-}
-
-
-/*
-** Try to find a boundary in the hash part of table 't'. From the
-** caller, we know that 'j' is zero or present and that 'j + 1' is
-** present. We want to find a larger key that is absent from the
-** table, so that we can do a binary search between the two keys to
-** find a boundary. We keep doubling 'j' until we get an absent index.
-** If the doubling would overflow, we try LUA_MAXINTEGER. If it is
-** absent, we are ready for the binary search. ('j', being max integer,
-** is larger or equal to 'i', but it cannot be equal because it is
-** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a
-** boundary. ('j + 1' cannot be a present integer key because it is
-** not a valid integer in Lua.)
-*/
-static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
- lua_Unsigned i;
- if (j == 0) j++; /* the caller ensures 'j + 1' is present */
- do {
- i = j; /* 'i' is a present index */
- if (j <= l_castS2U(LUA_MAXINTEGER) / 2)
- j *= 2;
- else {
- j = LUA_MAXINTEGER;
- if (isempty(luaH_getint(t, j))) /* t[j] not present? */
- break; /* 'j' now is an absent index */
- else /* weird case */
- return j; /* well, max integer is a boundary... */
- }
- } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */
- /* i < j && t[i] present && t[j] absent */
- while (j - i > 1u) { /* do a binary search between them */
- lua_Unsigned m = (i + j) / 2;
- if (isempty(luaH_getint(t, m))) j = m;
- else i = m;
- }
- return i;
-}
-
-
-static unsigned int binsearch (const TValue *array, unsigned int i,
- unsigned int j) {
- while (j - i > 1u) { /* binary search */
- unsigned int m = (i + j) / 2;
- if (isempty(&array[m - 1])) j = m;
- else i = m;
- }
- return i;
-}
-
-
-/*
-** Try to find a boundary in table 't'. (A 'boundary' is an integer index
-** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent
-** and 'maxinteger' if t[maxinteger] is present.)
-** (In the next explanation, we use Lua indices, that is, with base 1.
-** The code itself uses base 0 when indexing the array part of the table.)
-** The code starts with 'limit = t->alimit', a position in the array
-** part that may be a boundary.
-**
-** (1) If 't[limit]' is empty, there must be a boundary before it.
-** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1'
-** is present. If so, it is a boundary. Otherwise, do a binary search
-** between 0 and limit to find a boundary. In both cases, try to
-** use this boundary as the new 'alimit', as a hint for the next call.
-**
-** (2) If 't[limit]' is not empty and the array has more elements
-** after 'limit', try to find a boundary there. Again, try first
-** the special case (which should be quite frequent) where 'limit+1'
-** is empty, so that 'limit' is a boundary. Otherwise, check the
-** last element of the array part. If it is empty, there must be a
-** boundary between the old limit (present) and the last element
-** (absent), which is found with a binary search. (This boundary always
-** can be a new limit.)
-**
-** (3) The last case is when there are no elements in the array part
-** (limit == 0) or its last element (the new limit) is present.
-** In this case, must check the hash part. If there is no hash part
-** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call
-** 'hash_search' to find a boundary in the hash part of the table.
-** (In those cases, the boundary is not inside the array part, and
-** therefore cannot be used as a new limit.)
-*/
-lua_Unsigned luaH_getn (Table *t) {
- unsigned int limit = t->alimit;
- if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */
- /* there must be a boundary before 'limit' */
- if (limit >= 2 && !isempty(&t->array[limit - 2])) {
- /* 'limit - 1' is a boundary; can it be a new limit? */
- if (ispow2realasize(t) && !ispow2(limit - 1)) {
- t->alimit = limit - 1;
- setnorealasize(t); /* now 'alimit' is not the real size */
- }
- return limit - 1;
- }
- else { /* must search for a boundary in [0, limit] */
- unsigned int boundary = binsearch(t->array, 0, limit);
- /* can this boundary represent the real size of the array? */
- if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) {
- t->alimit = boundary; /* use it as the new limit */
- setnorealasize(t);
- }
- return boundary;
- }
- }
- /* 'limit' is zero or present in table */
- if (!limitequalsasize(t)) { /* (2)? */
- /* 'limit' > 0 and array has more elements after 'limit' */
- if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */
- return limit; /* this is the boundary */
- /* else, try last element in the array */
- limit = luaH_realasize(t);
- if (isempty(&t->array[limit - 1])) { /* empty? */
- /* there must be a boundary in the array after old limit,
- and it must be a valid new limit */
- unsigned int boundary = binsearch(t->array, t->alimit, limit);
- t->alimit = boundary;
- return boundary;
- }
- /* else, new limit is present in the table; check the hash part */
- }
- /* (3) 'limit' is the last element and either is zero or present in table */
- lua_assert(limit == luaH_realasize(t) &&
- (limit == 0 || !isempty(&t->array[limit - 1])));
- if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1))))
- return limit; /* 'limit + 1' is absent */
- else /* 'limit + 1' is also present */
- return hash_search(t, limit);
-}
-
-
-
-#if defined(LUA_DEBUG)
-
-/* export these functions for the test library */
-
-Node *luaH_mainposition (const Table *t, const TValue *key) {
- return mainpositionTV(t, key);
-}
-
-int luaH_isdummy (const Table *t) { return isdummy(t); }
-
-#endif
diff --git a/lua-5.4.4/library/ltable.h b/lua-5.4.4/library/ltable.h
deleted file mode 100644
index 7bbbcb21..00000000
--- a/lua-5.4.4/library/ltable.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-** $Id: ltable.h $
-** Lua tables (hash)
-** See Copyright Notice in lua.h
-*/
-
-#ifndef ltable_h
-#define ltable_h
-
-#include "lobject.h"
-
-
-#define gnode(t,i) (&(t)->node[i])
-#define gval(n) (&(n)->i_val)
-#define gnext(n) ((n)->u.next)
-
-
-/*
-** Clear all bits of fast-access metamethods, which means that the table
-** may have any of these metamethods. (First access that fails after the
-** clearing will set the bit again.)
-*/
-#define invalidateTMcache(t) ((t)->flags &= ~maskflags)
-
-
-/* true when 't' is using 'dummynode' as its hash part */
-#define isdummy(t) ((t)->lastfree == NULL)
-
-
-/* allocated size for hash nodes */
-#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
-
-
-/* returns the Node, given the value of a table entry */
-#define nodefromval(v) cast(Node *, (v))
-
-
-LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
-LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
- TValue *value);
-LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
-LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
-LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
-LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key,
- TValue *value);
-LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
- TValue *value);
-LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
- const TValue *slot, TValue *value);
-LUAI_FUNC Table *luaH_new (lua_State *L);
-LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
- unsigned int nhsize);
-LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
-LUAI_FUNC void luaH_free (lua_State *L, Table *t);
-LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
-LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
-LUAI_FUNC unsigned int luaH_realasize (const Table *t);
-
-
-#if defined(LUA_DEBUG)
-LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
-LUAI_FUNC int luaH_isdummy (const Table *t);
-#endif
-
-
-#endif
diff --git a/lua-5.4.4/library/ltablib.c b/lua-5.4.4/library/ltablib.c
deleted file mode 100644
index 868d78fd..00000000
--- a/lua-5.4.4/library/ltablib.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
-** $Id: ltablib.c $
-** Library for Table Manipulation
-** See Copyright Notice in lua.h
-*/
-
-#define ltablib_c
-#define LUA_LIB
-
-#include "lprefix.h"
-
-
-#include
-#include
-#include
-
-#include "lua.h"
-
-#include "lauxlib.h"
-#include "lualib.h"
-
-
-/*
-** Operations that an object must define to mimic a table
-** (some functions only need some of them)
-*/
-#define TAB_R 1 /* read */
-#define TAB_W 2 /* write */
-#define TAB_L 4 /* length */
-#define TAB_RW (TAB_R | TAB_W) /* read/write */
-
-
-#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n))
-
-
-static int checkfield (lua_State *L, const char *key, int n) {
- lua_pushstring(L, key);
- return (lua_rawget(L, -n) != LUA_TNIL);
-}
-
-
-/*
-** Check that 'arg' either is a table or can behave like one (that is,
-** has a metatable with the required metamethods)
-*/
-static void checktab (lua_State *L, int arg, int what) {
- if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */
- int n = 1; /* number of elements to pop */
- if (lua_getmetatable(L, arg) && /* must have metatable */
- (!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
- (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
- (!(what & TAB_L) || checkfield(L, "__len", ++n))) {
- lua_pop(L, n); /* pop metatable and tested metamethods */
- }
- else
- luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
- }
-}
-
-
-static int tinsert (lua_State *L) {
- lua_Integer pos; /* where to insert new element */
- lua_Integer e = aux_getn(L, 1, TAB_RW);
- e = luaL_intop(+, e, 1); /* first empty element */
- switch (lua_gettop(L)) {
- case 2: { /* called with only 2 arguments */
- pos = e; /* insert new element at the end */
- break;
- }
- case 3: {
- lua_Integer i;
- pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
- /* check whether 'pos' is in [1, e] */
- luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2,
- "position out of bounds");
- for (i = e; i > pos; i--) { /* move up elements */
- lua_geti(L, 1, i - 1);
- lua_seti(L, 1, i); /* t[i] = t[i - 1] */
- }
- break;
- }
- default: {
- return luaL_error(L, "wrong number of arguments to 'insert'");
- }
- }
- lua_seti(L, 1, pos); /* t[pos] = v */
- return 0;
-}
-
-
-static int tremove (lua_State *L) {
- lua_Integer size = aux_getn(L, 1, TAB_RW);
- lua_Integer pos = luaL_optinteger(L, 2, size);
- if (pos != size) /* validate 'pos' if given */
- /* check whether 'pos' is in [1, size + 1] */
- luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1,
- "position out of bounds");
- lua_geti(L, 1, pos); /* result = t[pos] */
- for ( ; pos < size; pos++) {
- lua_geti(L, 1, pos + 1);
- lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
- }
- lua_pushnil(L);
- lua_seti(L, 1, pos); /* remove entry t[pos] */
- return 1;
-}
-
-
-/*
-** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
-** possible, copy in increasing order, which is better for rehashing.
-** "possible" means destination after original range, or smaller
-** than origin, or copying to another table.
-*/
-static int tmove (lua_State *L) {
- lua_Integer f = luaL_checkinteger(L, 2);
- lua_Integer e = luaL_checkinteger(L, 3);
- lua_Integer t = luaL_checkinteger(L, 4);
- int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
- checktab(L, 1, TAB_R);
- checktab(L, tt, TAB_W);
- if (e >= f) { /* otherwise, nothing to move */
- lua_Integer n, i;
- luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
- "too many elements to move");
- n = e - f + 1; /* number of elements to move */
- luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
- "destination wrap around");
- if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
- for (i = 0; i < n; i++) {
- lua_geti(L, 1, f + i);
- lua_seti(L, tt, t + i);
- }
- }
- else {
- for (i = n - 1; i >= 0; i--) {
- lua_geti(L, 1, f + i);
- lua_seti(L, tt, t + i);
- }
- }
- }
- lua_pushvalue(L, tt); /* return destination table */
- return 1;
-}
-
-
-static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
- lua_geti(L, 1, i);
- if (l_unlikely(!lua_isstring(L, -1)))
- luaL_error(L, "invalid value (%s) at index %I in table for 'concat'",
- luaL_typename(L, -1), (LUAI_UACINT)i);
- luaL_addvalue(b);
-}
-
-
-static int tconcat (lua_State *L) {
- luaL_Buffer b;
- lua_Integer last = aux_getn(L, 1, TAB_R);
- size_t lsep;
- const char *sep = luaL_optlstring(L, 2, "", &lsep);
- lua_Integer i = luaL_optinteger(L, 3, 1);
- last = luaL_optinteger(L, 4, last);
- luaL_buffinit(L, &b);
- for (; i < last; i++) {
- addfield(L, &b, i);
- luaL_addlstring(&b, sep, lsep);
- }
- if (i == last) /* add last value (if interval was not empty) */
- addfield(L, &b, i);
- luaL_pushresult(&b);
- return 1;
-}
-
-
-/*
-** {======================================================
-** Pack/unpack
-** =======================================================
-*/
-
-static int tpack (lua_State *L) {
- int i;
- int n = lua_gettop(L); /* number of elements to pack */
- lua_createtable(L, n, 1); /* create result table */
- lua_insert(L, 1); /* put it at index 1 */
- for (i = n; i >= 1; i--) /* assign elements */
- lua_seti(L, 1, i);
- lua_pushinteger(L, n);
- lua_setfield(L, 1, "n"); /* t.n = number of elements */
- return 1; /* return table */
-}
-
-
-static int tunpack (lua_State *L) {
- lua_Unsigned n;
- lua_Integer i = luaL_optinteger(L, 2, 1);
- lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
- if (i > e) return 0; /* empty range */
- n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
- if (l_unlikely(n >= (unsigned int)INT_MAX ||
- !lua_checkstack(L, (int)(++n))))
- return luaL_error(L, "too many results to unpack");
- for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */
- lua_geti(L, 1, i);
- }
- lua_geti(L, 1, e); /* push last element */
- return (int)n;
-}
-
-/* }====================================================== */
-
-
-
-/*
-** {======================================================
-** Quicksort
-** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
-** Addison-Wesley, 1993.)
-** =======================================================
-*/
-
-
-/* type for array indices */
-typedef unsigned int IdxT;
-
-
-/*
-** Produce a "random" 'unsigned int' to randomize pivot choice. This
-** macro is used only when 'sort' detects a big imbalance in the result
-** of a partition. (If you don't want/need this "randomness", ~0 is a
-** good choice.)
-*/
-#if !defined(l_randomizePivot) /* { */
-
-#include
-
-/* size of 'e' measured in number of 'unsigned int's */
-#define sof(e) (sizeof(e) / sizeof(unsigned int))
-
-/*
-** Use 'time' and 'clock' as sources of "randomness". Because we don't
-** know the types 'clock_t' and 'time_t', we cannot cast them to
-** anything without risking overflows. A safe way to use their values
-** is to copy them to an array of a known type and use the array values.
-*/
-static unsigned int l_randomizePivot (void) {
- clock_t c = clock();
- time_t t = time(NULL);
- unsigned int buff[sof(c) + sof(t)];
- unsigned int i, rnd = 0;
- memcpy(buff, &c, sof(c) * sizeof(unsigned int));
- memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
- for (i = 0; i < sof(buff); i++)
- rnd += buff[i];
- return rnd;
-}
-
-#endif /* } */
-
-
-/* arrays larger than 'RANLIMIT' may use randomized pivots */
-#define RANLIMIT 100u
-
-
-static void set2 (lua_State *L, IdxT i, IdxT j) {
- lua_seti(L, 1, i);
- lua_seti(L, 1, j);
-}
-
-
-/*
-** Return true iff value at stack index 'a' is less than the value at
-** index 'b' (according to the order of the sort).
-*/
-static int sort_comp (lua_State *L, int a, int b) {
- if (lua_isnil(L, 2)) /* no function? */
- return lua_compare(L, a, b, LUA_OPLT); /* a < b */
- else { /* function */
- int res;
- lua_pushvalue(L, 2); /* push function */
- lua_pushvalue(L, a-1); /* -1 to compensate function */
- lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
- lua_call(L, 2, 1); /* call function */
- res = lua_toboolean(L, -1); /* get result */
- lua_pop(L, 1); /* pop result */
- return res;
- }
-}
-
-
-/*
-** Does the partition: Pivot P is at the top of the stack.
-** precondition: a[lo] <= P == a[up-1] <= a[up],
-** so it only needs to do the partition from lo + 1 to up - 2.
-** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
-** returns 'i'.
-*/
-static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
- IdxT i = lo; /* will be incremented before first use */
- IdxT j = up - 1; /* will be decremented before first use */
- /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
- for (;;) {
- /* next loop: repeat ++i while a[i] < P */
- while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
- if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */
- luaL_error(L, "invalid order function for sorting");
- lua_pop(L, 1); /* remove a[i] */
- }
- /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
- /* next loop: repeat --j while P < a[j] */
- while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
- if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */
- luaL_error(L, "invalid order function for sorting");
- lua_pop(L, 1); /* remove a[j] */
- }
- /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
- if (j < i) { /* no elements out of place? */
- /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
- lua_pop(L, 1); /* pop a[j] */
- /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
- set2(L, up - 1, i);
- return i;
- }
- /* otherwise, swap a[i] - a[j] to restore invariant and repeat */
- set2(L, i, j);
- }
-}
-
-
-/*
-** Choose an element in the middle (2nd-3th quarters) of [lo,up]
-** "randomized" by 'rnd'
-*/
-static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
- IdxT r4 = (up - lo) / 4; /* range/4 */
- IdxT p = rnd % (r4 * 2) + (lo + r4);
- lua_assert(lo + r4 <= p && p <= up - r4);
- return p;
-}
-
-
-/*
-** Quicksort algorithm (recursive function)
-*/
-static void auxsort (lua_State *L, IdxT lo, IdxT up,
- unsigned int rnd) {
- while (lo < up) { /* loop for tail recursion */
- IdxT p; /* Pivot index */
- IdxT n; /* to be used later */
- /* sort elements 'lo', 'p', and 'up' */
- lua_geti(L, 1, lo);
- lua_geti(L, 1, up);
- if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */
- set2(L, lo, up); /* swap a[lo] - a[up] */
- else
- lua_pop(L, 2); /* remove both values */
- if (up - lo == 1) /* only 2 elements? */
- return; /* already sorted */
- if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */
- p = (lo + up)/2; /* middle element is a good pivot */
- else /* for larger intervals, it is worth a random pivot */
- p = choosePivot(lo, up, rnd);
- lua_geti(L, 1, p);
- lua_geti(L, 1, lo);
- if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
- set2(L, p, lo); /* swap a[p] - a[lo] */
- else {
- lua_pop(L, 1); /* remove a[lo] */
- lua_geti(L, 1, up);
- if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */
- set2(L, p, up); /* swap a[up] - a[p] */
- else
- lua_pop(L, 2);
- }
- if (up - lo == 2) /* only 3 elements? */
- return; /* already sorted */
- lua_geti(L, 1, p); /* get middle element (Pivot) */
- lua_pushvalue(L, -1); /* push Pivot */
- lua_geti(L, 1, up - 1); /* push a[up - 1] */
- set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */
- p = partition(L, lo, up);
- /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
- if (p - lo < up - p) { /* lower interval is smaller? */
- auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */
- n = p - lo; /* size of smaller interval */
- lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */
- }
- else {
- auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */
- n = up - p; /* size of smaller interval */
- up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
- }
- if ((up - lo) / 128 > n) /* partition too imbalanced? */
- rnd = l_randomizePivot(); /* try a new randomization */
- } /* tail call auxsort(L, lo, up, rnd) */
-}
-
-
-static int sort (lua_State *L) {
- lua_Integer n = aux_getn(L, 1, TAB_RW);
- if (n > 1) { /* non-trivial interval? */
- luaL_argcheck(L, n < INT_MAX, 1, "array too big");
- if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
- luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
- lua_settop(L, 2); /* make sure there are two arguments */
- auxsort(L, 1, (IdxT)n, 0);
- }
- return 0;
-}
-
-/* }====================================================== */
-
-
-static const luaL_Reg tab_funcs[] = {
- {"concat", tconcat},
- {"insert", tinsert},
- {"pack", tpack},
- {"unpack", tunpack},
- {"remove", tremove},
- {"move", tmove},
- {"sort", sort},
- {NULL, NULL}
-};
-
-
-LUAMOD_API int luaopen_table (lua_State *L) {
- luaL_newlib(L, tab_funcs);
- return 1;
-}
-
diff --git a/lua-5.4.4/library/ltm.c b/lua-5.4.4/library/ltm.c
deleted file mode 100644
index b657b783..00000000
--- a/lua-5.4.4/library/ltm.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-** $Id: ltm.c $
-** Tag methods
-** See Copyright Notice in lua.h
-*/
-
-#define ltm_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-
-#include "lua.h"
-
-#include "ldebug.h"
-#include "ldo.h"
-#include "lgc.h"
-#include "lobject.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-#include "ltm.h"
-#include "lvm.h"
-
-
-static const char udatatypename[] = "userdata";
-
-LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = {
- "no value",
- "nil", "boolean", udatatypename, "number",
- "string", "table", "function", udatatypename, "thread",
- "upvalue", "proto" /* these last cases are used for tests only */
-};
-
-
-void luaT_init (lua_State *L) {
- static const char *const luaT_eventname[] = { /* ORDER TM */
- "__index", "__newindex",
- "__gc", "__mode", "__len", "__eq",
- "__add", "__sub", "__mul", "__mod", "__pow",
- "__div", "__idiv",
- "__band", "__bor", "__bxor", "__shl", "__shr",
- "__unm", "__bnot", "__lt", "__le",
- "__concat", "__call", "__close"
- };
- int i;
- for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]);
- luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */
- }
-}
-
-
-/*
-** function to be used with macro "fasttm": optimized for absence of
-** tag methods
-*/
-const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
- const TValue *tm = luaH_getshortstr(events, ename);
- lua_assert(event <= TM_EQ);
- if (notm(tm)) { /* no tag method? */
- events->flags |= cast_byte(1u<metatable;
- break;
- case LUA_TUSERDATA:
- mt = uvalue(o)->metatable;
- break;
- default:
- mt = G(L)->mt[ttype(o)];
- }
- return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue);
-}
-
-
-/*
-** Return the name of the type of an object. For tables and userdata
-** with metatable, use their '__name' metafield, if present.
-*/
-const char *luaT_objtypename (lua_State *L, const TValue *o) {
- Table *mt;
- if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
- (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
- const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
- if (ttisstring(name)) /* is '__name' a string? */
- return getstr(tsvalue(name)); /* use it as type name */
- }
- return ttypename(ttype(o)); /* else use standard type name */
-}
-
-
-void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, const TValue *p3) {
- StkId func = L->top;
- setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
- setobj2s(L, func + 1, p1); /* 1st argument */
- setobj2s(L, func + 2, p2); /* 2nd argument */
- setobj2s(L, func + 3, p3); /* 3rd argument */
- L->top = func + 4;
- /* metamethod may yield only when called from Lua code */
- if (isLuacode(L->ci))
- luaD_call(L, func, 0);
- else
- luaD_callnoyield(L, func, 0);
-}
-
-
-void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, StkId res) {
- ptrdiff_t result = savestack(L, res);
- StkId func = L->top;
- setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
- setobj2s(L, func + 1, p1); /* 1st argument */
- setobj2s(L, func + 2, p2); /* 2nd argument */
- L->top += 3;
- /* metamethod may yield only when called from Lua code */
- if (isLuacode(L->ci))
- luaD_call(L, func, 1);
- else
- luaD_callnoyield(L, func, 1);
- res = restorestack(L, result);
- setobjs2s(L, res, --L->top); /* move result to its place */
-}
-
-
-static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
- if (notm(tm))
- tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
- if (notm(tm)) return 0;
- luaT_callTMres(L, tm, p1, p2, res);
- return 1;
-}
-
-
-void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- if (l_unlikely(!callbinTM(L, p1, p2, res, event))) {
- switch (event) {
- case TM_BAND: case TM_BOR: case TM_BXOR:
- case TM_SHL: case TM_SHR: case TM_BNOT: {
- if (ttisnumber(p1) && ttisnumber(p2))
- luaG_tointerror(L, p1, p2);
- else
- luaG_opinterror(L, p1, p2, "perform bitwise operation on");
- }
- /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
- default:
- luaG_opinterror(L, p1, p2, "perform arithmetic on");
- }
- }
-}
-
-
-void luaT_tryconcatTM (lua_State *L) {
- StkId top = L->top;
- if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2,
- TM_CONCAT)))
- luaG_concaterror(L, s2v(top - 2), s2v(top - 1));
-}
-
-
-void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2,
- int flip, StkId res, TMS event) {
- if (flip)
- luaT_trybinTM(L, p2, p1, res, event);
- else
- luaT_trybinTM(L, p1, p2, res, event);
-}
-
-
-void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
- int flip, StkId res, TMS event) {
- TValue aux;
- setivalue(&aux, i2);
- luaT_trybinassocTM(L, p1, &aux, flip, res, event);
-}
-
-
-/*
-** Calls an order tag method.
-** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old
-** behavior: if there is no '__le', try '__lt', based on l <= r iff
-** !(r < l) (assuming a total order). If the metamethod yields during
-** this substitution, the continuation has to know about it (to negate
-** the result of rtop, event)) /* try original event */
- return !l_isfalse(s2v(L->top));
-#if defined(LUA_COMPAT_LT_LE)
- else if (event == TM_LE) {
- /* try '!(p2 < p1)' for '(p1 <= p2)' */
- L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
- if (callbinTM(L, p2, p1, L->top, TM_LT)) {
- L->ci->callstatus ^= CIST_LEQ; /* clear mark */
- return l_isfalse(s2v(L->top));
- }
- /* else error will remove this 'ci'; no need to clear mark */
- }
-#endif
- luaG_ordererror(L, p1, p2); /* no metamethod found */
- return 0; /* to avoid warnings */
-}
-
-
-int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
- int flip, int isfloat, TMS event) {
- TValue aux; const TValue *p2;
- if (isfloat) {
- setfltvalue(&aux, cast_num(v2));
- }
- else
- setivalue(&aux, v2);
- if (flip) { /* arguments were exchanged? */
- p2 = p1; p1 = &aux; /* correct them */
- }
- else
- p2 = &aux;
- return luaT_callorderTM(L, p1, p2, event);
-}
-
-
-void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
- const Proto *p) {
- int i;
- int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */
- int nextra = actual - nfixparams; /* number of extra arguments */
- ci->u.l.nextraargs = nextra;
- luaD_checkstack(L, p->maxstacksize + 1);
- /* copy function to the top of the stack */
- setobjs2s(L, L->top++, ci->func);
- /* move fixed parameters to the top of the stack */
- for (i = 1; i <= nfixparams; i++) {
- setobjs2s(L, L->top++, ci->func + i);
- setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */
- }
- ci->func += actual + 1;
- ci->top += actual + 1;
- lua_assert(L->top <= ci->top && ci->top <= L->stack_last);
-}
-
-
-void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
- int i;
- int nextra = ci->u.l.nextraargs;
- if (wanted < 0) {
- wanted = nextra; /* get all extra arguments available */
- checkstackGCp(L, nextra, where); /* ensure stack space */
- L->top = where + nextra; /* next instruction will need top */
- }
- for (i = 0; i < wanted && i < nextra; i++)
- setobjs2s(L, where + i, ci->func - nextra + i);
- for (; i < wanted; i++) /* complete required results with nil */
- setnilvalue(s2v(where + i));
-}
-
diff --git a/lua-5.4.4/library/ltm.h b/lua-5.4.4/library/ltm.h
deleted file mode 100644
index 73b833c6..00000000
--- a/lua-5.4.4/library/ltm.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-** $Id: ltm.h $
-** Tag methods
-** See Copyright Notice in lua.h
-*/
-
-#ifndef ltm_h
-#define ltm_h
-
-
-#include "lobject.h"
-
-
-/*
-* WARNING: if you change the order of this enumeration,
-* grep "ORDER TM" and "ORDER OP"
-*/
-typedef enum {
- TM_INDEX,
- TM_NEWINDEX,
- TM_GC,
- TM_MODE,
- TM_LEN,
- TM_EQ, /* last tag method with fast access */
- TM_ADD,
- TM_SUB,
- TM_MUL,
- TM_MOD,
- TM_POW,
- TM_DIV,
- TM_IDIV,
- TM_BAND,
- TM_BOR,
- TM_BXOR,
- TM_SHL,
- TM_SHR,
- TM_UNM,
- TM_BNOT,
- TM_LT,
- TM_LE,
- TM_CONCAT,
- TM_CALL,
- TM_CLOSE,
- TM_N /* number of elements in the enum */
-} TMS;
-
-
-/*
-** Mask with 1 in all fast-access methods. A 1 in any of these bits
-** in the flag of a (meta)table means the metatable does not have the
-** corresponding metamethod field. (Bit 7 of the flag is used for
-** 'isrealasize'.)
-*/
-#define maskflags (~(~0u << (TM_EQ + 1)))
-
-
-/*
-** Test whether there is no tagmethod.
-** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
-*/
-#define notm(tm) ttisnil(tm)
-
-
-#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
- ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
-
-#define fasttm(l,et,e) gfasttm(G(l), et, e)
-
-#define ttypename(x) luaT_typenames_[(x) + 1]
-
-LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];)
-
-
-LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
-
-LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
-LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
- TMS event);
-LUAI_FUNC void luaT_init (lua_State *L);
-
-LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, const TValue *p3);
-LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f,
- const TValue *p1, const TValue *p2, StkId p3);
-LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event);
-LUAI_FUNC void luaT_tryconcatTM (lua_State *L);
-LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1,
- const TValue *p2, int inv, StkId res, TMS event);
-LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
- int inv, StkId res, TMS event);
-LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
- const TValue *p2, TMS event);
-LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
- int inv, int isfloat, TMS event);
-
-LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
- struct CallInfo *ci, const Proto *p);
-LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
- StkId where, int wanted);
-
-
-#endif
diff --git a/lua-5.4.4/library/lua.h b/lua-5.4.4/library/lua.h
deleted file mode 100644
index e6618392..00000000
--- a/lua-5.4.4/library/lua.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
-** $Id: lua.h $
-** Lua - A Scripting Language
-** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
-** See Copyright Notice at the end of this file
-*/
-
-
-#ifndef lua_h
-#define lua_h
-
-#include
-#include
-
-
-#include "luaconf.h"
-
-
-#define LUA_VERSION_MAJOR "5"
-#define LUA_VERSION_MINOR "4"
-#define LUA_VERSION_RELEASE "4"
-
-#define LUA_VERSION_NUM 504
-#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4)
-
-#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
-#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio"
-#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
-
-
-/* mark for precompiled code ('Lua') */
-#define LUA_SIGNATURE "\x1bLua"
-
-/* option for multiple returns in 'lua_pcall' and 'lua_call' */
-#define LUA_MULTRET (-1)
-
-
-/*
-** Pseudo-indices
-** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
-** space after that to help overflow detection)
-*/
-#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
-#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
-
-
-/* thread status */
-#define LUA_OK 0
-#define LUA_YIELD 1
-#define LUA_ERRRUN 2
-#define LUA_ERRSYNTAX 3
-#define LUA_ERRMEM 4
-#define LUA_ERRERR 5
-
-
-typedef struct lua_State lua_State;
-
-
-/*
-** basic types
-*/
-#define LUA_TNONE (-1)
-
-#define LUA_TNIL 0
-#define LUA_TBOOLEAN 1
-#define LUA_TLIGHTUSERDATA 2
-#define LUA_TNUMBER 3
-#define LUA_TSTRING 4
-#define LUA_TTABLE 5
-#define LUA_TFUNCTION 6
-#define LUA_TUSERDATA 7
-#define LUA_TTHREAD 8
-
-#define LUA_NUMTYPES 9
-
-
-
-/* minimum Lua stack available to a C function */
-#define LUA_MINSTACK 20
-
-
-/* predefined values in the registry */
-#define LUA_RIDX_MAINTHREAD 1
-#define LUA_RIDX_GLOBALS 2
-#define LUA_RIDX_LAST LUA_RIDX_GLOBALS
-
-
-/* type of numbers in Lua */
-typedef LUA_NUMBER lua_Number;
-
-
-/* type for integer functions */
-typedef LUA_INTEGER lua_Integer;
-
-/* unsigned integer type */
-typedef LUA_UNSIGNED lua_Unsigned;
-
-/* type for continuation-function contexts */
-typedef LUA_KCONTEXT lua_KContext;
-
-
-/*
-** Type for C functions registered with Lua
-*/
-typedef int (*lua_CFunction) (lua_State *L);
-
-/*
-** Type for continuation functions
-*/
-typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);
-
-
-/*
-** Type for functions that read/write blocks when loading/dumping Lua chunks
-*/
-typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
-
-typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud);
-
-
-/*
-** Type for memory-allocation functions
-*/
-typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
-
-
-/*
-** Type for warning functions
-*/
-typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
-
-
-
-
-/*
-** generic extra include file
-*/
-#if defined(LUA_USER_H)
-#include LUA_USER_H
-#endif
-
-
-/*
-** RCS ident string
-*/
-extern const char lua_ident[];
-
-
-/*
-** state manipulation
-*/
-LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
-LUA_API void (lua_close) (lua_State *L);
-LUA_API lua_State *(lua_newthread) (lua_State *L);
-LUA_API int (lua_resetthread) (lua_State *L);
-
-LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
-
-
-LUA_API lua_Number (lua_version) (lua_State *L);
-
-
-/*
-** basic stack manipulation
-*/
-LUA_API int (lua_absindex) (lua_State *L, int idx);
-LUA_API int (lua_gettop) (lua_State *L);
-LUA_API void (lua_settop) (lua_State *L, int idx);
-LUA_API void (lua_pushvalue) (lua_State *L, int idx);
-LUA_API void (lua_rotate) (lua_State *L, int idx, int n);
-LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
-LUA_API int (lua_checkstack) (lua_State *L, int n);
-
-LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
-
-
-/*
-** access functions (stack -> C)
-*/
-
-LUA_API int (lua_isnumber) (lua_State *L, int idx);
-LUA_API int (lua_isstring) (lua_State *L, int idx);
-LUA_API int (lua_iscfunction) (lua_State *L, int idx);
-LUA_API int (lua_isinteger) (lua_State *L, int idx);
-LUA_API int (lua_isuserdata) (lua_State *L, int idx);
-LUA_API int (lua_type) (lua_State *L, int idx);
-LUA_API const char *(lua_typename) (lua_State *L, int tp);
-
-LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
-LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
-LUA_API int (lua_toboolean) (lua_State *L, int idx);
-LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
-LUA_API lua_Unsigned (lua_rawlen) (lua_State *L, int idx);
-LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
-LUA_API void *(lua_touserdata) (lua_State *L, int idx);
-LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
-LUA_API const void *(lua_topointer) (lua_State *L, int idx);
-
-
-/*
-** Comparison and arithmetic functions
-*/
-
-#define LUA_OPADD 0 /* ORDER TM, ORDER OP */
-#define LUA_OPSUB 1
-#define LUA_OPMUL 2
-#define LUA_OPMOD 3
-#define LUA_OPPOW 4
-#define LUA_OPDIV 5
-#define LUA_OPIDIV 6
-#define LUA_OPBAND 7
-#define LUA_OPBOR 8
-#define LUA_OPBXOR 9
-#define LUA_OPSHL 10
-#define LUA_OPSHR 11
-#define LUA_OPUNM 12
-#define LUA_OPBNOT 13
-
-LUA_API void (lua_arith) (lua_State *L, int op);
-
-#define LUA_OPEQ 0
-#define LUA_OPLT 1
-#define LUA_OPLE 2
-
-LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
-LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
-
-
-/*
-** push functions (C -> stack)
-*/
-LUA_API void (lua_pushnil) (lua_State *L);
-LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
-LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
-LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
-LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
-LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
- va_list argp);
-LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
-LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
-LUA_API void (lua_pushboolean) (lua_State *L, int b);
-LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
-LUA_API int (lua_pushthread) (lua_State *L);
-
-
-/*
-** get functions (Lua -> stack)
-*/
-LUA_API int (lua_getglobal) (lua_State *L, const char *name);
-LUA_API int (lua_gettable) (lua_State *L, int idx);
-LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
-LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
-LUA_API int (lua_rawget) (lua_State *L, int idx);
-LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
-LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
-
-LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
-LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
-LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
-LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
-
-
-/*
-** set functions (stack -> Lua)
-*/
-LUA_API void (lua_setglobal) (lua_State *L, const char *name);
-LUA_API void (lua_settable) (lua_State *L, int idx);
-LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
-LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n);
-LUA_API void (lua_rawset) (lua_State *L, int idx);
-LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
-LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
-LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
-LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n);
-
-
-/*
-** 'load' and 'call' functions (load and run Lua code)
-*/
-LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults,
- lua_KContext ctx, lua_KFunction k);
-#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
-
-LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
- lua_KContext ctx, lua_KFunction k);
-#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
-
-LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
- const char *chunkname, const char *mode);
-
-LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
-
-
-/*
-** coroutine functions
-*/
-LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
- lua_KFunction k);
-LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg,
- int *nres);
-LUA_API int (lua_status) (lua_State *L);
-LUA_API int (lua_isyieldable) (lua_State *L);
-
-#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
-
-
-/*
-** Warning-related functions
-*/
-LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
-LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont);
-
-
-/*
-** garbage-collection function and options
-*/
-
-#define LUA_GCSTOP 0
-#define LUA_GCRESTART 1
-#define LUA_GCCOLLECT 2
-#define LUA_GCCOUNT 3
-#define LUA_GCCOUNTB 4
-#define LUA_GCSTEP 5
-#define LUA_GCSETPAUSE 6
-#define LUA_GCSETSTEPMUL 7
-#define LUA_GCISRUNNING 9
-#define LUA_GCGEN 10
-#define LUA_GCINC 11
-
-LUA_API int (lua_gc) (lua_State *L, int what, ...);
-
-
-/*
-** miscellaneous functions
-*/
-
-LUA_API int (lua_error) (lua_State *L);
-
-LUA_API int (lua_next) (lua_State *L, int idx);
-
-LUA_API void (lua_concat) (lua_State *L, int n);
-LUA_API void (lua_len) (lua_State *L, int idx);
-
-LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
-
-LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
-LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
-
-LUA_API void (lua_toclose) (lua_State *L, int idx);
-LUA_API void (lua_closeslot) (lua_State *L, int idx);
-
-
-/*
-** {==============================================================
-** some useful macros
-** ===============================================================
-*/
-
-#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
-
-#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL)
-#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL)
-
-#define lua_pop(L,n) lua_settop(L, -(n)-1)
-
-#define lua_newtable(L) lua_createtable(L, 0, 0)
-
-#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
-
-#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
-
-#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
-#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
-#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
-#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
-#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
-#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
-#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
-
-#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
-
-#define lua_pushglobaltable(L) \
- ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
-
-#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
-
-
-#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
-
-#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
-
-#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
-
-/* }============================================================== */
-
-
-/*
-** {==============================================================
-** compatibility macros
-** ===============================================================
-*/
-#if defined(LUA_COMPAT_APIINTCASTS)
-
-#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
-#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is))
-#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
-
-#endif
-
-#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
-#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
-#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1)
-
-#define LUA_NUMTAGS LUA_NUMTYPES
-
-/* }============================================================== */
-
-/*
-** {======================================================================
-** Debug API
-** =======================================================================
-*/
-
-
-/*
-** Event codes
-*/
-#define LUA_HOOKCALL 0
-#define LUA_HOOKRET 1
-#define LUA_HOOKLINE 2
-#define LUA_HOOKCOUNT 3
-#define LUA_HOOKTAILCALL 4
-
-
-/*
-** Event masks
-*/
-#define LUA_MASKCALL (1 << LUA_HOOKCALL)
-#define LUA_MASKRET (1 << LUA_HOOKRET)
-#define LUA_MASKLINE (1 << LUA_HOOKLINE)
-#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
-
-typedef struct lua_Debug lua_Debug; /* activation record */
-
-
-/* Functions to be called by the debugger in specific events */
-typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
-
-
-LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar);
-LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
-LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
-LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
-LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n);
-LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n);
-
-LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
-LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
- int fidx2, int n2);
-
-LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
-LUA_API lua_Hook (lua_gethook) (lua_State *L);
-LUA_API int (lua_gethookmask) (lua_State *L);
-LUA_API int (lua_gethookcount) (lua_State *L);
-
-LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit);
-
-struct lua_Debug {
- int event;
- const char *name; /* (n) */
- const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */
- const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */
- const char *source; /* (S) */
- size_t srclen; /* (S) */
- int currentline; /* (l) */
- int linedefined; /* (S) */
- int lastlinedefined; /* (S) */
- unsigned char nups; /* (u) number of upvalues */
- unsigned char nparams;/* (u) number of parameters */
- char isvararg; /* (u) */
- char istailcall; /* (t) */
- unsigned short ftransfer; /* (r) index of first value transferred */
- unsigned short ntransfer; /* (r) number of transferred values */
- char short_src[LUA_IDSIZE]; /* (S) */
- /* private part */
- struct CallInfo *i_ci; /* active function */
-};
-
-/* }====================================================================== */
-
-
-/******************************************************************************
-* Copyright (C) 1994-2022 Lua.org, PUC-Rio.
-*
-* Permission is hereby granted, free of charge, to any person obtaining
-* a copy of this software and associated documentation files (the
-* "Software"), to deal in the Software without restriction, including
-* without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Software, and to
-* permit persons to whom the Software is furnished to do so, subject to
-* the following conditions:
-*
-* The above copyright notice and this permission notice shall be
-* included in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-******************************************************************************/
-
-
-#endif
diff --git a/lua-5.4.4/library/luaconf.h b/lua-5.4.4/library/luaconf.h
deleted file mode 100644
index 7ce878fd..00000000
--- a/lua-5.4.4/library/luaconf.h
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
-** $Id: luaconf.h $
-** Configuration file for Lua
-** See Copyright Notice in lua.h
-*/
-
-
-#ifndef luaconf_h
-#define luaconf_h
-
-#define LUA_BUILD_AS_DLL
-
-#include
-#include
-
-
-/*
-** ===================================================================
-** General Configuration File for Lua
-**
-** Some definitions here can be changed externally, through the compiler
-** (e.g., with '-D' options): They are commented out or protected
-** by '#if !defined' guards. However, several other definitions
-** should be changed directly here, either because they affect the
-** Lua ABI (by making the changes here, you ensure that all software
-** connected to Lua, such as C libraries, will be compiled with the same
-** configuration); or because they are seldom changed.
-**
-** Search for "@@" to find all configurable definitions.
-** ===================================================================
-*/
-
-
-/*
-** {====================================================================
-** System Configuration: macros to adapt (if needed) Lua to some
-** particular platform, for instance restricting it to C89.
-** =====================================================================
-*/
-
-/*
-@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
-** Define it if you want Lua to avoid the use of a few C99 features
-** or Windows-specific features on Windows.
-*/
-/* #define LUA_USE_C89 */
-
-
-/*
-** By default, Lua on Windows use (some) specific Windows features
-*/
-#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
-#define LUA_USE_WINDOWS /* enable goodies for regular Windows */
-#endif
-
-
-#if defined(LUA_USE_WINDOWS)
-#define LUA_DL_DLL /* enable support for DLL */
-#define LUA_USE_C89 /* broadly, Windows is C89 */
-#endif
-
-
-#if defined(LUA_USE_LINUX)
-#define LUA_USE_POSIX
-#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
-#endif
-
-
-#if defined(LUA_USE_MACOSX)
-#define LUA_USE_POSIX
-#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
-#endif
-
-
-/*
-@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
-*/
-#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)
-
-/* }================================================================== */
-
-
-
-/*
-** {==================================================================
-** Configuration for Number types. These options should not be
-** set externally, because any other code connected to Lua must
-** use the same configuration.
-** ===================================================================
-*/
-
-/*
-@@ LUA_INT_TYPE defines the type for Lua integers.
-@@ LUA_FLOAT_TYPE defines the type for Lua floats.
-** Lua should work fine with any mix of these options supported
-** by your C compiler. The usual configurations are 64-bit integers
-** and 'double' (the default), 32-bit integers and 'float' (for
-** restricted platforms), and 'long'/'double' (for C compilers not
-** compliant with C99, which may not have support for 'long long').
-*/
-
-/* predefined options for LUA_INT_TYPE */
-#define LUA_INT_INT 1
-#define LUA_INT_LONG 2
-#define LUA_INT_LONGLONG 3
-
-/* predefined options for LUA_FLOAT_TYPE */
-#define LUA_FLOAT_FLOAT 1
-#define LUA_FLOAT_DOUBLE 2
-#define LUA_FLOAT_LONGDOUBLE 3
-
-
-/* Default configuration ('long long' and 'double', for 64-bit Lua) */
-#define LUA_INT_DEFAULT LUA_INT_LONGLONG
-#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE
-
-
-/*
-@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
-*/
-#define LUA_32BITS 0
-
-
-/*
-@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
-** C89 ('long' and 'double'); Windows always has '__int64', so it does
-** not need to use this case.
-*/
-#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
-#define LUA_C89_NUMBERS 1
-#else
-#define LUA_C89_NUMBERS 0
-#endif
-
-
-#if LUA_32BITS /* { */
-/*
-** 32-bit integers and 'float'
-*/
-#if LUAI_IS32INT /* use 'int' if big enough */
-#define LUA_INT_TYPE LUA_INT_INT
-#else /* otherwise use 'long' */
-#define LUA_INT_TYPE LUA_INT_LONG
-#endif
-#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
-
-#elif LUA_C89_NUMBERS /* }{ */
-/*
-** largest types available for C89 ('long' and 'double')
-*/
-#define LUA_INT_TYPE LUA_INT_LONG
-#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
-
-#else /* }{ */
-/* use defaults */
-
-#define LUA_INT_TYPE LUA_INT_DEFAULT
-#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT
-
-#endif /* } */
-
-
-/* }================================================================== */
-
-
-
-/*
-** {==================================================================
-** Configuration for Paths.
-** ===================================================================
-*/
-
-/*
-** LUA_PATH_SEP is the character that separates templates in a path.
-** LUA_PATH_MARK is the string that marks the substitution points in a
-** template.
-** LUA_EXEC_DIR in a Windows path is replaced by the executable's
-** directory.
-*/
-#define LUA_PATH_SEP ";"
-#define LUA_PATH_MARK "?"
-#define LUA_EXEC_DIR "!"
-
-
-/*
-@@ 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.
-*/
-
-#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
-#if defined(_WIN32) /* { */
-/*
-** In Windows, any exclamation mark ('!') in the path is replaced by the
-** path of the directory of the executable file of the current process.
-*/
-#define LUA_LDIR "!\\lua\\"
-#define LUA_CDIR "!\\"
-#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
-
-#if !defined(LUA_PATH_DEFAULT)
-#define LUA_PATH_DEFAULT \
- LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
- LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
- ".\\?.lua;" ".\\?\\init.lua"
-#endif
-
-#if !defined(LUA_CPATH_DEFAULT)
-#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.dll;" \
- LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
- LUA_CDIR"loadall.dll;" ".\\?.dll"
-#endif
-
-#else /* }{ */
-
-#define LUA_ROOT "/usr/local/"
-#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
-#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
-
-#if !defined(LUA_PATH_DEFAULT)
-#define LUA_PATH_DEFAULT \
- LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
- "./?.lua;" "./?/init.lua"
-#endif
-
-#if !defined(LUA_CPATH_DEFAULT)
-#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
-#endif
-
-#endif /* } */
-
-
-/*
-@@ LUA_DIRSEP is the directory separator (for submodules).
-** CHANGE it if your machine does not use "/" as the directory separator
-** and is not Windows. (On Windows Lua automatically uses "\".)
-*/
-#if !defined(LUA_DIRSEP)
-
-#if defined(_WIN32)
-#define LUA_DIRSEP "\\"
-#else
-#define LUA_DIRSEP "/"
-#endif
-
-#endif
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Marks for exported symbols in the C code
-** ===================================================================
-*/
-
-/*
-@@ LUA_API is a mark for all core API functions.
-@@ LUALIB_API is a mark for all auxiliary library functions.
-@@ LUAMOD_API is a mark for all standard library opening functions.
-** CHANGE them if you need to define those functions in some special way.
-** For instance, if you want to create one Windows DLL with the core and
-** the libraries, you may want to use the following definition (define
-** LUA_BUILD_AS_DLL to get it).
-*/
-#if defined(LUA_BUILD_AS_DLL) /* { */
-
-#if defined(LUA_CORE) || defined(LUA_LIB) /* { */
-#define LUA_API __declspec(dllexport)
-#else /* }{ */
-#define LUA_API __declspec(dllimport)
-#endif /* } */
-
-#else /* }{ */
-
-#define LUA_API extern
-
-#endif /* } */
-
-
-/*
-** More often than not the libs go together with the core.
-*/
-#define LUALIB_API LUA_API
-#define LUAMOD_API LUA_API
-
-
-/*
-@@ LUAI_FUNC is a mark for all extern functions that are not to be
-** exported to outside modules.
-@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
-** none of which to be exported to outside modules (LUAI_DDEF for
-** definitions and LUAI_DDEC for declarations).
-** 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. Not all elf targets support
-** this attribute. Unfortunately, gcc does not offer a way to check
-** whether the target offers that support, and those without support
-** give a warning about it. To avoid these warnings, change to the
-** default definition.
-*/
-#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
- defined(__ELF__) /* { */
-#define LUAI_FUNC __attribute__((visibility("internal"))) extern
-#else /* }{ */
-#define LUAI_FUNC extern
-#endif /* } */
-
-#define LUAI_DDEC(dec) LUAI_FUNC dec
-#define LUAI_DDEF /* empty */
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Compatibility with previous versions
-** ===================================================================
-*/
-
-/*
-@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3.
-** You can define it to get all options, or change specific options
-** to fit your specific needs.
-*/
-#if defined(LUA_COMPAT_5_3) /* { */
-
-/*
-@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
-** functions in the mathematical library.
-** (These functions were already officially removed in 5.3;
-** nevertheless they are still available here.)
-*/
-#define LUA_COMPAT_MATHLIB
-
-/*
-@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
-** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
-** luaL_checkint, luaL_checklong, etc.)
-** (These macros were also officially removed in 5.3, but they are still
-** available here.)
-*/
-#define LUA_COMPAT_APIINTCASTS
-
-
-/*
-@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
-** using '__lt'.
-*/
-#define LUA_COMPAT_LT_LE
-
-
-/*
-@@ The following macros supply trivial compatibility for some
-** changes in the API. The macros themselves document how to
-** change your code to avoid using them.
-** (Once more, these macros were officially removed in 5.3, but they are
-** still available here.)
-*/
-#define lua_strlen(L,i) lua_rawlen(L, (i))
-
-#define lua_objlen(L,i) lua_rawlen(L, (i))
-
-#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
-#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
-
-#endif /* } */
-
-/* }================================================================== */
-
-
-
-/*
-** {==================================================================
-** Configuration for Numbers (low-level part).
-** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
-** satisfy your needs.
-** ===================================================================
-*/
-
-/*
-@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
-@@ over a floating number.
-@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
-** by prefixing it with one of FLT/DBL/LDBL.
-@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
-@@ LUA_NUMBER_FMT is the format for writing floats.
-@@ lua_number2str converts a float to a string.
-@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
-@@ l_floor takes the floor of a float.
-@@ lua_str2number converts a decimal numeral to a number.
-*/
-
-
-/* The following definitions are good for most cases here */
-
-#define l_floor(x) (l_mathop(floor)(x))
-
-#define lua_number2str(s,sz,n) \
- l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
-
-/*
-@@ lua_numbertointeger converts a float number with an integral value
-** to an integer, or returns 0 if float is not within the range of
-** a lua_Integer. (The range comparisons are tricky because of
-** rounding. The tests here assume a two-complement representation,
-** where MININTEGER always has an exact representation as a float;
-** MAXINTEGER may not have one, and therefore its conversion to float
-** may have an ill-defined value.)
-*/
-#define lua_numbertointeger(n,p) \
- ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
- (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
- (*(p) = (LUA_INTEGER)(n), 1))
-
-
-/* now the variable definitions */
-
-#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
-
-#define LUA_NUMBER float
-
-#define l_floatatt(n) (FLT_##n)
-
-#define LUAI_UACNUMBER double
-
-#define LUA_NUMBER_FRMLEN ""
-#define LUA_NUMBER_FMT "%.7g"
-
-#define l_mathop(op) op##f
-
-#define lua_str2number(s,p) strtof((s), (p))
-
-
-#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
-
-#define LUA_NUMBER long double
-
-#define l_floatatt(n) (LDBL_##n)
-
-#define LUAI_UACNUMBER long double
-
-#define LUA_NUMBER_FRMLEN "L"
-#define LUA_NUMBER_FMT "%.19Lg"
-
-#define l_mathop(op) op##l
-
-#define lua_str2number(s,p) strtold((s), (p))
-
-#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
-
-#define LUA_NUMBER double
-
-#define l_floatatt(n) (DBL_##n)
-
-#define LUAI_UACNUMBER double
-
-#define LUA_NUMBER_FRMLEN ""
-#define LUA_NUMBER_FMT "%.14g"
-
-#define l_mathop(op) op
-
-#define lua_str2number(s,p) strtod((s), (p))
-
-#else /* }{ */
-
-#error "numeric float type not defined"
-
-#endif /* } */
-
-
-
-/*
-@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
-@@ LUAI_UACINT is the result of a 'default argument promotion'
-@@ over a LUA_INTEGER.
-@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
-@@ LUA_INTEGER_FMT is the format for writing integers.
-@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
-@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
-@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
-@@ lua_integer2str converts an integer to a string.
-*/
-
-
-/* The following definitions are good for most cases here */
-
-#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
-
-#define LUAI_UACINT LUA_INTEGER
-
-#define lua_integer2str(s,sz,n) \
- l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n))
-
-/*
-** use LUAI_UACINT here to avoid problems with promotions (which
-** can turn a comparison between unsigneds into a signed comparison)
-*/
-#define LUA_UNSIGNED unsigned LUAI_UACINT
-
-
-/* now the variable definitions */
-
-#if LUA_INT_TYPE == LUA_INT_INT /* { int */
-
-#define LUA_INTEGER int
-#define LUA_INTEGER_FRMLEN ""
-
-#define LUA_MAXINTEGER INT_MAX
-#define LUA_MININTEGER INT_MIN
-
-#define LUA_MAXUNSIGNED UINT_MAX
-
-#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
-
-#define LUA_INTEGER long
-#define LUA_INTEGER_FRMLEN "l"
-
-#define LUA_MAXINTEGER LONG_MAX
-#define LUA_MININTEGER LONG_MIN
-
-#define LUA_MAXUNSIGNED ULONG_MAX
-
-#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
-
-/* use presence of macro LLONG_MAX as proxy for C99 compliance */
-#if defined(LLONG_MAX) /* { */
-/* use ISO C99 stuff */
-
-#define LUA_INTEGER long long
-#define LUA_INTEGER_FRMLEN "ll"
-
-#define LUA_MAXINTEGER LLONG_MAX
-#define LUA_MININTEGER LLONG_MIN
-
-#define LUA_MAXUNSIGNED ULLONG_MAX
-
-#elif defined(LUA_USE_WINDOWS) /* }{ */
-/* in Windows, can use specific Windows types */
-
-#define LUA_INTEGER __int64
-#define LUA_INTEGER_FRMLEN "I64"
-
-#define LUA_MAXINTEGER _I64_MAX
-#define LUA_MININTEGER _I64_MIN
-
-#define LUA_MAXUNSIGNED _UI64_MAX
-
-#else /* }{ */
-
-#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
- or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
-
-#endif /* } */
-
-#else /* }{ */
-
-#error "numeric integer type not defined"
-
-#endif /* } */
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Dependencies with C99 and other C details
-** ===================================================================
-*/
-
-/*
-@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
-** (All uses in Lua have only one format item.)
-*/
-#if !defined(LUA_USE_C89)
-#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i)
-#else
-#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i))
-#endif
-
-
-/*
-@@ lua_strx2number converts a hexadecimal numeral to a number.
-** In C99, 'strtod' does that conversion. Otherwise, you can
-** leave 'lua_strx2number' undefined and Lua will provide its own
-** implementation.
-*/
-#if !defined(LUA_USE_C89)
-#define lua_strx2number(s,p) lua_str2number(s,p)
-#endif
-
-
-/*
-@@ lua_pointer2str converts a pointer to a readable string in a
-** non-specified way.
-*/
-#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p)
-
-
-/*
-@@ lua_number2strx converts a float to a hexadecimal numeral.
-** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
-** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
-** provide its own implementation.
-*/
-#if !defined(LUA_USE_C89)
-#define lua_number2strx(L,b,sz,f,n) \
- ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n)))
-#endif
-
-
-/*
-** 'strtof' and 'opf' variants for math functions are not valid in
-** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
-** availability of these variants. ('math.h' is already included in
-** all files that use these macros.)
-*/
-#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
-#undef l_mathop /* variants not available */
-#undef lua_str2number
-#define l_mathop(op) (lua_Number)op /* no variant */
-#define lua_str2number(s,p) ((lua_Number)strtod((s), (p)))
-#endif
-
-
-/*
-@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
-** functions. It must be a numerical type; Lua will use 'intptr_t' if
-** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
-** 'intptr_t' in C89)
-*/
-#define LUA_KCONTEXT ptrdiff_t
-
-#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
- __STDC_VERSION__ >= 199901L
-#include
-#if defined(INTPTR_MAX) /* even in C99 this type is optional */
-#undef LUA_KCONTEXT
-#define LUA_KCONTEXT intptr_t
-#endif
-#endif
-
-
-/*
-@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
-** Change that if you do not want to use C locales. (Code using this
-** macro must include the header 'locale.h'.)
-*/
-#if !defined(lua_getlocaledecpoint)
-#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
-#endif
-
-
-/*
-** macros to improve jump prediction, used mostly for error handling
-** and debug facilities. (Some macros in the Lua API use these macros.
-** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your
-** code.)
-*/
-#if !defined(luai_likely)
-
-#if defined(__GNUC__) && !defined(LUA_NOBUILTIN)
-#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
-#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
-#else
-#define luai_likely(x) (x)
-#define luai_unlikely(x) (x)
-#endif
-
-#endif
-
-
-#if defined(LUA_CORE) || defined(LUA_LIB)
-/* shorter names for Lua's own use */
-#define l_likely(x) luai_likely(x)
-#define l_unlikely(x) luai_unlikely(x)
-#endif
-
-
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Language Variations
-** =====================================================================
-*/
-
-/*
-@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
-** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
-** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
-** coercion from strings to numbers.
-*/
-/* #define LUA_NOCVTN2S */
-/* #define LUA_NOCVTS2N */
-
-
-/*
-@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
-** Define it as a help when debugging C code.
-*/
-#if defined(LUA_USE_APICHECK)
-#include
-#define luai_apicheck(l,e) assert(e)
-#endif
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Macros that affect the API and must be stable (that is, must be the
-** same when you compile Lua and when you compile code that links to
-** Lua).
-** =====================================================================
-*/
-
-/*
-@@ LUAI_MAXSTACK limits the size of the Lua stack.
-** CHANGE it if you need a different limit. This limit is arbitrary;
-** its only purpose is to stop Lua from consuming unlimited stack
-** space (and to reserve some numbers for pseudo-indices).
-** (It must fit into max(size_t)/32.)
-*/
-#if LUAI_IS32INT
-#define LUAI_MAXSTACK 1000000
-#else
-#define LUAI_MAXSTACK 15000
-#endif
-
-
-/*
-@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
-** a Lua state with very fast access.
-** CHANGE it if you need a different size.
-*/
-#define LUA_EXTRASPACE (sizeof(void *))
-
-
-/*
-@@ LUA_IDSIZE gives the maximum size for the description of the source
-@@ of a function in debug information.
-** CHANGE it if you want a different size.
-*/
-#define LUA_IDSIZE 60
-
-
-/*
-@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
-*/
-#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number)))
-
-
-/*
-@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
-** maximum alignment for the other items in that union.
-*/
-#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l
-
-/* }================================================================== */
-
-
-
-
-
-/* =================================================================== */
-
-/*
-** Local configuration. You can use this space to add your redefinitions
-** without modifying the main part of the file.
-*/
-
-
-
-
-
-#endif
-
diff --git a/lua-5.4.4/library/lualib.h b/lua-5.4.4/library/lualib.h
deleted file mode 100644
index 26255290..00000000
--- a/lua-5.4.4/library/lualib.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-** $Id: lualib.h $
-** Lua standard libraries
-** See Copyright Notice in lua.h
-*/
-
-
-#ifndef lualib_h
-#define lualib_h
-
-#include "lua.h"
-
-
-/* version suffix for environment variable names */
-#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
-
-
-LUAMOD_API int (luaopen_base) (lua_State *L);
-
-#define LUA_COLIBNAME "coroutine"
-LUAMOD_API int (luaopen_coroutine) (lua_State *L);
-
-#define LUA_TABLIBNAME "table"
-LUAMOD_API int (luaopen_table) (lua_State *L);
-
-#define LUA_IOLIBNAME "io"
-LUAMOD_API int (luaopen_io) (lua_State *L);
-
-#define LUA_OSLIBNAME "os"
-LUAMOD_API int (luaopen_os) (lua_State *L);
-
-#define LUA_STRLIBNAME "string"
-LUAMOD_API int (luaopen_string) (lua_State *L);
-
-#define LUA_UTF8LIBNAME "utf8"
-LUAMOD_API int (luaopen_utf8) (lua_State *L);
-
-#define LUA_MATHLIBNAME "math"
-LUAMOD_API int (luaopen_math) (lua_State *L);
-
-#define LUA_DBLIBNAME "debug"
-LUAMOD_API int (luaopen_debug) (lua_State *L);
-
-#define LUA_LOADLIBNAME "package"
-LUAMOD_API int (luaopen_package) (lua_State *L);
-
-
-/* open all previous libraries */
-LUALIB_API void (luaL_openlibs) (lua_State *L);
-
-
-#endif
diff --git a/lua-5.4.4/library/lundump.c b/lua-5.4.4/library/lundump.c
deleted file mode 100644
index 5aa55c44..00000000
--- a/lua-5.4.4/library/lundump.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
-** $Id: lundump.c $
-** load precompiled Lua chunks
-** See Copyright Notice in lua.h
-*/
-
-#define lundump_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-#include
-
-#include "lua.h"
-
-#include "ldebug.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lstring.h"
-#include "lundump.h"
-#include "lzio.h"
-
-
-#if !defined(luai_verifycode)
-#define luai_verifycode(L,f) /* empty */
-#endif
-
-
-typedef struct {
- lua_State *L;
- ZIO *Z;
- const char *name;
-} LoadState;
-
-
-static l_noret error (LoadState *S, const char *why) {
- luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
- luaD_throw(S->L, LUA_ERRSYNTAX);
-}
-
-
-/*
-** All high-level loads go through loadVector; you can change it to
-** adapt to the endianness of the input
-*/
-#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0]))
-
-static void loadBlock (LoadState *S, void *b, size_t size) {
- if (luaZ_read(S->Z, b, size) != 0)
- error(S, "truncated chunk");
-}
-
-
-#define loadVar(S,x) loadVector(S,&x,1)
-
-
-static lu_byte loadByte (LoadState *S) {
- int b = zgetc(S->Z);
- if (b == EOZ)
- error(S, "truncated chunk");
- return cast_byte(b);
-}
-
-
-static size_t loadUnsigned (LoadState *S, size_t limit) {
- size_t x = 0;
- int b;
- limit >>= 7;
- do {
- b = loadByte(S);
- if (x >= limit)
- error(S, "integer overflow");
- x = (x << 7) | (b & 0x7f);
- } while ((b & 0x80) == 0);
- return x;
-}
-
-
-static size_t loadSize (LoadState *S) {
- return loadUnsigned(S, ~(size_t)0);
-}
-
-
-static int loadInt (LoadState *S) {
- return cast_int(loadUnsigned(S, INT_MAX));
-}
-
-
-static lua_Number loadNumber (LoadState *S) {
- lua_Number x;
- loadVar(S, x);
- return x;
-}
-
-
-static lua_Integer loadInteger (LoadState *S) {
- lua_Integer x;
- loadVar(S, x);
- return x;
-}
-
-
-/*
-** Load a nullable string into prototype 'p'.
-*/
-static TString *loadStringN (LoadState *S, Proto *p) {
- lua_State *L = S->L;
- TString *ts;
- size_t size = loadSize(S);
- if (size == 0) /* no string? */
- return NULL;
- else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
- char buff[LUAI_MAXSHORTLEN];
- loadVector(S, buff, size); /* load string into buffer */
- ts = luaS_newlstr(L, buff, size); /* create string */
- }
- else { /* long string */
- ts = luaS_createlngstrobj(L, size); /* create string */
- setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */
- luaD_inctop(L);
- loadVector(S, getstr(ts), size); /* load directly in final place */
- L->top--; /* pop string */
- }
- luaC_objbarrier(L, p, ts);
- return ts;
-}
-
-
-/*
-** Load a non-nullable string into prototype 'p'.
-*/
-static TString *loadString (LoadState *S, Proto *p) {
- TString *st = loadStringN(S, p);
- if (st == NULL)
- error(S, "bad format for constant string");
- return st;
-}
-
-
-static void loadCode (LoadState *S, Proto *f) {
- int n = loadInt(S);
- f->code = luaM_newvectorchecked(S->L, n, Instruction);
- f->sizecode = n;
- loadVector(S, f->code, n);
-}
-
-
-static void loadFunction(LoadState *S, Proto *f, TString *psource);
-
-
-static void loadConstants (LoadState *S, Proto *f) {
- int i;
- int n = loadInt(S);
- f->k = luaM_newvectorchecked(S->L, n, TValue);
- f->sizek = n;
- for (i = 0; i < n; i++)
- setnilvalue(&f->k[i]);
- for (i = 0; i < n; i++) {
- TValue *o = &f->k[i];
- int t = loadByte(S);
- switch (t) {
- case LUA_VNIL:
- setnilvalue(o);
- break;
- case LUA_VFALSE:
- setbfvalue(o);
- break;
- case LUA_VTRUE:
- setbtvalue(o);
- break;
- case LUA_VNUMFLT:
- setfltvalue(o, loadNumber(S));
- break;
- case LUA_VNUMINT:
- setivalue(o, loadInteger(S));
- break;
- case LUA_VSHRSTR:
- case LUA_VLNGSTR:
- setsvalue2n(S->L, o, loadString(S, f));
- break;
- default: lua_assert(0);
- }
- }
-}
-
-
-static void loadProtos (LoadState *S, Proto *f) {
- int i;
- int n = loadInt(S);
- f->p = luaM_newvectorchecked(S->L, n, Proto *);
- f->sizep = n;
- for (i = 0; i < n; i++)
- f->p[i] = NULL;
- for (i = 0; i < n; i++) {
- f->p[i] = luaF_newproto(S->L);
- luaC_objbarrier(S->L, f, f->p[i]);
- loadFunction(S, f->p[i], f->source);
- }
-}
-
-
-/*
-** Load the upvalues for a function. The names must be filled first,
-** because the filling of the other fields can raise read errors and
-** the creation of the error message can call an emergency collection;
-** in that case all prototypes must be consistent for the GC.
-*/
-static void loadUpvalues (LoadState *S, Proto *f) {
- int i, n;
- n = loadInt(S);
- f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
- f->sizeupvalues = n;
- for (i = 0; i < n; i++) /* make array valid for GC */
- f->upvalues[i].name = NULL;
- for (i = 0; i < n; i++) { /* following calls can raise errors */
- f->upvalues[i].instack = loadByte(S);
- f->upvalues[i].idx = loadByte(S);
- f->upvalues[i].kind = loadByte(S);
- }
-}
-
-
-static void loadDebug (LoadState *S, Proto *f) {
- int i, n;
- n = loadInt(S);
- f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
- f->sizelineinfo = n;
- loadVector(S, f->lineinfo, n);
- n = loadInt(S);
- f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
- f->sizeabslineinfo = n;
- for (i = 0; i < n; i++) {
- f->abslineinfo[i].pc = loadInt(S);
- f->abslineinfo[i].line = loadInt(S);
- }
- n = loadInt(S);
- f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
- f->sizelocvars = n;
- for (i = 0; i < n; i++)
- f->locvars[i].varname = NULL;
- for (i = 0; i < n; i++) {
- f->locvars[i].varname = loadStringN(S, f);
- f->locvars[i].startpc = loadInt(S);
- f->locvars[i].endpc = loadInt(S);
- }
- n = loadInt(S);
- for (i = 0; i < n; i++)
- f->upvalues[i].name = loadStringN(S, f);
-}
-
-
-static void loadFunction (LoadState *S, Proto *f, TString *psource) {
- f->source = loadStringN(S, f);
- if (f->source == NULL) /* no source in dump? */
- f->source = psource; /* reuse parent's source */
- f->linedefined = loadInt(S);
- f->lastlinedefined = loadInt(S);
- f->numparams = loadByte(S);
- f->is_vararg = loadByte(S);
- f->maxstacksize = loadByte(S);
- loadCode(S, f);
- loadConstants(S, f);
- loadUpvalues(S, f);
- loadProtos(S, f);
- loadDebug(S, f);
-}
-
-
-static void checkliteral (LoadState *S, const char *s, const char *msg) {
- char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
- size_t len = strlen(s);
- loadVector(S, buff, len);
- if (memcmp(s, buff, len) != 0)
- error(S, msg);
-}
-
-
-static void fchecksize (LoadState *S, size_t size, const char *tname) {
- if (loadByte(S) != size)
- error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
-}
-
-
-#define checksize(S,t) fchecksize(S,sizeof(t),#t)
-
-static void checkHeader (LoadState *S) {
- /* skip 1st char (already read and checked) */
- checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
- if (loadByte(S) != LUAC_VERSION)
- error(S, "version mismatch");
- if (loadByte(S) != LUAC_FORMAT)
- error(S, "format mismatch");
- checkliteral(S, LUAC_DATA, "corrupted chunk");
- checksize(S, Instruction);
- checksize(S, lua_Integer);
- checksize(S, lua_Number);
- if (loadInteger(S) != LUAC_INT)
- error(S, "integer format mismatch");
- if (loadNumber(S) != LUAC_NUM)
- error(S, "float format mismatch");
-}
-
-
-/*
-** Load precompiled chunk.
-*/
-LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
- LoadState S;
- LClosure *cl;
- if (*name == '@' || *name == '=')
- S.name = name + 1;
- else if (*name == LUA_SIGNATURE[0])
- S.name = "binary string";
- else
- S.name = name;
- S.L = L;
- S.Z = Z;
- checkHeader(&S);
- cl = luaF_newLclosure(L, loadByte(&S));
- setclLvalue2s(L, L->top, cl);
- luaD_inctop(L);
- cl->p = luaF_newproto(L);
- luaC_objbarrier(L, cl, cl->p);
- loadFunction(&S, cl->p, NULL);
- lua_assert(cl->nupvalues == cl->p->sizeupvalues);
- luai_verifycode(L, cl->p);
- return cl;
-}
-
diff --git a/lua-5.4.4/library/lundump.h b/lua-5.4.4/library/lundump.h
deleted file mode 100644
index f3748a99..00000000
--- a/lua-5.4.4/library/lundump.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-** $Id: lundump.h $
-** load precompiled Lua chunks
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lundump_h
-#define lundump_h
-
-#include "llimits.h"
-#include "lobject.h"
-#include "lzio.h"
-
-
-/* data to catch conversion errors */
-#define LUAC_DATA "\x19\x93\r\n\x1a\n"
-
-#define LUAC_INT 0x5678
-#define LUAC_NUM cast_num(370.5)
-
-/*
-** Encode major-minor version in one byte, one nibble for each
-*/
-#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */
-#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
-
-#define LUAC_FORMAT 0 /* this is the official format */
-
-/* load one chunk; from lundump.c */
-LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
-
-/* dump one chunk; from ldump.c */
-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
- void* data, int strip);
-
-#endif
diff --git a/lua-5.4.4/library/lutf8lib.c b/lua-5.4.4/library/lutf8lib.c
deleted file mode 100644
index e7bf098f..00000000
--- a/lua-5.4.4/library/lutf8lib.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-** $Id: lutf8lib.c $
-** Standard library for UTF-8 manipulation
-** See Copyright Notice in lua.h
-*/
-
-#define lutf8lib_c
-#define LUA_LIB
-
-#include "lprefix.h"
-
-
-#include
-#include
-#include
-#include
-
-#include "lua.h"
-
-#include "lauxlib.h"
-#include "lualib.h"
-
-
-#define MAXUNICODE 0x10FFFFu
-
-#define MAXUTF 0x7FFFFFFFu
-
-/*
-** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits.
-*/
-#if (UINT_MAX >> 30) >= 1
-typedef unsigned int utfint;
-#else
-typedef unsigned long utfint;
-#endif
-
-
-#define iscont(p) ((*(p) & 0xC0) == 0x80)
-
-
-/* from strlib */
-/* translate a relative string position: negative means back from end */
-static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
- if (pos >= 0) return pos;
- else if (0u - (size_t)pos > len) return 0;
- else return (lua_Integer)len + pos + 1;
-}
-
-
-/*
-** Decode one UTF-8 sequence, returning NULL if byte sequence is
-** invalid. The array 'limits' stores the minimum value for each
-** sequence length, to check for overlong representations. Its first
-** entry forces an error for non-ascii bytes with no continuation
-** bytes (count == 0).
-*/
-static const char *utf8_decode (const char *s, utfint *val, int strict) {
- static const utfint limits[] =
- {~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u};
- unsigned int c = (unsigned char)s[0];
- utfint res = 0; /* final result */
- if (c < 0x80) /* ascii? */
- res = c;
- else {
- int count = 0; /* to count number of continuation bytes */
- for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
- unsigned int cc = (unsigned char)s[++count]; /* read next byte */
- if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
- return NULL; /* invalid byte sequence */
- res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
- }
- res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */
- if (count > 5 || res > MAXUTF || res < limits[count])
- return NULL; /* invalid byte sequence */
- s += count; /* skip continuation bytes read */
- }
- if (strict) {
- /* check for invalid code points; too large or surrogates */
- if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu))
- return NULL;
- }
- if (val) *val = res;
- return s + 1; /* +1 to include first byte */
-}
-
-
-/*
-** utf8len(s [, i [, j [, lax]]]) --> number of characters that
-** start in the range [i,j], or nil + current position if 's' is not
-** well formed in that interval
-*/
-static int utflen (lua_State *L) {
- lua_Integer n = 0; /* counter for the number of characters */
- size_t len; /* string length in bytes */
- const char *s = luaL_checklstring(L, 1, &len);
- lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
- lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
- int lax = lua_toboolean(L, 4);
- luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
- "initial position out of bounds");
- luaL_argcheck(L, --posj < (lua_Integer)len, 3,
- "final position out of bounds");
- while (posi <= posj) {
- const char *s1 = utf8_decode(s + posi, NULL, !lax);
- if (s1 == NULL) { /* conversion error? */
- luaL_pushfail(L); /* return fail ... */
- lua_pushinteger(L, posi + 1); /* ... and current position */
- return 2;
- }
- posi = s1 - s;
- n++;
- }
- lua_pushinteger(L, n);
- return 1;
-}
-
-
-/*
-** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all
-** characters that start in the range [i,j]
-*/
-static int codepoint (lua_State *L) {
- size_t len;
- const char *s = luaL_checklstring(L, 1, &len);
- lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
- lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
- int lax = lua_toboolean(L, 4);
- int n;
- const char *se;
- luaL_argcheck(L, posi >= 1, 2, "out of bounds");
- luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of bounds");
- if (posi > pose) return 0; /* empty interval; return no values */
- if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */
- return luaL_error(L, "string slice too long");
- n = (int)(pose - posi) + 1; /* upper bound for number of returns */
- luaL_checkstack(L, n, "string slice too long");
- n = 0; /* count the number of returns */
- se = s + pose; /* string end */
- for (s += posi - 1; s < se;) {
- utfint code;
- s = utf8_decode(s, &code, !lax);
- if (s == NULL)
- return luaL_error(L, "invalid UTF-8 code");
- lua_pushinteger(L, code);
- n++;
- }
- return n;
-}
-
-
-static void pushutfchar (lua_State *L, int arg) {
- lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg);
- luaL_argcheck(L, code <= MAXUTF, arg, "value out of range");
- lua_pushfstring(L, "%U", (long)code);
-}
-
-
-/*
-** utfchar(n1, n2, ...) -> char(n1)..char(n2)...
-*/
-static int utfchar (lua_State *L) {
- int n = lua_gettop(L); /* number of arguments */
- if (n == 1) /* optimize common case of single char */
- pushutfchar(L, 1);
- else {
- int i;
- luaL_Buffer b;
- luaL_buffinit(L, &b);
- for (i = 1; i <= n; i++) {
- pushutfchar(L, i);
- luaL_addvalue(&b);
- }
- luaL_pushresult(&b);
- }
- return 1;
-}
-
-
-/*
-** offset(s, n, [i]) -> index where n-th character counting from
-** position 'i' starts; 0 means character at 'i'.
-*/
-static int byteoffset (lua_State *L) {
- size_t len;
- const char *s = luaL_checklstring(L, 1, &len);
- lua_Integer n = luaL_checkinteger(L, 2);
- lua_Integer posi = (n >= 0) ? 1 : len + 1;
- posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
- luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
- "position out of bounds");
- if (n == 0) {
- /* find beginning of current byte sequence */
- while (posi > 0 && iscont(s + posi)) posi--;
- }
- else {
- if (iscont(s + posi))
- return luaL_error(L, "initial position is a continuation byte");
- if (n < 0) {
- while (n < 0 && posi > 0) { /* move back */
- do { /* find beginning of previous character */
- posi--;
- } while (posi > 0 && iscont(s + posi));
- n++;
- }
- }
- else {
- n--; /* do not move for 1st character */
- while (n > 0 && posi < (lua_Integer)len) {
- do { /* find beginning of next character */
- posi++;
- } while (iscont(s + posi)); /* (cannot pass final '\0') */
- n--;
- }
- }
- }
- if (n == 0) /* did it find given character? */
- lua_pushinteger(L, posi + 1);
- else /* no such character */
- luaL_pushfail(L);
- return 1;
-}
-
-
-static int iter_aux (lua_State *L, int strict) {
- size_t len;
- const char *s = luaL_checklstring(L, 1, &len);
- lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2);
- if (n < len) {
- while (iscont(s + n)) n++; /* skip continuation bytes */
- }
- if (n >= len) /* (also handles original 'n' being negative) */
- return 0; /* no more codepoints */
- else {
- utfint code;
- const char *next = utf8_decode(s + n, &code, strict);
- if (next == NULL)
- return luaL_error(L, "invalid UTF-8 code");
- lua_pushinteger(L, n + 1);
- lua_pushinteger(L, code);
- return 2;
- }
-}
-
-
-static int iter_auxstrict (lua_State *L) {
- return iter_aux(L, 1);
-}
-
-static int iter_auxlax (lua_State *L) {
- return iter_aux(L, 0);
-}
-
-
-static int iter_codes (lua_State *L) {
- int lax = lua_toboolean(L, 2);
- luaL_checkstring(L, 1);
- lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict);
- lua_pushvalue(L, 1);
- lua_pushinteger(L, 0);
- return 3;
-}
-
-
-/* pattern to match a single UTF-8 character */
-#define UTF8PATT "[\0-\x7F\xC2-\xFD][\x80-\xBF]*"
-
-
-static const luaL_Reg funcs[] = {
- {"offset", byteoffset},
- {"codepoint", codepoint},
- {"char", utfchar},
- {"len", utflen},
- {"codes", iter_codes},
- /* placeholders */
- {"charpattern", NULL},
- {NULL, NULL}
-};
-
-
-LUAMOD_API int luaopen_utf8 (lua_State *L) {
- luaL_newlib(L, funcs);
- lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
- lua_setfield(L, -2, "charpattern");
- return 1;
-}
-
diff --git a/lua-5.4.4/library/lvm.c b/lua-5.4.4/library/lvm.c
deleted file mode 100644
index 2ec34400..00000000
--- a/lua-5.4.4/library/lvm.c
+++ /dev/null
@@ -1,1840 +0,0 @@
-/*
-** $Id: lvm.c $
-** Lua virtual machine
-** See Copyright Notice in lua.h
-*/
-
-#define lvm_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "lua.h"
-
-#include "ldebug.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lgc.h"
-#include "lobject.h"
-#include "lopcodes.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-#include "ltm.h"
-#include "lvm.h"
-
-
-/*
-** By default, use jump tables in the main interpreter loop on gcc
-** and compatible compilers.
-*/
-#if !defined(LUA_USE_JUMPTABLE)
-#if defined(__GNUC__)
-#define LUA_USE_JUMPTABLE 1
-#else
-#define LUA_USE_JUMPTABLE 0
-#endif
-#endif
-
-
-
-/* limit for table tag-method chains (to avoid infinite loops) */
-#define MAXTAGLOOP 2000
-
-
-/*
-** 'l_intfitsf' checks whether a given integer is in the range that
-** can be converted to a float without rounding. Used in comparisons.
-*/
-
-/* number of bits in the mantissa of a float */
-#define NBM (l_floatatt(MANT_DIG))
-
-/*
-** Check whether some integers may not fit in a float, testing whether
-** (maxinteger >> NBM) > 0. (That implies (1 << NBM) <= maxinteger.)
-** (The shifts are done in parts, to avoid shifting by more than the size
-** of an integer. In a worst case, NBM == 113 for long double and
-** sizeof(long) == 32.)
-*/
-#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
- >> (NBM - (3 * (NBM / 4)))) > 0
-
-/* limit for integers that fit in a float */
-#define MAXINTFITSF ((lua_Unsigned)1 << NBM)
-
-/* check whether 'i' is in the interval [-MAXINTFITSF, MAXINTFITSF] */
-#define l_intfitsf(i) ((MAXINTFITSF + l_castS2U(i)) <= (2 * MAXINTFITSF))
-
-#else /* all integers fit in a float precisely */
-
-#define l_intfitsf(i) 1
-
-#endif
-
-
-/*
-** Try to convert a value from string to a number value.
-** If the value is not a string or is a string not representing
-** a valid numeral (or if coercions from strings to numbers
-** are disabled via macro 'cvt2num'), do not modify 'result'
-** and return 0.
-*/
-static int l_strton (const TValue *obj, TValue *result) {
- lua_assert(obj != result);
- if (!cvt2num(obj)) /* is object not a string? */
- return 0;
- else
- return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
-}
-
-
-/*
-** Try to convert a value to a float. The float case is already handled
-** by the macro 'tonumber'.
-*/
-int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
- TValue v;
- if (ttisinteger(obj)) {
- *n = cast_num(ivalue(obj));
- return 1;
- }
- else if (l_strton(obj, &v)) { /* string coercible to number? */
- *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
- return 1;
- }
- else
- return 0; /* conversion failed */
-}
-
-
-/*
-** try to convert a float to an integer, rounding according to 'mode'.
-*/
-int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) {
- lua_Number f = l_floor(n);
- if (n != f) { /* not an integral value? */
- if (mode == F2Ieq) return 0; /* fails if mode demands integral value */
- else if (mode == F2Iceil) /* needs ceil? */
- f += 1; /* convert floor to ceil (remember: n != f) */
- }
- return lua_numbertointeger(f, p);
-}
-
-
-/*
-** try to convert a value to an integer, rounding according to 'mode',
-** without string coercion.
-** ("Fast track" handled by macro 'tointegerns'.)
-*/
-int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode) {
- if (ttisfloat(obj))
- return luaV_flttointeger(fltvalue(obj), p, mode);
- else if (ttisinteger(obj)) {
- *p = ivalue(obj);
- return 1;
- }
- else
- return 0;
-}
-
-
-/*
-** try to convert a value to an integer.
-*/
-int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode) {
- TValue v;
- if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */
- obj = &v; /* change it to point to its corresponding number */
- return luaV_tointegerns(obj, p, mode);
-}
-
-
-/*
-** Try to convert a 'for' limit to an integer, preserving the semantics
-** of the loop. Return true if the loop must not run; otherwise, '*p'
-** gets the integer limit.
-** (The following explanation assumes a positive step; it is valid for
-** negative steps mutatis mutandis.)
-** If the limit is an integer or can be converted to an integer,
-** rounding down, that is the limit.
-** Otherwise, check whether the limit can be converted to a float. If
-** the float is too large, clip it to LUA_MAXINTEGER. If the float
-** is too negative, the loop should not run, because any initial
-** integer value is greater than such limit; so, the function returns
-** true to signal that. (For this latter case, no integer limit would be
-** correct; even a limit of LUA_MININTEGER would run the loop once for
-** an initial value equal to LUA_MININTEGER.)
-*/
-static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
- lua_Integer *p, lua_Integer step) {
- if (!luaV_tointeger(lim, p, (step < 0 ? F2Iceil : F2Ifloor))) {
- /* not coercible to in integer */
- lua_Number flim; /* try to convert to float */
- if (!tonumber(lim, &flim)) /* cannot convert to float? */
- luaG_forerror(L, lim, "limit");
- /* else 'flim' is a float out of integer bounds */
- if (luai_numlt(0, flim)) { /* if it is positive, it is too large */
- if (step < 0) return 1; /* initial value must be less than it */
- *p = LUA_MAXINTEGER; /* truncate */
- }
- else { /* it is less than min integer */
- if (step > 0) return 1; /* initial value must be greater than it */
- *p = LUA_MININTEGER; /* truncate */
- }
- }
- return (step > 0 ? init > *p : init < *p); /* not to run? */
-}
-
-
-/*
-** Prepare a numerical for loop (opcode OP_FORPREP).
-** Return true to skip the loop. Otherwise,
-** after preparation, stack will be as follows:
-** ra : internal index (safe copy of the control variable)
-** ra + 1 : loop counter (integer loops) or limit (float loops)
-** ra + 2 : step
-** ra + 3 : control variable
-*/
-static int forprep (lua_State *L, StkId ra) {
- TValue *pinit = s2v(ra);
- TValue *plimit = s2v(ra + 1);
- TValue *pstep = s2v(ra + 2);
- if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */
- lua_Integer init = ivalue(pinit);
- lua_Integer step = ivalue(pstep);
- lua_Integer limit;
- if (step == 0)
- luaG_runerror(L, "'for' step is zero");
- setivalue(s2v(ra + 3), init); /* control variable */
- if (forlimit(L, init, plimit, &limit, step))
- return 1; /* skip the loop */
- else { /* prepare loop counter */
- lua_Unsigned count;
- if (step > 0) { /* ascending loop? */
- count = l_castS2U(limit) - l_castS2U(init);
- if (step != 1) /* avoid division in the too common case */
- count /= l_castS2U(step);
- }
- else { /* step < 0; descending loop */
- count = l_castS2U(init) - l_castS2U(limit);
- /* 'step+1' avoids negating 'mininteger' */
- count /= l_castS2U(-(step + 1)) + 1u;
- }
- /* store the counter in place of the limit (which won't be
- needed anymore) */
- setivalue(plimit, l_castU2S(count));
- }
- }
- else { /* try making all values floats */
- lua_Number init; lua_Number limit; lua_Number step;
- if (l_unlikely(!tonumber(plimit, &limit)))
- luaG_forerror(L, plimit, "limit");
- if (l_unlikely(!tonumber(pstep, &step)))
- luaG_forerror(L, pstep, "step");
- if (l_unlikely(!tonumber(pinit, &init)))
- luaG_forerror(L, pinit, "initial value");
- if (step == 0)
- luaG_runerror(L, "'for' step is zero");
- if (luai_numlt(0, step) ? luai_numlt(limit, init)
- : luai_numlt(init, limit))
- return 1; /* skip the loop */
- else {
- /* make sure internal values are all floats */
- setfltvalue(plimit, limit);
- setfltvalue(pstep, step);
- setfltvalue(s2v(ra), init); /* internal index */
- setfltvalue(s2v(ra + 3), init); /* control variable */
- }
- }
- return 0;
-}
-
-
-/*
-** Execute a step of a float numerical for loop, returning
-** true iff the loop must continue. (The integer case is
-** written online with opcode OP_FORLOOP, for performance.)
-*/
-static int floatforloop (StkId ra) {
- lua_Number step = fltvalue(s2v(ra + 2));
- lua_Number limit = fltvalue(s2v(ra + 1));
- lua_Number idx = fltvalue(s2v(ra)); /* internal index */
- idx = luai_numadd(L, idx, step); /* increment index */
- if (luai_numlt(0, step) ? luai_numle(idx, limit)
- : luai_numle(limit, idx)) {
- chgfltvalue(s2v(ra), idx); /* update internal index */
- setfltvalue(s2v(ra + 3), idx); /* and control variable */
- return 1; /* jump back */
- }
- else
- return 0; /* finish the loop */
-}
-
-
-/*
-** Finish the table access 'val = t[key]'.
-** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
-** t[k] entry (which must be empty).
-*/
-void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
- const TValue *slot) {
- int loop; /* counter to avoid infinite loops */
- const TValue *tm; /* metamethod */
- for (loop = 0; loop < MAXTAGLOOP; loop++) {
- if (slot == NULL) { /* 't' is not a table? */
- lua_assert(!ttistable(t));
- tm = luaT_gettmbyobj(L, t, TM_INDEX);
- if (l_unlikely(notm(tm)))
- luaG_typeerror(L, t, "index"); /* no metamethod */
- /* else will try the metamethod */
- }
- else { /* 't' is a table */
- lua_assert(isempty(slot));
- tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
- if (tm == NULL) { /* no metamethod? */
- setnilvalue(s2v(val)); /* result is nil */
- return;
- }
- /* else will try the metamethod */
- }
- if (ttisfunction(tm)) { /* is metamethod a function? */
- luaT_callTMres(L, tm, t, key, val); /* call it */
- return;
- }
- t = tm; /* else try to access 'tm[key]' */
- if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */
- setobj2s(L, val, slot); /* done */
- return;
- }
- /* else repeat (tail call 'luaV_finishget') */
- }
- luaG_runerror(L, "'__index' chain too long; possible loop");
-}
-
-
-/*
-** Finish a table assignment 't[key] = val'.
-** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
-** to the entry 't[key]', or to a value with an absent key if there
-** is no such entry. (The value at 'slot' must be empty, otherwise
-** 'luaV_fastget' would have done the job.)
-*/
-void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
- TValue *val, const TValue *slot) {
- int loop; /* counter to avoid infinite loops */
- for (loop = 0; loop < MAXTAGLOOP; loop++) {
- const TValue *tm; /* '__newindex' metamethod */
- if (slot != NULL) { /* is 't' a table? */
- Table *h = hvalue(t); /* save 't' table */
- lua_assert(isempty(slot)); /* slot must be empty */
- tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
- if (tm == NULL) { /* no metamethod? */
- luaH_finishset(L, h, key, slot, val); /* set new value */
- invalidateTMcache(h);
- luaC_barrierback(L, obj2gco(h), val);
- return;
- }
- /* else will try the metamethod */
- }
- else { /* not a table; check metamethod */
- tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
- if (l_unlikely(notm(tm)))
- luaG_typeerror(L, t, "index");
- }
- /* try the metamethod */
- if (ttisfunction(tm)) {
- luaT_callTM(L, tm, t, key, val);
- return;
- }
- t = tm; /* else repeat assignment over 'tm' */
- if (luaV_fastget(L, t, key, slot, luaH_get)) {
- luaV_finishfastset(L, t, slot, val);
- return; /* done */
- }
- /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
- }
- luaG_runerror(L, "'__newindex' chain too long; possible loop");
-}
-
-
-/*
-** Compare two strings 'ls' x 'rs', returning an integer less-equal-
-** -greater than zero if 'ls' is less-equal-greater than 'rs'.
-** The code is a little tricky because it allows '\0' in the strings
-** and it uses 'strcoll' (to respect locales) for each segments
-** of the strings.
-*/
-static int l_strcmp (const TString *ls, const TString *rs) {
- const char *l = getstr(ls);
- size_t ll = tsslen(ls);
- const char *r = getstr(rs);
- size_t lr = tsslen(rs);
- for (;;) { /* for each segment */
- int temp = strcoll(l, r);
- if (temp != 0) /* not equal? */
- return temp; /* done */
- else { /* strings are equal up to a '\0' */
- size_t len = strlen(l); /* index of first '\0' in both strings */
- if (len == lr) /* 'rs' is finished? */
- return (len == ll) ? 0 : 1; /* check 'ls' */
- else if (len == ll) /* 'ls' is finished? */
- return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
- /* both strings longer than 'len'; go on comparing after the '\0' */
- len++;
- l += len; ll -= len; r += len; lr -= len;
- }
- }
-}
-
-
-/*
-** Check whether integer 'i' is less than float 'f'. If 'i' has an
-** exact representation as a float ('l_intfitsf'), compare numbers as
-** floats. Otherwise, use the equivalence 'i < f <=> i < ceil(f)'.
-** If 'ceil(f)' is out of integer range, either 'f' is greater than
-** all integers or less than all integers.
-** (The test with 'l_intfitsf' is only for performance; the else
-** case is correct for all values, but it is slow due to the conversion
-** from float to int.)
-** When 'f' is NaN, comparisons must result in false.
-*/
-l_sinline int LTintfloat (lua_Integer i, lua_Number f) {
- if (l_intfitsf(i))
- return luai_numlt(cast_num(i), f); /* compare them as floats */
- else { /* i < f <=> i < ceil(f) */
- lua_Integer fi;
- if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */
- return i < fi; /* compare them as integers */
- else /* 'f' is either greater or less than all integers */
- return f > 0; /* greater? */
- }
-}
-
-
-/*
-** Check whether integer 'i' is less than or equal to float 'f'.
-** See comments on previous function.
-*/
-l_sinline int LEintfloat (lua_Integer i, lua_Number f) {
- if (l_intfitsf(i))
- return luai_numle(cast_num(i), f); /* compare them as floats */
- else { /* i <= f <=> i <= floor(f) */
- lua_Integer fi;
- if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */
- return i <= fi; /* compare them as integers */
- else /* 'f' is either greater or less than all integers */
- return f > 0; /* greater? */
- }
-}
-
-
-/*
-** Check whether float 'f' is less than integer 'i'.
-** See comments on previous function.
-*/
-l_sinline int LTfloatint (lua_Number f, lua_Integer i) {
- if (l_intfitsf(i))
- return luai_numlt(f, cast_num(i)); /* compare them as floats */
- else { /* f < i <=> floor(f) < i */
- lua_Integer fi;
- if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */
- return fi < i; /* compare them as integers */
- else /* 'f' is either greater or less than all integers */
- return f < 0; /* less? */
- }
-}
-
-
-/*
-** Check whether float 'f' is less than or equal to integer 'i'.
-** See comments on previous function.
-*/
-l_sinline int LEfloatint (lua_Number f, lua_Integer i) {
- if (l_intfitsf(i))
- return luai_numle(f, cast_num(i)); /* compare them as floats */
- else { /* f <= i <=> ceil(f) <= i */
- lua_Integer fi;
- if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */
- return fi <= i; /* compare them as integers */
- else /* 'f' is either greater or less than all integers */
- return f < 0; /* less? */
- }
-}
-
-
-/*
-** Return 'l < r', for numbers.
-*/
-l_sinline int LTnum (const TValue *l, const TValue *r) {
- lua_assert(ttisnumber(l) && ttisnumber(r));
- if (ttisinteger(l)) {
- lua_Integer li = ivalue(l);
- if (ttisinteger(r))
- return li < ivalue(r); /* both are integers */
- else /* 'l' is int and 'r' is float */
- return LTintfloat(li, fltvalue(r)); /* l < r ? */
- }
- else {
- lua_Number lf = fltvalue(l); /* 'l' must be float */
- if (ttisfloat(r))
- return luai_numlt(lf, fltvalue(r)); /* both are float */
- else /* 'l' is float and 'r' is int */
- return LTfloatint(lf, ivalue(r));
- }
-}
-
-
-/*
-** Return 'l <= r', for numbers.
-*/
-l_sinline int LEnum (const TValue *l, const TValue *r) {
- lua_assert(ttisnumber(l) && ttisnumber(r));
- if (ttisinteger(l)) {
- lua_Integer li = ivalue(l);
- if (ttisinteger(r))
- return li <= ivalue(r); /* both are integers */
- else /* 'l' is int and 'r' is float */
- return LEintfloat(li, fltvalue(r)); /* l <= r ? */
- }
- else {
- lua_Number lf = fltvalue(l); /* 'l' must be float */
- if (ttisfloat(r))
- return luai_numle(lf, fltvalue(r)); /* both are float */
- else /* 'l' is float and 'r' is int */
- return LEfloatint(lf, ivalue(r));
- }
-}
-
-
-/*
-** return 'l < r' for non-numbers.
-*/
-static int lessthanothers (lua_State *L, const TValue *l, const TValue *r) {
- lua_assert(!ttisnumber(l) || !ttisnumber(r));
- if (ttisstring(l) && ttisstring(r)) /* both are strings? */
- return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
- else
- return luaT_callorderTM(L, l, r, TM_LT);
-}
-
-
-/*
-** Main operation less than; return 'l < r'.
-*/
-int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
- if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
- return LTnum(l, r);
- else return lessthanothers(L, l, r);
-}
-
-
-/*
-** return 'l <= r' for non-numbers.
-*/
-static int lessequalothers (lua_State *L, const TValue *l, const TValue *r) {
- lua_assert(!ttisnumber(l) || !ttisnumber(r));
- if (ttisstring(l) && ttisstring(r)) /* both are strings? */
- return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
- else
- return luaT_callorderTM(L, l, r, TM_LE);
-}
-
-
-/*
-** Main operation less than or equal to; return 'l <= r'.
-*/
-int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
- if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
- return LEnum(l, r);
- else return lessequalothers(L, l, r);
-}
-
-
-/*
-** Main operation for equality of Lua values; return 't1 == t2'.
-** L == NULL means raw equality (no metamethods)
-*/
-int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
- const TValue *tm;
- if (ttypetag(t1) != ttypetag(t2)) { /* not the same variant? */
- if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER)
- return 0; /* only numbers can be equal with different variants */
- else { /* two numbers with different variants */
- /* One of them is an integer. If the other does not have an
- integer value, they cannot be equal; otherwise, compare their
- integer values. */
- lua_Integer i1, i2;
- return (luaV_tointegerns(t1, &i1, F2Ieq) &&
- luaV_tointegerns(t2, &i2, F2Ieq) &&
- i1 == i2);
- }
- }
- /* values have same type and same variant */
- switch (ttypetag(t1)) {
- case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1;
- case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2));
- case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
- case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
- case LUA_VLCF: return fvalue(t1) == fvalue(t2);
- case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
- case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
- case LUA_VUSERDATA: {
- if (uvalue(t1) == uvalue(t2)) return 1;
- else if (L == NULL) return 0;
- tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
- if (tm == NULL)
- tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
- break; /* will try TM */
- }
- case LUA_VTABLE: {
- if (hvalue(t1) == hvalue(t2)) return 1;
- else if (L == NULL) return 0;
- tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
- if (tm == NULL)
- tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
- break; /* will try TM */
- }
- default:
- return gcvalue(t1) == gcvalue(t2);
- }
- if (tm == NULL) /* no TM? */
- return 0; /* objects are different */
- else {
- luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */
- return !l_isfalse(s2v(L->top));
- }
-}
-
-
-/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
-#define tostring(L,o) \
- (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
-
-#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
-
-/* copy strings in stack from top - n up to top - 1 to buffer */
-static void copy2buff (StkId top, int n, char *buff) {
- size_t tl = 0; /* size already copied */
- do {
- size_t l = vslen(s2v(top - n)); /* length of string being copied */
- memcpy(buff + tl, svalue(s2v(top - n)), l * sizeof(char));
- tl += l;
- } while (--n > 0);
-}
-
-
-/*
-** Main operation for concatenation: concat 'total' values in the stack,
-** from 'L->top - total' up to 'L->top - 1'.
-*/
-void luaV_concat (lua_State *L, int total) {
- if (total == 1)
- return; /* "all" values already concatenated */
- do {
- StkId top = L->top;
- int n = 2; /* number of elements handled in this pass (at least 2) */
- if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) ||
- !tostring(L, s2v(top - 1)))
- luaT_tryconcatTM(L);
- else if (isemptystr(s2v(top - 1))) /* second operand is empty? */
- cast_void(tostring(L, s2v(top - 2))); /* result is first operand */
- else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */
- setobjs2s(L, top - 2, top - 1); /* result is second op. */
- }
- else {
- /* at least two non-empty string values; get as many as possible */
- size_t tl = vslen(s2v(top - 1));
- TString *ts;
- /* collect total length and number of strings */
- for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
- size_t l = vslen(s2v(top - n - 1));
- if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
- luaG_runerror(L, "string length overflow");
- tl += l;
- }
- if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
- char buff[LUAI_MAXSHORTLEN];
- copy2buff(top, n, buff); /* copy strings to buffer */
- ts = luaS_newlstr(L, buff, tl);
- }
- else { /* long string; copy strings directly to final result */
- ts = luaS_createlngstrobj(L, tl);
- copy2buff(top, n, getstr(ts));
- }
- setsvalue2s(L, top - n, ts); /* create result */
- }
- total -= n-1; /* got 'n' strings to create 1 new */
- L->top -= n-1; /* popped 'n' strings and pushed one */
- } while (total > 1); /* repeat until only 1 result left */
-}
-
-
-/*
-** Main operation 'ra = #rb'.
-*/
-void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
- const TValue *tm;
- switch (ttypetag(rb)) {
- case LUA_VTABLE: {
- Table *h = hvalue(rb);
- tm = fasttm(L, h->metatable, TM_LEN);
- if (tm) break; /* metamethod? break switch to call it */
- setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */
- return;
- }
- case LUA_VSHRSTR: {
- setivalue(s2v(ra), tsvalue(rb)->shrlen);
- return;
- }
- case LUA_VLNGSTR: {
- setivalue(s2v(ra), tsvalue(rb)->u.lnglen);
- return;
- }
- default: { /* try metamethod */
- tm = luaT_gettmbyobj(L, rb, TM_LEN);
- if (l_unlikely(notm(tm))) /* no metamethod? */
- luaG_typeerror(L, rb, "get length of");
- break;
- }
- }
- luaT_callTMres(L, tm, rb, rb, ra);
-}
-
-
-/*
-** Integer division; return 'm // n', that is, floor(m/n).
-** C division truncates its result (rounds towards zero).
-** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
-** otherwise 'floor(q) == trunc(q) - 1'.
-*/
-lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
- if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
- if (n == 0)
- luaG_runerror(L, "attempt to divide by zero");
- return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
- }
- else {
- lua_Integer q = m / n; /* perform C division */
- if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */
- q -= 1; /* correct result for different rounding */
- return q;
- }
-}
-
-
-/*
-** Integer modulus; return 'm % n'. (Assume that C '%' with
-** negative operands follows C99 behavior. See previous comment
-** about luaV_idiv.)
-*/
-lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
- if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
- if (n == 0)
- luaG_runerror(L, "attempt to perform 'n%%0'");
- return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
- }
- else {
- lua_Integer r = m % n;
- if (r != 0 && (r ^ n) < 0) /* 'm/n' would be non-integer negative? */
- r += n; /* correct result for different rounding */
- return r;
- }
-}
-
-
-/*
-** Float modulus
-*/
-lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
- lua_Number r;
- luai_nummod(L, m, n, r);
- return r;
-}
-
-
-/* number of bits in an integer */
-#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
-
-/*
-** Shift left operation. (Shift right just negates 'y'.)
-*/
-#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y))
-
-
-lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
- if (y < 0) { /* shift right? */
- if (y <= -NBITS) return 0;
- else return intop(>>, x, -y);
- }
- else { /* shift left */
- if (y >= NBITS) return 0;
- else return intop(<<, x, y);
- }
-}
-
-
-/*
-** create a new Lua closure, push it in the stack, and initialize
-** its upvalues.
-*/
-static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
- StkId ra) {
- int nup = p->sizeupvalues;
- Upvaldesc *uv = p->upvalues;
- int i;
- LClosure *ncl = luaF_newLclosure(L, nup);
- ncl->p = p;
- setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */
- for (i = 0; i < nup; i++) { /* fill in its upvalues */
- if (uv[i].instack) /* upvalue refers to local variable? */
- ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
- else /* get upvalue from enclosing function */
- ncl->upvals[i] = encup[uv[i].idx];
- luaC_objbarrier(L, ncl, ncl->upvals[i]);
- }
-}
-
-
-/*
-** finish execution of an opcode interrupted by a yield
-*/
-void luaV_finishOp (lua_State *L) {
- CallInfo *ci = L->ci;
- StkId base = ci->func + 1;
- Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
- OpCode op = GET_OPCODE(inst);
- switch (op) { /* finish its execution */
- case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
- setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top);
- break;
- }
- case OP_UNM: case OP_BNOT: case OP_LEN:
- case OP_GETTABUP: case OP_GETTABLE: case OP_GETI:
- case OP_GETFIELD: case OP_SELF: {
- setobjs2s(L, base + GETARG_A(inst), --L->top);
- break;
- }
- case OP_LT: case OP_LE:
- case OP_LTI: case OP_LEI:
- case OP_GTI: case OP_GEI:
- case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */
- int res = !l_isfalse(s2v(L->top - 1));
- L->top--;
-#if defined(LUA_COMPAT_LT_LE)
- if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */
- ci->callstatus ^= CIST_LEQ; /* clear mark */
- res = !res; /* negate result */
- }
-#endif
- lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
- if (res != GETARG_k(inst)) /* condition failed? */
- ci->u.l.savedpc++; /* skip jump instruction */
- break;
- }
- case OP_CONCAT: {
- StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */
- int a = GETARG_A(inst); /* first element to concatenate */
- int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */
- setobjs2s(L, top - 2, top); /* put TM result in proper position */
- L->top = top - 1; /* top is one after last element (at top-2) */
- luaV_concat(L, total); /* concat them (may yield again) */
- break;
- }
- case OP_CLOSE: { /* yielded closing variables */
- ci->u.l.savedpc--; /* repeat instruction to close other vars. */
- break;
- }
- case OP_RETURN: { /* yielded closing variables */
- StkId ra = base + GETARG_A(inst);
- /* adjust top to signal correct number of returns, in case the
- return is "up to top" ('isIT') */
- L->top = ra + ci->u2.nres;
- /* repeat instruction to close other vars. and complete the return */
- ci->u.l.savedpc--;
- break;
- }
- default: {
- /* only these other opcodes can yield */
- lua_assert(op == OP_TFORCALL || op == OP_CALL ||
- op == OP_TAILCALL || op == OP_SETTABUP || op == OP_SETTABLE ||
- op == OP_SETI || op == OP_SETFIELD);
- break;
- }
- }
-}
-
-
-
-
-/*
-** {==================================================================
-** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute'
-** ===================================================================
-*/
-
-#define l_addi(L,a,b) intop(+, a, b)
-#define l_subi(L,a,b) intop(-, a, b)
-#define l_muli(L,a,b) intop(*, a, b)
-#define l_band(a,b) intop(&, a, b)
-#define l_bor(a,b) intop(|, a, b)
-#define l_bxor(a,b) intop(^, a, b)
-
-#define l_lti(a,b) (a < b)
-#define l_lei(a,b) (a <= b)
-#define l_gti(a,b) (a > b)
-#define l_gei(a,b) (a >= b)
-
-
-/*
-** Arithmetic operations with immediate operands. 'iop' is the integer
-** operation, 'fop' is the float operation.
-*/
-#define op_arithI(L,iop,fop) { \
- TValue *v1 = vRB(i); \
- int imm = GETARG_sC(i); \
- if (ttisinteger(v1)) { \
- lua_Integer iv1 = ivalue(v1); \
- pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \
- } \
- else if (ttisfloat(v1)) { \
- lua_Number nb = fltvalue(v1); \
- lua_Number fimm = cast_num(imm); \
- pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \
- }}
-
-
-/*
-** Auxiliary function for arithmetic operations over floats and others
-** with two register operands.
-*/
-#define op_arithf_aux(L,v1,v2,fop) { \
- lua_Number n1; lua_Number n2; \
- if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
- pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \
- }}
-
-
-/*
-** Arithmetic operations over floats and others with register operands.
-*/
-#define op_arithf(L,fop) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = vRC(i); \
- op_arithf_aux(L, v1, v2, fop); }
-
-
-/*
-** Arithmetic operations with K operands for floats.
-*/
-#define op_arithfK(L,fop) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
- op_arithf_aux(L, v1, v2, fop); }
-
-
-/*
-** Arithmetic operations over integers and floats.
-*/
-#define op_arith_aux(L,v1,v2,iop,fop) { \
- if (ttisinteger(v1) && ttisinteger(v2)) { \
- lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
- pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
- } \
- else op_arithf_aux(L, v1, v2, fop); }
-
-
-/*
-** Arithmetic operations with register operands.
-*/
-#define op_arith(L,iop,fop) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = vRC(i); \
- op_arith_aux(L, v1, v2, iop, fop); }
-
-
-/*
-** Arithmetic operations with K operands.
-*/
-#define op_arithK(L,iop,fop) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
- op_arith_aux(L, v1, v2, iop, fop); }
-
-
-/*
-** Bitwise operations with constant operand.
-*/
-#define op_bitwiseK(L,op) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = KC(i); \
- lua_Integer i1; \
- lua_Integer i2 = ivalue(v2); \
- if (tointegerns(v1, &i1)) { \
- pc++; setivalue(s2v(ra), op(i1, i2)); \
- }}
-
-
-/*
-** Bitwise operations with register operands.
-*/
-#define op_bitwise(L,op) { \
- TValue *v1 = vRB(i); \
- TValue *v2 = vRC(i); \
- lua_Integer i1; lua_Integer i2; \
- if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) { \
- pc++; setivalue(s2v(ra), op(i1, i2)); \
- }}
-
-
-/*
-** Order operations with register operands. 'opn' actually works
-** for all numbers, but the fast track improves performance for
-** integers.
-*/
-#define op_order(L,opi,opn,other) { \
- int cond; \
- TValue *rb = vRB(i); \
- if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
- lua_Integer ia = ivalue(s2v(ra)); \
- lua_Integer ib = ivalue(rb); \
- cond = opi(ia, ib); \
- } \
- else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
- cond = opn(s2v(ra), rb); \
- else \
- Protect(cond = other(L, s2v(ra), rb)); \
- docondjump(); }
-
-
-/*
-** Order operations with immediate operand. (Immediate operand is
-** always small enough to have an exact representation as a float.)
-*/
-#define op_orderI(L,opi,opf,inv,tm) { \
- int cond; \
- int im = GETARG_sB(i); \
- if (ttisinteger(s2v(ra))) \
- cond = opi(ivalue(s2v(ra)), im); \
- else if (ttisfloat(s2v(ra))) { \
- lua_Number fa = fltvalue(s2v(ra)); \
- lua_Number fim = cast_num(im); \
- cond = opf(fa, fim); \
- } \
- else { \
- int isf = GETARG_C(i); \
- Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \
- } \
- docondjump(); }
-
-/* }================================================================== */
-
-
-/*
-** {==================================================================
-** Function 'luaV_execute': main interpreter loop
-** ===================================================================
-*/
-
-/*
-** some macros for common tasks in 'luaV_execute'
-*/
-
-
-#define RA(i) (base+GETARG_A(i))
-#define RB(i) (base+GETARG_B(i))
-#define vRB(i) s2v(RB(i))
-#define KB(i) (k+GETARG_B(i))
-#define RC(i) (base+GETARG_C(i))
-#define vRC(i) s2v(RC(i))
-#define KC(i) (k+GETARG_C(i))
-#define RKC(i) ((TESTARG_k(i)) ? k + GETARG_C(i) : s2v(base + GETARG_C(i)))
-
-
-
-#define updatetrap(ci) (trap = ci->u.l.trap)
-
-#define updatebase(ci) (base = ci->func + 1)
-
-
-#define updatestack(ci) \
- { if (l_unlikely(trap)) { updatebase(ci); ra = RA(i); } }
-
-
-/*
-** Execute a jump instruction. The 'updatetrap' allows signals to stop
-** tight loops. (Without it, the local copy of 'trap' could never change.)
-*/
-#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatetrap(ci); }
-
-
-/* for test instructions, execute the jump instruction that follows it */
-#define donextjump(ci) { Instruction ni = *pc; dojump(ci, ni, 1); }
-
-/*
-** do a conditional jump: skip next instruction if 'cond' is not what
-** was expected (parameter 'k'), else do next instruction, which must
-** be a jump.
-*/
-#define docondjump() if (cond != GETARG_k(i)) pc++; else donextjump(ci);
-
-
-/*
-** Correct global 'pc'.
-*/
-#define savepc(L) (ci->u.l.savedpc = pc)
-
-
-/*
-** Whenever code can raise errors, the global 'pc' and the global
-** 'top' must be correct to report occasional errors.
-*/
-#define savestate(L,ci) (savepc(L), L->top = ci->top)
-
-
-/*
-** Protect code that, in general, can raise errors, reallocate the
-** stack, and change the hooks.
-*/
-#define Protect(exp) (savestate(L,ci), (exp), updatetrap(ci))
-
-/* special version that does not change the top */
-#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
-
-/*
-** Protect code that can only raise errors. (That is, it cannot change
-** the stack or hooks.)
-*/
-#define halfProtect(exp) (savestate(L,ci), (exp))
-
-/* 'c' is the limit of live values in the stack */
-#define checkGC(L,c) \
- { luaC_condGC(L, (savepc(L), L->top = (c)), \
- updatetrap(ci)); \
- luai_threadyield(L); }
-
-
-/* fetch an instruction and prepare its execution */
-#define vmfetch() { \
- if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \
- trap = luaG_traceexec(L, pc); /* handle hooks */ \
- updatebase(ci); /* correct stack */ \
- } \
- i = *(pc++); \
- ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
-}
-
-#define vmdispatch(o) switch(o)
-#define vmcase(l) case l:
-#define vmbreak break
-
-
-void luaV_execute (lua_State *L, CallInfo *ci) {
- LClosure *cl;
- TValue *k;
- StkId base;
- const Instruction *pc;
- int trap;
-#if LUA_USE_JUMPTABLE
-#include "ljumptab.h"
-#endif
- startfunc:
- trap = L->hookmask;
- returning: /* trap already set */
- cl = clLvalue(s2v(ci->func));
- k = cl->p->k;
- pc = ci->u.l.savedpc;
- if (l_unlikely(trap)) {
- if (pc == cl->p->code) { /* first instruction (not resuming)? */
- if (cl->p->is_vararg)
- trap = 0; /* hooks will start after VARARGPREP instruction */
- else /* check 'call' hook */
- luaD_hookcall(L, ci);
- }
- ci->u.l.trap = 1; /* assume trap is on, for now */
- }
- base = ci->func + 1;
- /* main loop of interpreter */
- for (;;) {
- Instruction i; /* instruction being executed */
- StkId ra; /* instruction's A register */
- vmfetch();
- #if 0
- /* low-level line tracing for debugging Lua */
- printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
- #endif
- lua_assert(base == ci->func + 1);
- lua_assert(base <= L->top && L->top < L->stack_last);
- /* invalidate top for instructions not expecting it */
- lua_assert(isIT(i) || (cast_void(L->top = base), 1));
- vmdispatch (GET_OPCODE(i)) {
- vmcase(OP_MOVE) {
- setobjs2s(L, ra, RB(i));
- vmbreak;
- }
- vmcase(OP_LOADI) {
- lua_Integer b = GETARG_sBx(i);
- setivalue(s2v(ra), b);
- vmbreak;
- }
- vmcase(OP_LOADF) {
- int b = GETARG_sBx(i);
- setfltvalue(s2v(ra), cast_num(b));
- vmbreak;
- }
- vmcase(OP_LOADK) {
- TValue *rb = k + GETARG_Bx(i);
- setobj2s(L, ra, rb);
- vmbreak;
- }
- vmcase(OP_LOADKX) {
- TValue *rb;
- rb = k + GETARG_Ax(*pc); pc++;
- setobj2s(L, ra, rb);
- vmbreak;
- }
- vmcase(OP_LOADFALSE) {
- setbfvalue(s2v(ra));
- vmbreak;
- }
- vmcase(OP_LFALSESKIP) {
- setbfvalue(s2v(ra));
- pc++; /* skip next instruction */
- vmbreak;
- }
- vmcase(OP_LOADTRUE) {
- setbtvalue(s2v(ra));
- vmbreak;
- }
- vmcase(OP_LOADNIL) {
- int b = GETARG_B(i);
- do {
- setnilvalue(s2v(ra++));
- } while (b--);
- vmbreak;
- }
- vmcase(OP_GETUPVAL) {
- int b = GETARG_B(i);
- setobj2s(L, ra, cl->upvals[b]->v);
- vmbreak;
- }
- vmcase(OP_SETUPVAL) {
- UpVal *uv = cl->upvals[GETARG_B(i)];
- setobj(L, uv->v, s2v(ra));
- luaC_barrier(L, uv, s2v(ra));
- vmbreak;
- }
- vmcase(OP_GETTABUP) {
- const TValue *slot;
- TValue *upval = cl->upvals[GETARG_B(i)]->v;
- TValue *rc = KC(i);
- TString *key = tsvalue(rc); /* key must be a string */
- if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
- setobj2s(L, ra, slot);
- }
- else
- Protect(luaV_finishget(L, upval, rc, ra, slot));
- vmbreak;
- }
- vmcase(OP_GETTABLE) {
- const TValue *slot;
- TValue *rb = vRB(i);
- TValue *rc = vRC(i);
- lua_Unsigned n;
- if (ttisinteger(rc) /* fast track for integers? */
- ? (cast_void(n = ivalue(rc)), luaV_fastgeti(L, rb, n, slot))
- : luaV_fastget(L, rb, rc, slot, luaH_get)) {
- setobj2s(L, ra, slot);
- }
- else
- Protect(luaV_finishget(L, rb, rc, ra, slot));
- vmbreak;
- }
- vmcase(OP_GETI) {
- const TValue *slot;
- TValue *rb = vRB(i);
- int c = GETARG_C(i);
- if (luaV_fastgeti(L, rb, c, slot)) {
- setobj2s(L, ra, slot);
- }
- else {
- TValue key;
- setivalue(&key, c);
- Protect(luaV_finishget(L, rb, &key, ra, slot));
- }
- vmbreak;
- }
- vmcase(OP_GETFIELD) {
- const TValue *slot;
- TValue *rb = vRB(i);
- TValue *rc = KC(i);
- TString *key = tsvalue(rc); /* key must be a string */
- if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) {
- setobj2s(L, ra, slot);
- }
- else
- Protect(luaV_finishget(L, rb, rc, ra, slot));
- vmbreak;
- }
- vmcase(OP_SETTABUP) {
- const TValue *slot;
- TValue *upval = cl->upvals[GETARG_A(i)]->v;
- TValue *rb = KB(i);
- TValue *rc = RKC(i);
- TString *key = tsvalue(rb); /* key must be a string */
- if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
- luaV_finishfastset(L, upval, slot, rc);
- }
- else
- Protect(luaV_finishset(L, upval, rb, rc, slot));
- vmbreak;
- }
- vmcase(OP_SETTABLE) {
- const TValue *slot;
- TValue *rb = vRB(i); /* key (table is in 'ra') */
- TValue *rc = RKC(i); /* value */
- lua_Unsigned n;
- if (ttisinteger(rb) /* fast track for integers? */
- ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot))
- : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) {
- luaV_finishfastset(L, s2v(ra), slot, rc);
- }
- else
- Protect(luaV_finishset(L, s2v(ra), rb, rc, slot));
- vmbreak;
- }
- vmcase(OP_SETI) {
- const TValue *slot;
- int c = GETARG_B(i);
- TValue *rc = RKC(i);
- if (luaV_fastgeti(L, s2v(ra), c, slot)) {
- luaV_finishfastset(L, s2v(ra), slot, rc);
- }
- else {
- TValue key;
- setivalue(&key, c);
- Protect(luaV_finishset(L, s2v(ra), &key, rc, slot));
- }
- vmbreak;
- }
- vmcase(OP_SETFIELD) {
- const TValue *slot;
- TValue *rb = KB(i);
- TValue *rc = RKC(i);
- TString *key = tsvalue(rb); /* key must be a string */
- if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
- luaV_finishfastset(L, s2v(ra), slot, rc);
- }
- else
- Protect(luaV_finishset(L, s2v(ra), rb, rc, slot));
- vmbreak;
- }
- vmcase(OP_NEWTABLE) {
- int b = GETARG_B(i); /* log2(hash size) + 1 */
- int c = GETARG_C(i); /* array size */
- Table *t;
- if (b > 0)
- b = 1 << (b - 1); /* size is 2^(b - 1) */
- lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0));
- if (TESTARG_k(i)) /* non-zero extra argument? */
- c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */
- pc++; /* skip extra argument */
- L->top = ra + 1; /* correct top in case of emergency GC */
- t = luaH_new(L); /* memory allocation */
- sethvalue2s(L, ra, t);
- if (b != 0 || c != 0)
- luaH_resize(L, t, c, b); /* idem */
- checkGC(L, ra + 1);
- vmbreak;
- }
- vmcase(OP_SELF) {
- const TValue *slot;
- TValue *rb = vRB(i);
- TValue *rc = RKC(i);
- TString *key = tsvalue(rc); /* key must be a string */
- setobj2s(L, ra + 1, rb);
- if (luaV_fastget(L, rb, key, slot, luaH_getstr)) {
- setobj2s(L, ra, slot);
- }
- else
- Protect(luaV_finishget(L, rb, rc, ra, slot));
- vmbreak;
- }
- vmcase(OP_ADDI) {
- op_arithI(L, l_addi, luai_numadd);
- vmbreak;
- }
- vmcase(OP_ADDK) {
- op_arithK(L, l_addi, luai_numadd);
- vmbreak;
- }
- vmcase(OP_SUBK) {
- op_arithK(L, l_subi, luai_numsub);
- vmbreak;
- }
- vmcase(OP_MULK) {
- op_arithK(L, l_muli, luai_nummul);
- vmbreak;
- }
- vmcase(OP_MODK) {
- op_arithK(L, luaV_mod, luaV_modf);
- vmbreak;
- }
- vmcase(OP_POWK) {
- op_arithfK(L, luai_numpow);
- vmbreak;
- }
- vmcase(OP_DIVK) {
- op_arithfK(L, luai_numdiv);
- vmbreak;
- }
- vmcase(OP_IDIVK) {
- op_arithK(L, luaV_idiv, luai_numidiv);
- vmbreak;
- }
- vmcase(OP_BANDK) {
- op_bitwiseK(L, l_band);
- vmbreak;
- }
- vmcase(OP_BORK) {
- op_bitwiseK(L, l_bor);
- vmbreak;
- }
- vmcase(OP_BXORK) {
- op_bitwiseK(L, l_bxor);
- vmbreak;
- }
- vmcase(OP_SHRI) {
- TValue *rb = vRB(i);
- int ic = GETARG_sC(i);
- lua_Integer ib;
- if (tointegerns(rb, &ib)) {
- pc++; setivalue(s2v(ra), luaV_shiftl(ib, -ic));
- }
- vmbreak;
- }
- vmcase(OP_SHLI) {
- TValue *rb = vRB(i);
- int ic = GETARG_sC(i);
- lua_Integer ib;
- if (tointegerns(rb, &ib)) {
- pc++; setivalue(s2v(ra), luaV_shiftl(ic, ib));
- }
- vmbreak;
- }
- vmcase(OP_ADD) {
- op_arith(L, l_addi, luai_numadd);
- vmbreak;
- }
- vmcase(OP_SUB) {
- op_arith(L, l_subi, luai_numsub);
- vmbreak;
- }
- vmcase(OP_MUL) {
- op_arith(L, l_muli, luai_nummul);
- vmbreak;
- }
- vmcase(OP_MOD) {
- op_arith(L, luaV_mod, luaV_modf);
- vmbreak;
- }
- vmcase(OP_POW) {
- op_arithf(L, luai_numpow);
- vmbreak;
- }
- vmcase(OP_DIV) { /* float division (always with floats) */
- op_arithf(L, luai_numdiv);
- vmbreak;
- }
- vmcase(OP_IDIV) { /* floor division */
- op_arith(L, luaV_idiv, luai_numidiv);
- vmbreak;
- }
- vmcase(OP_BAND) {
- op_bitwise(L, l_band);
- vmbreak;
- }
- vmcase(OP_BOR) {
- op_bitwise(L, l_bor);
- vmbreak;
- }
- vmcase(OP_BXOR) {
- op_bitwise(L, l_bxor);
- vmbreak;
- }
- vmcase(OP_SHR) {
- op_bitwise(L, luaV_shiftr);
- vmbreak;
- }
- vmcase(OP_SHL) {
- op_bitwise(L, luaV_shiftl);
- vmbreak;
- }
- vmcase(OP_MMBIN) {
- Instruction pi = *(pc - 2); /* original arith. expression */
- TValue *rb = vRB(i);
- TMS tm = (TMS)GETARG_C(i);
- StkId result = RA(pi);
- lua_assert(OP_ADD <= GET_OPCODE(pi) && GET_OPCODE(pi) <= OP_SHR);
- Protect(luaT_trybinTM(L, s2v(ra), rb, result, tm));
- vmbreak;
- }
- vmcase(OP_MMBINI) {
- Instruction pi = *(pc - 2); /* original arith. expression */
- int imm = GETARG_sB(i);
- TMS tm = (TMS)GETARG_C(i);
- int flip = GETARG_k(i);
- StkId result = RA(pi);
- Protect(luaT_trybiniTM(L, s2v(ra), imm, flip, result, tm));
- vmbreak;
- }
- vmcase(OP_MMBINK) {
- Instruction pi = *(pc - 2); /* original arith. expression */
- TValue *imm = KB(i);
- TMS tm = (TMS)GETARG_C(i);
- int flip = GETARG_k(i);
- StkId result = RA(pi);
- Protect(luaT_trybinassocTM(L, s2v(ra), imm, flip, result, tm));
- vmbreak;
- }
- vmcase(OP_UNM) {
- TValue *rb = vRB(i);
- lua_Number nb;
- if (ttisinteger(rb)) {
- lua_Integer ib = ivalue(rb);
- setivalue(s2v(ra), intop(-, 0, ib));
- }
- else if (tonumberns(rb, nb)) {
- setfltvalue(s2v(ra), luai_numunm(L, nb));
- }
- else
- Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
- vmbreak;
- }
- vmcase(OP_BNOT) {
- TValue *rb = vRB(i);
- lua_Integer ib;
- if (tointegerns(rb, &ib)) {
- setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib));
- }
- else
- Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));
- vmbreak;
- }
- vmcase(OP_NOT) {
- TValue *rb = vRB(i);
- if (l_isfalse(rb))
- setbtvalue(s2v(ra));
- else
- setbfvalue(s2v(ra));
- vmbreak;
- }
- vmcase(OP_LEN) {
- Protect(luaV_objlen(L, ra, vRB(i)));
- vmbreak;
- }
- vmcase(OP_CONCAT) {
- int n = GETARG_B(i); /* number of elements to concatenate */
- L->top = ra + n; /* mark the end of concat operands */
- ProtectNT(luaV_concat(L, n));
- checkGC(L, L->top); /* 'luaV_concat' ensures correct top */
- vmbreak;
- }
- vmcase(OP_CLOSE) {
- Protect(luaF_close(L, ra, LUA_OK, 1));
- vmbreak;
- }
- vmcase(OP_TBC) {
- /* create new to-be-closed upvalue */
- halfProtect(luaF_newtbcupval(L, ra));
- vmbreak;
- }
- vmcase(OP_JMP) {
- dojump(ci, i, 0);
- vmbreak;
- }
- vmcase(OP_EQ) {
- int cond;
- TValue *rb = vRB(i);
- Protect(cond = luaV_equalobj(L, s2v(ra), rb));
- docondjump();
- vmbreak;
- }
- vmcase(OP_LT) {
- op_order(L, l_lti, LTnum, lessthanothers);
- vmbreak;
- }
- vmcase(OP_LE) {
- op_order(L, l_lei, LEnum, lessequalothers);
- vmbreak;
- }
- vmcase(OP_EQK) {
- TValue *rb = KB(i);
- /* basic types do not use '__eq'; we can use raw equality */
- int cond = luaV_rawequalobj(s2v(ra), rb);
- docondjump();
- vmbreak;
- }
- vmcase(OP_EQI) {
- int cond;
- int im = GETARG_sB(i);
- if (ttisinteger(s2v(ra)))
- cond = (ivalue(s2v(ra)) == im);
- else if (ttisfloat(s2v(ra)))
- cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im));
- else
- cond = 0; /* other types cannot be equal to a number */
- docondjump();
- vmbreak;
- }
- vmcase(OP_LTI) {
- op_orderI(L, l_lti, luai_numlt, 0, TM_LT);
- vmbreak;
- }
- vmcase(OP_LEI) {
- op_orderI(L, l_lei, luai_numle, 0, TM_LE);
- vmbreak;
- }
- vmcase(OP_GTI) {
- op_orderI(L, l_gti, luai_numgt, 1, TM_LT);
- vmbreak;
- }
- vmcase(OP_GEI) {
- op_orderI(L, l_gei, luai_numge, 1, TM_LE);
- vmbreak;
- }
- vmcase(OP_TEST) {
- int cond = !l_isfalse(s2v(ra));
- docondjump();
- vmbreak;
- }
- vmcase(OP_TESTSET) {
- TValue *rb = vRB(i);
- if (l_isfalse(rb) == GETARG_k(i))
- pc++;
- else {
- setobj2s(L, ra, rb);
- donextjump(ci);
- }
- vmbreak;
- }
- vmcase(OP_CALL) {
- CallInfo *newci;
- int b = GETARG_B(i);
- int nresults = GETARG_C(i) - 1;
- if (b != 0) /* fixed number of arguments? */
- L->top = ra + b; /* top signals number of arguments */
- /* else previous instruction set top */
- savepc(L); /* in case of errors */
- if ((newci = luaD_precall(L, ra, nresults)) == NULL)
- updatetrap(ci); /* C call; nothing else to be done */
- else { /* Lua call: run function in this same C frame */
- ci = newci;
- goto startfunc;
- }
- vmbreak;
- }
- vmcase(OP_TAILCALL) {
- int b = GETARG_B(i); /* number of arguments + 1 (function) */
- int n; /* number of results when calling a C function */
- int nparams1 = GETARG_C(i);
- /* delta is virtual 'func' - real 'func' (vararg functions) */
- int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
- if (b != 0)
- L->top = ra + b;
- else /* previous instruction set top */
- b = cast_int(L->top - ra);
- savepc(ci); /* several calls here can raise errors */
- if (TESTARG_k(i)) {
- luaF_closeupval(L, base); /* close upvalues from current call */
- lua_assert(L->tbclist < base); /* no pending tbc variables */
- lua_assert(base == ci->func + 1);
- }
- if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */
- goto startfunc; /* execute the callee */
- else { /* C function? */
- ci->func -= delta; /* restore 'func' (if vararg) */
- luaD_poscall(L, ci, n); /* finish caller */
- updatetrap(ci); /* 'luaD_poscall' can change hooks */
- goto ret; /* caller returns after the tail call */
- }
- }
- vmcase(OP_RETURN) {
- int n = GETARG_B(i) - 1; /* number of results */
- int nparams1 = GETARG_C(i);
- if (n < 0) /* not fixed? */
- n = cast_int(L->top - ra); /* get what is available */
- savepc(ci);
- if (TESTARG_k(i)) { /* may there be open upvalues? */
- ci->u2.nres = n; /* save number of returns */
- if (L->top < ci->top)
- L->top = ci->top;
- luaF_close(L, base, CLOSEKTOP, 1);
- updatetrap(ci);
- updatestack(ci);
- }
- if (nparams1) /* vararg function? */
- ci->func -= ci->u.l.nextraargs + nparams1;
- L->top = ra + n; /* set call for 'luaD_poscall' */
- luaD_poscall(L, ci, n);
- updatetrap(ci); /* 'luaD_poscall' can change hooks */
- goto ret;
- }
- vmcase(OP_RETURN0) {
- if (l_unlikely(L->hookmask)) {
- L->top = ra;
- savepc(ci);
- luaD_poscall(L, ci, 0); /* no hurry... */
- trap = 1;
- }
- else { /* do the 'poscall' here */
- int nres;
- L->ci = ci->previous; /* back to caller */
- L->top = base - 1;
- for (nres = ci->nresults; l_unlikely(nres > 0); nres--)
- setnilvalue(s2v(L->top++)); /* all results are nil */
- }
- goto ret;
- }
- vmcase(OP_RETURN1) {
- if (l_unlikely(L->hookmask)) {
- L->top = ra + 1;
- savepc(ci);
- luaD_poscall(L, ci, 1); /* no hurry... */
- trap = 1;
- }
- else { /* do the 'poscall' here */
- int nres = ci->nresults;
- L->ci = ci->previous; /* back to caller */
- if (nres == 0)
- L->top = base - 1; /* asked for no results */
- else {
- setobjs2s(L, base - 1, ra); /* at least this result */
- L->top = base;
- for (; l_unlikely(nres > 1); nres--)
- setnilvalue(s2v(L->top++)); /* complete missing results */
- }
- }
- ret: /* return from a Lua function */
- if (ci->callstatus & CIST_FRESH)
- return; /* end this frame */
- else {
- ci = ci->previous;
- goto returning; /* continue running caller in this frame */
- }
- }
- vmcase(OP_FORLOOP) {
- if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
- lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1)));
- if (count > 0) { /* still more iterations? */
- lua_Integer step = ivalue(s2v(ra + 2));
- lua_Integer idx = ivalue(s2v(ra)); /* internal index */
- chgivalue(s2v(ra + 1), count - 1); /* update counter */
- idx = intop(+, idx, step); /* add step to index */
- chgivalue(s2v(ra), idx); /* update internal index */
- setivalue(s2v(ra + 3), idx); /* and control variable */
- pc -= GETARG_Bx(i); /* jump back */
- }
- }
- else if (floatforloop(ra)) /* float loop */
- pc -= GETARG_Bx(i); /* jump back */
- updatetrap(ci); /* allows a signal to break the loop */
- vmbreak;
- }
- vmcase(OP_FORPREP) {
- savestate(L, ci); /* in case of errors */
- if (forprep(L, ra))
- pc += GETARG_Bx(i) + 1; /* skip the loop */
- vmbreak;
- }
- vmcase(OP_TFORPREP) {
- /* create to-be-closed upvalue (if needed) */
- halfProtect(luaF_newtbcupval(L, ra + 3));
- pc += GETARG_Bx(i);
- i = *(pc++); /* go to next instruction */
- lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
- goto l_tforcall;
- }
- vmcase(OP_TFORCALL) {
- l_tforcall:
- /* 'ra' has the iterator function, 'ra + 1' has the state,
- 'ra + 2' has the control variable, and 'ra + 3' has the
- to-be-closed variable. The call will use the stack after
- these values (starting at 'ra + 4')
- */
- /* push function, state, and control variable */
- memcpy(ra + 4, ra, 3 * sizeof(*ra));
- L->top = ra + 4 + 3;
- ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
- updatestack(ci); /* stack may have changed */
- i = *(pc++); /* go to next instruction */
- lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
- goto l_tforloop;
- }
- vmcase(OP_TFORLOOP) {
- l_tforloop:
- if (!ttisnil(s2v(ra + 4))) { /* continue loop? */
- setobjs2s(L, ra + 2, ra + 4); /* save control variable */
- pc -= GETARG_Bx(i); /* jump back */
- }
- vmbreak;
- }
- vmcase(OP_SETLIST) {
- int n = GETARG_B(i);
- unsigned int last = GETARG_C(i);
- Table *h = hvalue(s2v(ra));
- if (n == 0)
- n = cast_int(L->top - ra) - 1; /* get up to the top */
- else
- L->top = ci->top; /* correct top in case of emergency GC */
- last += n;
- if (TESTARG_k(i)) {
- last += GETARG_Ax(*pc) * (MAXARG_C + 1);
- pc++;
- }
- if (last > luaH_realasize(h)) /* needs more space? */
- luaH_resizearray(L, h, last); /* preallocate it at once */
- for (; n > 0; n--) {
- TValue *val = s2v(ra + n);
- setobj2t(L, &h->array[last - 1], val);
- last--;
- luaC_barrierback(L, obj2gco(h), val);
- }
- vmbreak;
- }
- vmcase(OP_CLOSURE) {
- Proto *p = cl->p->p[GETARG_Bx(i)];
- halfProtect(pushclosure(L, p, cl->upvals, base, ra));
- checkGC(L, ra + 1);
- vmbreak;
- }
- vmcase(OP_VARARG) {
- int n = GETARG_C(i) - 1; /* required results */
- Protect(luaT_getvarargs(L, ci, ra, n));
- vmbreak;
- }
- vmcase(OP_VARARGPREP) {
- ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p));
- if (l_unlikely(trap)) { /* previous "Protect" updated trap */
- luaD_hookcall(L, ci);
- L->oldpc = 1; /* next opcode will be seen as a "new" line */
- }
- updatebase(ci); /* function has new base after adjustment */
- vmbreak;
- }
- vmcase(OP_EXTRAARG) {
- lua_assert(0);
- vmbreak;
- }
- }
- }
-}
-
-/* }================================================================== */
diff --git a/lua-5.4.4/library/lvm.h b/lua-5.4.4/library/lvm.h
deleted file mode 100644
index 1bc16f3a..00000000
--- a/lua-5.4.4/library/lvm.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-** $Id: lvm.h $
-** Lua virtual machine
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lvm_h
-#define lvm_h
-
-
-#include "ldo.h"
-#include "lobject.h"
-#include "ltm.h"
-
-
-#if !defined(LUA_NOCVTN2S)
-#define cvt2str(o) ttisnumber(o)
-#else
-#define cvt2str(o) 0 /* no conversion from numbers to strings */
-#endif
-
-
-#if !defined(LUA_NOCVTS2N)
-#define cvt2num(o) ttisstring(o)
-#else
-#define cvt2num(o) 0 /* no conversion from strings to numbers */
-#endif
-
-
-/*
-** You can define LUA_FLOORN2I if you want to convert floats to integers
-** by flooring them (instead of raising an error if they are not
-** integral values)
-*/
-#if !defined(LUA_FLOORN2I)
-#define LUA_FLOORN2I F2Ieq
-#endif
-
-
-/*
-** Rounding modes for float->integer coercion
- */
-typedef enum {
- F2Ieq, /* no rounding; accepts only integral values */
- F2Ifloor, /* takes the floor of the number */
- F2Iceil /* takes the ceil of the number */
-} F2Imod;
-
-
-/* convert an object to a float (including string coercion) */
-#define tonumber(o,n) \
- (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
-
-
-/* convert an object to a float (without string coercion) */
-#define tonumberns(o,n) \
- (ttisfloat(o) ? ((n) = fltvalue(o), 1) : \
- (ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0))
-
-
-/* convert an object to an integer (including string coercion) */
-#define tointeger(o,i) \
- (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
- : luaV_tointeger(o,i,LUA_FLOORN2I))
-
-
-/* convert an object to an integer (without string coercion) */
-#define tointegerns(o,i) \
- (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
- : luaV_tointegerns(o,i,LUA_FLOORN2I))
-
-
-#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
-
-#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
-
-
-/*
-** fast track for 'gettable': if 't' is a table and 't[k]' is present,
-** return 1 with 'slot' pointing to 't[k]' (position of final result).
-** Otherwise, return 0 (meaning it will have to check metamethod)
-** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL
-** (otherwise). 'f' is the raw get function to use.
-*/
-#define luaV_fastget(L,t,k,slot,f) \
- (!ttistable(t) \
- ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
- : (slot = f(hvalue(t), k), /* else, do raw access */ \
- !isempty(slot))) /* result not empty? */
-
-
-/*
-** Special case of 'luaV_fastget' for integers, inlining the fast case
-** of 'luaH_getint'.
-*/
-#define luaV_fastgeti(L,t,k,slot) \
- (!ttistable(t) \
- ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
- : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \
- ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
- !isempty(slot))) /* result not empty? */
-
-
-/*
-** Finish a fast set operation (when fast get succeeds). In that case,
-** 'slot' points to the place to put the value.
-*/
-#define luaV_finishfastset(L,t,slot,v) \
- { setobj2t(L, cast(TValue *,slot), v); \
- luaC_barrierback(L, gcvalue(t), v); }
-
-
-
-
-LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
-LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
-LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
-LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
-LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode);
-LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
- F2Imod mode);
-LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
-LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
- StkId val, const TValue *slot);
-LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
- TValue *val, const TValue *slot);
-LUAI_FUNC void luaV_finishOp (lua_State *L);
-LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
-LUAI_FUNC void luaV_concat (lua_State *L, int total);
-LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y);
-LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
-LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
-LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
-LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
-
-#endif
diff --git a/lua-5.4.4/library/lzio.c b/lua-5.4.4/library/lzio.c
deleted file mode 100644
index cd0a02d5..00000000
--- a/lua-5.4.4/library/lzio.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-** $Id: lzio.c $
-** Buffered streams
-** See Copyright Notice in lua.h
-*/
-
-#define lzio_c
-#define LUA_CORE
-
-#include "lprefix.h"
-
-
-#include
-
-#include "lua.h"
-
-#include "llimits.h"
-#include "lmem.h"
-#include "lstate.h"
-#include "lzio.h"
-
-
-int luaZ_fill (ZIO *z) {
- size_t size;
- lua_State *L = z->L;
- const char *buff;
- lua_unlock(L);
- buff = z->reader(L, z->data, &size);
- lua_lock(L);
- if (buff == NULL || size == 0)
- return EOZ;
- z->n = size - 1; /* discount char being returned */
- z->p = buff;
- return cast_uchar(*(z->p++));
-}
-
-
-void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
- z->L = L;
- z->reader = reader;
- z->data = data;
- z->n = 0;
- z->p = NULL;
-}
-
-
-/* --------------------------------------------------------------- read --- */
-size_t luaZ_read (ZIO *z, void *b, size_t n) {
- while (n) {
- size_t m;
- if (z->n == 0) { /* no bytes in buffer? */
- if (luaZ_fill(z) == EOZ) /* try to read more */
- return n; /* no more input; return number of missing bytes */
- else {
- z->n++; /* luaZ_fill consumed first byte; put it back */
- z->p--;
- }
- }
- m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
- memcpy(b, z->p, m);
- z->n -= m;
- z->p += m;
- b = (char *)b + m;
- n -= m;
- }
- return 0;
-}
-
diff --git a/lua-5.4.4/library/lzio.h b/lua-5.4.4/library/lzio.h
deleted file mode 100644
index 38f397fd..00000000
--- a/lua-5.4.4/library/lzio.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-** $Id: lzio.h $
-** Buffered streams
-** See Copyright Notice in lua.h
-*/
-
-
-#ifndef lzio_h
-#define lzio_h
-
-#include "lua.h"
-
-#include "lmem.h"
-
-
-#define EOZ (-1) /* end of stream */
-
-typedef struct Zio ZIO;
-
-#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z))
-
-
-typedef struct Mbuffer {
- char *buffer;
- size_t n;
- size_t buffsize;
-} Mbuffer;
-
-#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
-
-#define luaZ_buffer(buff) ((buff)->buffer)
-#define luaZ_sizebuffer(buff) ((buff)->buffsize)
-#define luaZ_bufflen(buff) ((buff)->n)
-
-#define luaZ_buffremove(buff,i) ((buff)->n -= (i))
-#define luaZ_resetbuffer(buff) ((buff)->n = 0)
-
-
-#define luaZ_resizebuffer(L, buff, size) \
- ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \
- (buff)->buffsize, size), \
- (buff)->buffsize = size)
-
-#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
-
-
-LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
- void *data);
-LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */
-
-
-
-/* --------- Private Part ------------------ */
-
-struct Zio {
- size_t n; /* bytes still unread */
- const char *p; /* current position in buffer */
- lua_Reader reader; /* reader function */
- void *data; /* additional data */
- lua_State *L; /* Lua state (for reader) */
-};
-
-
-LUAI_FUNC int luaZ_fill (ZIO *z);
-
-#endif
diff --git a/lua-5.4.4/lua-win.sln b/lua-5.4.4/lua-win.sln
deleted file mode 100644
index 9d26536f..00000000
--- a/lua-5.4.4/lua-win.sln
+++ /dev/null
@@ -1,57 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.1.32407.343
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "library\library.vcxproj", "{8E84841E-61A4-40C8-87AA-7DF461E4C9CA}"
- ProjectSection(ProjectDependencies) = postProject
- {ABB5EAE7-B3E6-432E-B636-333449892EA6} = {ABB5EAE7-B3E6-432E-B636-333449892EA6}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console", "console\console.vcxproj", "{D9CCCCA8-43BE-4771-8256-D62A7C624AD0}"
- ProjectSection(ProjectDependencies) = postProject
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA} = {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc\ide\vs2022\mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Debug|x64.ActiveCfg = Debug|x64
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Debug|x64.Build.0 = Debug|x64
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Debug|x86.ActiveCfg = Debug|Win32
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Debug|x86.Build.0 = Debug|Win32
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Release|x64.ActiveCfg = Release|x64
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Release|x64.Build.0 = Release|x64
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Release|x86.ActiveCfg = Release|Win32
- {8E84841E-61A4-40C8-87AA-7DF461E4C9CA}.Release|x86.Build.0 = Release|Win32
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Debug|x64.ActiveCfg = Debug|x64
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Debug|x64.Build.0 = Debug|x64
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Debug|x86.ActiveCfg = Debug|Win32
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Debug|x86.Build.0 = Debug|Win32
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Release|x64.ActiveCfg = Release|x64
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Release|x64.Build.0 = Release|x64
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Release|x86.ActiveCfg = Release|Win32
- {D9CCCCA8-43BE-4771-8256-D62A7C624AD0}.Release|x86.Build.0 = Release|Win32
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.ActiveCfg = Debug|x64
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x64.Build.0 = Debug|x64
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.ActiveCfg = Debug|Win32
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Debug|x86.Build.0 = Debug|Win32
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.ActiveCfg = Release|x64
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x64.Build.0 = Release|x64
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.ActiveCfg = Release|Win32
- {ABB5EAE7-B3E6-432E-B636-333449892EA6}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {D606D927-58E8-49D8-A6FE-F2A8A5A86167}
- EndGlobalSection
-EndGlobal
diff --git a/lua-5.4.4/mimalloc b/lua-5.4.4/mimalloc
deleted file mode 160000
index dd734806..00000000
--- a/lua-5.4.4/mimalloc
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit dd7348066fe40e8bf372fa4e9538910a5e24a75f
diff --git a/lua-5.4.4/readme.txt b/lua-5.4.4/readme.txt
deleted file mode 100644
index bbcad805..00000000
--- a/lua-5.4.4/readme.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-this is required only for (properly) building Lua on Windows
-
-because realloc on windows somehow causes heap corruption
-
-mi_realloc doesn't
diff --git a/lua_glue.c b/lua_glue.c
deleted file mode 100644
index b345be6b..00000000
--- a/lua_glue.c
+++ /dev/null
@@ -1,77 +0,0 @@
-
-#include "build/generated/sources/headers/java/main/ru_dbotthepony_kstarbound_lua_LuaJNI.h"
-#include "lua-5.4.4/library/lapi.h"
-#include "lua-5.4.4/library/lua.h"
-#include "lua-5.4.4/library/lauxlib.h"
-#include
-
-static int lua_jniFunc(lua_State *state) {
- JNIEnv *env = (JNIEnv *) lua_touserdata(state, lua_upvalueindex(1));
- jmethodID callback = (jmethodID) lua_touserdata(state, lua_upvalueindex(2));
- jobject* lua_JCClosure = (jobject*) lua_touserdata(state, lua_upvalueindex(3));
-
- jint result = (*env)->CallIntMethod(env, *lua_JCClosure, callback, (long long) state);
-
- if (result <= -1) {
- const char* errMsg = lua_tostring(state, -1);
-
- if (errMsg == NULL)
- return luaL_error(state, "Internal JVM Error");
-
- return luaL_error(state, "%s", errMsg);
- }
-
- return result;
-}
-
-static int mark_closure_free(lua_State *state) {
- JNIEnv *env = (JNIEnv *) lua_touserdata(state, lua_upvalueindex(1));
- jobject* lua_JCClosure = (jobject*) lua_touserdata(state, 1);
-
- if (lua_JCClosure == NULL) {
- printf("Lua Glue: mark_closure_free: lua_JCClosure is NULL!\n");
- return 0;
- }
-
- (*env)->DeleteGlobalRef(env, *lua_JCClosure);
- return 0;
-}
-
-static JNIEXPORT void JNICALL Java_ru_dbotthepony_kstarbound_lua_LuaJNI_lua_1pushcclosure(JNIEnv *env, jclass interface, jlong luaState, jobject lua_JCClosure) {
- lua_State* LluaState = (lua_State*) luaState;
-
- jclass clazz = (*env)->GetObjectClass(env, lua_JCClosure);
-
- if (clazz == NULL)
- return;
-
- jmethodID callback = (*env)->GetMethodID(env, clazz, "invoke", "(J)I");
-
- if (callback == NULL)
- return;
-
- lua_pushlightuserdata(LluaState, env);
- lua_pushlightuserdata(LluaState, callback);
-
- void *umemory = lua_newuserdatauv(LluaState, sizeof(jobject), 0);
- jobject* rawBlock = (jobject*) umemory;
- *rawBlock = (*env)->NewGlobalRef(env, lua_JCClosure);
-
- int userdataIndex = lua_gettop(LluaState);
-
- // local table = {}
- lua_createtable(LluaState, 0, 1);
- int tableIndex = lua_gettop(LluaState);
-
- // function()
- lua_pushlightuserdata(LluaState, env);
- lua_pushcclosure(LluaState, mark_closure_free, 1);
-
- // table.__gc = fn
- lua_setfield(LluaState, tableIndex, "__gc");
-
- // setmetatable(userdata, table)
- lua_setmetatable(LluaState, userdataIndex);
-
- lua_pushcclosure(LluaState, lua_jniFunc, 3);
-}
diff --git a/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNI.java b/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNI.java
deleted file mode 100644
index 5a0d1bd7..00000000
--- a/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNI.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package ru.dbotthepony.kstarbound.lua;
-
-import java.io.File;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * Так как не все возможно сделать через JNA, некоторые вещи должны быть сделаны через JNI и немного магии указателей.
- */
-public final class LuaJNI {
- public static native void lua_pushcclosure(long luaState, lua_CClosure callback);
-
- public interface lua_CClosure {
- // 0 - успешное выполнение
- // != 0 - была ошибка
- int invoke(long luaState);
- }
-
- static {
- System.load(new File("lua_glue.dll").getAbsolutePath());
- }
-}
diff --git a/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNR.java b/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNR.java
deleted file mode 100644
index a5b95e28..00000000
--- a/src/main/java/ru/dbotthepony/kstarbound/lua/LuaJNR.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package ru.dbotthepony.kstarbound.lua;
-
-import com.kenai.jffi.Closure;
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.Pointer;
-import jnr.ffi.Runtime;
-import jnr.ffi.annotations.LongLong;
-import org.jetbrains.annotations.NotNull;
-
-import javax.annotation.Nullable;
-
-@SuppressWarnings({"UnnecessaryModifier", "SpellCheckingInspection", "unused"})
-public interface LuaJNR {
- public int lua_pcallk(@NotNull Pointer luaState, int numArgs, int numResults, int msgh, @LongLong long ctx, @LongLong long callback);
- public int lua_callk(@NotNull Pointer luaState, int numArgs, int numResults, @LongLong long ctx, @LongLong long callback);
- public long lua_atpanic(@NotNull Pointer luaState, @LongLong long fn);
-
- @Nullable
- public Pointer luaL_newstate();
- public void lua_close(@NotNull Pointer luaState);
-
- // Стандартные библиотеки
- public void luaopen_base(@NotNull Pointer luaState);
- public void luaopen_package(@NotNull Pointer luaState);
- public void luaopen_coroutine(@NotNull Pointer luaState);
- public void luaopen_table(@NotNull Pointer luaState);
- public void luaopen_io(@NotNull Pointer luaState);
- public void luaopen_os(@NotNull Pointer luaState);
- public void luaopen_string(@NotNull Pointer luaState);
- public void luaopen_math(@NotNull Pointer luaState);
- public void luaopen_utf8(@NotNull Pointer luaState);
- public void luaopen_debug(@NotNull Pointer luaState);
-
- @Nullable
- public Pointer lua_tolstring(@NotNull Pointer luaState, int index, @LongLong long size);
-
- public int lua_load(@NotNull Pointer luaState, @LongLong long reader, long userData, @NotNull String chunkName, @NotNull String mode);
-
- public interface lua_CFunction extends Closure {
- int invoke(@NotNull Pointer luaState);
-
- @Override
- default void invoke(Buffer buffer) {
- //buffer.setIntReturn(invoke());
- }
- }
-
- public interface lua_Reader extends Closure {
- public long readNextChunk(@NotNull Pointer luaState, long userData, @NotNull Pointer sizeToRead);
-
- @Override
- default void invoke(Buffer buffer) {
- throw new RuntimeException();
- }
- }
-
- public interface lua_KFunction extends Closure {
- public int invoke(@NotNull Pointer luaState, int status, long context);
-
- @Override
- default void invoke(Buffer buffer) {
- throw new RuntimeException();
- }
- }
-
- // Операции над стаком
- // загрузка значений из Java на стек
- public void lua_createtable(@NotNull Pointer luaState, int arraySize, int hashSize);
- public void lua_pushnil(@NotNull Pointer luaState);
- public void lua_pushnumber(@NotNull Pointer luaState, double value);
- public void lua_pushinteger(@NotNull Pointer luaState, @LongLong long value);
- public void lua_pushboolean(@NotNull Pointer luaState, int value);
- public void lua_pushglobaltable(@NotNull Pointer luaState);
-
- // NUL терминированная строка
- public void lua_pushstring(@NotNull Pointer luaState, @NotNull String value);
-
- // двоичная строка
- public long lua_pushlstring(@NotNull Pointer luaState, @LongLong long stringPointer, @LongLong long length);
-
- // Загрузка Lua значений на стек
- public int lua_getglobal(@NotNull Pointer luaState, @NotNull String name);
-
- // запись значений со стека
- public void lua_settable(@NotNull Pointer luaState, int stackIndex);
- public void lua_setglobal(@NotNull Pointer luaState, @NotNull String name);
-
- // проверка стека
- public int lua_checkstack(@NotNull Pointer luaState, int value);
- public int lua_absindex(@NotNull Pointer luaState, int value);
- public int lua_iscfunction(@NotNull Pointer luaState, int index);
- public int lua_isinteger(@NotNull Pointer luaState, int index);
- public int lua_isnumber(@NotNull Pointer luaState, int index);
- public int lua_isstring(@NotNull Pointer luaState, int index);
- public int lua_isuserdata(@NotNull Pointer luaState, int index);
-
- public int lua_toboolean(@NotNull Pointer luaState, int index);
- public int lua_tocfunction(@NotNull Pointer luaState, int index);
- public int lua_toclose(@NotNull Pointer luaState, int index);
- public int lua_gettable(@NotNull Pointer luaState, int index);
-
- @LongLong
- public long lua_tointegerx(@NotNull Pointer luaState, int index, @LongLong long successCode);
- public double lua_tonumberx(@NotNull Pointer luaState, int index, @LongLong long successCode);
-
- public int lua_settop(@NotNull Pointer luaState, int index);
-
- public int lua_next(@NotNull Pointer luaState, int index);
- public int lua_type(@NotNull Pointer luaState, int index);
-
- /**
- * Returns the index of the top element in the stack.
- * Because indices start at 1, this result is equal to the number of elements in the stack; in particular, 0 means an empty stack.
- */
- public int lua_gettop(@NotNull Pointer luaState);
-
- @NotNull
- public static final LuaJNR INSTANCE = LibraryLoader.create(LuaJNR.class).load("lua54");
-
- @NotNull
- public static final Runtime RUNTIME = Runtime.getRuntime(INSTANCE);
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt
index f7f6548a..57ed26a7 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/GlobalDefaults.kt
@@ -1,6 +1,7 @@
package ru.dbotthepony.kstarbound
import org.apache.logging.log4j.LogManager
+import ru.dbotthepony.kstarbound.defs.ClientConfigParameters
import ru.dbotthepony.kstarbound.defs.MovementParameters
import ru.dbotthepony.kstarbound.defs.player.PlayerMovementParameters
import ru.dbotthepony.kstarbound.util.AssetPathStack
@@ -17,6 +18,9 @@ object GlobalDefaults {
var movementParameters = MovementParameters()
private set
+ var clientParameters = ClientConfigParameters()
+ private set
+
private object EmptyTask : ForkJoinTask() {
private fun readResolve(): Any = EmptyTask
override fun getRawResult() {
@@ -53,6 +57,7 @@ object GlobalDefaults {
tasks.add(load("/default_actor_movement.config", ::playerMovementParameters, executor))
tasks.add(load("/default_movement.config", ::movementParameters, executor))
+ tasks.add(load("/client.config", ::clientParameters, executor))
return listOf(executor.submit {
val line = log.line("Loading global defaults...")
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt
index 108f8a6c..4d629d96 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt
@@ -8,9 +8,6 @@ import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
import ru.dbotthepony.kstarbound.io.BTreeDB
import ru.dbotthepony.kstarbound.player.Avatar
-import ru.dbotthepony.kstarbound.player.QuestDescriptor
-import ru.dbotthepony.kstarbound.player.QuestInstance
-import ru.dbotthepony.kstarbound.util.JVMTimeSource
import ru.dbotthepony.kstarbound.world.entities.ItemEntity
import ru.dbotthepony.kstarbound.io.json.VersionedJson
import ru.dbotthepony.kstarbound.io.readVarInt
@@ -30,6 +27,14 @@ import java.util.zip.InflaterInputStream
private val LOGGER = LogManager.getLogger()
fun main() {
+ /*if (true) {
+ val state = NewLuaState()
+ provideRootBindings(state)
+ state.load("print(root.itemType('haha'))")
+
+ return
+ }*/
+
LOGGER.info("Running LWJGL ${Version.getVersion()}")
//Thread.sleep(6_000L)
@@ -134,18 +139,19 @@ fun main() {
AssetPathStack.pop()
val avatar = Avatar(UUID.randomUUID())
+ /*
val quest = QuestInstance(avatar, descriptor = QuestDescriptor("floran_mission1"))
quest.init()
quest.start()
- var last = JVMTimeSource.INSTANCE.millis
+ var last = 0
client.onPostDrawWorld {
- if (JVMTimeSource.INSTANCE.millis - last > 20L) {
- quest.update(1)
- last = JVMTimeSource.INSTANCE.millis
+ if (++last >= 10) {
+ quest.update(10)
+ last = 0
}
- }
+ }*/
println(Registries.treasurePools["motherpoptopTreasure"]!!.value.evaluate(Random(), 2.0))
}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt
index 0968550d..a9aa3969 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt
@@ -21,7 +21,6 @@ import ru.dbotthepony.kstarbound.defs.`object`.ObjectOrientation
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
import ru.dbotthepony.kstarbound.defs.player.BlueprintLearnList
import ru.dbotthepony.kstarbound.defs.player.PlayerDefinition
-import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
import ru.dbotthepony.kstarbound.util.JsonArrayCollector
import ru.dbotthepony.kstarbound.io.*
import ru.dbotthepony.kstarbound.io.json.AABBTypeAdapter
@@ -47,8 +46,6 @@ import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementationTypeFactory
import ru.dbotthepony.kstarbound.io.json.factory.ArrayListAdapterFactory
import ru.dbotthepony.kstarbound.io.json.factory.ImmutableCollectionAdapterFactory
import ru.dbotthepony.kstarbound.io.json.factory.PairAdapterFactory
-import ru.dbotthepony.kstarbound.lua.LuaState
-import ru.dbotthepony.kstarbound.lua.loadInternalScript
import ru.dbotthepony.kstarbound.math.*
import ru.dbotthepony.kstarbound.util.ITimeSource
import ru.dbotthepony.kstarbound.util.ItemStack
@@ -92,8 +89,6 @@ object Starbound : ISBFileLocator {
// val strings: Interner = Interner { it }
val STRINGS: Interner = HashTableInterner(5)
- private val polyfill by lazy { loadInternalScript("polyfill") }
-
private val LOGGER = LogManager.getLogger()
val gson: Gson = with(GsonBuilder()) {
@@ -218,6 +213,21 @@ object Starbound : ISBFileLocator {
create()
}
+ data class ItemConfig(
+ val directory: String?,
+ val parameters: JsonObject,
+ val config: JsonObject
+ )
+
+ fun itemConfig(name: String, parameters: JsonObject, level: Double? = null, seed: Long? = null): ItemConfig {
+ val obj = Registries.items[name] ?: throw NoSuchElementException("No such item $name")
+
+ val directory = obj.file?.computeDirectory()
+ val parameters = parameters.deepCopy()
+
+ TODO()
+ }
+
fun item(name: String): ItemStack {
return ItemStack(Registries.items[name] ?: return ItemStack.EMPTY)
}
@@ -283,469 +293,6 @@ object Starbound : ISBFileLocator {
return traverseJsonPath(jsonPath, gson.fromJson(file.reader(), JsonElement::class.java))
}
- private fun luaRequire(it: LuaState, args: LuaState.ArgStack) {
- val name = args.getString()
- val file = locate(name)
-
- if (!file.exists) {
- throw FileNotFoundException("File $name does not exist")
- }
-
- if (!file.isFile) {
- throw FileNotFoundException("File $name is a directory")
- }
-
- val read = file.readToString()
- it.load(read, chunkName = "@" + file.computeFullPath())
- it.call()
- }
-
- // wrapping for Lua refs
- private fun getImage(path: String) = Image.get(path)
-
- /**
- * **ПРЕДУПРЕЖДЕНИЕ:**
- * [time] не должен иметь ссылок (прямые или непрямые) на [state], иначе произойдёт утечка памяти!
- */
- fun pushLuaAPI(state: LuaState, time: ITimeSource = JVMTimeSource.INSTANCE) {
- state.pushWeak(this) { args ->
- luaRequire(args.lua, args)
- 0
- }
-
- state.storeGlobal("require")
-
- state.pushTable()
- state.storeGlobal("root")
- state.loadGlobal("root")
-
- state.setTableFunction("assetJson", this) {args ->
- args.lua.push(loadJsonAsset(args.getString()))
- 1
- }
-
- state.setTableFunction("makeCurrentVersionedJson", this) {args ->
- TODO("makeCurrentVersionedJson")
- }
-
- state.setTableFunction("loadVersionedJson", this) {args ->
- TODO("loadVersionedJson")
- }
-
- state.setTableFunction("evalFunction", this) {args ->
- val name = args.getString()
- val fn = Registries.jsonFunctions[name] ?: throw NoSuchElementException("No such function $name")
- args.push(fn.value.evaluate(args.getDouble()))
- 1
- }
-
- state.setTableFunction("evalFunction2", this) {args ->
- val name = args.getString()
- val fn = Registries.json2Functions[name] ?: throw NoSuchElementException("No such 2function $name")
- args.push(fn.value.evaluate(args.getDouble(), args.getDouble()))
- 1
- }
-
- state.setTableFunction("imageSize", this) {args ->
- val name = args.getString()
- args.lua.push(getImage(name)?.size ?: throw FileNotFoundException("No such file $name"))
- 1
- }
-
- state.setTableFunction("imageSpaces", this) { args ->
- // List root.imageSpaces(String imagePath, Vec2F worldPosition, float spaceScan, bool flip)
- val name = args.getString()
- val values = getImage(name)?.worldSpaces(args.getVector2i(), args.getDouble(), args.getBool()) ?: throw FileNotFoundException("No such file $name")
-
- args.lua.pushTable(arraySize = values.size)
- val table = args.lua.stackTop
-
- for ((i, value) in values.withIndex()) {
- args.lua.push(i + 1)
- args.lua.push(value)
- args.lua.setTableValue(table)
- }
-
- 1
- }
-
- state.setTableFunction("nonEmptyRegion", this) { args ->
- val name = args.getString()
- args.lua.push(getImage(name)?.nonEmptyRegion ?: throw FileNotFoundException("No such file $name"))
- 1
- }
-
- state.setTableFunction("npcConfig", this) { args ->
- // Json root.npcConfig(String npcType)
- val name = args.getString()
- args.push(Registries.npcTypes[name] ?: throw NoSuchElementException("No such NPC type $name"))
- 1
- }
-
- state.setTableFunction("npcVariant", this) { args ->
- // Json root.npcVariant(String species, String npcType, float level, [unsigned seed], [Json parameters])
- TODO("npcVariant")
- }
-
- state.setTableFunction("projectileGravityMultiplier", this) { args ->
- // float root.projectileGravityMultiplier(String projectileName)
- TODO("projectileGravityMultiplier")
- }
-
- state.setTableFunction("projectileConfig", this) { args ->
- // Json root.projectileConfig(String projectileName)
- val name = args.getString()
- args.lua.push(Registries.projectiles[name]?.json ?: throw kotlin.NoSuchElementException("No such Projectile type $name"))
- 1
- }
-
- state.setTableFunction("recipesForItem", this) { args ->
- args.lua.push(JsonArray().also { a ->
- RecipeRegistry.output2recipes[args.getString()]?.stream()?.map { it.json }?.forEach {
- a.add(it)
- }
- })
-
- 1
- }
-
- state.setTableFunction("itemType", this) { args ->
- val name = args.getString()
- args.lua.push(Registries.items[name]?.value?.itemType ?: throw NoSuchElementException("No such item $name"))
- 1
- }
-
- state.setTableFunction("itemTags", this) { args ->
- val name = args.getString()
- args.lua.pushStrings(Registries.items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name"))
- 1
- }
-
- state.setTableFunction("itemHasTag", this) { args ->
- val name = args.getString()
- val tag = args.getString()
- args.push((Registries.items[name]?.value?.itemTags ?: throw NoSuchElementException("No such item $name")).contains(tag))
- 1
- }
-
- // TODO: генерация
- state.setTableFunction("itemConfig", this) { args ->
- // Json root.itemConfig(ItemDescriptor descriptor, [float level], [unsigned seed])
- val item = item(args.getValue())
- val level = if (args.hasSomethingAt()) args.getDouble() else null
- val seed = if (args.hasSomethingAt()) args.getLong() else null
-
- if (item.isEmpty) {
- args.push()
- } else {
- args.push(JsonObject().also {
- it["directory"] = item.item?.file?.computeDirectory()?.let(::JsonPrimitive) ?: JsonNull.INSTANCE
- it["config"] = item.item!!.json
- it["parameters"] = item.parameters
- })
- }
-
- 1
- }
-
- // TODO: генерация
- state.setTableFunction("createItem", this) { args ->
- // ItemDescriptor root.createItem(ItemDescriptor descriptor, [float level], [unsigned seed])
- val item = item(args.getValue())
- val level = if (args.hasSomethingAt()) args.getDouble() else null
- val seed = if (args.hasSomethingAt()) args.getLong() else null
-
- if (item.isEmpty) {
- args.push()
- return@setTableFunction 1
- }
-
- if (item.maxStackSize < item.size) {
- item.size = item.maxStackSize
- }
-
- args.push(gson.toJsonTree(item))
- 1
- }
-
- state.setTableFunction("tenantConfig", this) { args ->
- // Json root.tenantConfig(String tenantName)
- val name = args.getString()
- args.push(Registries.tenants[name] ?: throw NoSuchElementException("No such tenant $name"))
- 1
- }
-
- state.setTableFunction("getMatchingTenants", this) { args ->
- // Json root.tenantConfig(String tenantName)
- val tags = args.getTable()
- val actualTags = Object2IntOpenHashMap()
-
- for ((k, v) in tags.entrySet()) {
- if (v is JsonPrimitive && v.isNumber) {
- actualTags[k] = v.asInt
- }
- }
-
- args.push(Registries.tenants.keys.values
- .stream()
- .filter { it.value.test(actualTags) }
- .sorted { a, b -> b.value.compareTo(a.value) }
- .map { it.json }
- .collect(JsonArrayCollector))
-
- 1
- }
-
- state.setTableFunction("liquidStatusEffects", this) { args ->
- val liquid: LiquidDefinition
-
- if (args.isStringAt()) {
- val name = args.getString()
- liquid = Registries.liquid[name]?.value ?: throw NoSuchElementException("No such liquid with name $name")
- } else {
- val id = args.getInt()
- liquid = Registries.liquid[id]?.value ?: throw NoSuchElementException("No such liquid with ID $id")
- }
-
- args.lua.pushStrings(liquid.statusEffects.stream().map { it.value?.name }.filterNotNull().toList())
-
- 1
- }
-
- state.setTableFunction("generateName", this) { args ->
- val assetName = args.getString()
- val seed = if (args.hasSomethingAt()) args.getLong() else time.nanos
- val names = loadJsonAsset(assetName) ?: throw NoSuchElementException("No such JSON asset $assetName")
-
- if (names !is JsonArray) {
- var possibleName: String? = null
-
- if (names is JsonObject) {
- for ((k, v) in names.entrySet()) {
- if (v is JsonArray && !v.isEmpty) {
- if (possibleName == null || (names[possibleName] as JsonArray).size() < v.size())
- possibleName = k
- }
- }
- }
-
- if (possibleName != null) {
- if (assetName.contains(':')) {
- throw IllegalArgumentException("JSON asset $assetName is not an array, did you mean $assetName.$possibleName?")
- } else {
- throw IllegalArgumentException("JSON asset $assetName is not an array, did you mean $assetName:$possibleName?")
- }
- } else {
- throw IllegalArgumentException("JSON asset $assetName is not an array")
- }
- }
-
- if (names.isEmpty) {
- throw IllegalStateException("JSON array $assetName is empty")
- }
-
- args.push(names[Random(seed).nextInt(0, names.size())])
- 1
- }
-
- state.setTableFunction("questConfig", this) { args ->
- val name = args.getString()
- args.push(Registries.questTemplates[name] ?: throw NoSuchElementException("No such quest template $name"))
- 1
- }
-
- state.setTableFunction("npcPortrait", this) { args ->
- // JsonArray root.npcPortrait(String portraitMode, String species, String npcType, float level, [unsigned seed], [Json parameters])
- // Generates an NPC with the specified type, level, seed and parameters and returns a portrait in the given portraitMode as a list of drawables.
- TODO("npcPortrait")
- }
-
- state.setTableFunction("monsterPortrait", this) { args ->
- // JsonArray root.monsterPortrait(String typeName, [Json parameters])
- // Generates a monster of the given type with the given parameters and returns its portrait as a list of drawables.
- TODO("monsterPortrait")
- }
-
- state.setTableFunction("isTreasurePool", this) { args ->
- args.push(args.getString() in Registries.treasurePools)
- 1
- }
-
- state.setTableFunction("createTreasure", this) { args ->
- val name = args.getString()
- val level = args.getDouble()
- val rand = if (args.hasSomethingAt()) java.util.Random(args.getLong()) else java.util.Random()
- args.push(Registries.treasurePools[name]?.value?.evaluate(rand, level)?.stream()?.map { it.toJson() }?.filterNotNull()?.collect(JsonArrayCollector) ?: throw NoSuchElementException("No such treasure pool $name"))
- 1
- }
-
- state.setTableFunction("materialMiningSound", this) { args ->
- val name = args.getString()
- val mod = if (args.hasSomethingAt()) args.getString() else null
- val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
-
- if (mod == null) {
- args.push(mat.value.miningSounds.firstOrNull())
- } else {
- val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
- args.push(getMod.value.miningSounds.firstOrNull() ?: mat.value.miningSounds.firstOrNull())
- }
-
- 1
- }
-
- state.setTableFunction("materialFootstepSound", this) { args ->
- val name = args.getString()
- val mod = if (args.hasSomethingAt()) args.getString() else null
- val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
-
- if (mod == null) {
- args.push(mat.value.footstepSound)
- } else {
- val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
- args.push(getMod.value.footstepSound ?: mat.value.footstepSound)
- }
-
- 1
- }
-
- state.setTableFunction("materialHealth", this) { args ->
- val name = args.getString()
- val mod = if (args.hasSomethingAt()) args.getString() else null
- val mat = Registries.tiles[name] ?: throw NoSuchElementException("No such material $name")
-
- if (mod == null) {
- args.push(mat.value.health)
- } else {
- val getMod = Registries.tileModifiers[mod] ?: throw NoSuchElementException("No such material modifier $mod")
- args.push(getMod.value.health + mat.value.health)
- }
-
- 1
- }
-
- state.setTableFunction("materialConfig", this) { args ->
- val name = args.getString()
- args.pushFull(Registries.tiles[name])
- 1
- }
-
- state.setTableFunction("modConfig", this) { args ->
- val name = args.getString()
- args.pushFull(Registries.tileModifiers[name])
- 1
- }
-
- state.setTableFunction("liquidConfig", this) { args ->
- if (args.isNumberAt()) {
- val id = args.getLong().toInt()
- args.pushFull(Registries.liquid[id])
- } else {
- val name = args.getString()
- args.pushFull(Registries.liquid[name])
- }
-
- 1
- }
-
- state.setTableFunction("liquidName", this) { args ->
- val id = args.getLong().toInt()
- args.push(Registries.liquid[id]?.value?.name ?: throw NoSuchElementException("No such liquid with ID $id"))
- 1
- }
-
- state.setTableFunction("liquidId", this) { args ->
- val name = args.getString()
- args.push(Registries.liquid[name]?.value?.name ?: throw NoSuchElementException("No such liquid $name"))
- 1
- }
-
- state.setTableFunction("monsterSkillParameter", this) { args ->
- val name = args.getString()
- val param = args.getString()
- // parity: если скила не существует, то оригинальный движок просто возвращает nil
- args.push(Registries.monsterSkills[name]?.value?.config?.get(param))
- 1
- }
-
- state.setTableFunction("monsterParameters", this) { args ->
- val name = args.getString()
- val monster = Registries.monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
- args.push(monster.traverseJsonPath("baseParameters"))
- 1
- }
-
- state.setTableFunction("monsterMovementSettings", this) { args ->
- val name = args.getString()
- val monster = Registries.monsterTypes[name] ?: throw NoSuchElementException("No such monster type $name")
- args.push(gson.toJsonTree(monster.value.baseParameters.movementSettings))
- 1
- }
-
- state.setTableFunction("createBiome", this) { args ->
- TODO("createBiome")
- }
-
- state.setTableFunction("hasTech", this) { args ->
- args.push(args.getString() in Registries.techs)
- 1
- }
-
- state.setTableFunction("techType", this) { args ->
- val name = args.getString()
- val tech = Registries.techs[name] ?: throw NoSuchElementException("No such tech $name")
- args.push(tech.value.type)
- 1
- }
-
- state.setTableFunction("techConfig", this) { args ->
- val name = args.getString()
- val tech = Registries.techs[name] ?: throw NoSuchElementException("No such tech $name")
- args.push(tech)
- 1
- }
-
- state.setTableFunction("treeStemDirectory", this) { args ->
- // String root.treeStemDirectory(String stemName)
- TODO("treeStemDirectory")
- }
-
- state.setTableFunction("treeFoliageDirectory", this) { args ->
- // String root.treeFoliageDirectory(String foliageName)
- TODO("treeFoliageDirectory")
- }
-
- state.setTableFunction("collection", this) { args ->
- // Collection root.collection(String collectionName)
- TODO("collection")
- }
-
- state.setTableFunction("collectables", this) { args ->
- // List root.collectables(String collectionName)
- TODO("collectables")
- }
-
- state.setTableFunction("elementalResistance", this) { args ->
- // String root.elementalResistance(String elementalType)
- TODO("elementalResistance")
- }
-
- state.setTableFunction("dungeonMetadata", this) { args ->
- // Json root.dungeonMetadata(String dungeonName)
- TODO("dungeonMetadata")
- }
-
- state.setTableFunction("behavior", this) { args ->
- // BehaviorState root.behavior(`LuaTable` context, Json config, `JsonObject` parameters)
- TODO("behavior")
- }
-
- state.pop()
-
- state.load(polyfill, "@starbound.jar!/scripts/polyfill.lua")
- state.call()
- }
-
private val archivePaths = ArrayList()
private val fileSystems = ArrayList()
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt
new file mode 100644
index 00000000..cfb213b3
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/ClientConfigParameters.kt
@@ -0,0 +1,7 @@
+package ru.dbotthepony.kstarbound.defs
+
+import com.google.common.collect.ImmutableList
+
+data class ClientConfigParameters(
+ val defaultFootstepSound: ImmutableList = ImmutableList.of(),
+)
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/ItemDescriptor.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/ItemDescriptor.kt
new file mode 100644
index 00000000..3b2c5602
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/ItemDescriptor.kt
@@ -0,0 +1,90 @@
+package ru.dbotthepony.kstarbound.defs.item
+
+import com.google.gson.JsonArray
+import com.google.gson.JsonElement
+import com.google.gson.JsonNull
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import com.google.gson.JsonSyntaxException
+import org.classdump.luna.ByteString
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.Table
+import org.classdump.luna.TableFactory
+import ru.dbotthepony.kstarbound.lua.StateMachine
+import ru.dbotthepony.kstarbound.lua.from
+import ru.dbotthepony.kstarbound.lua.toJsonObject
+import ru.dbotthepony.kstarbound.util.KOptional
+import ru.dbotthepony.kstarbound.util.get
+import java.util.function.Supplier
+
+fun ItemDescriptor(data: JsonElement): ItemDescriptor {
+ if (data is JsonPrimitive) {
+ return ItemDescriptor(data.asString, 1L)
+ } else if (data is JsonArray) {
+ val name = data[0].asString
+ val count = data.get(1, 1L)
+ val parameters = data.get(2, ::JsonObject)
+ return ItemDescriptor(name, count, parameters)
+ } else if (data is JsonObject) {
+ val name = (data.get("name") ?: data.get("item") ?: throw JsonSyntaxException("Missing item name")).asString
+ val count = data.get("count", 1L)
+ val parameters = data.get("parameters") { data.get("parameters", ::JsonObject) }
+ return ItemDescriptor(name, count, parameters)
+ } else if (data is JsonNull) {
+ return ItemDescriptor("air", 0L)
+ } else {
+ throw JsonSyntaxException("Invalid item descriptor: $data")
+ }
+}
+
+fun ItemDescriptor(data: Table, stateMachine: StateMachine): Supplier {
+ val name = stateMachine.index(data, 1L, "name", "item")
+ val count = stateMachine.optionalIndex(data, 2L, "count")
+ val parameters = stateMachine.optionalIndex(data, 3L, "parameters", "data")
+ var result: KOptional = KOptional.empty()
+
+ stateMachine.add {
+ val iname = name.get()
+ val icount = count.get().orElse(1L)
+ val iparameters = parameters.get().map { if (it is Table) it.toJsonObject() else throw LuaRuntimeException("Invalid item descriptor parameters ($it)") }.orElse { JsonObject() }
+
+ if (iname !is ByteString) throw LuaRuntimeException("Invalid item descriptor name (${iname})")
+ if (icount !is Number) throw LuaRuntimeException("Invalid item descriptor count (${icount})")
+
+ result = KOptional(ItemDescriptor(iname.decode(), icount.toLong(), iparameters))
+ }
+
+ return Supplier { result.value }
+}
+
+data class ItemDescriptor(
+ val name: String,
+ val count: Long,
+ val parameters: JsonObject = JsonObject()
+) {
+ val isEmpty get() = count <= 0L
+
+ fun toJson(): JsonObject? {
+ if (isEmpty) {
+ return null
+ }
+
+ return JsonObject().also {
+ it.add("name", JsonPrimitive(name))
+ it.add("count", JsonPrimitive(count))
+ it.add("parameters", parameters.deepCopy())
+ }
+ }
+
+ fun toTable(allocator: TableFactory): Table? {
+ if (isEmpty) {
+ return null
+ }
+
+ return allocator.newTable(0, 3).also {
+ it.rawset("name", name)
+ it.rawset("count", count)
+ it.rawset("parameters", allocator.from(parameters))
+ }
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/TreasurePoolDefinition.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/TreasurePoolDefinition.kt
index 0b952276..b444416f 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/TreasurePoolDefinition.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/TreasurePoolDefinition.kt
@@ -19,6 +19,7 @@ import ru.dbotthepony.kstarbound.io.json.stream
import ru.dbotthepony.kstarbound.util.Either
import ru.dbotthepony.kstarbound.util.ItemStack
import ru.dbotthepony.kstarbound.util.WriteOnce
+import java.util.Random
import java.util.random.RandomGenerator
class TreasurePoolDefinition(pieces: List) {
@@ -46,6 +47,10 @@ class TreasurePoolDefinition(pieces: List) {
}
}
+ fun evaluate(seed: Long, level: Double): List {
+ return evaluate(Random(seed), level)
+ }
+
data class Piece(
val level: Double,
val pool: ImmutableList = ImmutableList.of(),
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/api/IItemDefinition.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/api/IItemDefinition.kt
index ed181369..6bf53e90 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/api/IItemDefinition.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/api/IItemDefinition.kt
@@ -1,6 +1,7 @@
package ru.dbotthepony.kstarbound.defs.item.api
import ru.dbotthepony.kstarbound.Registry
+import ru.dbotthepony.kstarbound.defs.AssetPath
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.item.IInventoryIcon
import ru.dbotthepony.kstarbound.defs.item.ItemRarity
@@ -115,6 +116,11 @@ interface IItemDefinition : IThingWithDescription {
*/
val mediumStackLimit: Long?
+ /**
+ * Lua script path for item config builder
+ */
+ val builder: AssetPath?
+
/**
* Тип предмета, используется Lua скриптами
*/
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/impl/ItemDefinition.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/impl/ItemDefinition.kt
index 9368cc78..3831ec26 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/impl/ItemDefinition.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/item/impl/ItemDefinition.kt
@@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.defs.item.impl
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.Registry
+import ru.dbotthepony.kstarbound.defs.AssetPath
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kstarbound.defs.item.IInventoryIcon
@@ -35,4 +36,5 @@ data class ItemDefinition(
override val pickupSoundsLarge: ImmutableList = ImmutableList.of(),
override val smallStackLimit: Long? = null,
override val mediumStackLimit: Long? = null,
+ override val builder: AssetPath? = null,
) : IItemDefinition, IThingWithDescription by descriptionData
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt
index ceec4a6e..cd7c44b1 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt
@@ -1,6 +1,8 @@
package ru.dbotthepony.kstarbound.defs.tile
import com.google.common.collect.ImmutableList
+import it.unimi.dsi.fastutil.objects.Object2DoubleMap
+import it.unimi.dsi.fastutil.objects.Object2DoubleMaps
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetReference
@@ -16,7 +18,14 @@ object BuiltinMetaMaterials {
renderTemplate = AssetReference.empty(),
renderParameters = RenderParameters.META,
isMeta = true,
- collisionKind = collisionType
+ collisionKind = collisionType,
+ damageConfig = TileDamageConfig(
+ damageFactors = Object2DoubleMaps.emptyMap(),
+ damageRecovery = 1.0,
+ maximumEffectTime = 0.0,
+ health = null,
+ harvestLevel = null,
+ )
))
/**
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDamageConfig.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDamageConfig.kt
index d5c83e5c..736bf00e 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDamageConfig.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDamageConfig.kt
@@ -1,13 +1,14 @@
package ru.dbotthepony.kstarbound.defs.tile
import it.unimi.dsi.fastutil.objects.Object2DoubleMap
+import it.unimi.dsi.fastutil.objects.Object2DoubleMaps
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
@JsonFactory
class TileDamageConfig(
- val damageFactors: Object2DoubleMap,
- val damageRecovery: Double,
- val maximumEffectTime: Double,
+ val damageFactors: Object2DoubleMap = Object2DoubleMaps.emptyMap(),
+ val damageRecovery: Double = 1.0,
+ val maximumEffectTime: Double = 0.0,
val health: Double? = null,
val harvestLevel: Int? = null
)
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt
index 0e4e24e3..b34d472f 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt
@@ -16,15 +16,17 @@ data class TileDefinition(
val materialName: String,
val particleColor: RGBAColor? = null,
val itemDrop: String? = null,
- val footstepSound: String? = null,
+ val footstepSound: ImmutableList = ImmutableList.of(),
val miningSounds: ImmutableList = ImmutableList.of(),
val blocksLiquidFlow: Boolean = true,
val soil: Boolean = false,
- val health: Double = 0.0,
val category: String,
+ @JsonFlat
+ val damageConfig: TileDamageConfig,
+
@JsonFlat
val descriptionData: ThingDescription,
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/AssetJsonFunction.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/AssetJsonFunction.kt
new file mode 100644
index 00000000..e7966962
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/AssetJsonFunction.kt
@@ -0,0 +1,26 @@
+package ru.dbotthepony.kstarbound.lua
+
+import org.classdump.luna.ByteString
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.TableFactory
+import org.classdump.luna.impl.NonsuspendableFunctionException
+import org.classdump.luna.runtime.AbstractFunction1
+import org.classdump.luna.runtime.ExecutionContext
+import ru.dbotthepony.kstarbound.Starbound
+
+class AssetJsonFunction(private val tables: TableFactory) : AbstractFunction1() {
+ override fun resume(context: ExecutionContext?, suspendedState: Any?) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: ByteString?) {
+ arg1 ?: throw LuaRuntimeException("bad argument #1 to root.assetJson (string expected, got nil)")
+ val load = Starbound.loadJsonAsset(arg1.decode())
+
+ if (load == null) {
+ context.returnBuffer.setTo()
+ } else {
+ context.returnBuffer.setTo(tables.from(load))
+ }
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Errors.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Errors.kt
deleted file mode 100644
index ca5638b9..00000000
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Errors.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package ru.dbotthepony.kstarbound.lua
-
-/* thread status */
-// #define LUA_OK 0
-// #define LUA_YIELD 1
-// #define LUA_ERRRUN 2
-// #define LUA_ERRSYNTAX 3
-// #define LUA_ERRMEM 4
-// #define LUA_ERRERR 5
-
-const val LUA_OK = 0
-const val LUA_YIELD = 1
-const val LUA_ERRRUN = 2
-const val LUA_ERRSYNTAX = 3
-const val LUA_ERRMEM = 4
-const val LUA_ERRERR = 5
-
-class InvalidLuaSyntaxException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause)
-class LuaMemoryAllocException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause)
-class LuaGCException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause)
-class LuaException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause)
-class LuaRuntimeException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause)
-
-fun throwPcallError(code: Int) {
- when (code) {
- LUA_OK -> {}
- LUA_ERRRUN -> throw LuaException("Runtime Error")
- LUA_ERRMEM -> throw LuaMemoryAllocException()
- LUA_ERRERR -> throw LuaException("Exception inside Exception handler")
- else -> throw LuaException("Unknown Lua Loading error: $code")
- }
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Functions.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Functions.kt
new file mode 100644
index 00000000..d2bd68c1
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Functions.kt
@@ -0,0 +1,403 @@
+package ru.dbotthepony.kstarbound.lua
+
+import com.google.gson.JsonArray
+import com.google.gson.JsonElement
+import com.google.gson.JsonNull
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
+import it.unimi.dsi.fastutil.objects.ObjectIterators
+import org.classdump.luna.ByteString
+import org.classdump.luna.Conversions
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.Table
+import org.classdump.luna.TableFactory
+import org.classdump.luna.impl.NonsuspendableFunctionException
+import org.classdump.luna.lib.ArgumentIterator
+import org.classdump.luna.lib.BadArgumentException
+import org.classdump.luna.runtime.AbstractFunction0
+import org.classdump.luna.runtime.AbstractFunction1
+import org.classdump.luna.runtime.AbstractFunction2
+import org.classdump.luna.runtime.AbstractFunction3
+import org.classdump.luna.runtime.AbstractFunction4
+import org.classdump.luna.runtime.AbstractFunctionAnyArg
+import org.classdump.luna.runtime.ExecutionContext
+import org.classdump.luna.runtime.LuaFunction
+import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter
+import ru.dbotthepony.kvector.api.IStruct2i
+import ru.dbotthepony.kvector.api.IStruct3i
+import ru.dbotthepony.kvector.api.IStruct4i
+import java.lang.ClassCastException
+import java.lang.IllegalArgumentException
+import java.lang.IndexOutOfBoundsException
+
+fun ArgumentIterator.nextOptionalFloat(): Double? {
+ if (hasNext()) {
+ return nextFloat()
+ } else {
+ return null
+ }
+}
+
+fun ArgumentIterator.nextOptionalInteger(): Long? {
+ if (hasNext()) {
+ return nextInteger()
+ } else {
+ return null
+ }
+}
+
+operator fun Table.set(index: Any, value: Any?) {
+ rawset(index, value)
+}
+
+@Deprecated("Trying to set JSON to Lua table", level = DeprecationLevel.ERROR)
+operator fun Table.set(index: Any, value: JsonElement?) {
+ rawset(index, value)
+}
+
+operator fun Table.set(index: Long, value: Any?) {
+ rawset(index, value)
+}
+
+@Deprecated("Trying to set JSON to Lua table", level = DeprecationLevel.ERROR)
+operator fun Table.set(index: Long, value: JsonElement?) {
+ rawset(index, value)
+}
+
+operator fun Table.set(index: Int, value: Any?) {
+ rawset(index.toLong(), value)
+}
+
+@Deprecated("Trying to set JSON to Lua table", level = DeprecationLevel.ERROR)
+operator fun Table.set(index: Int, value: JsonElement?) {
+ rawset(index.toLong(), value)
+}
+
+operator fun Table.get(index: Any): Any? = rawget(index)
+operator fun Table.get(index: Long): Any? = rawget(index)
+operator fun Table.get(index: Int): Any? = rawget(index.toLong())
+
+operator fun Table.iterator(): Iterator> {
+ var key: Any? = initialKey() ?: return ObjectIterators.emptyIterator()
+ data class Pair(override val key: Any, override val value: Any) : Map.Entry
+
+ return object : Iterator> {
+ override fun hasNext(): Boolean {
+ return key != null
+ }
+
+ override fun next(): Map.Entry {
+ val ikey = key ?: throw NoSuchElementException()
+ val value = get(ikey)!!
+ key = successorKeyOf(ikey)
+ return Pair(ikey, value)
+ }
+ }
+}
+
+fun Table.toJson(): JsonElement {
+ val arrayValues = Long2ObjectAVLTreeMap()
+ val hashValues = Object2ObjectOpenHashMap()
+
+ for ((k, v) in this) {
+ if (k is Number) {
+ arrayValues[k.toLong()] = v
+ } else {
+ hashValues[k] = v
+ }
+ }
+
+ if (hashValues.isEmpty()) {
+ return JsonArray(arrayValues.size).also {
+ for (v in arrayValues.values) {
+ if (v is ByteString) {
+ it.add(JsonPrimitive(v.decode()))
+ } else if (v is Number) {
+ it.add(JsonPrimitive(v))
+ } else if (v is Boolean) {
+ it.add(InternedJsonElementAdapter.of(v))
+ } else if (v is Table) {
+ it.add(v.toJson())
+ }
+ }
+ }
+ } else {
+ return JsonObject().also {
+ for ((k, v) in arrayValues) {
+ if (v is ByteString) {
+ it.add(k.toString(), JsonPrimitive(v.decode()))
+ } else if (v is Number) {
+ it.add(k.toString(), JsonPrimitive(v))
+ } else if (v is Boolean) {
+ it.add(k.toString(), InternedJsonElementAdapter.of(v))
+ } else if (v is Table) {
+ it.add(k.toString(), v.toJson())
+ }
+ }
+
+ for ((k, v) in hashValues) {
+ if (v is ByteString) {
+ it.add(k.toString(), JsonPrimitive(v.decode()))
+ } else if (v is Number) {
+ it.add(k.toString(), JsonPrimitive(v))
+ } else if (v is Boolean) {
+ it.add(k.toString(), InternedJsonElementAdapter.of(v))
+ } else if (v is Table) {
+ it.add(k.toString(), v.toJson())
+ }
+ }
+ }
+ }
+}
+
+fun Table.toJsonObject(): JsonObject {
+ val hashValues = Object2ObjectOpenHashMap()
+
+ for ((k, v) in this) {
+ hashValues[k] = v
+ }
+
+ return JsonObject().also {
+ for ((k, v) in hashValues) {
+ if (v is ByteString) {
+ it.add(k.toString(), JsonPrimitive(v.decode()))
+ } else if (v is Number) {
+ it.add(k.toString(), JsonPrimitive(v))
+ } else if (v is Boolean) {
+ it.add(k.toString(), InternedJsonElementAdapter.of(v))
+ } else if (v is Table) {
+ it.add(k.toString(), v.toJson())
+ }
+ }
+ }
+}
+
+fun TableFactory.from(value: JsonElement?): Any? {
+ when (value) {
+ is JsonPrimitive -> {
+ if (value.isNumber) {
+ return value.asDouble
+ } else if (value.isString) {
+ return ByteString.of(value.asString)
+ } else if (value.isBoolean) {
+ return value.asBoolean
+ } else {
+ throw RuntimeException("unreachable code")
+ }
+ }
+
+ is JsonNull -> return null
+ is JsonArray -> return from(value)
+ is JsonObject -> return from(value)
+ null -> return null
+ else -> throw RuntimeException(value::class.qualifiedName)
+ }
+}
+
+fun TableFactory.from(value: JsonObject): Table {
+ val table = newTable(0, value.size())
+
+ for ((k, v) in value.entrySet()) {
+ table.rawset(Conversions.normaliseKey(k), from(v))
+ }
+
+ return table
+}
+
+fun TableFactory.from(value: JsonArray): Table {
+ val table = newTable(value.size(), 0)
+
+ for ((k, v) in value.withIndex()) {
+ table.rawset(Conversions.normaliseKey(k + 1), from(v))
+ }
+
+ return table
+}
+
+fun TableFactory.fromCollection(value: Collection): Table {
+ val table = newTable(value.size, 0)
+
+ for ((k, v) in value.withIndex()) {
+ table.rawset(Conversions.normaliseKey(k + 1), from(v))
+ }
+
+ return table
+}
+
+fun TableFactory.from(value: IStruct2i): Table {
+ return newTable(2, 0).also {
+ it.rawset(1L, value.component1())
+ it.rawset(2L, value.component2())
+ }
+}
+
+fun TableFactory.from(value: IStruct3i): Table {
+ return newTable(3, 0).also {
+ it.rawset(1L, value.component1())
+ it.rawset(2L, value.component2())
+ it.rawset(3L, value.component3())
+ }
+}
+
+fun TableFactory.from(value: IStruct4i): Table {
+ return newTable(3, 0).also {
+ it.rawset(1L, value.component1())
+ it.rawset(2L, value.component2())
+ it.rawset(3L, value.component3())
+ it.rawset(4L, value.component4())
+ }
+}
+
+fun TableFactory.from(value: Collection): Table {
+ return newTable(value.size, 0).also {
+ for ((i, v) in value.withIndex()) {
+ it.rawset(i + 1L, v)
+ }
+ }
+}
+
+@Deprecated("Function is a stub")
+fun luaStub(message: String = "not yet implemented"): LuaFunction {
+ return object : LuaFunction() {
+ override fun resume(context: ExecutionContext?, suspendedState: Any?) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, arg1: Any?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, arg1: Any?, arg2: Any?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, arg1: Any?, arg2: Any?, arg3: Any?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, arg1: Any?, arg2: Any?, arg3: Any?, arg4: Any?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, arg1: Any?, arg2: Any?, arg3: Any?, arg4: Any?, arg5: Any?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+
+ override fun invoke(context: ExecutionContext?, args: Array?) {
+ throw LuaRuntimeException("NYI: $message")
+ }
+ }
+}
+
+fun luaFunction0String(name: String, callable: (String) -> Any?): LuaFunction {
+ return object : AbstractFunction1() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg: Any?) {
+ if (arg !is ByteString)
+ throw BadArgumentException(1, name, "string expected, got ${if (arg == null) "nil" else arg::class.qualifiedName}")
+
+ val result = callable.invoke(arg.decode())
+
+ if (result != null && result !== Unit) {
+ context.returnBuffer.setTo(result)
+ }
+ }
+ }
+}
+
+fun luaFunctionN(name: String, callable: (ExecutionContext, ArgumentIterator) -> Any?): LuaFunction {
+ return object : AbstractFunctionAnyArg() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, args: Array) {
+ val result = callable.invoke(context, ArgumentIterator.of(context, name, args))
+
+ if (result != null && result !== Unit) {
+ context.returnBuffer.setTo(result)
+ }
+ }
+ }
+}
+
+fun luaFunctionNS(name: String, callable: (ExecutionContext, ArgumentIterator) -> StateMachine): LuaFunction {
+ return object : AbstractFunctionAnyArg() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ (suspendedState as StateMachine).run(context)
+ }
+
+ override fun invoke(context: ExecutionContext, args: Array) {
+ callable.invoke(context, ArgumentIterator.of(context, name, args)).run(context)
+ }
+ }
+}
+
+fun luaFunction(callable: (ExecutionContext) -> Unit): LuaFunction<*, *, *, *, *> {
+ return object : AbstractFunction0() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext) {
+ callable.invoke(context)
+ }
+ }
+}
+
+fun luaFunction(callable: (ExecutionContext, T) -> Unit): LuaFunction {
+ return object : AbstractFunction1() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: T) {
+ callable.invoke(context, arg1)
+ }
+ }
+}
+
+fun luaFunction(callable: (ExecutionContext, T, T2) -> Unit): LuaFunction {
+ return object : AbstractFunction2() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: T, arg2: T2) {
+ callable.invoke(context, arg1, arg2)
+ }
+ }
+}
+
+fun luaFunction(callable: (ExecutionContext, T, T2, T3) -> Unit): LuaFunction {
+ return object : AbstractFunction3() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3) {
+ callable.invoke(context, arg1, arg2, arg3)
+ }
+ }
+}
+
+fun luaFunction(callable: (ExecutionContext, T, T2, T3, T4) -> Unit): LuaFunction {
+ return object : AbstractFunction4() {
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3, arg4: T4) {
+ callable.invoke(context, arg1, arg2, arg3, arg4)
+ }
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/JVM2LuaWrapper.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/JVM2LuaWrapper.kt
deleted file mode 100644
index 72d626e8..00000000
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/JVM2LuaWrapper.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package ru.dbotthepony.kstarbound.lua
-
-@Retention(AnnotationRetention.RUNTIME)
-@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
-annotation class LuaExposed
-
-interface ILuaIndex {
- fun luaIndex(index: Any?): Any?
-}
-
-interface ILuaNewIndex {
- fun luaIndex(index: Any?, value: Any?)
-}
-
-class JVM2LuaWrapper(val value: R) {
- private abstract class LuaBinding {
- abstract fun invoke(receiver: R, values: Array): Any?
- abstract fun read(receiver: R): Any?
- abstract fun write(receiver: R, value: Any?)
- }
-
- private class LuaFunctionBinding(private val func: (R, Array) -> Any?) : LuaBinding() {
- override fun invoke(receiver: R, values: Array): Any? {
- return func.invoke(receiver, values)
- }
-
- override fun read(receiver: R) {
- throw UnsupportedOperationException("attempt to index a function value")
- }
-
- override fun write(receiver: R, value: Any?) {
- throw UnsupportedOperationException("attempt to new index a function value")
- }
- }
-
- private class LuaPropertyBinding(private val read: (R) -> Any?, private val write: ((R, Any?) -> Unit)?) : LuaBinding() {
- override fun invoke(receiver: R, values: Array): Any? {
- throw UnsupportedOperationException("attempt to call a value")
- }
-
- override fun read(receiver: R): Any? {
- return read.invoke(receiver)
- }
-
- override fun write(receiver: R, value: Any?) {
- if (write == null)
- throw UnsupportedOperationException("attempt to new index a read-only value")
-
- write.invoke(receiver, value)
- }
- }
-
- companion object {
- //private val decls =
- }
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaRequire.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaRequire.kt
new file mode 100644
index 00000000..a3a73c39
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaRequire.kt
@@ -0,0 +1,30 @@
+package ru.dbotthepony.kstarbound.lua
+
+import org.classdump.luna.ByteString
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.impl.NonsuspendableFunctionException
+import org.classdump.luna.runtime.AbstractFunction1
+import org.classdump.luna.runtime.ExecutionContext
+import ru.dbotthepony.kstarbound.Starbound
+
+class LuaRequire(private val state: NewLuaState) : AbstractFunction1() {
+ override fun resume(context: ExecutionContext?, suspendedState: Any?) {
+ throw NonsuspendableFunctionException(this::class.java)
+ }
+
+ override fun invoke(context: ExecutionContext, arg1: ByteString) {
+ val name = arg1.decode()
+
+ val file = Starbound.locate(name)
+
+ if (!file.exists) {
+ throw LuaRuntimeException("File $name does not exist")
+ }
+
+ if (!file.isFile) {
+ throw LuaRuntimeException("File $name is a directory")
+ }
+
+ state.load(context, file.readToString(), file.computeFullPath())
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt
deleted file mode 100644
index 28c374b6..00000000
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt
+++ /dev/null
@@ -1,1125 +0,0 @@
-package ru.dbotthepony.kstarbound.lua
-
-import com.github.benmanes.caffeine.cache.Interner
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonNull
-import com.google.gson.JsonObject
-import com.google.gson.JsonPrimitive
-import com.kenai.jffi.CallContext
-import com.kenai.jffi.CallingConvention
-import com.kenai.jffi.Closure
-import com.kenai.jffi.ClosureManager
-import com.kenai.jffi.MemoryIO
-import com.kenai.jffi.Type
-import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
-import jnr.ffi.Pointer
-import org.apache.logging.log4j.LogManager
-import org.lwjgl.system.MemoryStack
-import org.lwjgl.system.MemoryUtil
-import ru.dbotthepony.kstarbound.Registry
-import ru.dbotthepony.kstarbound.Starbound
-import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter
-import ru.dbotthepony.kvector.api.IStruct2i
-import ru.dbotthepony.kvector.api.IStruct3i
-import ru.dbotthepony.kvector.api.IStruct4i
-import ru.dbotthepony.kvector.vector.Vector2i
-import java.io.Closeable
-import java.lang.ref.Cleaner
-import java.lang.ref.WeakReference
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
-import kotlin.system.exitProcess
-
-@Suppress("unused")
-class LuaState private constructor(private val pointer: Pointer, val stringInterner: Interner = Starbound.STRINGS) : Closeable {
- constructor(stringInterner: Interner = Starbound.STRINGS) : this(LuaJNR.INSTANCE.luaL_newstate() ?: throw OutOfMemoryError("Unable to allocate new LuaState"), stringInterner) {
- val pointer = this.pointer
- val panic = ClosureManager.getInstance().newClosure(
- {
- LOGGER.fatal("Engine Error: LuaState at $pointer has panicked!")
- exitProcess(1)
- },
-
- CallContext.getCallContext(Type.SINT, arrayOf(Type.POINTER), CallingConvention.DEFAULT, false)
- )
-
- this.cleanable = Starbound.CLEANER.register(this) {
- LuaJNR.INSTANCE.lua_close(pointer)
- panic.dispose()
- }
-
- panic.setAutoRelease(false)
- LuaJNR.INSTANCE.lua_atpanic(pointer, panic.address)
-
- LuaJNR.INSTANCE.luaopen_base(this.pointer)
- this.storeGlobal("_G")
- LuaJNR.INSTANCE.luaopen_table(this.pointer)
- this.storeGlobal("table")
- LuaJNR.INSTANCE.luaopen_coroutine(this.pointer)
- this.storeGlobal("coroutine")
- LuaJNR.INSTANCE.luaopen_string(this.pointer)
- this.storeGlobal("string")
- LuaJNR.INSTANCE.luaopen_math(this.pointer)
- this.storeGlobal("math")
- LuaJNR.INSTANCE.luaopen_utf8(this.pointer)
- this.storeGlobal("utf8")
- LuaJNR.INSTANCE.luaopen_debug(this.pointer)
- this.storeGlobal("debug")
- }
-
- private val thread = Thread.currentThread()
- private var cleanable: Cleaner.Cleanable? = null
-
- override fun close() {
- this.cleanable?.clean()
- }
-
- val stackTop: Int get() {
- val value = LuaJNR.INSTANCE.lua_gettop(this.pointer)
- check(value >= 0) { "Invalid stack top $value" }
- return value
- }
-
- /**
- * Converts the acceptable index idx into an equivalent absolute index (that is, one that does not depend on the stack size).
- */
- fun absStackIndex(index: Int): Int {
- if (index >= 0)
- return index
-
- return LuaJNR.INSTANCE.lua_absindex(this.pointer, index)
- }
-
- private fun throwLoadError(code: Int) {
- when (code) {
- LUA_OK -> {}
- LUA_ERRSYNTAX -> throw InvalidLuaSyntaxException(this.popString())
- LUA_ERRMEM -> throw LuaMemoryAllocException()
- // LUA_ERRGCMM -> throw LuaGCException()
- else -> throw LuaException("Unknown Lua Loading error: $code")
- }
- }
-
- fun load(code: String, chunkName: String = "main chunk") {
- val bytes = code.toByteArray(charset = Charsets.UTF_8)
- val buf = ByteBuffer.allocateDirect(bytes.size)
- buf.order(ByteOrder.nativeOrder())
- bytes.forEach(buf::put)
- buf.position(0)
-
- val closure = ClosureManager.getInstance().newClosure(
- object : Closure {
- override fun invoke(buffer: Closure.Buffer) {
- val amountToRead = LuaJNR.RUNTIME.memoryManager.newPointer(buffer.getAddress(2))
-
- if (buf.remaining() == 0) {
- amountToRead.putLong(0L, 0L)
- buffer.setAddressReturn(0L)
- return
- }
-
- amountToRead.putLongLong(0L, buf.remaining().toLong())
- val p = MemoryUtil.memAddress(buf)
- buf.position(buf.remaining())
- buffer.setAddressReturn(p)
- }
- },
-
- CallContext.getCallContext(Type.POINTER, arrayOf(Type.POINTER, Type.ULONG_LONG, Type.POINTER), CallingConvention.DEFAULT, false)
- )
-
- this.throwLoadError(LuaJNR.INSTANCE.lua_load(this.pointer, closure.address, 0L, chunkName, "t"))
- closure.dispose()
- }
-
- fun call(numArgs: Int = 0, numResults: Int = 0): Int {
- val status = LuaJNR.INSTANCE.lua_pcallk(this.pointer, numArgs, numResults, 0, 0L, 0L)
-
- if (status == LUA_ERRRUN) {
- throw LuaRuntimeException(this.getString())
- }
-
- return status
- }
-
- fun getString(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): String? {
- if (!this.isString(stackIndex))
- return null
-
- return getStringRaw(stackIndex, limit)
- }
-
- private fun getStringRaw(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): String? {
- check(limit <= Int.MAX_VALUE) { "Can't allocate string bigger than ${Int.MAX_VALUE} characters" }
- val stack = MemoryStack.stackPush()
- val status = stack.mallocLong(1)
- val p = LuaJNR.INSTANCE.lua_tolstring(this.pointer, this.absStackIndex(stackIndex), MemoryUtil.memAddress(status)) ?: return null
- val len = status[0]
- stack.close()
-
- if (len == 0L)
- return ""
- else if (len >= limit)
- throw IllegalStateException("Unreasonably long Lua string: $len")
-
- val readBytes = ByteArray(len.toInt())
- p.get(0L, readBytes, 0, readBytes.size)
- return this.stringInterner.intern(readBytes.toString(charset = Charsets.UTF_8))
- }
-
- fun isCFunction(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_iscfunction(this.pointer, this.absStackIndex(stackIndex)) > 0
- fun isFunction(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.FUNCTION
- fun isInteger(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isinteger(this.pointer, this.absStackIndex(stackIndex)) > 0
- fun isLightUserdata(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.LIGHTUSERDATA
- fun isNil(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.NIL
- fun isNone(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.NONE
- fun isNoneOrNil(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex).let { it == LuaType.NIL || it == LuaType.NONE }
- fun isNumber(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isnumber(this.pointer, this.absStackIndex(stackIndex)) > 0
- fun isString(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isstring(this.pointer, this.absStackIndex(stackIndex)) > 0
- fun isTable(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.TABLE
- fun isThread(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.THREAD
- fun isUserdata(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isuserdata(this.pointer, this.absStackIndex(stackIndex)) > 0
- fun isBoolean(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.BOOLEAN
-
- fun getBoolean(stackIndex: Int = -1): Boolean? {
- if (!this.isBoolean(stackIndex))
- return null
-
- return LuaJNR.INSTANCE.lua_toboolean(this.pointer, stackIndex) > 0
- }
-
- private fun getBooleanRaw(stackIndex: Int = -1): Boolean {
- return LuaJNR.INSTANCE.lua_toboolean(this.pointer, stackIndex) > 0
- }
-
- fun getLong(stackIndex: Int = -1): Long? {
- if (!this.isNumber(stackIndex))
- return null
-
- val stack = MemoryStack.stackPush()
- val status = stack.mallocInt(1)
- val value = LuaJNR.INSTANCE.lua_tointegerx(this.pointer, stackIndex, MemoryUtil.memAddress(status))
- val b = status[0] > 0
- stack.close()
-
- if (!b)
- return null
-
- return value
- }
-
- private fun getLongRaw(stackIndex: Int = -1): Long {
- val stack = MemoryStack.stackPush()
- val status = stack.mallocInt(1)
- val value = LuaJNR.INSTANCE.lua_tointegerx(this.pointer, stackIndex, MemoryUtil.memAddress(status))
- val b = status[0] > 0
- stack.close()
- if (!b) throw NumberFormatException("Lua was unable to parse Long present on stack at ${this.absStackIndex(stackIndex)} ($stackIndex)")
- return value
- }
-
- fun getDouble(stackIndex: Int = -1): Double? {
- if (!this.isNumber(stackIndex))
- return null
-
- val stack = MemoryStack.stackPush()
- val status = stack.mallocInt(1)
- val value = LuaJNR.INSTANCE.lua_tonumberx(this.pointer, stackIndex, MemoryUtil.memAddress(status))
- val b = status[0] > 0
- stack.close()
-
- if (!b)
- return null
-
- return value
- }
-
- private fun getDoubleRaw(stackIndex: Int = -1): Double {
- val stack = MemoryStack.stackPush()
- val status = stack.mallocInt(1)
- val value = LuaJNR.INSTANCE.lua_tonumberx(this.pointer, stackIndex, MemoryUtil.memAddress(status))
- val b = status[0] > 0
- stack.close()
- if (!b) throw NumberFormatException("Lua was unable to parse Double present on stack at ${this.absStackIndex(stackIndex)} ($stackIndex)")
- return value
- }
-
- fun typeAt(stackIndex: Int = -1): LuaType {
- return when (val value = LuaJNR.INSTANCE.lua_type(this.pointer, stackIndex)) {
- LUA_TNONE -> LuaType.NONE
- LUA_TNIL -> LuaType.NIL
- LUA_TBOOLEAN -> LuaType.BOOLEAN
- LUA_TLIGHTUSERDATA -> LuaType.LIGHTUSERDATA
- LUA_TNUMBER -> LuaType.NUMBER
- LUA_TSTRING -> LuaType.STRING
- LUA_TTABLE -> LuaType.TABLE
- LUA_TFUNCTION -> LuaType.FUNCTION
- LUA_TUSERDATA -> LuaType.USERDATA
- LUA_TTHREAD -> LuaType.THREAD
- LUA_NUMTYPES -> LuaType.UMTYPES
- else -> throw RuntimeException("Invalid Lua type: $value")
- }
- }
-
- fun getValue(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): JsonElement? {
- val abs = this.absStackIndex(stackIndex)
-
- if (abs == 0)
- return null
-
- return when (this.typeAt(abs)) {
- LuaType.NONE -> null
- LuaType.NIL -> null // JsonNull.INSTANCE
- LuaType.BOOLEAN -> InternedJsonElementAdapter.of(this.getBooleanRaw(abs))
- LuaType.LIGHTUSERDATA -> throw IllegalArgumentException("Can not get light userdata from Lua stack at $abs")
- LuaType.NUMBER -> JsonPrimitive(if (this.isInteger(abs)) this.getLongRaw(abs) else this.getDoubleRaw(abs))
- LuaType.STRING -> JsonPrimitive(this.getStringRaw(abs, limit = limit))
- LuaType.TABLE -> this.getTableRaw(abs)
- LuaType.FUNCTION -> throw IllegalArgumentException("Can not get function from Lua stack at $abs")
- LuaType.USERDATA -> throw IllegalArgumentException("Can not get userdata from Lua stack at $abs")
- LuaType.THREAD -> throw IllegalArgumentException("Can not get thread from Lua stack at $abs")
- LuaType.UMTYPES -> throw IllegalArgumentException("Can not get umtypes from Lua stack at $abs")
- }
- }
-
- fun getTable(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): JsonObject? {
- val abs = this.absStackIndex(stackIndex)
-
- if (!this.isTable(abs))
- return null
-
- return getTableRaw(abs, limit)
- }
-
- private fun getTableRaw(abs: Int, limit: Long = DEFAULT_STRING_LIMIT): JsonObject {
- val pairs = JsonObject()
- this.push()
- val top = this.stackTop
-
- while (LuaJNR.INSTANCE.lua_next(this.pointer, abs) != 0) {
- val key = this.getValue(abs + 1, limit = limit)
- val value = this.getValue(abs + 2, limit = limit)
-
- if (key is JsonPrimitive && value != null) {
- pairs.add(this.stringInterner.intern(key.asString), value)
- }
-
- LuaJNR.INSTANCE.lua_settop(this.pointer, top)
- }
-
- return pairs
- }
-
- fun getVector2i(stackIndex: Int = -1): Vector2i? {
- val abs = this.absStackIndex(stackIndex)
-
- if (!this.isTable(abs))
- return null
-
- push(1)
- loadTableValue(abs)
-
- val x = getLong(abs + 1)
- pop()
- x ?: return null
-
- push(2)
- loadTableValue(abs)
-
- val y = getLong(abs + 1)
- pop()
- y ?: return null
-
- return Vector2i(x.toInt(), y.toInt())
- }
-
- /**
- * Пропуски заполняются [JsonNull.INSTANCE]
- *
- * Не числовые индексы игнорируются
- */
- fun getArray(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): JsonArray? {
- val abs = this.absStackIndex(stackIndex)
-
- if (!this.isTable(abs))
- return null
-
- val pairs = Int2ObjectAVLTreeMap()
- this.push()
-
- while (LuaJNR.INSTANCE.lua_next(this.pointer, abs) != 0) {
- val key = this.getValue(abs + 1, limit = limit)
- val value = this.getValue(abs + 2, limit = limit)
-
- if (key is JsonPrimitive && key.isNumber && value != null) {
- pairs.put(key.asInt, value)
- }
-
- this.pop()
- }
-
- val result = JsonArray()
-
- for ((index, value) in pairs) {
- while (index > result.size()) {
- result.add(JsonNull.INSTANCE)
- }
-
- result.add(value)
- }
-
- return result
- }
-
- fun getTableValue(stackIndex: Int = -2, limit: Long = DEFAULT_STRING_LIMIT): JsonElement? {
- this.loadTableValue(stackIndex)
- return this.getValue(limit = limit)
- }
-
- fun loadTableValue(stackIndex: Int = -2, allowNothing: Boolean = false) {
- val abs = this.absStackIndex(stackIndex)
-
- if (!this.isTable(abs))
- throw IllegalArgumentException("Attempt to index an ${this.typeAt(abs)} value")
-
- if (LuaJNR.INSTANCE.lua_gettable(this.pointer, abs) == LUA_TNONE && !allowNothing)
- throw IllegalStateException("loaded TNONE from Lua table")
- }
-
- fun loadTableValue(name: String, stackIndex: Int = -2) {
- this.push(name)
- this.loadTableValue(stackIndex)
- }
-
- fun popBoolean(): Boolean? {
- try {
- return this.getBoolean()
- } finally {
- this.pop()
- }
- }
-
- fun popLong(): Long? {
- try {
- return this.getLong()
- } finally {
- this.pop()
- }
- }
-
- fun popDouble(): Double? {
- try {
- return this.getDouble()
- } finally {
- this.pop()
- }
- }
-
- fun popValue(): JsonElement? {
- try {
- return this.getValue()
- } finally {
- this.pop()
- }
- }
-
- fun popTable(): JsonObject? {
- try {
- return this.getTable()
- } finally {
- this.pop()
- }
- }
-
- fun popString(limit: Long = DEFAULT_STRING_LIMIT): String? {
- try {
- return this.getString(limit = limit)
- } finally {
- this.pop()
- }
- }
-
- fun pop(amount: Int = 1): Int {
- if (amount == 0) return 0
- check(amount > 0) { "Invalid amount to pop: $amount" }
- val old = this.stackTop
- val new = (old - amount).coerceAtLeast(0)
- LuaJNR.INSTANCE.lua_settop(this.pointer, new)
- return old - new
- }
-
- fun storeGlobal(name: String) {
- LuaJNR.INSTANCE.lua_setglobal(this.pointer, name)
- }
-
- fun loadGlobal(name: String) {
- LuaJNR.INSTANCE.lua_getglobal(this.pointer, name)
- }
-
- inner class ArgStack(val top: Int) {
- val lua get() = this@LuaState
- var position = 1
-
- fun hasSomethingAt(position: Int): Boolean {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.typeAt(position) != LuaType.NONE
- }
-
- fun hasSomethingAt(): Boolean {
- if (hasSomethingAt(this.position + 1)) {
- return true
- }
-
- this.position++
- return false
- }
-
- fun isStringAt(position: Int = this.position): Boolean {
- return this@LuaState.typeAt(position) == LuaType.STRING
- }
-
- fun isNumberAt(position: Int = this.position): Boolean {
- return this@LuaState.typeAt(position) == LuaType.NUMBER
- }
-
- fun getString(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): String {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getString(position, limit = limit)
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: string expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getLong(position: Int = this.position++): Long {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getLong(position)
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: long expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getStringOrNil(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): String? {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
-
- val type = this@LuaState.typeAt(position)
-
- if (type != LuaType.STRING && type != LuaType.NIL)
- throw IllegalArgumentException("Lua code error: Bad argument #$position: string expected, got $type")
-
- return this@LuaState.getString(position, limit = limit)
- }
-
- fun getStringOrNull(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): String? {
- if (position > this.top)
- return null
-
- return this.getStringOrNil(position, limit = limit)
- }
-
- fun getValue(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): JsonElement {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- val value = this@LuaState.getValue(position, limit = limit)
- return value ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: anything expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getTable(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): JsonObject {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- val value = this@LuaState.getTable(position, limit = limit)
- return value ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: table expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getArray(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): JsonArray {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- val value = this@LuaState.getArray(position, limit = limit)
- return value ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: table expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getAnything(position: Int = this.position++, limit: Long = DEFAULT_STRING_LIMIT): JsonElement? {
- check(position in 1..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getValue(position, limit = limit)
- }
-
- fun getDoubleOrNil(position: Int = this.position++): Double? {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
-
- val type = this@LuaState.typeAt(position)
-
- if (type != LuaType.NUMBER && type != LuaType.NIL)
- throw IllegalArgumentException("Lua code error: Bad argument #$position: double expected, got $type")
-
- return this@LuaState.getDouble(position)
- }
-
- fun getDouble(position: Int = this.position++): Double {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getDouble(position)
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: double expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getInt(position: Int = this.position++): Int {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getLong(position)?.toInt()
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: integer expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getVector2i(position: Int = this.position++): Vector2i {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getVector2i(position)
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: Vector2i expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getBoolOrNil(position: Int = this.position++): Boolean? {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
-
- val type = this@LuaState.typeAt(position)
-
- if (type != LuaType.BOOLEAN && type != LuaType.NIL)
- throw IllegalArgumentException("Lua code error: Bad argument #$position: boolean expected, got $type")
-
- return this@LuaState.getBoolean(position)
- }
-
- fun getBool(position: Int = this.position++): Boolean {
- check(position in 1 ..this.top) { "JVM code error: Invalid argument position: $position" }
- return this@LuaState.getBoolean(position)
- ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: boolean expected, got ${this@LuaState.typeAt(position)}")
- }
-
- fun getBoolOrNull(position: Int = this.position++): Boolean? {
- if (position > this.top) return null
- return this.getBoolOrNil(position)
- }
-
- fun push() = this@LuaState.push()
- fun push(value: Int) = this@LuaState.push(value)
- fun push(value: Long) = this@LuaState.push(value)
- fun push(value: Double) = this@LuaState.push(value)
- fun push(value: Float) = this@LuaState.push(value)
- fun push(value: Boolean) = this@LuaState.push(value)
- fun push(value: String?) = this@LuaState.push(value)
- fun push(value: JsonElement?) = this@LuaState.push(value)
- fun push(value: Registry.Entry<*>?) = this@LuaState.push(value)
- fun pushFull(value: Registry.Entry<*>?) = this@LuaState.pushFull(value)
- }
-
- /**
- * Создаёт новое замыкание на стороне Lua. [function], будучи переданным в Lua,
- * создаст новый **GC Root**.
- *
- * Вышестоящий код ОБЯЗАН использовать [ArgStack] и его [ArgStack.lua] для доступа к [LuaState], так как
- * при вызове замыкания из Lua текущий [LuaState] может отличаться от того, которому был передан [function].
- */
- fun push(function: ArgStack.() -> Int, performanceCritical: Boolean) {
- val weak = WeakReference(this)
- val pointer = this.pointer
-
- LuaJNI.lua_pushcclosure(pointer.address()) lazy@{
- var realLuaState = weak.get()
-
- if (realLuaState == null || realLuaState.pointer.address() != it) {
- if (realLuaState == null)
- realLuaState = LuaState(LuaJNR.RUNTIME.memoryManager.newPointer(it))
- else
- realLuaState = LuaState(LuaJNR.RUNTIME.memoryManager.newPointer(it), stringInterner = realLuaState.stringInterner)
- }
-
- val args = realLuaState.ArgStack(realLuaState.stackTop)
- val rememberStack: ArrayList?
-
- if (performanceCritical) {
- rememberStack = null
- } else {
- rememberStack = ArrayList(Exception().stackTraceToString().split('\n'))
-
- rememberStack.removeAt(0) // java.lang. ...
- // rememberStack.removeAt(0) // at ... push( ... )
- }
-
- try {
- val value = function.invoke(args)
- check(value >= 0) { "Internal JVM error: ${function::class.qualifiedName} returned incorrect number of arguments to be popped from stack by Lua" }
- return@lazy value
- } catch (err: Throwable) {
- try {
- if (performanceCritical) {
- realLuaState.push(err.stackTraceToString())
- return@lazy -1
- } else {
- rememberStack!!
- val newStack = err.stackTraceToString().split('\n').toMutableList()
-
- val rememberIterator = rememberStack.listIterator(rememberStack.size)
- val iterator = newStack.listIterator(newStack.size)
- var hit = false
-
- while (rememberIterator.hasPrevious() && iterator.hasPrevious()) {
- val a = rememberIterator.previous()
- val b = iterator.previous()
-
- if (a == b) {
- hit = true
- iterator.remove()
- } else {
- break
- }
- }
-
- if (hit) {
- newStack[newStack.size - 1] = "\t<...>"
- }
-
- realLuaState.push(newStack.joinToString("\n"))
- return@lazy -1
- }
- } catch(err2: Throwable) {
- realLuaState.push("JVM suffered an exception while handling earlier exception: ${err2.stackTraceToString()}; earlier: ${err.stackTraceToString()}")
- return@lazy -1
- }
- }
- }
- }
-
- /**
- * Создаёт новое замыкание на стороне Lua. [function], будучи переданным в Lua,
- * создаст новый **GC Root**, что может создать утечку память если будет создана циклическая зависимость,
- * если быть неаккуратным.
- *
- * Пример: Parent -> Lua -> Closure -> Parent
- *
- * В примере выше Lua никогда не будет собран сборщиком мусора, тем самым никогда не будет (автоматически) вызван [close]
- *
- * Во избежание данной ситуации предоставлена функция [pushWeak]
- *
- * @see CClosure.invoke
- */
- fun push(function: ArgStack.() -> Int) = this.push(function, !RECORD_STACK_TRACES)
-
- /**
- * Создаёт новое замыкание на стороне Lua. [function], будучи переданным в Lua,
- * создаст новый **GC Root**, что может создать утечку память если будет создана циклическая зависимость,
- * если быть неаккуратным.
- *
- * В отличие от обычного [push] для замыканий, данный вариант создаёт [WeakReference] на [self],
- * который, в свою очередь, может ссылаться обратно на данный [LuaState] через свои структуры.
- *
- * В силу того, что замыкание более не может создать циклическую ссылку на данный [LuaState] через [self], сборщик
- * мусора сможет удалить [self], а затем удалить [LuaState].
- *
- */
- fun pushWeak(self: T, function: T.(args: ArgStack) -> Int, performanceCritical: Boolean) {
- val weakSelf = WeakReference(self)
-
- return push(performanceCritical = performanceCritical, function = lazy@{
- @Suppress("name_shadowing")
- val self = weakSelf.get()
-
- if (self == null) {
- this.lua.push("Referenced 'this' got reclaimed by JVM GC")
- return@lazy -1
- }
-
- function.invoke(self, this)
- })
- }
-
- /**
- * Создаёт новое замыкание на стороне Lua. [function], будучи переданным в Lua,
- * создаст новый **GC Root**, что может создать утечку память если будет создана циклическая зависимость,
- * если быть неаккуратным.
- *
- * В отличие от обычного [push] для замыканий, данный вариант создаёт [WeakReference] на [self],
- * который, в свою очередь, может ссылаться обратно на данный [LuaState] через свои структуры.
- *
- * В силу того, что замыкание более не может создать циклическую ссылку на данный [LuaState] через [self], сборщик
- * мусора сможет удалить [self], а затем удалить [LuaState].
- *
- */
- fun pushWeak(self: T, function: T.(args: ArgStack) -> Int) = this.pushWeak(self, function, !RECORD_STACK_TRACES)
-
- fun push() {
- LuaJNR.INSTANCE.lua_pushnil(this.pointer)
- }
-
- fun push(value: Int) {
- LuaJNR.INSTANCE.lua_pushinteger(this.pointer, value.toLong())
- }
-
- fun push(value: Long) {
- LuaJNR.INSTANCE.lua_pushinteger(this.pointer, value)
- }
-
- fun push(value: Double) {
- LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value)
- }
-
- fun push(value: Float) {
- LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value.toDouble())
- }
-
- fun push(value: Boolean) {
- LuaJNR.INSTANCE.lua_pushboolean(this.pointer, if (value) 1 else 0)
- }
-
- fun push(value: IStruct4i) {
- pushTable(arraySize = 4)
- val table = stackTop
- val (x, y, z, w) = value
-
- push(1)
- push(x)
- setTableValue(table)
-
- push(2)
- push(y)
- setTableValue(table)
-
- push(3)
- push(z)
- setTableValue(table)
-
- push(4)
- push(w)
- setTableValue(table)
- }
-
- fun push(value: IStruct3i) {
- pushTable(arraySize = 3)
- val table = stackTop
- val (x, y, z) = value
-
- push(1)
- push(x)
- setTableValue(table)
-
- push(2)
- push(y)
- setTableValue(table)
-
- push(3)
- push(z)
- setTableValue(table)
- }
-
- fun push(value: IStruct2i) {
- pushTable(arraySize = 2)
- val table = stackTop
- val (x, y) = value
-
- push(1)
- push(x)
- setTableValue(table)
-
- push(2)
- push(y)
- setTableValue(table)
- }
-
- fun pushStrings(strings: Iterable) {
- val index = this.pushTable(arraySize = if (strings is Collection) strings.size else 0)
-
- for ((i, v) in strings.withIndex()) {
- this.push(i + 1L)
- this.push(v)
- this.setTableValue(index)
- }
- }
-
- fun pushStrings(strings: Iterator) {
- val index = this.pushTable()
-
- for ((i, v) in strings.withIndex()) {
- this.push(i + 1L)
- this.push(v)
- this.setTableValue(index)
- }
- }
-
- fun push(value: String?) {
- if (value == null) {
- this.push()
- return
- }
-
- val bytes = value.toByteArray(Charsets.UTF_8)
-
- if (bytes.size < 2 shl 16) {
- MemoryIO.getInstance().putByteArray(sharedStringBufferPtr, bytes, 0, bytes.size)
- LuaJNR.INSTANCE.lua_pushlstring(this.pointer, sharedStringBufferPtr, bytes.size.toLong())
- } else {
- val mem = MemoryIO.getInstance()
- val block = mem.allocateMemory(bytes.size.toLong(), false)
-
- if (block == 0L)
- throw OutOfMemoryError("Unable to allocate ${bytes.size} bytes on heap")
-
- try {
- mem.putByteArray(block, bytes, 0, bytes.size)
- LuaJNR.INSTANCE.lua_pushlstring(this.pointer, block, bytes.size.toLong())
- } finally {
- mem.freeMemory(block)
- }
- }
- }
-
- fun pushTable(arraySize: Int = 0, hashSize: Int = 0): Int {
- LuaJNR.INSTANCE.lua_createtable(this.pointer, arraySize, hashSize)
- return this.stackTop
- }
-
- fun setTableValue(stackIndex: Int) {
- LuaJNR.INSTANCE.lua_settable(this.pointer, stackIndex)
- }
-
- fun setTableFunction(key: String, self: T, value: T.(args: ArgStack) -> Int) {
- val table = this.stackTop
- this.push(key)
- this.pushWeak(self, value)
- this.setTableValue(table)
- }
-
- fun setTableClosure(key: String, self: T, value: T.(args: ArgStack) -> Unit) {
- val table = this.stackTop
- this.push(key)
- this.pushWeak(self) { value.invoke(this, it); 0 }
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: JsonElement?) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: Int) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: Long) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: String?) {
- value ?: return
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: Float) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: String, value: Double) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: JsonElement?) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: Int) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: Long) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: String) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: Float) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Int, value: Double) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: JsonElement?) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: Int) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: Long) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: String) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: Float) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun setTableValue(key: Long, value: Double) {
- val table = this.stackTop
- this.push(key)
- this.push(value)
- this.setTableValue(table)
- }
-
- fun push(value: JsonElement?) {
- when (value) {
- null, JsonNull.INSTANCE -> {
- this.push()
- }
-
- is JsonPrimitive -> {
- if (value.isNumber) {
- val num = value.asNumber
-
- when (num) {
- is Int, is Long -> this.push(num.toLong())
- else -> this.push(num.toDouble())
- }
- } else if (value.isString) {
- this.push(value.asString)
- } else if (value.isBoolean) {
- this.push(value.asBoolean)
- } else {
- throw IllegalArgumentException(value.toString())
- }
- }
-
- is JsonArray -> {
- val index = this.pushTable(arraySize = value.size())
-
- for ((i, v) in value.withIndex()) {
- this.push(i + 1L)
- this.push(v)
-
- this.setTableValue(index)
- }
- }
-
- is JsonObject -> {
- val index = this.pushTable(hashSize = value.size())
-
- for ((k, v) in value.entrySet()) {
- this.push(k)
- this.push(v)
-
- this.setTableValue(index)
- }
- }
-
- else -> {
- throw IllegalArgumentException(value.toString())
- }
- }
- }
-
- fun push(value: Registry.Entry<*>?) {
- if (value == null)
- push()
- else
- push(value.json)
- }
-
- fun pushFull(value: Registry.Entry<*>?) {
- if (value == null)
- push()
- else {
- pushTable(hashSize = 2)
- setTableValue("path", value.file?.computeFullPath())
- setTableValue("config", value.json)
- }
- }
-
- companion object {
- private val LOGGER = LogManager.getLogger()
-
- private val sharedBuffers = ThreadLocal()
-
- private val sharedStringBufferPtr: Long get() {
- var p: Long? = sharedBuffers.get()
-
- if (p == null) {
- p = MemoryIO.getInstance().allocateMemory(DEFAULT_STRING_LIMIT, false)
-
- if (p == 0L) {
- throw OutOfMemoryError("Unable to allocate new string shared buffer")
- }
-
- sharedBuffers.set(p)
- val p2 = p
-
- Starbound.CLEANER.register(Thread.currentThread()) {
- MemoryIO.getInstance().freeMemory(p2)
- }
- }
-
- return p
- }
-
- const val LUA_TNONE = -1
-
- const val LUA_TNIL = 0
- const val LUA_TBOOLEAN = 1
- const val LUA_TLIGHTUSERDATA = 2
- const val LUA_TNUMBER = 3
- const val LUA_TSTRING = 4
- const val LUA_TTABLE = 5
- const val LUA_TFUNCTION = 6
- const val LUA_TUSERDATA = 7
- const val LUA_TTHREAD = 8
-
- const val LUA_NUMTYPES = 9
-
- const val CHUNK_READ_SIZE = 2L shl 10
-
- const val DEFAULT_STRING_LIMIT = 2L shl 16
-
- const val RECORD_STACK_TRACES = false
- }
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaType.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaType.kt
deleted file mode 100644
index ac971293..00000000
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaType.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package ru.dbotthepony.kstarbound.lua
-
-enum class LuaType {
- NONE,
- NIL,
- BOOLEAN,
- LIGHTUSERDATA,
- NUMBER,
- STRING,
- TABLE,
- FUNCTION,
- USERDATA,
- THREAD,
- UMTYPES;
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/NewLuaState.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/NewLuaState.kt
new file mode 100644
index 00000000..7a6087cd
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/NewLuaState.kt
@@ -0,0 +1,77 @@
+package ru.dbotthepony.kstarbound.lua
+
+import org.classdump.luna.StateContext
+import org.classdump.luna.Table
+import org.classdump.luna.Variable
+import org.classdump.luna.compiler.CompilerChunkLoader
+import org.classdump.luna.compiler.CompilerSettings
+import org.classdump.luna.env.RuntimeEnvironments
+import org.classdump.luna.exec.DirectCallExecutor
+import org.classdump.luna.impl.StateContexts
+import org.classdump.luna.lib.BasicLib
+import org.classdump.luna.lib.CoroutineLib
+import org.classdump.luna.lib.MathLib
+import org.classdump.luna.lib.OsLib
+import org.classdump.luna.lib.StringLib
+import org.classdump.luna.lib.TableLib
+import org.classdump.luna.lib.Utf8Lib
+import org.classdump.luna.runtime.Dispatch
+import org.classdump.luna.runtime.ExecutionContext
+import java.util.concurrent.atomic.AtomicInteger
+
+class NewLuaState {
+ val state: StateContext = StateContexts.newDefaultInstance()
+ val chunkLoader: CompilerChunkLoader = CompilerChunkLoader.of(CompilerSettings.defaultNoAccountingSettings(), "kstarbound_${COUNTER.getAndIncrement()}_")
+ val env: Table = state.newTable()
+ val executor: DirectCallExecutor = DirectCallExecutor.newExecutor()
+
+ init {
+ env["_G"] = env
+
+ env["assert"] = BasicLib.assertFn()
+ env["error"] = BasicLib.error()
+ env["getmetatable"] = BasicLib.getmetatable()
+ env["ipairs"] = BasicLib.ipairs()
+ env["next"] = BasicLib.next()
+ env["pairs"] = BasicLib.pairs()
+ env["pcall"] = BasicLib.pcall()
+
+ env["rawequal"] = BasicLib.rawequal()
+ env["rawget"] = BasicLib.rawget()
+ env["rawlen"] = BasicLib.rawlen()
+ env["rawset"] = BasicLib.rawset()
+ env["select"] = BasicLib.select()
+ env["setmetatable"] = BasicLib.setmetatable()
+ env["tostring"] = BasicLib.tostring()
+ env["tonumber"] = BasicLib.tonumber()
+ env["type"] = BasicLib.type()
+ env["_VERSION"] = BasicLib._VERSION
+ env["xpcall"] = BasicLib.xpcall()
+
+ env["print"] = PrintFunction(env)
+
+ env["require"] = LuaRequire(this)
+
+ CoroutineLib.installInto(state, env)
+ TableLib.installInto(state, env)
+ MathLib.installInto(state, env)
+ StringLib.installInto(state, env)
+ OsLib.installInto(state, env, RuntimeEnvironments.system())
+
+ // TODO: NYI, maybe polyfill?
+ Utf8Lib.installInto(state, env)
+ }
+
+ fun load(code: String, name: String = "main chunk") {
+ val main = chunkLoader.loadTextChunk(Variable(env), name, code)
+ executor.call(state, main)
+ }
+
+ fun load(context: ExecutionContext, code: String, name: String = "main chunk") {
+ Dispatch.call(context, chunkLoader.loadTextChunk(Variable(env), name, code))
+ }
+
+ companion object {
+ private val COUNTER = AtomicInteger()
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/PrintFunction.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/PrintFunction.kt
new file mode 100644
index 00000000..ce39a76e
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/PrintFunction.kt
@@ -0,0 +1,63 @@
+package ru.dbotthepony.kstarbound.lua
+
+import org.apache.logging.log4j.LogManager
+import org.classdump.luna.ByteString
+import org.classdump.luna.Conversions
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.runtime.AbstractFunctionAnyArg
+import org.classdump.luna.runtime.Dispatch
+import org.classdump.luna.runtime.ExecutionContext
+
+class PrintFunction(val env: Any) : AbstractFunctionAnyArg() {
+ private inner class State(arguments: Array) {
+ private val resolved = ArrayList(arguments.size)
+ private var tostring: Any? = null
+
+ private val machine = StateMachine()
+
+ init {
+ machine.add { Dispatch.index(it, env, "tostring") }
+ machine.add {
+ tostring = it.returnBuffer.get0()
+
+ if (tostring == null) {
+ throw LuaRuntimeException("global 'tostring' is nil (required by 'print')")
+ }
+ }
+
+ for (argument in arguments) {
+ machine.add { Dispatch.call(it, tostring, argument) }
+ machine.add {
+ val canonical = Conversions.canonicalRepresentationOf(it.returnBuffer.get0())
+
+ if (canonical is ByteString) {
+ resolved.add(canonical)
+ } else {
+ throw LuaRuntimeException("Illegal value returned by 'tostring' (required by 'print')")
+ }
+ }
+ }
+
+ machine.add {
+ LOGGER.info(resolved.joinToString("\t") { it.decode() })
+ it.returnBuffer.setTo()
+ }
+ }
+
+ fun run(context: ExecutionContext) {
+ machine.run(context, this@PrintFunction, this)
+ }
+ }
+
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ (suspendedState as State).run(context)
+ }
+
+ override fun invoke(context: ExecutionContext, args: Array) {
+ State(args).run(context)
+ }
+
+ companion object {
+ private val LOGGER = LogManager.getLogger()
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt
new file mode 100644
index 00000000..c1ade3e3
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/RootBindings.kt
@@ -0,0 +1,339 @@
+package ru.dbotthepony.kstarbound.lua
+
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
+import org.classdump.luna.ByteString
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.Table
+import org.classdump.luna.lib.ArgumentIterator
+import org.classdump.luna.runtime.ExecutionContext
+import org.classdump.luna.runtime.LuaFunction
+import ru.dbotthepony.kstarbound.GlobalDefaults
+import ru.dbotthepony.kstarbound.RecipeRegistry
+import ru.dbotthepony.kstarbound.Registries
+import ru.dbotthepony.kstarbound.Registry
+import ru.dbotthepony.kstarbound.Starbound
+import ru.dbotthepony.kstarbound.defs.image.Image
+import ru.dbotthepony.kstarbound.defs.item.ItemDescriptor
+import kotlin.collections.component1
+import kotlin.collections.component2
+import kotlin.collections.isNotEmpty
+import kotlin.collections.random
+import kotlin.collections.set
+import kotlin.collections.withIndex
+
+private fun lookup(registry: Registry, key: Any?): Registry.Entry? {
+ if (key is ByteString) {
+ return registry[key.decode()]
+ } else if (key is Number) {
+ return registry[key.toInt()]
+ } else {
+ return null
+ }
+}
+
+private fun lookupStrict(registry: Registry, key: Any?): Registry.Entry {
+ if (key is ByteString) {
+ return registry[key.decode()] ?: throw LuaRuntimeException("No such ${registry.name}: $key")
+ } else if (key is Number) {
+ return registry[key.toInt()] ?: throw LuaRuntimeException("No such ${registry.name}: $key")
+ } else {
+ throw LuaRuntimeException("No such ${registry.name}: $key")
+ }
+}
+
+private fun evalFunction(context: ExecutionContext, name: ByteString, value: Double) {
+ val fn = Registries.jsonFunctions[name.decode()] ?: throw LuaRuntimeException("No such function $name")
+ context.returnBuffer.setTo(fn.value.evaluate(value))
+}
+
+private fun evalFunction2(context: ExecutionContext, name: ByteString, value: Double, value2: Double) {
+ val fn = Registries.json2Functions[name.decode()] ?: throw LuaRuntimeException("No such function $name")
+ context.returnBuffer.setTo(fn.value.evaluate(value, value2))
+}
+
+private fun imageSize(context: ExecutionContext, name: ByteString) {
+ context.returnBuffer.setTo(Image.get(name.decode())?.size ?: throw LuaRuntimeException("No such image $name"))
+}
+
+private fun imageSpaces(context: ExecutionContext, arguments: ArgumentIterator): StateMachine {
+ val machine = StateMachine()
+
+ val name = arguments.nextString()
+ val image = Image.get(name.decode()) ?: throw LuaRuntimeException("No such image $name")
+
+ val pixelOffset = machine.loadVector2i(arguments.nextTable())
+ val fillFactor = arguments.nextFloat()
+ val flip = arguments.nextOptionalBoolean(false)
+
+ return machine
+ .add {
+ val values = image.worldSpaces(pixelOffset.get(), fillFactor, flip)
+ val table = context.newTable(values.size, 0)
+
+ for ((i, value) in values.withIndex()) {
+ table.rawset(i.toLong() + 1, value)
+ }
+ }
+}
+
+private fun nonEmptyRegion(context: ExecutionContext, name: ByteString) {
+ val image = Image.get(name.decode()) ?: throw LuaRuntimeException("No such image $name")
+ context.returnBuffer.setTo(context.from(image.nonEmptyRegion))
+}
+
+private fun registryDef(registry: Registry<*>): LuaFunction {
+ return luaFunction { context, name ->
+ val value = registry[name.decode()] ?: throw LuaRuntimeException("No such NPC type $name")
+ context.returnBuffer.setTo(context.from(value.json))
+ }
+}
+
+private fun registryDef2(registry: Registry<*>): LuaFunction {
+ return luaFunction { context, name ->
+ val def = lookup(registry, name)
+
+ if (def != null) {
+ context.returnBuffer.setTo(context.newTable(0, 2).also {
+ it["path"] = def.file?.computeFullPath()
+ it["config"] = context.from(def.json)
+ })
+ } else {
+ context.returnBuffer.setTo()
+ }
+ }
+}
+
+private fun registryDefExists(registry: Registry<*>): LuaFunction {
+ return luaFunction { context, name ->
+ context.returnBuffer.setTo(name.decode() in registry)
+ }
+}
+
+private fun recipesForItem(context: ExecutionContext, name: ByteString) {
+ val list = RecipeRegistry.output2recipes[name.decode()]
+
+ if (list == null) {
+ context.returnBuffer.setTo(context.newTable())
+ } else {
+ context.returnBuffer.setTo(context.newTable(list.size, 0).also {
+ for ((i, v) in list.withIndex()) {
+ it.rawset(i + 1L, context.from(v.json))
+ }
+ })
+ }
+}
+
+private fun itemType(context: ExecutionContext, name: ByteString) {
+ context.returnBuffer.setTo(Registries.items[name.decode()]?.value?.itemType ?: throw NoSuchElementException("No such item $name"))
+}
+
+private fun itemTags(context: ExecutionContext, name: ByteString) {
+ context.returnBuffer.setTo(context.from(Registries.items[name.decode()]?.value?.itemTags ?: throw NoSuchElementException("No such item $name")))
+}
+
+private fun itemHasTag(context: ExecutionContext, name: ByteString, tag: ByteString) {
+ context.returnBuffer.setTo(Registries.items[name.decode()]?.value?.itemTags?.contains(tag.decode()) ?: throw NoSuchElementException("No such item $name"))
+}
+
+private fun itemConfig(context: ExecutionContext, args: ArgumentIterator): StateMachine {
+ val name = args.nextString().decode()
+ val state = StateMachine()
+
+ if (name !in Registries.items) {
+ context.returnBuffer.setTo()
+ return state
+ }
+
+ val desc = ItemDescriptor(args.nextTable(), state)
+ val level = args.nextOptionalFloat()
+ val seed = args.nextOptionalInteger()
+
+ state.add {
+ val build = Starbound.itemConfig(desc.get().name, desc.get().parameters, level, seed)
+
+ context.returnBuffer.setTo(context.newTable(0, 3).also {
+ it["directory"] = build.directory
+ it["config"] = context.from(build.config)
+ it["parameters"] = context.from(build.parameters)
+ })
+ }
+
+ return state
+}
+
+private fun getMatchingTenants(context: ExecutionContext, tags: Table) {
+ val actualTags = Object2IntOpenHashMap()
+
+ for ((k, v) in tags) {
+ if (k is ByteString && v is Number) {
+ actualTags[k.decode()] = v.toInt()
+ }
+ }
+
+ val result = Registries.tenants.keys.values
+ .stream()
+ .filter { it.value.test(actualTags) }
+ .sorted { a, b -> b.value.compareTo(a.value) }
+ .map { context.from(it.json) }
+ .toList()
+
+ context.returnBuffer.setTo(context.newTable(result.size, 0).also {
+ for ((k, v) in result.withIndex()) {
+ it[k + 1] = v
+ }
+ })
+}
+
+private fun liquidStatusEffects(context: ExecutionContext, id: Any) {
+ val liquid = lookup(Registries.liquid, id)
+
+ if (liquid == null) {
+ context.returnBuffer.setTo(context.newTable())
+ } else {
+ context.returnBuffer.setTo(context.newTable(liquid.value.statusEffects.size, 0).also {
+ for ((k, v) in liquid.value.statusEffects.withIndex()) {
+ it[k + 1] = v.key.map({ it }, { it })
+ }
+ })
+ }
+}
+
+private fun createTreasure(context: ExecutionContext, arguments: ArgumentIterator) {
+ val pool = arguments.nextString().decode()
+ val level = arguments.nextFloat()
+ val seed = arguments.nextOptionalInteger()
+
+ val get = Registries.treasurePools[pool] ?: throw LuaRuntimeException("No such treasure pool $pool")
+
+ val result = get.value.evaluate(seed ?: System.nanoTime(), level)
+ .stream().filter { it.isNotEmpty }.map { it.toTable(context)!! }.toList()
+
+ context.returnBuffer.setTo(context.from(result))
+}
+
+private fun materialMiningSound(context: ExecutionContext, arguments: ArgumentIterator) {
+ val tile = lookup(Registries.tiles, arguments.nextAny())
+ val mod = lookup(Registries.tiles, arguments.nextOptionalAny(null))
+
+ if (mod != null && mod.value.miningSounds.isNotEmpty()) {
+ context.returnBuffer.setTo(mod.value.miningSounds.random())
+ return
+ }
+
+ if (tile != null && tile.value.miningSounds.isNotEmpty()) {
+ context.returnBuffer.setTo(tile.value.miningSounds.random())
+ return
+ }
+
+ // original engine parity
+ context.returnBuffer.setTo("")
+}
+
+private fun materialFootstepSound(context: ExecutionContext, arguments: ArgumentIterator) {
+ val tile = lookup(Registries.tiles, arguments.nextAny())
+ val mod = lookup(Registries.tiles, arguments.nextOptionalAny(null))
+
+ if (mod != null && mod.value.footstepSound.isNotEmpty()) {
+ context.returnBuffer.setTo(mod.value.footstepSound.random())
+ return
+ }
+
+ if (tile != null && tile.value.footstepSound.isNotEmpty()) {
+ context.returnBuffer.setTo(tile.value.footstepSound.random())
+ return
+ }
+
+ context.returnBuffer.setTo(GlobalDefaults.clientParameters.defaultFootstepSound.random())
+}
+
+private fun materialHealth(context: ExecutionContext, arguments: ArgumentIterator) {
+ context.returnBuffer.setTo(lookupStrict(Registries.tiles, arguments.nextAny()).value.damageConfig.health)
+}
+
+private fun liquidName(context: ExecutionContext, arguments: ArgumentIterator) {
+ context.returnBuffer.setTo(lookupStrict(Registries.liquid, arguments.nextAny()).key)
+}
+
+private fun liquidId(context: ExecutionContext, arguments: ArgumentIterator) {
+ context.returnBuffer.setTo(lookupStrict(Registries.liquid, arguments.nextAny()).id)
+}
+
+private fun techType(context: ExecutionContext, arguments: ArgumentIterator) {
+ context.returnBuffer.setTo(lookupStrict(Registries.techs, arguments.nextAny()).value.type)
+}
+
+private fun techConfig(context: ExecutionContext, arguments: ArgumentIterator) {
+ context.returnBuffer.setTo(lookupStrict(Registries.techs, arguments.nextAny()).json)
+}
+
+fun provideRootBindings(state: NewLuaState) {
+ val table = state.state.newTable()
+ state.env["root"] = table
+
+ table["assetJson"] = AssetJsonFunction(state.state)
+ table["makeCurrentVersionedJson"] = luaStub("makeCurrentVersionedJson")
+ table["loadVersionedJson"] = luaStub("loadVersionedJson")
+
+ table["evalFunction"] = luaFunction(::evalFunction)
+ table["evalFunction2"] = luaFunction(::evalFunction2)
+ table["imageSize"] = luaFunction(::imageSize)
+ table["imageSpaces"] = luaFunctionNS("imageSpaces", ::imageSpaces)
+ table["nonEmptyRegion"] = luaFunction(::nonEmptyRegion)
+ table["npcConfig"] = registryDef(Registries.npcTypes)
+
+ table["npcVariant"] = luaStub("npcVariant")
+ table["projectileGravityMultiplier"] = luaStub("projectileGravityMultiplier")
+ table["projectileConfig"] = registryDef(Registries.projectiles)
+
+ table["recipesForItem"] = luaFunction(::recipesForItem)
+ table["itemType"] = luaFunction(::itemType)
+ table["itemTags"] = luaFunction(::itemTags)
+ table["itemHasTag"] = luaFunction(::itemHasTag)
+
+ table["itemConfig"] = luaFunctionNS("itemConfig", ::itemConfig)
+
+ table["createItem"] = luaStub("createItem")
+ table["tenantConfig"] = registryDef(Registries.tenants)
+
+ table["getMatchingTenants"] = luaFunction(::getMatchingTenants)
+ table["liquidStatusEffects"] = luaFunction(::liquidStatusEffects)
+
+ table["generateName"] = luaStub("generateName")
+ table["questConfig"] = registryDef(Registries.questTemplates)
+
+ table["npcPortrait"] = luaStub("npcPortrait")
+ table["monsterPortrait"] = luaStub("monsterPortrait")
+ table["npcPortrait"] = luaStub("npcPortrait")
+
+ table["isTreasurePool"] = registryDefExists(Registries.treasurePools)
+ table["createTreasure"] = luaFunctionN("createTreasure", ::createTreasure)
+ table["materialMiningSound"] = luaFunctionN("materialMiningSound", ::materialMiningSound)
+ table["materialFootstepSound"] = luaFunctionN("materialFootstepSound", ::materialFootstepSound)
+ table["materialHealth"] = luaFunctionN("materialHealth", ::materialHealth)
+
+ table["materialConfig"] = registryDef2(Registries.tiles)
+ table["modConfig"] = registryDef2(Registries.tileModifiers)
+
+ table["liquidName"] = luaFunctionN("liquidName", ::liquidName)
+ table["liquidId"] = luaFunctionN("liquidId", ::liquidId)
+
+ table["createBiome"] = luaStub("createBiome")
+ table["monsterSkillParameter"] = luaStub("monsterSkillParameter")
+ table["monsterParameters"] = luaStub("monsterParameters")
+ table["monsterMovementSettings"] = luaStub("monsterMovementSettings")
+
+ table["hasTech"] = registryDefExists(Registries.techs)
+ table["techType"] = luaFunctionN("techType", ::techType)
+ table["techConfig"] = luaFunctionN("techConfig", ::techConfig)
+
+ table["treeStemDirectory"] = luaStub("treeStemDirectory")
+ table["treeFoliageDirectory"] = luaStub("treeFoliageDirectory")
+ table["collection"] = luaStub("collection")
+ table["collectables"] = luaStub("collectables")
+ table["elementalResistance"] = luaStub("elementalResistance")
+ table["dungeonMetadata"] = luaStub("dungeonMetadata")
+ table["behavior"] = luaStub("behavior")
+
+ state.env["jobject"] = luaFunction { executionContext -> executionContext.returnBuffer.setTo(executionContext.newTable()) }
+ state.env["jarray"] = luaFunction { executionContext -> executionContext.returnBuffer.setTo(executionContext.newTable()) }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt
deleted file mode 100644
index 83b2d666..00000000
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-package ru.dbotthepony.kstarbound.lua
-
-import com.google.gson.JsonElement
-import com.google.gson.JsonNull
-import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
-import ru.dbotthepony.kstarbound.util.traverseJsonPath
-
-fun loadInternalScript(name: String): String {
- return LuaState::class.java.getResourceAsStream("/scripts/$name.lua")?.readAllBytes()?.toString(Charsets.UTF_8) ?: throw RuntimeException("/scripts/$name.lua is missing!")
-}
-
-private val messageHandlerLua by lazy { loadInternalScript("message_handler") }
-private val configLua by lazy { loadInternalScript("config") }
-
-fun LuaState.exposeConfig(config: JsonElement) {
- load(configLua, "@starbound.jar!/scripts/config.lua")
- call()
-
- loadGlobal("config")
- val table = stackTop
- push("_get")
- push {
- push(traverseJsonPath(getString(), config))
- return@push 1
- }
-
- setTableValue(table)
- pop()
-}
-
-class MessageHandler(val lua: LuaState) {
- init {
- lua.load(messageHandlerLua, "@starbound.jar!/scripts/message_handler.lua")
- lua.call()
-
- lua.loadGlobal("message")
-
- lua.setTableClosure("subscribe", this) { subscriptions.add(it.getString()) }
-
- lua.pop()
- }
-
- private val subscriptions = ObjectOpenHashSet()
-
- fun isSubscribed(name: String): Boolean {
- return name in subscriptions
- }
-
- fun call(name: String, vararg values: JsonElement): JsonElement? {
- if (!isSubscribed(name))
- return null
-
- lua.loadGlobal("message")
- lua.loadTableValue("call")
-
- lua.push(name)
-
- for (value in values)
- lua.push(value)
-
- lua.call(numArgs = 1 + values.size, numResults = 1)
- val value = lua.getValue()
- lua.pop() // message
- return value
- }
-}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/StateMachine.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/StateMachine.kt
new file mode 100644
index 00000000..de6f4193
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/StateMachine.kt
@@ -0,0 +1,103 @@
+package ru.dbotthepony.kstarbound.lua
+
+import org.classdump.luna.LuaRuntimeException
+import org.classdump.luna.Table
+import org.classdump.luna.runtime.Dispatch
+import org.classdump.luna.runtime.ExecutionContext
+import org.classdump.luna.runtime.Resumable
+import org.classdump.luna.runtime.UnresolvedControlThrowable
+import ru.dbotthepony.kstarbound.util.KOptional
+import ru.dbotthepony.kvector.vector.Vector2i
+import java.util.function.Supplier
+
+class StateMachine : Resumable {
+ private val states = ArrayDeque<(ExecutionContext) -> Unit>()
+
+ fun add(state: (ExecutionContext) -> Unit): StateMachine {
+ states.add(state)
+ return this
+ }
+
+ fun mergeInto(other: StateMachine): StateMachine {
+ states.addAll(other.states)
+ return other
+ }
+
+ fun mergeFrom(other: StateMachine): StateMachine {
+ other.mergeInto(this)
+ return this
+ }
+
+ override fun resume(context: ExecutionContext, suspendedState: Any) {
+ run(context, this, this)
+ }
+
+ fun run(context: ExecutionContext): Boolean = run(context, this, this)
+
+ fun run(context: ExecutionContext, resumable: Resumable, suspendState: Any): Boolean {
+ if (states.isEmpty())
+ return false
+
+ while (states.isNotEmpty()) {
+ val next = states.removeFirst()
+
+ try {
+ next.invoke(context)
+ } catch (err: UnresolvedControlThrowable) {
+ throw err.resolve(resumable, suspendState)
+ }
+ }
+
+ return true
+ }
+
+ fun index(table: Table, vararg indexes: Any): Supplier {
+ var value: KOptional = KOptional.empty()
+
+ for (index in indexes) {
+ add {
+ if (!value.isPresent) {
+ value = KOptional.ofNullable(Dispatch.index(it, table, index))
+ }
+ }
+ }
+
+ return Supplier {
+ if (!value.isPresent) {
+ throw LuaRuntimeException("Unable to locate value in table using following keys: ${indexes.joinToString()}")
+ }
+ }
+ }
+
+ fun optionalIndex(table: Table, vararg indexes: Any): Supplier> {
+ var value: KOptional = KOptional.empty()
+
+ for (index in indexes) {
+ add {
+ if (!value.isPresent) {
+ value = KOptional.ofNullable(Dispatch.index(it, table, index))
+ }
+ }
+ }
+
+ return Supplier { value }
+ }
+
+ fun loadVector2i(table: Table): Supplier {
+ val x = index(table, 1, "x")
+ val y = index(table, 2, "y")
+ var value = KOptional.empty()
+
+ add {
+ val ix = x.get()
+ val iy = y.get()
+
+ if (ix !is Number) throw LuaRuntimeException("Invalid 'x' value for vector: ${x.get()}")
+ if (iy !is Number) throw LuaRuntimeException("Invalid 'y' value for vector: ${x.get()}")
+
+ value = KOptional(Vector2i(ix.toInt(), iy.toInt()))
+ }
+
+ return Supplier { value.value }
+ }
+}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt
index c636697d..7e525fd7 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt
@@ -10,8 +10,12 @@ import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.player.TechDefinition
-import ru.dbotthepony.kstarbound.lua.LuaState
-import ru.dbotthepony.kstarbound.lua.loadInternalScript
+import ru.dbotthepony.kstarbound.lua.NewLuaState
+import ru.dbotthepony.kstarbound.lua.luaFunction
+import ru.dbotthepony.kstarbound.lua.luaFunction0String
+import ru.dbotthepony.kstarbound.lua.luaFunctionN
+import ru.dbotthepony.kstarbound.lua.luaStub
+import ru.dbotthepony.kstarbound.lua.set
import ru.dbotthepony.kstarbound.util.ItemStack
import ru.dbotthepony.kstarbound.util.immutableMap
import java.util.*
@@ -298,180 +302,75 @@ class Avatar(val uniqueId: UUID) {
}
}
- fun pushLuaAPI(lua: LuaState) {
- lua.load(playerLua)
+ fun provideBindings(lua: NewLuaState) {
+ val table = lua.state.newTable()
- lua.pushTable()
+ lua.env["player"] = table
- lua.setTableValue("uniqueId", uniqueId.toString())
- lua.setTableValue("species", "human")
- lua.setTableValue("gender", "male")
+ lua.env["uniqueId"] = luaFunction { it.returnBuffer.setTo(uniqueId.toString()) }
+ lua.env["species"] = luaFunction { it.returnBuffer.setTo("human") }
+ lua.env["gender"] = luaFunction { it.returnBuffer.setTo("male") }
+ lua.env["giveBlueprint"] = luaFunction0String("giveBlueprint", ::giveBlueprint)
+ lua.env["blueprintKnown"] = luaFunction0String("blueprintKnown", ::blueprintKnown)
+ lua.env["makeTechAvailable"] = luaFunction0String("makeTechAvailable", ::makeTechAvailable)
+ lua.env["makeTechUnavailable"] = luaFunction0String("makeTechUnavailable", ::makeTechUnavailable)
+ lua.env["enableTech"] = luaFunction0String("enableTech", ::enableTech)
+ lua.env["equipTech"] = luaFunction0String("equipTech", ::equipTech)
+ lua.env["unequipTech"] = luaFunction0String("unequipTech", ::unequipTech)
- lua.call(numArgs = 1)
+ lua.env["availableTechs"] = luaFunction {
+ val result = it.newTable(availableTechs.size, 0)
- lua.loadGlobal("player")
- lua.setTableClosure("giveBlueprint", this) { giveBlueprint(it.getValue()) }
- lua.setTableFunction("blueprintKnown", this) { it.lua.push(blueprintKnown(it.getValue())); 1 }
- lua.setTableClosure("makeTechAvailable", this) { makeTechAvailable(it.getString()) }
- lua.setTableClosure("makeTechUnavailable", this) { makeTechUnavailable(it.getString()) }
- lua.setTableClosure("enableTech", this) { enableTech(it.getString()) }
- lua.setTableClosure("equipTech", this) { equipTech(it.getString()) }
- lua.setTableClosure("unequipTech", this) { unequipTech(it.getString()) }
- lua.setTableFunction("availableTechs", this) { it.lua.pushStrings(availableTechs.stream().map { it.value.name }.iterator()); 1 }
- lua.setTableFunction("enabledTechs", this) { it.lua.pushStrings(enabledTechs.stream().map { it.value.name }.iterator()); 1 }
- lua.setTableFunction("equippedTech", this) { it.lua.push(equippedTechs[it.getString()]?.value?.name); 1 }
- lua.setTableFunction("currency", this) { it.lua.push(currency(it.getString())); 1 }
- lua.setTableClosure("addCurrency", this) { addCurrency(it.getString(), it.getLong()) }
- lua.setTableFunction("consumeCurrency", this) { it.lua.push(consumeCurrency(it.getString(), it.getLong())); 1 }
- lua.setTableClosure("cleanupItems", this) { cleanupItems() }
- lua.setTableClosure("giveItem", this) { giveItem(Starbound.item(it.getValue())) }
-
- lua.setTableFunction("hasItem", this) {
- it.lua.push(hasItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
- 1
- }
-
- lua.setTableFunction("hasCountOfItem", this) {
- it.lua.push(hasCountOfItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false))
- 1
- }
-
- lua.setTableFunction("consumeItem", this) {
- it.lua.push(consumeItem(Starbound.item(it.getValue()), it.getBoolOrNull() ?: false, it.getBoolOrNull() ?: false).toJson())
- 1
- }
-
- lua.setTableFunction("inventoryTags", this) {
- val mapping = inventoryTags()
-
- it.lua.pushTable(hashSize = mapping.size)
-
- for ((k, v) in mapping) {
- it.lua.setTableValue(k, v)
+ for ((i, v) in availableTechs.withIndex()) {
+ result[i + 1] = v
}
- 1
+ it.returnBuffer.setTo(result)
}
- lua.setTableFunction("itemsWithTag", this) {
- val mapping = itemsWithTag()
+ lua.env["enabledTechs"] = luaFunction {
+ val result = it.newTable(enabledTechs.size, 0)
- it.lua.pushTable(arraySize = mapping.size)
-
- for ((k, v) in mapping.withIndex()) {
- it.lua.setTableValue(k, v.toJson())
+ for ((i, v) in enabledTechs.withIndex()) {
+ result[i + 1] = v
}
- 1
+ it.returnBuffer.setTo(result)
}
- lua.setTableFunction("consumeTaggedItem", this) {
- it.lua.push(consumeTaggedItem(it.getString()))
- 1
- }
+ lua.env["equippedTech"] = luaFunctionN("equippedTech") { it, args -> equippedTechs[args.nextString().decode()]?.key }
+ lua.env["currency"] = luaFunction0String("currency", ::currency)
+ lua.env["addCurrency"] = luaFunctionN("addCurrency") { it, args -> addCurrency(args.nextString().decode(), args.nextInteger()) }
+ lua.env["consumeCurrency"] = luaFunctionN("consumeCurrency") { it, args -> consumeCurrency(args.nextString().decode(), args.nextInteger()) }
+ lua.env["cleanupItems"] = luaFunction { cleanupItems() }
- lua.setTableFunction("hasItemWithParameter", this) {
- it.lua.push(hasItemWithParameter(it.getString(), it.getValue()))
- 1
- }
-
- lua.setTableFunction("consumeItemWithParameter", this) {
- it.lua.push(consumeItemWithParameter(it.getString(), it.getValue(), it.getLong()))
- 1
- }
-
- lua.setTableFunction("getItemWithParameter", this) {
- it.lua.push(getItemWithParameter(it.getString(), it.getValue()).toJson())
- 1
- }
-
- lua.setTableFunction("primaryHandItem", this) {
- it.lua.push(primaryHandItem?.toJson())
- 1
- }
-
- lua.setTableFunction("altHandItem", this) {
- it.lua.push(altHandItem?.toJson())
- 1
- }
-
- lua.setTableFunction("primaryHandItemTags", this) {
- val tags = primaryHandItem?.item?.value?.itemTags
- if (tags != null) it.lua.pushStrings(tags) else it.lua.push()
- 1
- }
-
- lua.setTableFunction("altHandItemTags", this) {
- val tags = altHandItem?.item?.value?.itemTags
- if (tags != null) it.lua.pushStrings(tags) else it.lua.push()
- 1
- }
-
- lua.setTableFunction("essentialItem", this) {
- val name = it.getString()
- val slot = essentialSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
- it.lua.push(essentialItem(slot)?.toJson())
- 1
- }
-
- lua.setTableClosure("giveEssentialItem", this) {
- val name = it.getString()
- val item = Starbound.item(it.getValue())
- val slot = essentialSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
- giveEssentialItem(slot, item)
- }
-
- lua.setTableClosure("removeEssentialItem", this) {
- val name = it.getString()
- val slot = essentialSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
- removeEssentialItem(slot)
- }
-
- lua.setTableFunction("equippedItem", this) {
- val name = it.getString()
- val slot = equipmentSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
- it.lua.push(equippedItem(slot).toJson())
- 1
- }
-
- lua.setTableClosure("setEquippedItem", this) {
- val name = it.getString()
- val item = Starbound.item(it.getValue())
- val slot = equipmentSlotsMap[name] ?: throw IllegalArgumentException("Invalid slot '$name'")
- setEquippedItem(slot, item)
- }
-
- lua.setTableFunction("swapSlotItem", this) {
- it.lua.push(cursorItem.toJson())
- 1
- }
-
- lua.setTableClosure("setSwapSlotItem", this) {
- cursorItem = Starbound.item(it.getValue())
- }
-
- lua.setTableFunction("startQuest", this) {
- it.lua.push(startQuest(it.getValue(), it.getStringOrNull(), it.getStringOrNull()))
- 1
- }
-
- lua.setTableFunction("hasQuest", this) {
- it.lua.push(quests[it.getString()] != null)
- 1
- }
-
- lua.setTableFunction("hasCompletedQuest", this) {
- val quest = quests[it.getString()]
- it.lua.push(quest != null && quest.state == QuestInstance.State.COMPLETE)
- 1
- }
-
- lua.pop()
+ lua.env["giveItem"] = luaStub("giveItem")
+ lua.env["hasItem"] = luaStub("hasItem")
+ lua.env["hasCountOfItem"] = luaStub("hasCountOfItem")
+ lua.env["consumeItem"] = luaStub("consumeItem")
+ lua.env["inventoryTags"] = luaStub("inventoryTags")
+ lua.env["itemsWithTag"] = luaStub("itemsWithTag")
+ lua.env["consumeTaggedItem"] = luaStub("consumeTaggedItem")
+ lua.env["hasItemWithParameter"] = luaStub("hasItemWithParameter")
+ lua.env["consumeItemWithParameter"] = luaStub("consumeItemWithParameter")
+ lua.env["getItemWithParameter"] = luaStub("getItemWithParameter")
+ lua.env["primaryHandItem"] = luaStub("primaryHandItem")
+ lua.env["altHandItem"] = luaStub("altHandItem")
+ lua.env["primaryHandItemTags"] = luaStub("primaryHandItemTags")
+ lua.env["altHandItemTags"] = luaStub("altHandItemTags")
+ lua.env["essentialItem"] = luaStub("essentialItem")
+ lua.env["giveEssentialItem"] = luaStub("giveEssentialItem")
+ lua.env["removeEssentialItem"] = luaStub("removeEssentialItem")
+ lua.env["equippedItem"] = luaStub("equippedItem")
+ lua.env["setEquippedItem"] = luaStub("setEquippedItem")
+ lua.env["swapSlotItem"] = luaStub("swapSlotItem")
+ lua.env["setSwapSlotItem"] = luaStub("setSwapSlotItem")
+ lua.env["startQuest"] = luaStub("startQuest")
+ lua.env["hasQuest"] = luaStub("hasQuest")
+ lua.env["hasCompletedQuest"] = luaStub("hasCompletedQuest")
}
companion object {
- private val playerLua by lazy { loadInternalScript("player") }
-
private val essentialSlotsMap = immutableMap {
put("beamaxe", EssentialSlot.BEAM_AXE)
put("inspectiontool", EssentialSlot.INSPECTION_TOOL)
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/player/AvatarBag.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/player/AvatarBag.kt
index 81717698..0da0e32a 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/player/AvatarBag.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/player/AvatarBag.kt
@@ -20,10 +20,10 @@ class AvatarBag(val avatar: Avatar, val config: InventoryConfig.Bag, val filter:
fun mergeFrom(value: ItemStack, simulate: Boolean) {
if (item == null) {
if (!simulate) {
- item = value.copy().also { it.size = value.size.coerceAtMost(value.item!!.value.maxStack) }
+ item = value.copy().also { it.count = value.count.coerceAtMost(value.item!!.value.maxStack) }
}
- value.size -= value.item!!.value.maxStack
+ value.count -= value.item!!.value.maxStack
} else {
item!!.mergeFrom(value, simulate)
}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt
index 2e943e7a..a54ca1de 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt
@@ -8,9 +8,7 @@ import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.quest.QuestTemplate
-import ru.dbotthepony.kstarbound.lua.LuaState
-import ru.dbotthepony.kstarbound.lua.MessageHandler
-import ru.dbotthepony.kstarbound.lua.exposeConfig
+import ru.dbotthepony.kstarbound.lua.NewLuaState
import ru.dbotthepony.kstarbound.util.ItemStack
import ru.dbotthepony.kstarbound.util.set
import java.util.UUID
@@ -25,8 +23,7 @@ class QuestInstance(
val template: QuestTemplate = Registries.questTemplates[descriptor.templateId]?.value ?: throw IllegalArgumentException("No such quest template ${descriptor.templateId}")
val id get() = descriptor.questId
- val lua = LuaState()
- val messages = MessageHandler(lua)
+ val lua = NewLuaState()
enum class State(val serializedName: String) {
NEW("New"),
@@ -79,173 +76,12 @@ class QuestInstance(
}
}
- init {
- lua.pushTable()
- lua.storeGlobal("self")
- lua.pushTable()
- lua.storeGlobal("storage")
-
- lua.pushTable()
- lua.storeGlobal("quest")
- lua.loadGlobal("quest")
-
- lua.setTableClosure("setParameter", this) { setParameter(it) }
-
- lua.setTableFunction("parameters", this) {
- it.lua.push(params)
- 1
- }
-
- lua.setTableClosure("setPortrait", this) { setPortrait(it) }
- lua.setTableClosure("setPortraitTitle", this) { setPortraitTitle(it) }
-
- lua.setTableFunction("state", this) { it.lua.push(state.serializedName); 1 }
- lua.setTableClosure("complete", this) { complete() }
- lua.setTableClosure("fail", this) { fail() }
- lua.setTableClosure("setCanTurnIn", this) { canTurnIn = it.getBool() }
- lua.setTableFunction("questDescriptor", this) { it.lua.push(Starbound.gson.toJsonTree(descriptor)); 1 }
- lua.setTableFunction("questId", this) { it.lua.push(id); 1 }
- lua.setTableFunction("templateId", this) { it.lua.push(template.id); 1 }
- lua.setTableFunction("seed", this) { it.lua.push(seed); 1 }
- lua.setTableFunction("questArcDescriptor", this) { TODO(); 1 }
- lua.setTableFunction("questArcPosition", this) { TODO(); 1 }
- lua.setTableFunction("worldId", this) { it.lua.push(worldID); 1 }
- lua.setTableFunction("serverUuid", this) { it.lua.push(serverID?.toString()); 1 }
- lua.setTableClosure("setObjectiveList", this) { setObjectiveList(it.getArray()) }
- lua.setTableClosure("setProgress", this) { progress = it.getDoubleOrNil() }
- lua.setTableClosure("setCompassDirection", this) { compassDirection = it.getDoubleOrNil() }
- lua.setTableClosure("setTitle", this) { title = it.getString() }
- lua.setTableClosure("setText", this) { text = it.getString() }
- lua.setTableClosure("setCompletionText", this) { completionText = it.getString() }
- lua.setTableClosure("setFailureText", this) { failureText = it.getString() }
- lua.setTableClosure("addReward", this) { addReward(it.getValue()) }
-
- lua.pop()
-
- Starbound.pushLuaAPI(lua)
- avatar.pushLuaAPI(lua)
- lua.exposeConfig(template.scriptConfig)
- }
-
- private fun setParameter(argStack: LuaState.ArgStack) {
- params.add(argStack.getString(), argStack.getValue())
- }
-
- private fun setPortrait(argStack: LuaState.ArgStack) {
- val name = argStack.getString()
- val value = argStack.getAnything()
-
- if (value == null)
- portraits.remove(name)
- else
- portraits.add(name, value)
- }
-
- private fun setPortraitTitle(argStack: LuaState.ArgStack) {
- val name = argStack.getString()
- val title = argStack.getStringOrNil()
-
- if (title == null)
- portraitTitles.remove(name)
- else
- portraitTitles[name] = title
- }
-
init {
for ((k, v) in descriptor.parameters.entrySet()) {
params[k] = v.deepCopy()
}
}
- /**
- * Читает главный скриптовый файл квеста и вызывает его (глобальную) функцию init()
- */
- fun init(): Boolean {
- if (!isInitialized) {
- isInitialized = true
-
- val script = Starbound.locate(template.script.fullPath)
-
- if (!script.isFile) {
- LOGGER.error("Quest ${template.id} specifies ${template.script.fullPath} as its script, but it is not a file or does not exist!")
- return false
- }
-
- try {
- lua.load(script.readToString(), "@" + template.script.fullPath)
- } catch(err: Throwable) {
- LOGGER.error("Error loading Lua code for quest ${descriptor.questId}", err)
- return false
- }
-
- try {
- lua.call()
- } catch(err: Throwable) {
- LOGGER.error("Error running Lua code for quest ${descriptor.questId}", err)
- return false
- }
-
- try {
- lua.loadGlobal("init")
- lua.call()
- } catch(err: Throwable) {
- LOGGER.error("Error running init() function for quest ${descriptor.questId}", err)
- return false
- }
-
- successfulInit = true
- }
-
- return successfulInit
- }
-
- fun start(): Boolean {
- if (!init()) {
- return false
- }
-
- if (calledStart) {
- return successfulStart
- }
-
- lua.loadGlobal("questStart")
-
- try {
- if (lua.isFunction()) {
- lua.call()
- } else {
- lua.pop()
- }
- } catch(err: Throwable) {
- LOGGER.error("Error running questStart() function for quest ${descriptor.questId}", err)
- return false
- }
-
- return successfulStart
- }
-
- fun update(delta: Int): Boolean {
- if (!init()) {
- return false
- }
-
- lua.loadGlobal("update")
-
- try {
- if (lua.isFunction()) {
- lua.push(delta)
- lua.call(numArgs = 1)
- } else {
- lua.pop()
- }
- } catch(err: Throwable) {
- LOGGER.error("Error running update() function for quest ${descriptor.questId}", err)
- return false
- }
-
- return true
- }
-
companion object {
private val LOGGER = LogManager.getLogger()
}
diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/Ext.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/Ext.kt
index 487bcfa7..f031f54d 100644
--- a/src/main/kotlin/ru/dbotthepony/kstarbound/util/Ext.kt
+++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/Ext.kt
@@ -20,6 +20,19 @@ operator fun JsonObject.set(key: String, value: Boolean) { add(key, InternedJson
operator fun JsonObject.set(key: String, value: Nothing?) { add(key, JsonNull.INSTANCE) }
operator fun JsonObject.contains(key: String): Boolean = has(key)
+fun JsonArray.get(key: Int, default: Boolean): Boolean {
+ if (key !in 0 until size())
+ return default
+
+ val value = this[key]
+
+ if (value !is JsonPrimitive || !value.isBoolean) {
+ throw JsonSyntaxException("Expected boolean at $key; got $value")
+ }
+
+ return value.asBoolean
+}
+
fun JsonObject.get(key: String, default: Boolean): Boolean {
if (!has(key))
return default
@@ -46,6 +59,19 @@ fun JsonObject.get(key: String, default: String): String {
return value.asString
}
+fun JsonArray.get(key: Int, default: String): String {
+ if (key !in 0 until size())
+ return default
+
+ val value = this[key]
+
+ if (value !is JsonPrimitive || !value.isString) {
+ throw JsonSyntaxException("Expected string at $key; got $value")
+ }
+
+ return value.asString
+}
+
fun JsonObject.get(key: String, default: Int): Int {
if (!has(key))
return default
@@ -59,6 +85,19 @@ fun JsonObject.get(key: String, default: Int): Int {
return value.asInt
}
+fun JsonArray.get(key: Int, default: Int): Int {
+ if (key !in 0 until size())
+ return default
+
+ val value = this[key]
+
+ if (value !is JsonPrimitive || !value.isNumber) {
+ throw JsonSyntaxException("Expected integer at $key; got $value")
+ }
+
+ return value.asInt
+}
+
fun JsonObject.get(key: String, default: Long): Long {
if (!has(key))
return default
@@ -72,6 +111,19 @@ fun JsonObject.get(key: String, default: Long): Long {
return value.asLong
}
+fun JsonArray.get(key: Int, default: Long): Long {
+ if (key !in 0 until size())
+ return default
+
+ val value = this[key]
+
+ if (value !is JsonPrimitive || !value.isNumber) {
+ throw JsonSyntaxException("Expected long at $key; got $value")
+ }
+
+ return value.asLong
+}
+
fun JsonObject.get(key: String, default: Double): Double {
if (!has(key))
return default
@@ -85,6 +137,19 @@ fun JsonObject.get(key: String, default: Double): Double {
return value.asDouble
}
+fun JsonArray.get(key: Int, default: Double): Double {
+ if (key !in 0 until size())
+ return default
+
+ val value = this[key]
+
+ if (value !is JsonPrimitive || !value.isNumber) {
+ throw JsonSyntaxException("Expected double at $key; got $value")
+ }
+
+ return value.asDouble
+}
+
fun JsonObject.get(key: String, default: JsonObject): JsonObject {
if (!has(key))
return default
@@ -97,6 +162,42 @@ fun JsonObject.get(key: String, default: JsonObject): JsonObject {
return value
}
+inline fun