/* ** $Id: lobject.h,v 2.143 2018/06/01 16:51:34 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ #ifndef lobject_h #define lobject_h #include #include "llimits.h" #include "lua.h" /* ** Extra tags for non-values */ #define LUA_TUPVAL LUA_NUMTAGS /* upvalues */ #define LUA_TPROTO (LUA_NUMTAGS+1) /* function prototypes */ /* ** number of all possible tags (including LUA_TNONE) */ #define LUA_TOTALTAGS (LUA_TPROTO + 2) /* ** tags for Tagged Values have the following use of bits: ** bits 0-3: actual tag (a LUA_T* value) ** bits 4-5: variant bits ** bit 6: whether value is collectable */ /* ** Union of all Lua values */ typedef union Value { struct GCObject *gc; /* collectable objects */ void *p; /* light userdata */ int b; /* booleans */ 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 */ #define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt) #define checkliveness(L,obj) \ lua_longassert(!iscollectable(obj) || \ (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) /* Macros to set values */ #define settt_(o,t) ((o)->tt_=(t)) #define setobj(L,obj1,obj2) \ { TValue *io1=(obj1); const TValue *io2=(obj2); \ io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ (void)L; checkliveness(L,io1); lua_assert(!isreallyempty(io1)); } /* ** different types of assignments, according to destination */ /* 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 typedef union StackValue { TValue val; } StackValue; typedef StackValue *StkId; /* index to stack elements */ /* convert a 'StackValue' to a 'TValue' */ #define s2v(o) (&(o)->val) /* ** {================================================================== ** Nil ** =================================================================== */ /* macro to test for (any kind of) nil */ #define ttisnil(v) checktype((v), LUA_TNIL) /* macro to test for a "pure" nil */ #define ttisstrictnil(o) checktag((o), LUA_TNIL) /* macro defining a nil value */ #define NILCONSTANT {NULL}, LUA_TNIL #define setnilvalue(obj) settt_(obj, LUA_TNIL) /* ** Variant tag, used only in tables to signal an empty slot ** (which might be different from a slot containing nil) */ #define LUA_TEMPTY (LUA_TNIL | (1 << 4)) /* ** Variant used only in the value returned for a key not found in a ** table (absent key). */ #define LUA_TABSTKEY (LUA_TNIL | (2 << 4)) #define isabstkey(v) checktag((v), LUA_TABSTKEY) /* ** macro to detect non-standard nils (used only in assertions) */ #define isreallyempty(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_TABSTKEY /* mark an entry as empty */ #define setempty(v) settt_(v, LUA_TEMPTY) /* }================================================================== */ /* ** {================================================================== ** Booleans ** =================================================================== */ #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) #define bvalue(o) check_exp(ttisboolean(o), val_(o).b) #define bvalueraw(v) ((v).b) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) #define setbvalue(obj,x) \ { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } /* }================================================================== */ /* ** {================================================================== ** Threads ** =================================================================== */ #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) #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_TTHREAD)); \ 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_TNUMFLT (LUA_TNUMBER | (1 << 4)) /* float numbers */ #define LUA_TNUMINT (LUA_TNUMBER | (2 << 4)) /* integer numbers */ #define ttisnumber(o) checktype((o), LUA_TNUMBER) #define ttisfloat(o) checktag((o), LUA_TNUMFLT) #define ttisinteger(o) checktag((o), LUA_TNUMINT) #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_TNUMFLT); } #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_TNUMINT); } #define chgivalue(obj,x) \ { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } /* }================================================================== */ /* ** {================================================================== ** Strings ** =================================================================== */ /* Variant tags for strings */ #define LUA_TSHRSTR (LUA_TSTRING | (1 << 4)) /* short strings */ #define LUA_TLNGSTR (LUA_TSTRING | (2 << 4)) /* long strings */ #define ttisstring(o) checktype((o), LUA_TSTRING) #define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) #define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) #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 string value; string bytes follow the end of this structure ** (aligned according to 'UTString'; see next). */ 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; } TString; /* ** Ensures that address after this type is always fully aligned. */ typedef union UTString { LUAI_MAXALIGN; /* ensures maximum alignment for strings */ TString tsv; } UTString; /* ** Get the actual string (array of bytes) from a 'TString'. ** (Access to 'extra' ensures that value is really a 'TString'.) */ #define getstr(ts) \ check_exp(sizeof((ts)->extra), cast_charp((ts)) + sizeof(UTString)) /* 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_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) /* get string length from 'TValue *o' */ #define vslen(o) tsslen(tsvalue(o)) /* }================================================================== */ /* ** {================================================================== ** Userdata ** =================================================================== */ #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) #define ttisfulluserdata(o) checktype((o), LUA_TUSERDATA) #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_TLIGHTUSERDATA); } #define setuvalue(L,obj,x) \ { TValue *io = (obj); Udata *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ 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 ** =================================================================== */ /* ** 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) */ } 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 */ lu_byte cachemiss; /* count for successive misses for 'cache' field */ 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 */ struct LClosure *cache; /* last-created closure with this prototype */ 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; /* }================================================================== */ /* ** {================================================================== ** Closures ** =================================================================== */ /* Variant tags for functions */ #define LUA_TLCL (LUA_TFUNCTION | (1 << 4)) /* Lua closure */ #define LUA_TLCF (LUA_TFUNCTION | (2 << 4)) /* light C function */ #define LUA_TCCL (LUA_TFUNCTION | (3 << 4)) /* C closure */ #define ttisfunction(o) checktype(o, LUA_TFUNCTION) #define ttisclosure(o) ((rawtt(o) & 0x1F) == LUA_TLCL) #define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) #define ttislcf(o) checktag((o), LUA_TLCF) #define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) #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_TLCL)); \ 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_TLCF); } #define setclCvalue(L,obj,x) \ { TValue *io = (obj); CClosure *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ checkliveness(L,io); } /* ** Upvalues for Lua closures */ typedef struct UpVal { CommonHeader; 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 ttistable(o) checktag((o), ctb(LUA_TTABLE)) #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_TTABLE)); \ 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_; \ (void)L; 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; \ (void)L; checkliveness(L,io_); } 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_TNUMINT) #define keyival(node) (keyval(node).i) #define keyisshrstr(node) (keytt(node) == ctb(LUA_TSHRSTR)) #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) /* ** Use a "nil table" to mark dead keys in a table. Those keys serve ** to keep space for removed entries, which may still be part of ** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE ** set, so these values are considered not collectable and are different ** from any valid value. */ #define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL) /* }================================================================== */ /* ** '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_int2fb (unsigned int x); LUAI_FUNC int luaO_fb2int (int x); 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 len); #endif