From 1e9d85353b1978028df3275b1a2dc05d6e75582f Mon Sep 17 00:00:00 2001 From: jim Date: Sun, 4 Mar 2018 13:09:23 +0800 Subject: [PATCH] improve lua generator --- .sconsign.dblite | Bin 131996 -> 159216 bytes 3rd/lua/SConscript | 5 + 3rd/lua/bugs | 3946 ++++++++++++++++++++++++++++++++++++++ 3rd/lua/lapi.c | 1341 +++++++++++++ 3rd/lua/lapi.h | 24 + 3rd/lua/lauxlib.c | 1043 ++++++++++ 3rd/lua/lauxlib.h | 271 +++ 3rd/lua/lbaselib.c | 525 +++++ 3rd/lua/lbitlib.c | 233 +++ 3rd/lua/lcode.c | 1641 ++++++++++++++++ 3rd/lua/lcode.h | 94 + 3rd/lua/lcorolib.c | 167 ++ 3rd/lua/lctype.c | 55 + 3rd/lua/lctype.h | 95 + 3rd/lua/ldblib.c | 456 +++++ 3rd/lua/ldebug.c | 798 ++++++++ 3rd/lua/ldebug.h | 43 + 3rd/lua/ldo.c | 801 ++++++++ 3rd/lua/ldo.h | 68 + 3rd/lua/ldump.c | 230 +++ 3rd/lua/lfunc.c | 165 ++ 3rd/lua/lfunc.h | 57 + 3rd/lua/lgc.c | 1558 +++++++++++++++ 3rd/lua/lgc.h | 182 ++ 3rd/lua/linit.c | 68 + 3rd/lua/liolib.c | 780 ++++++++ 3rd/lua/llex.c | 565 ++++++ 3rd/lua/llex.h | 85 + 3rd/lua/llimits.h | 316 +++ 3rd/lua/lmathlib.c | 410 ++++ 3rd/lua/lmem.c | 169 ++ 3rd/lua/lmem.h | 91 + 3rd/lua/loadlib.c | 790 ++++++++ 3rd/lua/lobject.c | 528 +++++ 3rd/lua/lobject.h | 646 +++++++ 3rd/lua/lopcodes.c | 176 ++ 3rd/lua/lopcodes.h | 361 ++++ 3rd/lua/loslib.c | 409 ++++ 3rd/lua/lparser.c | 1733 +++++++++++++++++ 3rd/lua/lparser.h | 143 ++ 3rd/lua/lprefix.h | 45 + 3rd/lua/lstate.c | 370 ++++ 3rd/lua/lstate.h | 265 +++ 3rd/lua/lstring.c | 283 +++ 3rd/lua/lstring.h | 56 + 3rd/lua/lstrlib.c | 1744 +++++++++++++++++ 3rd/lua/ltable.c | 785 ++++++++ 3rd/lua/ltable.h | 56 + 3rd/lua/ltablib.c | 450 +++++ 3rd/lua/ltests.c | 1735 +++++++++++++++++ 3rd/lua/ltests.h | 136 ++ 3rd/lua/ltm.c | 254 +++ 3rd/lua/ltm.h | 85 + 3rd/lua/lua | Bin 0 -> 627136 bytes 3rd/lua/lua.c | 613 ++++++ 3rd/lua/lua.h | 489 +++++ 3rd/lua/luaconf.h | 797 ++++++++ 3rd/lua/lualib.h | 61 + 3rd/lua/lundump.c | 293 +++ 3rd/lua/lundump.h | 32 + 3rd/lua/lutf8lib.c | 256 +++ 3rd/lua/lvm.c | 1717 +++++++++++++++++ 3rd/lua/lvm.h | 122 ++ 3rd/lua/lzio.c | 68 + 3rd/lua/lzio.h | 66 + 3rd/lua/makefile | 198 ++ 3rd/lua/tags | 2911 ++++++++++++++++++++++++++++ SConstruct | 6 +- lua/.gitignore | 1 + lua/button.lua | 2 +- lua/custom.c | 43 +- lua/demo1.lua | 31 + lua/lftk_lua.c | 485 +++-- lua/window.lua | 20 - src/base/events.h | 2 +- tools/idl_gen/gen_lua.js | 853 ++++---- 76 files changed, 35690 insertions(+), 708 deletions(-) create mode 100644 3rd/lua/SConscript create mode 100644 3rd/lua/bugs create mode 100644 3rd/lua/lapi.c create mode 100644 3rd/lua/lapi.h create mode 100644 3rd/lua/lauxlib.c create mode 100644 3rd/lua/lauxlib.h create mode 100644 3rd/lua/lbaselib.c create mode 100644 3rd/lua/lbitlib.c create mode 100644 3rd/lua/lcode.c create mode 100644 3rd/lua/lcode.h create mode 100644 3rd/lua/lcorolib.c create mode 100644 3rd/lua/lctype.c create mode 100644 3rd/lua/lctype.h create mode 100644 3rd/lua/ldblib.c create mode 100644 3rd/lua/ldebug.c create mode 100644 3rd/lua/ldebug.h create mode 100644 3rd/lua/ldo.c create mode 100644 3rd/lua/ldo.h create mode 100644 3rd/lua/ldump.c create mode 100644 3rd/lua/lfunc.c create mode 100644 3rd/lua/lfunc.h create mode 100644 3rd/lua/lgc.c create mode 100644 3rd/lua/lgc.h create mode 100644 3rd/lua/linit.c create mode 100644 3rd/lua/liolib.c create mode 100644 3rd/lua/llex.c create mode 100644 3rd/lua/llex.h create mode 100644 3rd/lua/llimits.h create mode 100644 3rd/lua/lmathlib.c create mode 100644 3rd/lua/lmem.c create mode 100644 3rd/lua/lmem.h create mode 100644 3rd/lua/loadlib.c create mode 100644 3rd/lua/lobject.c create mode 100644 3rd/lua/lobject.h create mode 100644 3rd/lua/lopcodes.c create mode 100644 3rd/lua/lopcodes.h create mode 100644 3rd/lua/loslib.c create mode 100644 3rd/lua/lparser.c create mode 100644 3rd/lua/lparser.h create mode 100644 3rd/lua/lprefix.h create mode 100644 3rd/lua/lstate.c create mode 100644 3rd/lua/lstate.h create mode 100644 3rd/lua/lstring.c create mode 100644 3rd/lua/lstring.h create mode 100644 3rd/lua/lstrlib.c create mode 100644 3rd/lua/ltable.c create mode 100644 3rd/lua/ltable.h create mode 100644 3rd/lua/ltablib.c create mode 100644 3rd/lua/ltests.c create mode 100644 3rd/lua/ltests.h create mode 100644 3rd/lua/ltm.c create mode 100644 3rd/lua/ltm.h create mode 100755 3rd/lua/lua create mode 100644 3rd/lua/lua.c create mode 100644 3rd/lua/lua.h create mode 100644 3rd/lua/luaconf.h create mode 100644 3rd/lua/lualib.h create mode 100644 3rd/lua/lundump.c create mode 100644 3rd/lua/lundump.h create mode 100644 3rd/lua/lutf8lib.c create mode 100644 3rd/lua/lvm.c create mode 100644 3rd/lua/lvm.h create mode 100644 3rd/lua/lzio.c create mode 100644 3rd/lua/lzio.h create mode 100644 3rd/lua/makefile create mode 100644 3rd/lua/tags create mode 100644 lua/.gitignore create mode 100644 lua/demo1.lua delete mode 100644 lua/window.lua diff --git a/.sconsign.dblite b/.sconsign.dblite index cd1c864e13ad170116d7dbd58095dfb30525306e..e9af93493902cdb0b2d19cec8a775a4e5e81ff5c 100644 GIT binary patch delta 59377 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 delta 33070 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 F{~y#qamfGx diff --git a/3rd/lua/SConscript b/3rd/lua/SConscript new file mode 100644 index 000000000..2fa4b53c1 --- /dev/null +++ b/3rd/lua/SConscript @@ -0,0 +1,5 @@ +import os + +env=DefaultEnvironment().Clone() +env.Library('lua', Glob('*.c')) + diff --git a/3rd/lua/bugs b/3rd/lua/bugs new file mode 100644 index 000000000..d796facb3 --- /dev/null +++ b/3rd/lua/bugs @@ -0,0 +1,3946 @@ +--[=[ +** lua.stx / llex.c +Tue Dec 2 10:45:48 EDT 1997 +>> BUG: "lastline" was not reset on function entry, so debug information +>> started only in the 2nd line of a function. + + + +================================================================= +--- Version 3.1 alpha + +** lua.c +Thu Jan 15 14:34:58 EDT 1998 +>> must include "stdlib.h" (for "exit()"). + +** lbuiltin.c / lobject.h +Thu Jan 15 14:34:58 EDT 1998 +>> MAX_WORD may be bigger than MAX_INT +(by lhf) + +** llex.c +Mon Jan 19 18:17:18 EDT 1998 +>> wrong line number (+1) in error report when file starts with "#..." + +** lstrlib.c +Tue Jan 27 15:27:49 EDT 1998 +>> formats like "%020d" were considered too big (3 digits); moreover, +>> some sistems limit printf to at most 500 chars, so we can limit sizes +>> to 2 digits (99). + +** lapi.c +Tue Jan 27 17:12:36 EDT 1998 +>> "lua_getstring" may create a new string, so should check GC + +** lstring.c / ltable.c +Wed Jan 28 14:48:12 EDT 1998 +>> tables can become full of "empty" slots, and keep growing without limits. + +** lstrlib.c +Mon Mar 9 15:26:09 EST 1998 +>> gsub('a', '(b?)%1*' ...) loops (because the capture is empty). + +** lstrlib.c +Mon May 18 19:20:00 EST 1998 +>> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int. + + + +================================================================= +--- Version 3.1 + +** liolib.c / lauxlib.c +Mon Sep 7 15:57:02 EST 1998 +>> function "luaL_argerror" prints wrong argument number (from a user's point +of view) when functions have upvalues. + +** lstrlib.c +Tue Nov 10 17:29:36 EDT 1998 +>> gsub/strfind do not check whether captures are properly finished. +(by roberto/tomas) + +** lbuiltin.c +Fri Dec 18 11:22:55 EDT 1998 +>> "tonumber" goes crazy with negative numbers in other bases (not 10), +because "strtol" returns long, not unsigned long. +(by Visual C++) + +** lstrlib.c +Mon Jan 4 10:41:40 EDT 1999 +>> "format" does not check size of format item (such as "%00000...00000d"). + +** lapi.c +Wed Feb 3 14:40:21 EDT 1999 +>> getlocal cannot return the local itself, since lua_isstring and +lua_isnumber can modify it. + +** lstrlib.c +Thu Feb 4 17:08:50 EDT 1999 +>> format "%s" may break limit of "sprintf" on some machines. +(by Marcelo Sales) + +** lzio.c +Thu Mar 4 11:49:37 EST 1999 +>> file stream cannot call fread after EOF. +(by lhf) + + + +================================================================= +--- Version 3.2 (beta) + +** lstrlib.c +Fri Apr 30 11:10:20 EST 1999 +>> '$' at end of pattern was matching regular '$', too. +(by anna; since 2.5) + +** lbuiltin.c +Fri May 21 17:15:11 EST 1999 +>> foreach, foreachi, foreachvar points to function in stack when stack +can be reallocated. +(by tomas; since 3.2 beta) + +** lparser.c +Wed Jun 16 10:32:46 EST 1999 +>> cannot assign to unlimited variables, because it causes overflow in +the number of returns of a function. +(since 3.1) + + + +================================================================= +--- Version 3.2 + +** lmathlib.c +Wed Aug 18 11:28:38 EST 1999 +>> random(0) and random(x,0) are wrong (0 is read as no argument!). +(by Dave Bollinger; since 3.1) + +** lparser.c +Thu Sep 2 10:07:20 EST 1999 +>> in the (old) expression << ls->fs->f->consts[checkname(ls)] >>, checkname +could realloc f->consts. +(by Supratik Champati; since 3.2 beta) + +** lobject.c / lbuiltin.c +Wed Sep 8 17:41:54 EST 1999 +>> tonumber'e1' and tonumber(' ', x), for x!=10, gave 0 instead of nil. +(since 3.1) + +** lstrlib.c +Thu Nov 11 14:36:30 EDT 1999 +>> `strfind' does not handle \0 in plain search. +(by Jon Kleiser; since 3.1) + +** lparser.c +Wed Dec 29 16:05:43 EDT 1999 +>> return gives wrong line in debug information +(by lhf; since 3.2 [at least]) + +** ldo.c +Thu Dec 30 16:39:33 EDT 1999 +>> cannot reopen stdin (for binary mode) +(by lhf & roberto; since 3.1) + +** lapi.c +Thu Mar 2 09:41:53 EST 2000 +>> lua_settable should check stack space (it could call a T.M.) +(by lhf & celes; since 3.2; it was already fixed by fixed stack) + +** lparser.c +Mon Apr 3 09:59:06 EST 2000 +>> '%' should be in expfollow +(by Edgar Toernig; since 3.1; it was already fixed) + +** lbuiltin.c +Mon Apr 3 10:05:05 EST 2000 +>> tostring() without arguments gives seg. fault. +(by Edgar Toernig; since 3.0) + + + +================================================================= +--- Version 4.0 alpha + +Tested with full test suites (as locked in Mon Apr 24 14:23:11 EST 2000) +in the following platforms: +* Linux - gcc, g++ +* AIX - gcc +* Solaris - gcc, cc +* IRIX - cc, cc-purify +* Windows - Visual C++ (.c e .cpp, warning level=4) + + +** lstrlib.c +Tue May 2 15:27:58 EST 2000 +>> `strfind' gets wrong subject length when there is an offset +(by Jon Kleiser; since 4.0a) + +** lparser.c +Fri May 12 15:11:12 EST 2000 +>> first element in a list constructor is not adjusted to one value +>> (e.g. «a = {gsub('a','a','')}») +(by Tomas; since 4.0a) + +** lparser.c +Wed May 24 14:50:16 EST 2000 +>> record-constructor starting with an upvalue name gets an error +>> (e.g. «local a; function f() x = {a=1} end») +(by Edgar Toernig; since 3.1) + +** lparser.c +Tue Aug 29 15:56:05 EST 2000 +>> error message for `for' uses `while' +(since 4.0a; already corrected) + +** lgc.c +Tue Aug 29 15:57:41 EST 2000 +>> gc tag method for nil could call line hook +(by ry; since ?) + + + +================================================================= +--- Version 4.0 Beta + +** liolib.c +Fri Sep 22 15:12:37 EST 2000 +>> `read("*w")' should return nil at EOF +(by roberto; since 4.0b) + +** lvm.c +Mon Sep 25 11:47:48 EST 2000 +>> lua_gettable does not get key from stack top +(by Philip Yi; since 4.0b) + +** lgc.c +Mon Sep 25 11:50:48 EST 2000 +>> GC may crash when checking locked C closures +(by Philip Yi; since 4.0b) + +** lapi.c +Wed Sep 27 09:50:19 EST 2000 +>> lua_tag should return LUA_NOTAG for non-valid indices +(by Paul Hankin; since 4.0b) + +** llex.h / llex.c / lparser.c +Wed Sep 27 13:39:45 EST 2000 +>> parser overwrites semantic information when looking ahead +>> (e.g. «a = {print'foo'}») +(by Edgar Toernig; since 4.0b, deriving from previous bug) + +** liolib.c +Thu Oct 26 10:50:46 EDT 2000 +>> in function `read_file', realloc() doesn't free the buffer if it can't +>> allocate new memory +(by Mauro Vezzosi; since 4.0b) + + + +================================================================= +--- Version 4.0 + +** lparser.c +Wed Nov 29 09:51:44 EDT 2000 +>> parser does not accept a `;' after a `return' +(by lhf; since 4.0b) + +** liolib.c +Fri Dec 22 15:30:42 EDT 2000 +>> when `read' fails it must return nil (and not no value) +(by cassino; since at least 3.1) + +** lstring.c/lapi.c +Thu Feb 1 11:55:45 EDT 2001 +>> lua_pushuserdata(L, NULL) is buggy +(by Edgar Toernig; since 4.0) + +** ldo.c +Fri Feb 2 14:06:40 EDT 2001 +>> «while 1 dostring[[print('hello\n')]] end» never reclaims memory +(by Andrew Paton; since 4.0b) + +** lbaselib.c +Tue Feb 6 11:57:13 EDT 2001 +>> ESC (which starts precompiled code) in C is \33, not \27 +(by Edgar Toernig and lhf; since 4.0b) + +** lparser.c +Tue Jul 10 16:59:18 EST 2001 +>> error message for `%a' gave wrong line number +(by Leonardo Constantino; since 4.0) + +** lbaselib.c +Fri Dec 21 15:21:05 EDT 2001 +>> seg. fault when rawget/rawset get extra arguments +(by Eric Mauger; since 4.0b) + +** lvm.c +Wed Jun 19 13:28:20 EST 2002 +>> line hook gets wrong `ar' +(by Daniel C. Sinclair; since 4.0.b) + +** ldo.c +Wed Jun 19 13:31:49 EST 2002 +>> `protectedparser' may run GC, and then collect `filename' +>> (in function `parse_file') +(by Alex Bilyk; since 4.0) + + + + +================================================================= +--- Version 5.0 alpha + +** lgc.c +Fri Aug 30 13:49:14 EST 2002 +>> GC metamethod stored in a weak metatable being collected together with +>> userdata may not be cleared properly +(by Roberto; since 5.0a) + +** lapi.c +Thu Nov 21 11:00:00 EST 2002 +>> ULONG_MAX>>10 may not fit into an int +(by Jeff Petkau; since 4.0) + +** lparser.c +Fri Dec 6 17:06:40 UTC 2002 +>> scope of generic for variables is not sound +(by Gavin Wraith; since 5.0a) + + + + +================================================================= +--- Version 5.0 beta +** lbaselib.c +Fri Dec 20 09:53:19 UTC 2002 +>> `resume' was checking the wrong value for stack overflow +(by Maik Zimmermann; since 5.0b) + +** ldo.c +Thu Jan 23 11:29:06 UTC 2003 +>> error during garbage collection in luaD_protectedparser is not being +>> protected +(by Benoit Germain; since 5.0a) + +** ldo.c (and others) +Fri Feb 28 14:20:33 EST 2003 +>> GC metamethod calls could mess C/Lua stack syncronization +(by Roberto; since 5.0b) + +** lzio.h/zlio.c +Thu Mar 20 11:40:12 EST 2003 +>> zio mixes a 255 as first char in a buffer with EOZ +(by lhf; since 5.0a) + + + +--]=] +----------------------------------------------------------------- +-- Lua 5.0 (final) + +Bug{ +what = [[lua_closethread exists only in the manual]], +report = [[by Nguyen Binh, 28/04/2003]], +patch = [[no patch; the manual is wrong]], +} + + +Bug{ +what = [[attempt to resume a running coroutine crashes Lua]], +example = [[ +function co_func (current_co) + coroutine.resume(co) +end +co = coroutine.create(co_func) +coroutine.resume(co) +coroutine.resume(co) --> seg. fault +]], +report = [[by Alex Bilyk, 09/05/2003]], +patch = [[ +* ldo.c: +325,326c325 +< if (nargs >= L->top - L->base) +< luaG_runerror(L, "cannot resume dead coroutine"); +--- +> lua_assert(nargs < L->top - L->base); +329c328,329 +< else if (ci->state & CI_YIELD) { /* inside a yield? */ +--- +> else { /* inside a yield */ +> lua_assert(ci->state & CI_YIELD); +344,345d343 +< else +< luaG_runerror(L, "cannot resume non-suspended coroutine"); +351a350,358 +> static int resume_error (lua_State *L, const char *msg) { +> L->top = L->ci->base; +> setsvalue2s(L->top, luaS_new(L, msg)); +> incr_top(L); +> lua_unlock(L); +> return LUA_ERRRUN; +> } +> +> +355a363,368 +> if (L->ci == L->base_ci) { +> if (nargs >= L->top - L->base) +> return resume_error(L, "cannot resume dead coroutine"); +> } +> else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */ +> return resume_error(L, "cannot resume non-suspended coroutine"); +]], +} + + +Bug{ +what = [[file:close cannot be called without a file. (results in seg fault)]], +example = [[ +> io.stdin.close() -- correct call shold be io.stdin:close() +]], +report = [[by Tuomo Valkonen, 27/05/2003]], +patch = [[ +* liolib.c: +161c161 +< if (lua_isnone(L, 1)) { +--- +> if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) { +]], --}} +} + + +Bug{ +what = [[C functions also may have stacks larger than current top]], +example = [[ +Must recompile lua with a change in lua.c and with lua_assert defined: +* lua.c: +381a382 +> lua_checkstack(l, 1000); +]], +report = [[Alex Bilyk, 09/06/2003]], +patch = [[ +* lgc.c: +247c247 +< if (!(ci->state & CI_C) && lim < ci->top) +--- +> if (lim < ci->top) +]], +} + + +Bug{ +what = [[`pc' address is invalidated when a coroutine is suspended]], +example = [[ +function g(x) + coroutine.yield(x) +end + +function f (i) + debug.sethook(print, "l") + for j=1,1000 do + g(i+j) + end +end + +co = coroutine.wrap(f) +co(10) +pcall(co) +pcall(co) +]], +report = [[Nick Trout, 07/07/2003]], +patch = [[ +* lvm.c: +402,403c402,403 +< L->ci->u.l.pc = &pc; +< if (L->hookmask & LUA_MASKCALL) +--- +> if (L->hookmask & LUA_MASKCALL) { +> L->ci->u.l.pc = &pc; +404a405 +> } +405a407 +> L->ci->u.l.pc = &pc; +676,678c678 +< lua_assert(ci->u.l.pc == &pc && +< ttisfunction(ci->base - 1) && +< (ci->state & CI_SAVEDPC)); +--- +> lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC)); +]] +} + + +Bug{ +what = [[userdata to be collected still counts into new GC threshold, +increasing memory consumption]], +report = [[Roberto, 25/07/2003]], +example = [[ +a = newproxy(true) +getmetatable(a).__gc = function () end +for i=1,10000000 do + newproxy(a) + if math.mod(i, 10000) == 0 then print(gcinfo()) end +end +]], +patch = [[ +* lgc.h: +18c18 +< void luaC_separateudata (lua_State *L); +--- +> size_t luaC_separateudata (lua_State *L); + +* lgc.c: +113c113,114 +< void luaC_separateudata (lua_State *L) { +--- +> size_t luaC_separateudata (lua_State *L) { +> size_t deadmem = 0; +127a129 +> deadmem += sizeudata(gcotou(curr)->uv.len); +136a139 +> return deadmem; +390c393 +< static void checkSizes (lua_State *L) { +--- +> static void checkSizes (lua_State *L, size_t deadmem) { +400c403 +< G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ +--- +> G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */ +454c457,458 +< static void mark (lua_State *L) { +--- +> static size_t mark (lua_State *L) { +> size_t deadmem; +467c471 +< luaC_separateudata(L); /* separate userdata to be preserved */ +--- +> deadmem = luaC_separateudata(L); /* separate userdata to be preserved */ +475a480 +> return deadmem; +480c485 +< mark(L); +--- +> size_t deadmem = mark(L); +482c487 +< checkSizes(L); +--- +> checkSizes(L, deadmem); +]] +} + +Bug{ +what=[[IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate +up to 60 characters in a `printf'. That causes a buffer overflow in +`tostring'.]], + +report = [[David Burgess, 25/08/2003]], + +example = [[print{}; (in an AS400 machine)]], + +patch = [[ +* liolib.c: +178c178 +< char buff[32]; +--- +> char buff[128]; + +* lbaselib.c: +327c327 +< char buff[64]; +--- +> char buff[128]; +]] +} + + +Bug{ +what = [[syntax `local function' does not increment stack size]], + +report = [[Rici Lake, 26/09/2003]], + +example = [[ +-- must run this with precompiled code +local a,b,c +local function d () end +]], + +patch = [[ +* lparser.c: +1143a1144 +> FuncState *fs = ls->fs; +1145c1146,1147 +< init_exp(&v, VLOCAL, ls->fs->freereg++); +--- +> init_exp(&v, VLOCAL, fs->freereg); +> luaK_reserveregs(fs, 1); +1148c1150,1152 +< luaK_storevar(ls->fs, &v, &b); +--- +> luaK_storevar(fs, &v, &b); +> /* debug information will only see the variable after this point! */ +> getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +]], + +} + + +Bug{ + +what = [[count hook may be called without being set]], + +report = [[Andreas Stenius, 06/10/2003]], + +example = [[ +set your hooks with + + lua_sethook(L, my_hook, LUA_MASKLINE | LUA_MASKRET, 1); + +(It is weird to use a count > 0 without setting the count hook, +but it is not wrong.) +]], + +patch = [[ +* lvm.c: +69c69 +< if (mask > LUA_MASKLINE) { /* instruction-hook set? */ +--- +> if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */ +]], + +} + + +Bug{ + +what = [[`dofile' eats one return value when called without arguments]], + +report = [[Frederico Abraham, 15/01/2004]], + +example = [[ +a,b = dofile() --< here you enter `return 1,2,3 ' +print(a,b) --> 2 3 (should be 1 and 2) +]], + +patch = [[ +* lbaselib.c: +313a314 +> int n = lua_gettop(L); +317c318 +< return lua_gettop(L) - 1; +--- +> return lua_gettop(L) - n; +]], + +} + + + +----------------------------------------------------------------- +-- Lua 5.0.2 + +Bug{ +what = [[string concatenation may cause arithmetic overflow, leading +to a buffer overflow]], + +report = [[Rici Lake, 20/05/2004]], + +example = [[ +longs = string.rep("\0", 2^25) +function catter(i) + return assert(loadstring( + string.format("return function(a) return a%s end", + string.rep("..a", i-1))))() +end +rep129 = catter(129) +rep129(longs) +]], + +patch = [[ +* lvm.c: +@@ -321,15 +321,15 @@ + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */ + /* at least two string values; get as many as possible */ +- lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) + +- cast(lu_mem, tsvalue(top-2)->tsv.len); ++ size_t tl = tsvalue(top-1)->tsv.len; + char *buffer; + int i; +- while (n < total && tostring(L, top-n-1)) { /* collect total length */ +- tl += tsvalue(top-n-1)->tsv.len; +- n++; ++ /* collect total length */ ++ for (n = 1; n < total && tostring(L, top-n-1); n++) { ++ size_t l = tsvalue(top-n-1)->tsv.len; ++ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); ++ tl += l; + } +- if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow"); + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ +]] +} + + +Bug{ +what = [[lua_getupvalue and setupvalue do not check for index too small]], + +report = [[Mike Pall, ?/2004]], + +example = [[debug.getupvalue(function() end, 0)]], + +patch = [[ +* lapi.c +941c941 +< if (n > f->c.nupvalues) return NULL; +--- +> if (!(1 <= n && n <= f->c.nupvalues)) return NULL; +947c947 +< if (n > p->sizeupvalues) return NULL; +--- +> if (!(1 <= n && n <= p->sizeupvalues)) return NULL; +]] +} + + +Bug{ +what = [[values holded in open upvalues of suspended threads may be +incorrectly collected]], + +report = [[Spencer Schumann, 31/12/2004]], + +example = [[ +local thread_id = 0 +local threads = {} + +function fn(thread) + thread_id = thread_id + 1 + threads[thread_id] = function() + thread = nil + end + coroutine.yield() +end + +while true do + local thread = coroutine.create(fn) + coroutine.resume(thread, thread) +end +]], + +patch = [[ +* lgc.c: +221,224c221,222 +< if (!u->marked) { +< markobject(st, &u->value); +< u->marked = 1; +< } +--- +> markobject(st, u->v); +> u->marked = 1; +]], +} + + +Bug{ +what = [[rawset/rawget do not ignore extra arguments]], + +report = [[Romulo Bahiense, 11/03/2005]], + +example = [[ +a = {} +rawset(a, 1, 2, 3) +print(a[1], a[2]) -- should be 2 and nil +]], + +patch = [[ +* lbaselib.c: +175a176 +> lua_settop(L, 2); +183a185 +> lua_settop(L, 3); +]], +} + + +Bug{ +what = [[weak tables that survive one collection are never collected]], + +report = [[Chromix, 02/01/2006]], + +example = [[ +a = {} +print(gcinfo()) +for i = 1, 10000 do + a[i] = setmetatable({}, {__mode = "v"}) +end +collectgarbage() +a = nil +collectgarbage() +print(gcinfo()) +]], + +patch = [[ +* lgc.c +@@ -366,7 +366,7 @@ + GCObject *curr; + int count = 0; /* number of collected items */ + while ((curr = *p) != NULL) { +- if (curr->gch.marked > limit) { ++ if ((curr->gch.marked & ~(KEYWEAK | VALUEWEAK)) > limit) { + unmark(curr); + p = &curr->gch.next; + } +]], + +} + + +Bug{ +what = [[Some "not not exp" may not result in boolean values]], +report = [[]], +since = [[4.0]], +example = [[ +-- should print false, but prints nil +print(not not (nil and 4)) +]], +patch = [[]], +} + + +Bug{ +what = [[On some machines, closing a "piped file" (created with io.popen) +may crash Lua]], +report = [[]], +since = [[5.0]], +example = [[ +-- only on some machines + f = io.popen("ls") + f:close() +]], +patch = [[]], +} + + + +----------------------------------------------------------------- +-- Lua 5.1 + +Bug{ +what = [[In 16-bit machines, expressions and/or with numeric constants as the +right operand may result in weird values]], + +report = [[Andreas Stenius/Kein-Hong Man, 15/03/2006]], + +example = [[ +print(false or 0) -- on 16-bit machines +]], + +patch = [[ +* lcode.c: +@@ -731,17 +731,15 @@ + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); +- luaK_concat(fs, &e1->f, e2->f); +- e1->k = e2->k; e1->u.s.info = e2->u.s.info; +- e1->u.s.aux = e2->u.s.aux; e1->t = e2->t; ++ luaK_concat(fs, &e2->f, e1->f); ++ *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); +- luaK_concat(fs, &e1->t, e2->t); +- e1->k = e2->k; e1->u.s.info = e2->u.s.info; +- e1->u.s.aux = e2->u.s.aux; e1->f = e2->f; ++ luaK_concat(fs, &e2->t, e1->t); ++ *e1 = *e2; + break; + } +]], + +} + + +Bug{ +what = [[luaL_checkudata may produce wrong error message]], + +report = [[Greg Falcon, 21/03/2006]], + +example = [[ +getmetatable(io.stdin).__gc() + --> bad argument #1 to '__gc' (FILE* expected, got table) +]], + +patch = [[ +* lauxlib.c: +@@ -123,11 +123,17 @@ + + LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); +- lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ +- if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2)) +- luaL_typerror(L, ud, tname); +- lua_pop(L, 2); /* remove both metatables */ +- return p; ++ if (p != NULL) { /* value is a userdata? */ ++ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ ++ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ ++ lua_pop(L, 2); /* remove both metatables */ ++ return p; ++ } ++ } ++ } ++ luaL_typerror(L, ud, tname); /* else error */ ++ return NULL; /* to avoid warnings */ + } +]] + +} + + +Bug{ +what = [[ +In Windows, +when Lua is used in an application that also uses DirectX, +it may present an erractic behavior. +THIS IS NOT A LUA BUG! +The problem is that DirectX violates an ABI that Lua depends on.]], + +patch = [[ +The simplest solution is to use DirectX with +the D3DCREATE_FPU_PRESERVE flag. + +Otherwise, you can change the definition of lua_number2int, +in luaconf.h, to this one: +#define lua_number2int(i,d) __asm fld d __asm fistp i +]], + +} + + +Bug{ +what = [[option '%q' in string.format does not handle '\r' correctly.]], + +example = [[ +local s = "a string with \r and \n and \r\n and \n\r" +local c = string.format("return %q", s) +assert(assert(loadstring(c))() == s) +]], + +patch = [[ +* lstrlib.c: +@@ -703,6 +703,10 @@ + luaL_addchar(b, *s); + break; + } ++ case '\r': { ++ luaL_addlstring(b, "\\r", 2); ++ break; ++ } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; +]], + +} + + +Bug{ +what = [[lua_dostring/lua_dofile should return any values returned +by the chunk]], + +patch = [[ +* lauxlib.h: +@@ -108,9 +108,11 @@ + + #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +-#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0)) ++#define luaL_dofile(L, fn) \ ++ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +-#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, 0, 0))+#define luaL_dostring(L, s) \ ++ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + + #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) +]], + +} + + +Bug{ + +what = [[garbage collector does not compensate enough for finalizers]], + +patch = [[ +lgc.c: +@@ -322,4 +322,6 @@ + +-static void propagateall (global_State *g) { +- while (g->gray) propagatemark(g); ++static size_t propagateall (global_State *g) { ++ size_t m = 0; ++ while (g->gray) m += propagatemark(g); ++ return m; + } +@@ -542,3 +544,3 @@ + marktmu(g); /* mark `preserved' userdata */ +- propagateall(g); /* remark, to propagate `preserveness' */ ++ udsize += propagateall(g); /* remark, to propagate `preserveness' */ + cleartable(g->weak); /* remove collected objects from weak tables */ +@@ -592,2 +594,4 @@ + GCTM(L); ++ if (g->estimate > GCFINALIZECOST) ++ g->estimate -= GCFINALIZECOST; +]] +} + + +Bug{ + +what = [[debug hooks may get wrong when mixed with coroutines]], + +report = [[by Ivko Stanilov, 03/06/2006]], + +example = [[ +co = coroutine.create(function (a,b) + coroutine.yield(a, b) + return b, "end" +end) + +debug.sethook(co, function() end, "lcr") +coroutine.resume(co, 100, 2000) +coroutine.resume(co, 100, 2000) +]], + +patch = [[ +* ldo.c: +@@ -389,6 +389,7 @@ + return; + } + else { /* resuming from previous yield */ ++ L->status = 0; + if (!f_isLua(ci)) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || +@@ -399,7 +400,6 @@ + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; + } +- L->status = 0; + luaV_execute(L, cast_int(L->ci - L->base_ci)); + } +]], + +} + + + +----------------------------------------------------------------- +-- Lua 5.1.1 + +Bug{ +what = [[list constructors have wrong limit]], + +report = [[by Norman Ramsey, June 2006]], + +since = "5.1", + +example = [[ +a = {} +a[1] = "x={1" +for i = 2, 2^20 do + a[i] = 1 +end +a[#a + 1] = "}" +s = table.concat(a, ",") +assert(loadstring(s))() +print(#x) +]], + +patch = [[ +* lparser.c: +@@ -489,7 +489,7 @@ + + static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); +- luaY_checklimit(ls->fs, cc->na, MAXARG_Bx, "items in a constructor"); ++ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; + } +]], + +} + + +Bug{ +what = [[wrong message error in some cases involving closures]], + +report = [[Shmuel Zeigerman, on 07/2006]], + +since = "5.1", + +example = [[ +local Var +local function main() + NoSuchName (function() Var=0 end) +end +main() +--> lua5.1: temp:3: attempt to call upvalue 'Var' (a nil value) +]], + +patch = [[ +*ldebug.c: +@@ -435,14 +435,16 @@ + break; + } + case OP_CLOSURE: { +- int nup; ++ int nup, j; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); +- for (; nup>0; nup--) { +- OpCode op1 = GET_OPCODE(pt->code[pc+nup]); ++ for (j = 1; j <= nup; j++) { ++ OpCode op1 = GET_OPCODE(pt->code[pc + j]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } ++ if (reg != NO_REG) /* tracing? */ ++ pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case OP_VARARG: { +]], + +} + + +Bug{ +what = [[string.format("%") may read past the string]], +report = [[Roberto, on 09/2006]], +since = [[5.0]], +example = [[print(string.format("%"))]], +patch = [[ +*lstrlib.c: +@@ -723,7 +723,7 @@ + + static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt; +- while (strchr(FLAGS, *p)) p++; /* skip flags */ ++ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ +]], +} + + +Bug{ +what = [[os.date throws an error when result is the empty string]], +report = [[]], +since = [[4.0]], +example = [[print(os.date(""))]], +patch = [[ +*loslib.c: +@@ -148,7 +148,18 @@ + else { +- char b[256]; +- if (strftime(b, sizeof(b), s, stm)) +- lua_pushstring(L, b); +- else +- return luaL_error(L, LUA_QL("date") " format too long"); ++ char cc[3]; ++ luaL_Buffer b; ++ cc[0] = '%'; cc[2] = '\0'; ++ luaL_buffinit(L, &b); ++ for (; *s; s++) { ++ if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ ++ luaL_addchar(&b, *s); ++ else { ++ size_t reslen; ++ char buff[200]; /* should be big enough for any conversion result */ ++ cc[1] = *(++s); ++ reslen = strftime(buff, sizeof(buff), cc, stm); ++ luaL_addlstring(&b, buff, reslen); ++ } ++ } ++ luaL_pushresult(&b); + } +]], +} + + +Bug{ +what = [[setfenv accepts invalid 1st argument]], +report = [[Doug Rogers, on 02/2007]], +since = [[5.0]], +example = [[setfenv(nil, {}) -- should throw an error]], +patch = [[ +*lbaselib.c: +@@ -116,3 +116,3 @@ + +-static void getfunc (lua_State *L) { ++static void getfunc (lua_State *L, int opt) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); +@@ -120,3 +120,3 @@ + lua_Debug ar; +- int level = luaL_optint(L, 1, 1); ++ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); +@@ -133,3 +133,3 @@ + static int luaB_getfenv (lua_State *L) { +- getfunc(L); ++ getfunc(L, 1); + if (lua_iscfunction(L, -1)) /* is a C function? */ +@@ -144,3 +144,3 @@ + luaL_checktype(L, 2, LUA_TTABLE); +- getfunc(L); ++ getfunc(L, 0); + lua_pushvalue(L, 2); +]], +} + + +Bug{ +what = [[wrong code for arithmetic expressions in some specific scenarios]], +report = [[Thierry Grellier, on 01/2007]], +since = [[5.1]], +example = [[ +-- use a large number of names (almost 256) +v1=1; v2=1; v3=1; v4=1; v5=1; v6=1; v7=1; v8=1; v9=1; +v10=1; v11=1; v12=1; v13=1; v14=1; v15=1; v16=1; v17=1; +v18=1; v19=1; v20=1; v21=1; v22=1; v23=1; v24=1; v25=1; +v26=1; v27=1; v28=1; v29=1; v30=1; v31=1; v32=1; v33=1; +v34=1; v35=1; v36=1; v37=1; v38=1; v39=1; v40=1; v41=1; +v42=1; v43=1; v44=1; v45=1; v46=1; v47=1; v48=1; v49=1; +v50=1; v51=1; v52=1; v53=1; v54=1; v55=1; v56=1; v57=1; +v58=1; v59=1; v60=1; v61=1; v62=1; v63=1; v64=1; v65=1; +v66=1; v67=1; v68=1; v69=1; v70=1; v71=1; v72=1; v73=1; +v74=1; v75=1; v76=1; v77=1; v78=1; v79=1; v80=1; v81=1; +v82=1; v83=1; v84=1; v85=1; v86=1; v87=1; v88=1; v89=1; +v90=1; v91=1; v92=1; v93=1; v94=1; v95=1; v96=1; v97=1; +v98=1; v99=1; v100=1; v101=1; v102=1; v103=1; v104=1; v105=1; +v106=1; v107=1; v108=1; v109=1; v110=1; v111=1; v112=1; v113=1; +v114=1; v115=1; v116=1; v117=1; v118=1; v119=1; v120=1; v121=1; +v122=1; v123=1; v124=1; v125=1; v126=1; v127=1; v128=1; v129=1; +v130=1; v131=1; v132=1; v133=1; v134=1; v135=1; v136=1; v137=1; +v138=1; v139=1; v140=1; v141=1; v142=1; v143=1; v144=1; v145=1; +v146=1; v147=1; v148=1; v149=1; v150=1; v151=1; v152=1; v153=1; +v154=1; v155=1; v156=1; v157=1; v158=1; v159=1; v160=1; v161=1; +v162=1; v163=1; v164=1; v165=1; v166=1; v167=1; v168=1; v169=1; +v170=1; v171=1; v172=1; v173=1; v174=1; v175=1; v176=1; v177=1; +v178=1; v179=1; v180=1; v181=1; v182=1; v183=1; v184=1; v185=1; +v186=1; v187=1; v188=1; v189=1; v190=1; v191=1; v192=1; v193=1; +v194=1; v195=1; v196=1; v197=1; v198=1; v199=1; v200=1; v201=1; +v202=1; v203=1; v204=1; v205=1; v206=1; v207=1; v208=1; v209=1; +v210=1; v211=1; v212=1; v213=1; v214=1; v215=1; v216=1; v217=1; +v218=1; v219=1; v220=1; v221=1; v222=1; v223=1; v224=1; v225=1; +v226=1; v227=1; v228=1; v229=1; v230=1; v231=1; v232=1; v233=1; +v234=1; v235=1; v236=1; v237=1; v238=1; v239=1; v240=1; v241=1; +v242=1; v243=1; v244=1; v245=1; v246=1; v247=1; v248=1; v249=1; +v250=1; +v251={k1 = 1}; +v252=1; +print(2 * v251.k1, v251.k1 * 2); -- 2 2, OK +v253=1; +print(2 * v251.k1, v251.k1 * 2); -- 1 2, ??? +]], +patch = [[ +*lcode.c: +@@ -657,10 +657,16 @@ + if (constfolding(op, e1, e2)) + return; + else { +- int o1 = luaK_exp2RK(fs, e1); + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; +- freeexp(fs, e2); +- freeexp(fs, e1); ++ int o1 = luaK_exp2RK(fs, e1); ++ if (o1 > o2) { ++ freeexp(fs, e1); ++ freeexp(fs, e2); ++ } ++ else { ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ } + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + } +@@ -718,10 +724,15 @@ + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } +- default: { ++ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: ++ case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } ++ default: { ++ luaK_exp2RK(fs, v); ++ break; ++ } + } + } +]], +} + +Bug{ +what = [[assignment of nil to parameter may be optimized away]], +report = [[Thomas Lauer, on 03/2007]], +since = [[5.1]], +example = [[ +function f (a) + a=nil + return a +end + +print(f("test")) +]], +patch = [[ +*lcode.c: +@@ -35,16 +35,20 @@ + void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ +- if (fs->pc == 0) /* function start? */ +- return; /* positions are already clean */ +- previous = &fs->f->code[fs->pc-1]; +- if (GET_OPCODE(*previous) == OP_LOADNIL) { +- int pfrom = GETARG_A(*previous); +- int pto = GETARG_B(*previous); +- if (pfrom <= from && from <= pto+1) { /* can connect both? */ +- if (from+n-1 > pto) +- SETARG_B(*previous, from+n-1); +- return; ++ if (fs->pc == 0) { /* function start? */ ++ if (from >= fs->nactvar) ++ return; /* positions are already clean */ ++ } ++ else { ++ previous = &fs->f->code[fs->pc-1]; ++ if (GET_OPCODE(*previous) == OP_LOADNIL) { ++ int pfrom = GETARG_A(*previous); ++ int pto = GETARG_B(*previous); ++ if (pfrom <= from && from <= pto+1) { /* can connect both? */ ++ if (from+n-1 > pto) ++ SETARG_B(*previous, from+n-1); ++ return; ++ } + } + } + } +]], +} + + +Bug{ +what = [[__concat metamethod converts numbers to strings]], +report = [[Paul Winwood, on 12/2006]], +since = [[5.0]], +example = [[ +a = {} +setmetatable(a, {__concat = function (a,b) print(type(a), type(b)) end}) +a = 4 .. a +]], +patch = [[ +*lvm.c: +@@ -281,10 +281,12 @@ + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ +- if (!tostring(L, top-2) || !tostring(L, top-1)) { ++ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); +- } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ ++ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ ++ (void)tostring(L, top - 2); /* result is first op (as string) */ ++ else { + /* at least two string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; +]], +} + + +Bug{ +what = [[As a library, loadlib.c should not access Lua internals +(via lobject.h)]], +report = [[Jérôme Vuarand, on 03/2007]], +since = [[5.0]], +example = [[the bug has no effect on external behavior]], +patch = [[remove the '#include "lobject.h" and use +'lua_pushfstring' instead of 'luaO_pushfstring']], +} + + + +----------------------------------------------------------------- +-- Lua 5.1.2 + +Bug{ +what = [[Lua may close standard files, +which then may be used by C]], +report = [[David Manura/Ross Berteig, on 04/2007]], +since = [[]], +example = [[ +io.close(io.stderr) +-- in some systems, following attempts to write to 'stderr' may crash +a = a + 1 +]], +patch = [[ +]], +} + +Bug{ +what = [[code generated for "-nil", "-true", and "-false" is wrong]], +report = [[David Manura/Rici Lake, on 04/2007]], +since = [[5.1]], +example = [[print(-nil)]], +patch = [[ +lcode.c: +@@ -699,7 +699,7 @@ + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { +- if (e->k == VK) ++ if (!isnumeral(e)) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_UNM, e, &e2); + break; +]], +} + +Bug{ +what = [[Count hook may be called without being set.]], +report = [[Mike Pall, on 05/2007]], +since = [[?]], +example = [[]], +patch = [[ +lvm.c: +@@ -61,11 +61,9 @@ + lu_byte mask = L->hookmask; + const Instruction *oldpc = L->savedpc; + L->savedpc = pc; +- if (mask > LUA_MASKLINE) { /* instruction-hook set? */ +- if (L->hookcount == 0) { +- resethookcount(L); +- luaD_callhook(L, LUA_HOOKCOUNT, -1); +- } ++ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { ++ resethookcount(L); ++ luaD_callhook(L, LUA_HOOKCOUNT, -1); + } + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(L->ci)->l.p; +]], +} + +Bug{ +what = [[recursive coroutines may overflow C stack]], +report = [[ , on ]], +since = [[5.0]], +example = [[ +a = function(a) coroutine.wrap(a)(a) end +a(a) +]], +patch = [[The 'nCcalls' counter should be shared by all threads. +(That is, it should be declared in the 'global_State' structure, +not in 'lua_State'.) +]], +} + +Bug{ +what = [[wrong error message in some concatenations]], +report = [[Alex Davies, on 05/2007]], +since = [[5.1.2]], +example = [[a = nil; a = (1)..a]], +patch = [[ +ldebug.c: +@@ -563,8 +563,8 @@ + + + void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { +- if (ttisstring(p1)) p1 = p2; +- lua_assert(!ttisstring(p1)); ++ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; ++ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); + } + +]], +} + +Bug{ +what = [[Very small numbers all collide in the hash function. +(This creates only performance problems; the behavoir is correct.)]], +report = [[, on ]], +since = [[5.0]], +example = [[]], +patch = [[ +ltable.c: +87,88c87,88 +< n += 1; /* normalize number (avoid -0) */ +< lua_assert(sizeof(a) <= sizeof(n)); +--- +> if (luai_numeq(n, 0)) /* avoid problems with -0 */ +> return gnode(t, 0); +]], +} + +Bug{ +what = [[Too many variables in an assignment may cause a +C stack overflow]], +report = [[Mike Pall, on 07/2007]], +since = [[5.0]], +example = [[ +$ ulimit -s 1024 # Reduce C stack to 1MB for quicker results +$ lua -e 'local s = "a,"; for i=1,18 do s = s..s end print(loadstring("local a;"..s.."a=nil", ""))' +]], +patch = [[ +lparser.c: +@@ -938,6 +938,8 @@ + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); ++ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, ++ "variable names"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ +]], +} + +Bug{ +what = [[An error in a module loaded through the '-l' option +shows no traceback]], +report = [[David Manura, on 08/2007]], +since = [[5.1]], +example = [[lua -ltemp (assuming temp.lua has an error)]], +patch = [[ +lua.c: +@@ -144,7 +144,7 @@ + static int dolibrary (lua_State *L, const char *name) { + lua_getglobal(L, "require"); + lua_pushstring(L, name); +- return report(L, lua_pcall(L, 1, 0, 0)); ++ return report(L, docall(L, 1, 1)); + } +]], +} + +Bug{ +what = [['gsub' may go wild when wrongly called without its third +argument and with a large subject]], +report = [[Florian Berger, on 10/2007]], +since = [[5.1]], +example = [[ +x = string.rep('a', 10000) .. string.rep('b', 10000) +print(#string.gsub(x, 'b')) +]], +patch = [[ +lstrlib.c: +@@ -631,6 +631,2 @@ + } +- default: { +- luaL_argerror(L, 3, "string/function/table expected"); +- return; +- } + } +@@ -650,2 +646,3 @@ + const char *p = luaL_checkstring(L, 2); ++ int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); +@@ -655,2 +652,5 @@ + luaL_Buffer b; ++ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || ++ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, ++ "string/function/table expected"); + luaL_buffinit(L, &b); +]], +} + +Bug{ +what = [[table.remove removes last element of a table when given +an out-of-bound index]], +report = [[Patrick Donnelly, on 11/2007]], +since = [[5.0]], +example = [[ +a = {1,2,3} +table.remove(a, 4) +print(a[3]) --> nil (should be 3) +]], +patch = [[ +ltablib.c: +@@ -118,7 +118,8 @@ + static int tremove (lua_State *L) { + int e = aux_getn(L, 1); + int pos = luaL_optint(L, 2, e); +- if (e == 0) return 0; /* table is `empty' */ ++ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ ++ return 0; /* nothing to remove */ + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos debug.setfenv(3, {}) +]], +patch = [[ +lapi.c: +@@ -749,7 +749,7 @@ + res = 0; + break; + } +- luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); ++ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + L->top--; + lua_unlock(L); + return res; +]], +} + +Bug{ +what = [[stand-alone interpreter shows incorrect error message +when the "message" is a coroutine]], +report = [[Patrick Donnelly, on 17/12/2007]], +since = [[5.1]], +example = [[> error(coroutine.create(function() end))]], +patch = [[ +lua.c: +@@ -74,6 +74,8 @@ + + + static int traceback (lua_State *L) { ++ if (!lua_isstring(L, 1)) /* 'message' not a string? */ ++ return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + +]], +} + +Bug{ +what = [[debug.sethook/gethook may overflow the thread's stack]], +report = [[Ivko Stanilov, on 2008/01/04]], +since = [[5.1]], +example = [[ +a = coroutine.create(function() yield() end) +coroutine.resume(a) +debug.sethook(a) -- may overflow the stack of 'a' +]], +patch = [[ +ldblib.c: +@@ -268,12 +268,11 @@ + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } +- gethooktable(L1); +- lua_pushlightuserdata(L1, L1); ++ gethooktable(L); ++ lua_pushlightuserdata(L, L1); + lua_pushvalue(L, arg+1); +- lua_xmove(L, L1, 1); +- lua_rawset(L1, -3); /* set new hook */ +- lua_pop(L1, 1); /* remove hook table */ ++ lua_rawset(L, -3); /* set new hook */ ++ lua_pop(L, 1); /* remove hook table */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; + } +@@ -288,11 +287,10 @@ + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { +- gethooktable(L1); +- lua_pushlightuserdata(L1, L1); +- lua_rawget(L1, -2); /* get hook */ +- lua_remove(L1, -2); /* remove hook table */ +- lua_xmove(L1, L, 1); ++ gethooktable(L); ++ lua_pushlightuserdata(L, L1); ++ lua_rawget(L, -2); /* get hook */ ++ lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); +]] +} + + + +----------------------------------------------------------------- +-- Lua 5.1.3 + +Bug{ +what = [[LUAI_MAXCSTACK must be smaller than -LUA_REGISTRYINDEX]], +report = [[Patrick Donnelly, on 2008/02/11]], +since = [[5.1.3]], +example = [[ +j = 1e4 +co = coroutine.create(function() + t = {} + for i = 1, j do t[i] = i end + return unpack(t) +end) +print(coroutine.resume(co)) +]], +patch = [[ +luaconf.h: +443c443,444 +< ** functions to consume unlimited stack space. +--- +> ** functions to consume unlimited stack space. (must be smaller than +> ** -LUA_REGISTRYINDEX) +445,446c446 +< #define LUAI_MCS_AUX ((int)(INT_MAX / (4*sizeof(LUA_NUMBER)))) +< #define LUAI_MAXCSTACK (LUAI_MCS_AUX > SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX) +--- +> #define LUAI_MAXCSTACK 8000 +]], +} + +Bug{ +what = [[coroutine.resume pushes element without ensuring stack size]], +report = [[on 2008/02/11]], +since = [[5.0]], +example = [[(this bug cannot be detected without internal assertions)]], +patch = [[ +lbaselib.c: +@@ -526,7 +526,7 @@ + status = lua_resume(co, narg); + if (status == 0 || status == LUA_YIELD) { + int nres = lua_gettop(co); +- if (!lua_checkstack(L, nres)) ++ if (!lua_checkstack(L, nres + 1)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; +]], +} + +Bug{ +what = [[lua_checkstack may have arithmetic overflow for large 'size']], +report = [[Patrick Donnelly, on 2008/02/12]], +since = [[5.0]], +example = [[ +print(unpack({1,2,3}, 0, 2^31-3)) +]], +patch = [[ +--- lapi.c 2008/01/03 15:20:39 2.55.1.3 ++++ lapi.c 2008/02/14 16:05:21 +@@ -93,15 +93,14 @@ + + + LUA_API int lua_checkstack (lua_State *L, int size) { +- int res; ++ int res = 1; + lua_lock(L); +- if ((L->top - L->base + size) > LUAI_MAXCSTACK) ++ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) + res = 0; /* stack overflow */ +- else { ++ else if (size > 0) { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; +- res = 1; + } + lua_unlock(L); + return res; +]], +} + +Bug{ +what = [[unpack with maximum indices may crash due to arithmetic overflow]], +report = [[Patrick Donnelly, on 2008/02/12]], +since = [[5.1]], +example = [[ +print(unpack({1,2,3}, 2^31-1, 2^31-1)) +]], +patch = [[ +--- lbaselib.c 2008/02/11 16:24:24 1.191.1.5 ++++ lbaselib.c 2008/02/14 16:10:25 +@@ -344,10 +344,12 @@ + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); ++ if (i > e) return 0; /* empty range */ + n = e - i + 1; /* number of elements */ +- if (n <= 0) return 0; /* empty range */ +- luaL_checkstack(L, n, "table too big to unpack"); +- for (; i<=e; i++) /* push arg[i...e] */ ++ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ ++ return luaL_error(L, "too many results to unpack"); ++ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ ++ while (i++ < e) /* push arg[i + 1...e] */ + lua_rawgeti(L, 1, i); + return n; + } +]], +} + +Bug{ +what = [[The validator for precompiled code has several flaws that +allow malicious binary code to crash the application]], +report = [[Peter Cawley, on 2008/03/24]], +since = [[5.0]], +example = [[ +a = string.dump(function()return;end) +a = a:gsub(string.char(30,37,122,128), string.char(34,0,0), 1) +loadstring(a)() +]], +patch = [[ +--- ldebug.c 2007/12/28 15:32:23 2.29.1.3 ++++ ldebug.c 2008/04/04 15:15:40 +@@ -275,12 +275,12 @@ + + static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); +- lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); +- lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) || ++ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); ++ check(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); +- check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); ++ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; + } + +@@ -363,7 +363,11 @@ + } + switch (op) { + case OP_LOADBOOL: { +- check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ ++ if (c == 1) { /* does it jump? */ ++ check(pc+2 < pt->sizecode); /* check its jump */ ++ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || ++ GETARG_C(pt->code[pc+1]) != 0); ++ } + break; + } + case OP_LOADNIL: { +@@ -428,7 +432,10 @@ + } + case OP_SETLIST: { + if (b > 0) checkreg(pt, a + b); +- if (c == 0) pc++; ++ if (c == 0) { ++ pc++; ++ check(pc < pt->sizecode - 1); ++ } + break; + } + case OP_CLOSURE: { +]], +} + +Bug{ +what = [[maliciously crafted precompiled code can blow the C stack]], +report = [[Greg Falcon, on 2008/03/25]], +since = [[5.0]], +example = [[ +function crash(depth) + local init = '\27\76\117\97\81\0\1\4\4\4\8\0\7\0\0\0\61\115\116' .. + '\100\105\110\0\1\0\0\0\1\0\0\0\0\0\0\2\2\0\0\0\36' .. + '\0\0\0\30\0\128\0\0\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0' .. + '\1\0\0\0\0\0\0\2' + local mid = '\1\0\0\0\30\0\128\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0' + local fin = '\0\0\0\0\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0' .. + '\0\0\97\0\1\0\0\0\1\0\0\0\0\0\0\0' + local lch = '\2\0\0\0\36\0\0\0\30\0\128\0\0\0\0\0\1\0\0\0\0\0\0' .. + '\0\1\0\0\0\1\0\0\0\0\0\0\2' + local rch = '\0\0\0\0\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0' .. + '\0\0\97\0\1\0\0\0\1' + for i=1,depth do lch,rch = lch..lch,rch..rch end + loadstring(init .. lch .. mid .. rch .. fin) +end +for i=1,25 do print(i); crash(i) end +]], +patch = [[ +--- lundump.c 2008/04/04 16:00:45 2.7.1.3 ++++ lundump.c 2008/04/04 19:51:41 2.7.1.4 +@@ -161,7 +161,9 @@ + + static Proto* LoadFunction(LoadState* S, TString* p) + { +- Proto* f=luaF_newproto(S->L); ++ Proto* f; ++ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); ++ f=luaF_newproto(S->L); + setptvalue2s(S->L,S->L->top,f); incr_top(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->linedefined=LoadInt(S); +@@ -175,6 +177,7 @@ + LoadDebug(S,f); + IF (!luaG_checkcode(f), "bad code"); + S->L->top--; ++ S->L->nCcalls--; + return f; + } +]], +} + +Bug{ +what = [[code validator may reject (maliciously crafted) correct code]], +report = [[Greg Falcon, on 2008/03/26]], +since = [[5.0]], +example = [[ +z={} +for i=1,27290 do z[i]='1,' end +z = 'if 1+1==2 then local a={' .. table.concat(z) .. '} end' +func = loadstring(z) +print(loadstring(string.dump(func))) +]], +patch = [[ +--- ldebug.c 2008/04/04 15:30:05 2.29.1.4 ++++ ldebug.c 2008/04/04 15:47:10 +@@ -346,9 +346,18 @@ + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + if (dest > 0) { +- /* cannot jump to a setlist count */ +- Instruction d = pt->code[dest-1]; +- check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)); ++ int j; ++ /* check that it does not jump to a setlist count; this ++ is tricky, because the count from a previous setlist may ++ have the same value of an invalid setlist; so, we must ++ go all the way back to the first of them (if any) */ ++ for (j = 0; j < dest; j++) { ++ Instruction d = pt->code[dest-1-j]; ++ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; ++ } ++ /* if 'j' is even, previous value is not a setlist (even if ++ it looks like one) */ ++ check((j&1) == 0); + } + } + break; +]], +} + +Bug{ +what = [[maliciously crafted precompiled code can inject invalid boolean +values into Lua code]], +report = [[Greg Falcon, on 2008/03/27]], +since = [[5.0]], +example = [[ +maybe = string.dump(function() return ({[true]=true})[true] end) +maybe = maybe:gsub('\1\1','\1\2') +maybe = loadstring(maybe)() +assert(type(maybe) == "boolean" and maybe ~= true and maybe ~= false) +]], +patch = [[ +--- lundump.c 2008/01/18 16:39:11 2.7.1.2 ++++ lundump.c 2008/04/04 15:50:39 +@@ -115,7 +115,7 @@ + setnilvalue(o); + break; + case LUA_TBOOLEAN: +- setbvalue(o,LoadChar(S)); ++ setbvalue(o,LoadChar(S)!=0); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); +]], +} + + +Bug{ +what = [['string.byte' gets confused with some out-of-range negative indices]], +report = [[Mike Pall, on 2008/06/03]], +since = [[5.1]], +example = [[ +print(string.byte("abc", -5)) --> 97 98 99 (should print nothing) +]], +patch = [[ +--- lstrlib.c 2007/12/28 15:32:23 1.132.1.3 ++++ lstrlib.c 2008/07/05 11:53:42 +@@ -35,7 +35,8 @@ + + static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ +- return (pos>=0) ? pos : (ptrdiff_t)len+pos+1; ++ if (pos < 0) pos += (ptrdiff_t)len + 1; ++ return (pos >= 0) ? pos : 0; + } + + +]], +} + + +Bug{ +what = [[user-requested GC step may loop forever]], +report = [[Makoto Hamanaka, on 2008/07/01]], +since = [[5.1]], +example = [[ +collectgarbage("setpause", 100) -- small value +collectgarbage("setstepmul", 2000) -- large value +collectgarbage("step",0) +]], +patch = [[ +--- lapi.c 2008/02/14 16:46:39 2.55.1.4 ++++ lapi.c 2008/07/04 18:34:48 +@@ -929,10 +929,13 @@ + g->GCthreshold = g->totalbytes - a; + else + g->GCthreshold = 0; +- while (g->GCthreshold <= g->totalbytes) ++ while (g->GCthreshold <= g->totalbytes) { + luaC_step(L); +- if (g->gcstate == GCSpause) /* end of cycle? */ +- res = 1; /* signal it */ ++ if (g->gcstate == GCSpause) { /* end of cycle? */ ++ res = 1; /* signal it */ ++ break; ++ } ++ } + break; + } + case LUA_GCSETPAUSE: { +]], +} + + +Bug{ +what = [['module' may change the environment of a C function]], +report = [[Peter Cawley, on 2008/07/16]], +since = [[5.1]], +example = [[ +pcall(module, "xuxu") +assert(debug.getfenv(pcall) == xuxu) +]], +patch = [[ +--- loadlib.c 2007/12/28 14:58:43 1.52.1.2 ++++ loadlib.c 2008/08/05 19:39:00 +@@ -506,8 +506,11 @@ + + static void setfenv (lua_State *L) { + lua_Debug ar; +- lua_getstack(L, 1, &ar); +- lua_getinfo(L, "f", &ar); ++ if (lua_getstack(L, 1, &ar) == 0 || ++ lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ ++ lua_iscfunction(L, -1)) ++ luaL_error(L, "function " LUA_QL("module") ++ " not called from a Lua function"); + lua_pushvalue(L, -2); + lua_setfenv(L, -2); + lua_pop(L, 1); +]], +} + + +Bug{ +what = [[internal macro 'svalue' is wrong]], +report = [[Martijn van Buul, on 2008/08/04]], +since = [[5.1]], +example = [[ +/* in luaconf.h */ +#define LUAI_USER_ALIGNMENT_T union { char b[32]; } +]], +patch = [[ +--- lobject.h 2007/12/27 13:02:25 2.20.1.1 ++++ lobject.h 2008/08/05 19:40:48 +@@ -210,3 +210,3 @@ + #define getstr(ts) cast(const char *, (ts) + 1) +-#define svalue(o) getstr(tsvalue(o)) ++#define svalue(o) getstr(rawtsvalue(o)) + +]], +} + + +----------------------------------------------------------------- +-- Lua 5.1.4 + +Bug{ +what = [[malicious zero-length string in binary code may segfault Lua]], +report = [[Peter Cawley, on 2008/09/01]], +since = [[5.1]], +example = [[ +loadstring(('').dump(function()X''end):gsub('\2%z%z%zX','\0\0\0'))() +]], +patch = [[ +]], +} + + +Bug{ +what = [[wrong code generation for some particular boolean expressions]], +report = [[Brian Kelley, on 2009/04/15]], +since = [[5.0]], +example = [[ +print(((1 or false) and true) or false) --> 1 +-- should be 'true' +]], +patch = [[ +--- lcode.c 2007/12/28 15:32:23 2.25.1.3 ++++ lcode.c 2009/06/15 14:07:34 +@@ -544,15 +544,18 @@ + pc = NO_JUMP; /* always true; do nothing */ + break; + } +- case VFALSE: { +- pc = luaK_jump(fs); /* always jump */ +- break; +- } + case VJMP: { + invertjump(fs, e); + pc = e->u.s.info; + break; + } ++ case VFALSE: { ++ if (!hasjumps(e)) { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ /* else go through */ ++ } + default: { + pc = jumponcond(fs, e, 0); + break; +@@ -572,14 +575,17 @@ + pc = NO_JUMP; /* always false; do nothing */ + break; + } +- case VTRUE: { +- pc = luaK_jump(fs); /* always jump */ +- break; +- } + case VJMP: { + pc = e->u.s.info; + break; + } ++ case VTRUE: { ++ if (!hasjumps(e)) { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ /* else go through */ ++ } + default: { + pc = jumponcond(fs, e, 1); + break; +]], +} + +Bug{ +what = [['luaV_settable' may invalidate a reference to a table and try +to reuse it]], +report = [[Mark Feldman, on 2009/06/27]], +since = [[5.0]], +example = [[ +grandparent = {} +grandparent.__newindex = function(s,_,_) print(s) end + +parent = {} +parent.__newindex = parent +setmetatable(parent, grandparent) + +child = setmetatable({}, parent) +child.foo = 10 --> (crash on some machines) +]], +patch = [[ +--- lvm.c 2007/12/28 15:32:23 2.63.1.3 ++++ lvm.c 2009/07/01 20:36:59 +@@ -133,6 +133,7 @@ + + void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; ++ TValue temp; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ +@@ -152,7 +153,9 @@ + callTM(L, tm, t, key, val); + return; + } +- t = tm; /* else repeat with `tm' */ ++ /* else repeat with `tm' */ ++ setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ ++ t = &temp; + } + luaG_runerror(L, "loop in settable"); + } +]], +} + +Bug{ +what = [[smart use of varargs may create functions that return too +many arguments and overflow the stack of C functions]], +report = [[Patrick Donnelly, on 2008/12/10]], +since = [[]], +example = [[ +local function lunpack(i, ...) + if i == 0 then return ... + else + return lunpack(i-1, 1, ...) + end +end + +Now, if C calls lunpack(n) with a huge n, it may end with +too many values in its stack and confuse its stack indices. +]], +patch = [[ +]], +} + +Bug{ +what = [['debug.getfenv' does not check whether it has an argument]], +report = [[Patrick Donnelly, 2009/07/30]], +since = [[5.1]], +example = [[debug.getfenv() -- should raise an error]], +patch = [[ +--- ldblib.c 2008/01/21 13:11:21 1.104.1.3 ++++ ldblib.c 2009/08/04 18:43:12 +@@ -45,6 +45,7 @@ + + + static int db_getfenv (lua_State *L) { ++ luaL_checkany(L, 1); + lua_getfenv(L, 1); + return 1; + } +]], +} + +Bug{ +what = [[GC may get stuck during a parser and avoids proper resizing of +the string table, +making its lists grow too much and degrading performance]], +report = [[Sean Conner, 2009/11/10]], +since = [[5.1]], +example = [[See http://lua-users.org/lists/lua-l/2009-11/msg00463.html]], +patch = [[ +--- llex.c 2007/12/27 13:02:25 2.20.1.1 ++++ llex.c 2009/11/23 14:49:40 +@@ -118,8 +118,10 @@ + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); + TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ +- if (ttisnil(o)) ++ if (ttisnil(o)) { + setbvalue(o, 1); /* make sure `str' will not be collected */ ++ luaC_checkGC(L); ++ } + return ts; + } + +]] +} + +Bug{ +what = [['string.format' may get buffer as an argument when there are +missing arguments and format string is too long]], +report = [[Roberto I., 2010/04/12]], +since = [[5.0]], +example = [[ +x = string.rep("x", 10000) .. "%d" +print(string.format(x)) -- gives wrong error message +]], +patch = [[ +--- lstrlib.c 2008/07/11 17:27:21 1.132.1.4 ++++ lstrlib.c 2010/05/14 15:12:53 +@@ -754,6 +754,7 @@ + + + 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); +@@ -768,7 +769,8 @@ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ +- arg++; ++ if (++arg > top) ++ luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { +]] +} + +Bug{ +what = [['io.read(op, "*n")' may return garbage if second read fails]], +report = [[Roberto I., 2010/04/12]], +since = [[5.0]], +example = [[ +print(io.read("*n", "*n")) --<< enter "10 hi" +--> file (0x884420) nil +]], +patch = [[ +--- liolib.c 2008/01/18 17:47:43 2.73.1.3 ++++ liolib.c 2010/05/14 15:29:29 +@@ -276,7 +276,10 @@ + lua_pushnumber(L, d); + return 1; + } +- else return 0; /* read fails */ ++ else { ++ lua_pushnil(L); /* "result" to be removed */ ++ return 0; /* read fails */ ++ } + } + + +]] +} + +Bug{ +what = [[wrong code generation for some particular boolean expressions]], +report = [[Thierry Van Elsuwe, 2011/01/20]], +since = [[5.0]], +example = [[ +print((('hi' or true) and true) or true) +--> hi (should be true) +print(((nil and nil) or false) and true) +--> nil (should be false) +]], +patch = [[ +--- lcode.c 2009/06/15 14:12:25 2.25.1.4 ++++ lcode.c 2011/01/31 14:44:25 +@@ -549,13 +549,6 @@ + pc = e->u.s.info; + break; + } +- case VFALSE: { +- if (!hasjumps(e)) { +- pc = luaK_jump(fs); /* always jump */ +- break; +- } +- /* else go through */ +- } + default: { + pc = jumponcond(fs, e, 0); + break; +@@ -579,13 +572,6 @@ + pc = e->u.s.info; + break; + } +- case VTRUE: { +- if (!hasjumps(e)) { +- pc = luaK_jump(fs); /* always jump */ +- break; +- } +- /* else go through */ +- } + default: { + pc = jumponcond(fs, e, 1); + break; +]] +} + +Bug{ +what = [[__newindex metamethod may not work if metatable is its own +metatable]], +report = [[Cuero Bugot, 2011/08/09]], +since = [[5.1]], +example = [[ +meta={} +setmetatable(meta, meta) +meta.__newindex = function(t, key, value) print("set") end +o = setmetatable({}, meta) +o.x = 10 -- should print 'set' +]], +patch = [[ +--- lvm.c 2009/07/01 21:10:33 2.63.1.4 ++++ lvm.c 2011/08/17 20:36:28 +@@ -142,6 +142,7 @@ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(L, oldval, val); ++ h->flags = 0; + luaC_barriert(L, h, val); + return; + } +]] +} + +Bug{ +what = [[parser may collect a prototype while building it]], +report = [[Ingo van Lil, 2011/10/13]], +since = [[5.1.4 (caused by patch 5.1.4-6)]], +example = nil, +patch = [[ +--- lparser.c 2007/12/28 15:32:23 2.42.1.3 ++++ lparser.c 2011/10/17 13:10:43 +@@ -374,9 +374,9 @@ + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; +- L->top -= 2; /* remove table and prototype from the stack */ + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); ++ L->top -= 2; /* remove table and prototype from the stack */ + } + + +]] +} + + +Bug{ +what = [[When loading a file, +Lua may call the reader function again after it returned end of input +]], +report = [[Chris Howie, 2013/06/05]], +since = [[5.1]], +fix = [[5.2]], +example = [[ +load(function () print("called"); return nil end) +--> called +--> called (should be called only once!) +]], +patch = [[ +--- lzio.h 2007/12/27 13:02:25 1.21.1.1 ++++ lzio.h 2013/07/04 13:55:59 +@@ -59,6 +59,7 @@ + lua_Reader reader; + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ ++ int eoz; /* true if reader has no more data */ + }; + + +--- lzio.c 2007/12/27 13:02:25 1.31.1.1 ++++ lzio.c 2013/07/04 13:53:06 +@@ -22,10 +22,14 @@ + size_t size; + lua_State *L = z->L; + const char *buff; ++ if (z->eoz) return EOZ; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); +- if (buff == NULL || size == 0) return EOZ; ++ if (buff == NULL || size == 0) { ++ z->eoz = 1; /* avoid calling reader function next time */ ++ return EOZ; ++ } + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +@@ -51,6 +55,7 @@ + z->data = data; + z->n = 0; + z->p = NULL; ++ z->eoz = 0; + } +]] +} + + +----------------------------------------------------------------- +-- Lua 5.2.0 + +Bug{ +what = [[memory hoarding when creating Lua hooks for coroutines]], +report = [[Arseny Vakhrushev, 2012/01/16]], +since = [[5.1]], +fix = [[5.2.1]], +example = [[ +collectgarbage(); print(collectgarbage'count' * 1024) + +for i = 1, 100 do + local co = coroutine.create(function () end) + local x = {} + for j=1,1000 do x[j] = j end + debug.sethook(co, function () return x end, 'l') +end + +collectgarbage(); print(collectgarbage'count' * 1024) +-- value should back to near the original level +]], +patch = [[ +-- For 5.2 + +--- ldblib.c 2011/10/24 14:54:05 1.131 ++++ ldblib.c 2012/01/18 02:36:59 +@@ -253,14 +253,15 @@ + } + + +-#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY); ++#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) + + + static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + gethooktable(L); +- lua_rawgetp(L, -1, L); ++ lua_pushthread(L); ++ lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) +@@ -306,10 +307,15 @@ + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } +- gethooktable(L); ++ if (gethooktable(L) == 0) { /* creating hook table? */ ++ lua_pushstring(L, "k"); ++ lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ ++ lua_pushvalue(L, -1); ++ lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ ++ } ++ lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_pushvalue(L, arg+1); +- lua_rawsetp(L, -2, L1); /* set new hook */ +- lua_pop(L, 1); /* remove hook table */ ++ lua_rawset(L, -3); /* set new hook */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; + } +@@ -325,7 +331,8 @@ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); +- lua_rawgetp(L, -1, L1); /* get hook */ ++ lua_pushthread(L1); lua_xmove(L1, L, 1); ++ lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); +]] +} + +Bug{ +what = [[Lexical gets confused with some combination of arithmetic +operators and hexadecimal numbers]], +report = [[Alexandra Barros, 2012/01/17]], +since = [[5.2.0]], +fix = [[5.2.1]], +example = [[print(0xE+1)]], +patch = [[ +--- llex.c 2011/11/30 12:43:51 2.59 ++++ llex.c 2012/01/20 18:22:50 +@@ -223,12 +223,19 @@ + + /* LUA_NUMBER */ + static void read_numeral (LexState *ls, SemInfo *seminfo) { ++ const char *expo = "Ee"; ++ int first = ls->current; + lua_assert(lisdigit(ls->current)); +- do { +- save_and_next(ls); +- if (check_next(ls, "EePp")) /* exponent part? */ ++ save_and_next(ls); ++ if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ ++ expo = "Pp"; ++ for (;;) { ++ if (check_next(ls, expo)) /* exponent part? */ + check_next(ls, "+-"); /* optional exponent sign */ +- } while (lislalnum(ls->current) || ls->current == '.'); ++ if (lisxdigit(ls->current) || ls->current == '.') ++ save_and_next(ls); ++ else break; ++ } + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ +]] +} + +Bug{ +what = [[Finalizers may call functions from a dynamic library after +the library has been unloaded]], +report = [[Josh Haberman, 2012/04/08]], +since = [[5.1]], +fix = [[5.2.1]], +example = [[ +local u = setmetatable({}, {__gc = function () foo() end}) +local m = require 'mod' -- 'mod' may be any dynamic library written in C +foo = m.foo -- 'foo' may be any function from 'mod' +-- end program; it crashes +]], +patch = [[ +loadlib.c: +95c95 +< #define LIBPREFIX "LOADLIB: " +--- +> #define CLIBS "_CLIBS" +251,266c251,256 +< +< static void **ll_register (lua_State *L, const char *path) { +< void **plib; +< lua_pushfstring(L, "%s%s", LIBPREFIX, path); +< lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ +< if (!lua_isnil(L, -1)) /* is there an entry? */ +< plib = (void **)lua_touserdata(L, -1); +< else { /* no entry yet; create one */ +< lua_pop(L, 1); /* remove result from gettable */ +< plib = (void **)lua_newuserdata(L, sizeof(const void *)); +< *plib = NULL; +< luaL_setmetatable(L, "_LOADLIB"); +< lua_pushfstring(L, "%s%s", LIBPREFIX, path); +< lua_pushvalue(L, -2); +< lua_settable(L, LUA_REGISTRYINDEX); +< } +--- +> static void *ll_checkclib (lua_State *L, const char *path) { +> void *plib; +> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); +> lua_getfield(L, -1, path); +> plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ +> lua_pop(L, 2); /* pop CLIBS table and 'plib' */ +270a261,270 +> static void ll_addtoclib (lua_State *L, const char *path, void *plib) { +> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); +> lua_pushlightuserdata(L, plib); +> lua_pushvalue(L, -1); +> lua_setfield(L, -3, path); /* CLIBS[path] = plib */ +> lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ +> lua_pop(L, 1); /* pop CLIBS table */ +> } +> +> +272,273c272,273 +< ** __gc tag method: calls library's `ll_unloadlib' function with the lib +< ** handle +--- +> ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib +> ** handles in list CLIBS +276,278c276,281 +< void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); +< if (*lib) ll_unloadlib(*lib); +< *lib = NULL; /* mark library as closed */ +--- +> int n = luaL_len(L, 1); +> for (; n >= 1; n--) { /* for each handle, in reverse order */ +> lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ +> ll_unloadlib(lua_touserdata(L, -1)); +> lua_pop(L, 1); /* pop handle */ +> } +284,286c287,292 +< void **reg = ll_register(L, path); +< if (*reg == NULL) *reg = ll_load(L, path, *sym == '*'); +< if (*reg == NULL) return ERRLIB; /* unable to load library */ +--- +> void *reg = ll_checkclib(L, path); /* check loaded C libraries */ +> if (reg == NULL) { /* must load library? */ +> reg = ll_load(L, path, *sym == '*'); +> if (reg == NULL) return ERRLIB; /* unable to load library */ +> ll_addtoclib(L, path, reg); +> } +292c298 +< lua_CFunction f = ll_sym(L, *reg, sym); +--- +> lua_CFunction f = ll_sym(L, reg, sym); +675,676c681,683 +< /* create new type _LOADLIB */ +< luaL_newmetatable(L, "_LOADLIB"); +--- +> /* create table CLIBS to keep track of loaded C libraries */ +> luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); +> lua_createtable(L, 0, 1); /* metatable for CLIBS */ +678a686 +> lua_setmetatable(L, -2); +]] +} + +Bug{ +what = [[wrong handling of 'nCcalls' in coroutines]], +report = [[Alexander Gavrilov, 2012/04/18]], +since = [[5.2.0]], +fix = [[5.2.1]], +example = [[ +coroutine.wrap(function() + print(pcall(pcall,pcall,pcall,pcall,pcall,error,3)) +end)() +]], +patch = [[ +--- ldo.c 2011/11/29 15:55:08 2.102 ++++ ldo.c 2012/04/26 20:38:32 +@@ -402,8 +402,6 @@ + int n; + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); +- /* finish 'luaD_call' */ +- L->nCcalls--; + /* finish 'lua_callk' */ + adjustresults(L, ci->nresults); + /* call continuation function */ +@@ -513,7 +511,6 @@ + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } +- L->nCcalls--; /* finish 'luaD_call' */ + luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ + } + unroll(L, NULL); +]] +} + +Bug{ +what = [[Internal Lua values may escape through the debug API]], +report = [[Dan Tull, 2012/04/20]], +since = [[5.1]], +fix = [[5.2.1]], +example = [[ +-- for Lua 5.1 +local firsttime = true +local function foo () + if firsttime then + firsttime = false + return "a = 1" + else + for i = 1, 10 do + print(debug.getlocal(2, i)) + end + end +end + +print(load(foo)) -- prints some lines and then seg. fault. +]], +patch = [[ +]] +} + +Bug{ +what = [[Problems when yielding from debug hooks]], +report = [[Erik Cassel, 2012/06/05]], +since = [[5.2.0]], +fix = [[5.2.1]], +example = [[ +Set, in C, a line hook that simply yields, +and then call any Lua function. +You get an infinite loop of yields. +]], +patch = [[ +]] +} + + +----------------------------------------------------------------- +-- Lua 5.2.1 + +Bug{ +what = [[Some patterns can overflow the C stack, due to recursion]], +report = [[Tim Starling, 2012/07/08]], +since = [[2.5]], +fix = [[5.2.2]], +example = [[print(string.find(string.rep("a", 2^20), string.rep(".?", 2^20)))]], +patch = [[ +]] +} + + +Bug{ +what = [['pcall' may not restore previous error function when +inside coroutines]], +report = [[Alexander Gavrilov, 2012/06/12]], +since = [[5.2.0]], +fix = [[5.2.2]], +example = [[ +function errfunc(x) + return 'errfunc' +end + +function test(do_yield) + print(do_yield and "yielding" or "not yielding") + pcall(function() -- this pcall sets errfunc back to none + if do_yield then + coroutine.yield() -- stops errfunc from being restored + end + end) + error('fail!') +end + +coro = coroutine.wrap(function() + print(xpcall(test, errfunc, false)) + print(xpcall(test, errfunc, true)) + print(xpcall(test, errfunc, false)) +end) + +coro() +--> not yielding +--> false errfunc +--> yielding +coro() +--> false temp:12: fail! <<<< should be 'errfunc' too +--> not yielding +--> false errfunc +]], +patch = [[ +--- ldo.c 2012/08/28 18:30:45 2.107 ++++ ldo.c 2012/09/23 15:49:55 +@@ -403,7 +403,11 @@ + int n; + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); +- /* finish 'lua_callk' */ ++ if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ ++ ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ ++ L->errfunc = ci->u.c.old_errfunc; ++ } ++ /* finish 'lua_callk'/'lua_pcall' */ + adjustresults(L, ci->nresults); + /* call continuation function */ + if (!(ci->callstatus & CIST_STAT)) /* no call status? */ +]] +} + +Bug{ +what = [[Check for garbage collector in function calls does not cover +all paths]], +report = [[Roberto, 2012/08/15]], +since = [[5.2.1]], +fix = [[5.2.2]], +example = [[ +See +http://lua-users.org/lists/lua-l/2012-08/msg00149.html +]], +patch = [[ +@@ -311,6 +311,7 @@ + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; ++ luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); +@@ -338,6 +339,7 @@ + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + L->top = ci->top; ++ luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; +@@ -393,7 +395,6 @@ + luaV_execute(L); /* call it */ + if (!allowyield) L->nny--; + L->nCcalls--; +- luaC_checkGC(L); + } +]] +} + +Bug{ +what = [[load/loadfile returns wrong result when given an environment +for a binary chunk with no upvalues]], +report = [[Vladimir Strakh, 2012/11/28]], +since = [[5.2.0]], +fix = [[5.2.2]], +example = [[ +f = load(string.dump(function () return 1 end), nil, "b", {}) +print(type(f)) --> table (whould be a function) +]], +patch = [[ +--- lbaselib.c 2012/04/27 14:13:19 1.274 ++++ lbaselib.c 2012/12/03 20:08:15 +@@ -244,5 +244,11 @@ + +-static int load_aux (lua_State *L, int status) { +- if (status == LUA_OK) ++static int load_aux (lua_State *L, int status, int envidx) { ++ if (status == LUA_OK) { ++ if (envidx != 0) { /* 'env' parameter? */ ++ lua_pushvalue(L, envidx); /* environment for loaded function */ ++ if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ ++ lua_pop(L, 1); /* remove 'env' if not used by previous call */ ++ } + return 1; ++ } + else { +@@ -258,9 +264,5 @@ + const char *mode = luaL_optstring(L, 2, NULL); +- int env = !lua_isnone(L, 3); /* 'env' parameter? */ ++ int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); +- if (status == LUA_OK && env) { /* 'env' parameter? */ +- lua_pushvalue(L, 3); +- lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ +- } +- return load_aux(L, status); ++ return load_aux(L, status, env); + } +@@ -309,5 +311,5 @@ + size_t l; +- int top = lua_gettop(L); + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); ++ int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ +@@ -322,7 +324,3 @@ + } +- if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */ +- lua_pushvalue(L, 4); /* environment for loaded function */ +- lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */ +- } +- return load_aux(L, status); ++ return load_aux(L, status, env); + } +]] +} + +Bug{ +what = [[Lua does not check memory use when creating error messages]], +report = [[John Dunn, 2012/09/24]], +since = [[5.2.0]], +fix = nil, +example = [[ +local code = "function test()\n bob.joe.larry = 23\n end" + +load(code)() + +-- memory will grow steadly +for i = 1, math.huge do + pcall(test) + if i % 100000 == 0 then + io.write(collectgarbage'count'*1024, "\n") + end +end +]], +patch = [[ +]] +} + + + + + +----------------------------------------------------------------- +-- Lua 5.2.2 + + +Bug{ +what = [[stack overflow in vararg functions with many fixed +parameters called with few arguments]], +report = [[云风, 2013/04/17]], +since = [[5.1]], +fix = [[5.2.3]], +example = [[ +function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, + p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, + p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, + p41, p42, p43, p44, p45, p46, p48, p49, p50, ...) + local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 +end + +f() -- seg. fault (on some machines) +]], +patch = [[ +--- ldo.c 2012/10/01 14:05:04 2.108 ++++ ldo.c 2013/04/19 20:56:06 +@@ -324,7 +324,7 @@ + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; +- luaD_checkstack(L, p->maxstacksize); ++ luaD_checkstack(L, p->maxstacksize + p->numparams); + func = restorestack(L, funcr); + n = cast_int(L->top - func) - 1; /* number of real arguments */ + for (; n < p->numparams; n++) +]], +} + +Bug{ +what = [[garbage collector can trigger too many times in recursive loops]], +report = [[Roberto, 2013/04/25]], +since = [[5.2.2]], +fix = [[5.2.3]], +example = [[ +function f() f() end +f() -- it takes too long before a "stack overflow" error +]], +patch = [[ +--- lgc.c 2013/04/12 18:48:47 2.140.1.1 ++++ lgc.c 2013/04/25 21:30:20 +@@ -495,2 +495,3 @@ + static lu_mem traversestack (global_State *g, lua_State *th) { ++ int n = 0; + StkId o = th->stack; +@@ -505,3 +506,9 @@ + } +- return sizeof(lua_State) + sizeof(TValue) * th->stacksize; ++ else { /* count call infos to compute size */ ++ CallInfo *ci; ++ for (ci = &th->base_ci; ci != th->ci; ci = ci->next) ++ n++; ++ } ++ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + ++ sizeof(CallInfo) * n; + } +]] +} + +-- [[]] +Bug{ +what = [[Wrong assert when reporting concatenation errors +(manifests only when Lua is compiled in debug mode)]], +report = [[Roberto, 2013/05/05]], +since = [[?]], +fix = [[5.2.3]], +example = [[ +-- only with Lua compiled in debug mode +print({} .. 2) +]], +patch = [[ +--- ldebug.c 2013/04/12 18:48:47 2.90.1.1 ++++ ldebug.c 2013/05/05 14:38:30 +@@ -519,5 +519,5 @@ + l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; +- lua_assert(!ttisstring(p1) && !ttisnumber(p2)); ++ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); + } +]] +} + +Bug{ +what = [[Wrong error message in some short-cut expressions]], +report = [[Egor Skriptunoff, 2013/05/10]], +since = [[5.0]], +fix = [[5.2.3]], +example = [[ +> a,b,c = true,true,true +> (a and b or c)('', '') +stdin:1: attempt to call a boolean value (global 'c') + + (It should be global 'b' instead of 'c'.) +]], +patch = [[ +--- ldebug.c 2013/05/06 17:20:22 2.90.1.2 ++++ ldebug.c 2013/05/14 19:52:48 +@@ -327,12 +327,20 @@ + } + + ++static int filterpc (int pc, int jmptarget) { ++ if (pc < jmptarget) /* is code conditional (inside a jump)? */ ++ return -1; /* cannot know who sets that register */ ++ else return pc; /* current position sets that register */ ++} ++ ++ + /* + ** try to find last instruction before 'lastpc' that modified register 'reg' + */ + static int findsetreg (Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ ++ int jmptarget = 0; /* any code before this address is conditional */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); +@@ -341,33 +349,38 @@ + case OP_LOADNIL: { + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ +- setreg = pc; ++ setreg = filterpc(pc, jmptarget); + break; + } + case OP_TFORCALL: { +- if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ ++ if (reg >= a + 2) /* affect all regs above its base */ ++ setreg = filterpc(pc, jmptarget); + break; + } + case OP_CALL: + case OP_TAILCALL: { +- if (reg >= a) setreg = pc; /* affect all registers above base */ ++ if (reg >= a) /* affect all registers above base */ ++ setreg = filterpc(pc, jmptarget); + break; + } + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip `lastpc'? */ +- if (pc < dest && dest <= lastpc) +- pc += b; /* do the jump */ ++ if (pc < dest && dest <= lastpc) { ++ if (dest > jmptarget) ++ jmptarget = dest; /* update 'jmptarget' */ ++ } + break; + } + case OP_TEST: { +- if (reg == a) setreg = pc; /* jumped code can change 'a' */ ++ if (reg == a) /* jumped code can change 'a' */ ++ setreg = filterpc(pc, jmptarget); + break; + } + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ +- setreg = pc; ++ setreg = filterpc(pc, jmptarget); + break; + } + } +]] +} + +Bug{ +what = [[luac listings choke on long strings]], +report = [[Ashwin Hirschi, 2013/07/03]], +since = [[5.1.2]], +fix = [[5.2.3]], +example = [[ +-- When you call 'luac -l' over this chunk, it chokes the output +s="Lorem ipsum dolor sit amet, consectetur, " +]], +patch = [[ +--- luac.c 2011-11-29 15:46:33 -0200 1.69 ++++ luac.c 2013-07-03 21:26:01 -0300 +@@ -251,7 +251,7 @@ + static void PrintConstant(const Proto* f, int i) + { + const TValue* o=&f->k[i]; +- switch (ttype(o)) ++ switch (ttypenv(o)) + { + case LUA_TNIL: + printf("nil"); +]] +} + +Bug{ +what = [[GC can collect a long string still in use during parser]], +report = [[Roberto, 2013/08/30]], +since = [[5.2]], +fix = [[5.2.3]], +example = [[This bug is very difficult to happen (and to reproduce), +because it depends on the GC running in a very specific way when +parsing a source code with long (larger than 40 characters) identifiers.]], +patch = [[ +--- ltable.h 2013/04/12 18:48:47 2.16.1.1 ++++ ltable.h 2013/08/30 15:34:24 +@@ -18,4 +18,8 @@ + #define invalidateTMcache(t) ((t)->flags = 0) + ++/* returns the key, given the value of a table entry */ ++#define keyfromval(v) \ ++ (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) ++ + + LUAI_FUNC const TValue *luaH_getint (Table *t, int key); + +--- llex.c 2013/04/12 18:48:47 2.63.1.1 ++++ llex.c 2013/08/30 15:34:59 +@@ -134,4 +134,7 @@ + luaC_checkGC(L); + } ++ else { /* string already present */ ++ ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ ++ } + L->top--; /* remove string from stack */ + return ts; +]] +} + + +Bug{ +what = [[Call to macro 'luai_userstateclose' should be done only +after the calls to __gc methods.]], +report = [[Jean-Luc Jumpertz, 2013/09/02]], +since = [[ ]], +fix = nil, +example = [[No example]], +patch = [[ +--- lstate.c 2013/04/12 18:48:47 2.99.1.1 ++++ lstate.c 2013/11/08 17:39:57 +@@ -194,2 +194,4 @@ + g->gcrunning = 1; /* allow gc */ ++ g->version = lua_version(NULL); ++ luai_userstateopen(L); + } +@@ -224,2 +226,4 @@ + luaC_freeallobjects(L); /* collect all objects */ ++ if (g->version) /* closing a fully built state? */ ++ luai_userstateclose(L); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); +@@ -289,3 +293,3 @@ + g->panic = NULL; +- g->version = lua_version(NULL); ++ g->version = NULL; + g->gcstate = GCSpause; +@@ -308,4 +312,2 @@ + } +- else +- luai_userstateopen(L); + return L; +@@ -317,3 +319,2 @@ + lua_lock(L); +- luai_userstateclose(L); + close_state(L); +]] +} + + +Bug{ +what = [[Resuming the running coroutine makes it unyieldable]], +report = [[Florian Nücke, 2013/10/28]], +since = [[5.2]], +fix = [[5.2.3]], +example = [[ +-- should print 'true' +print(coroutine.resume(coroutine.create(function() + coroutine.resume(coroutine.running()) + coroutine.yield() +end))) +]], +patch = [[ +--- ldo.c 2013/04/19 21:03:23 2.108.1.2 ++++ ldo.c 2013/11/08 18:20:57 +@@ -536,2 +536,3 @@ + int status; ++ int oldnny = L->nny; /* save 'nny' */ + lua_lock(L); +@@ -557,3 +558,3 @@ + } +- L->nny = 1; /* do not allow yields */ ++ L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; +]] +} + + + +----------------------------------------------------------------- +-- Lua 5.2.3 + +Bug{ +what = [[compiler can optimize away overflow check in 'table.unpack']], +report = [[Paige DePol, 2014/03/30]], +since = [[5.1 (at least)]], +fix = nil, +example = [[ +> unpack({}, 0, 2^31 - 1) +(segfaults on some platforms with some compiler options) +]], +patch = [[ +--- ltablib.c 2013/04/12 18:48:47 1.65.1.1 ++++ ltablib.c 2014/05/07 16:32:55 1.65.1.2 +@@ -134,13 +135,14 @@ + + + static int unpack (lua_State *L) { +- int i, e, n; ++ int i, e; ++ unsigned int n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ +- n = e - i + 1; /* number of elements */ +- if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ ++ n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */ ++ if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n)) + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ +]] +} + +Bug{ +what = [[Ephemeron table can wrongly collect entry with strong key]], +report = [[Jörg Richter, 2014/08/22]], +since = [[5.2]], +fix = nil, +example = [[ +(This bug is very hard to reproduce, +because it depends on a specific interleaving of +events between the incremental collector and the program.) +]], +patch = [[ +--- lgc.c 2013/04/26 18:22:05 2.140.1.2 ++++ lgc.c 2014/09/01 13:24:33 +@@ -403,7 +403,7 @@ + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } +- if (prop) ++ if (g->gcstate != GCSatomic || prop) + linktable(h, &g->ephemeron); /* have to propagate again */ + else if (hasclears) /* does table have white keys? */ + linktable(h, &g->allweak); /* may have to clean white keys */ +]] +} + +Bug{ +what = [[Chunk with too many lines can seg. fault]], +report = [[Roberto, 2014/11/14]], +since = [[5.1 (at least)]], +fix = nil, +example = [[ +-- the cause of the bug is the use of an unitialized variable, so +-- it cannot be reproduced reliably +local s = string.rep("\n", 2^24) +print(load(function () return s end)) +]], +patch = [[ +--- llex.c 2013/08/30 15:49:41 2.63.1.2 ++++ llex.c 2015/02/09 17:05:31 +@@ -153,5 +153,5 @@ + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) +- luaX_syntaxerror(ls, "chunk has too many lines"); ++ lexerror(ls, "chunk has too many lines", 0); + } + +]] +} + + +----------------------------------------------------------------- +-- Lua 5.3.0 + +Bug{ +what = [['string.format("%f")' can cause a buffer overflow +(only when 'lua_Number' is long double!)]], +report = [[Roberto, 2015/01/13]], +since = [[5.3]], +fix = nil, +example = [[string.format("%.99f", 1e4000) -- when floats are long double]], +patch = [[ +--- lstrlib.c 2014/12/11 14:03:07 1.221 ++++ lstrlib.c 2015/02/23 19:01:42 +@@ -800,3 +800,4 @@ + /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +-#define MAX_ITEM 512 ++#define MAX_ITEM \ ++ (sizeof(lua_Number) <= 4 ? 150 : sizeof(lua_Number) <= 8 ? 450 : 5050) + +]] +} + +Bug{ +what = [['debug.getlocal' on a coroutine suspended in a hook +can crash the interpreter]], +report = [[云风, 2015/02/11]], +since = [[5.2]], +fix = nil, +example = [[see http://lua-users.org/lists/lua-l/2015-02/msg00146.html]], +patch = [[ +--- ldebug.c 2015/01/02 12:52:22 2.110 ++++ ldebug.c 2015/02/13 16:03:23 +@@ -49,4 +49,14 @@ + + ++static void swapextra (lua_State *L) { ++ if (L->status == LUA_YIELD) { ++ CallInfo *ci = L->ci; /* get function that yielded */ ++ StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ ++ ci->func = restorestack(L, ci->extra); ++ ci->extra = savestack(L, temp); ++ } ++} ++ ++ + /* + ** this function can be called asynchronous (e.g. during a signal) +@@ -145,4 +155,5 @@ + const char *name; + lua_lock(L); ++ swapextra(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ +@@ -159,4 +170,5 @@ + } + } ++ swapextra(L); + lua_unlock(L); + return name; +@@ -166,10 +178,13 @@ + LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = 0; /* to avoid warnings */ +- const char *name = findlocal(L, ar->i_ci, n, &pos); ++ const char *name; + lua_lock(L); ++ swapextra(L); ++ name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } ++ swapextra(L); + lua_unlock(L); + return name; +@@ -271,4 +286,5 @@ + StkId func; + lua_lock(L); ++ swapextra(L); + if (*what == '>') { + ci = NULL; +@@ -289,4 +305,5 @@ + api_incr_top(L); + } ++ swapextra(L); + if (strchr(what, 'L')) + collectvalidlines(L, cl); +]] +} + + +Bug{ +what = [[suspended '__le' metamethod can give wrong result]], +report = [[Eric Zhong, 2015/04/07]], +since = [[5.2]], +fix = nil, + +example = [[ +mt = {__le = function (a,b) coroutine.yield("yield"); return a.x <= b.x end} +t1 = setmetatable({x=1}, mt) +t2 = {x=2} +co = coroutine.wrap(function (a,b) return t2 <= t1 end) +co() +print(co()) --> true (should be false) +]], + +patch = [[ +--- lstate.h 2014/10/30 18:53:28 2.119 ++++ lstate.h 2015/04/13 15:58:40 +@@ -94,6 +94,7 @@ + #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ + #define CIST_TAIL (1<<5) /* call was tail called */ + #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ ++#define CIST_LEQ (1<<7) /* using __lt for __le */ + + #define isLua(ci) ((ci)->callstatus & CIST_LUA) + +--- lvm.c 2014/12/27 20:30:38 2.232 ++++ lvm.c 2015/04/13 15:51:30 +@@ -292,9 +292,14 @@ + return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; + else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */ + return res; +- else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */ +- luaG_ordererror(L, l, r); +- return !res; ++ else { /* try 'lt': */ ++ L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ ++ res = luaT_callorderTM(L, r, l, TM_LT); ++ L->ci->callstatus ^= CIST_LEQ; /* clear mark */ ++ if (res < 0) ++ luaG_ordererror(L, l, r); ++ return !res; /* result is negated */ ++ } + } + + +@@ -553,11 +558,11 @@ + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; +- /* metamethod should not be called when operand is K */ +- lua_assert(!ISK(GETARG_B(inst))); +- if (op == OP_LE && /* "<=" using "<" instead? */ +- ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) +- res = !res; /* invert result */ ++ if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ ++ lua_assert(op == OP_LE); ++ ci->callstatus ^= CIST_LEQ; /* clear mark */ ++ res = !res; /* negate result */ ++ } + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ +]] +} + + +Bug{ +what = [[return hook may not see correct values for + active local variables when function returns]], +report = [[Philipp Janda/Peng Yi, 2015/05/19]], +since = [[5.0]], +fix = nil, +example = [[ +see messasge http://lua-users.org/lists/lua-l/2015-05/msg00376.html]], +patch = [[ +]] +} + + + +----------------------------------------------------------------- +-- Lua 5.3.1 + +Bug{ +what = [['io.lines' does not check maximum number of options]], +report = [[Patrick Donnell, 2015/07/10]], +since = [[5.3.0]], +fix = nil, +example = [[ +-- can segfault in some machines +t ={}; for i = 1, 253 do t[i] = 1 end +io.lines("someexistingfile", table.unpack(t))() +]], +patch = [[ +--- liolib.c 2015/07/07 17:03:34 2.146 ++++ liolib.c 2015/07/15 14:40:28 2.147 +@@ -318,8 +318,15 @@ + static int io_readline (lua_State *L); + + ++/* ++** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit ++** in the limit for upvalues of a closure) ++*/ ++#define MAXARGLINE 250 ++ + static void aux_lines (lua_State *L, int toclose) { + int n = lua_gettop(L) - 1; /* number of arguments to read */ ++ luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ +]] +} + + +----------------------------------------------------------------- +-- Lua 5.3.2 + +Bug{ +what = [[Metatable may access its own dealocated field when +it has a self reference in __newindex]], +report = [[actboy168@gmail.com, 2016/01/01]], +since = [[5.3.2]], +fix = nil, +example = [[ +local mt = {} +mt.__newindex = mt +local t = setmetatable({}, mt) +t[1] = 1 -- will segfault on some machines +]], +patch = [[ +--- lvm.c 2015/11/23 11:30:45 2.265 ++++ lvm.c 2016/01/01 14:34:12 +@@ -190,18 +190,19 @@ + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (oldval != NULL) { +- lua_assert(ttistable(t) && ttisnil(oldval)); ++ Table *h = hvalue(t); /* save 't' table */ ++ lua_assert(ttisnil(oldval)); + /* must check the metamethod */ +- if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL && ++ if ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + /* no metamethod; is there a previous entry in the table? */ + (oldval != luaO_nilobject || + /* no previous entry; must create one. (The next test is + always true; we only need the assignment.) */ +- (oldval = luaH_newkey(L, hvalue(t), key), 1))) { ++ (oldval = luaH_newkey(L, h, key), 1))) { + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, cast(TValue *, oldval), val); +- invalidateTMcache(hvalue(t)); +- luaC_barrierback(L, hvalue(t), val); ++ invalidateTMcache(h); ++ luaC_barrierback(L, h, val); + return; + } + /* else will try the metamethod */ +]] +} + + +Bug{ +what = [[label between local definitions can mix-up their initializations]], +report = [[Karel Tuma, 2016/03/01]], +since = [[5.2]], +fix = nil, +example = [[ +do + local k = 0 + local x + ::foo:: + local y -- should be reset to nil after goto, but it is not + assert(not y) + y = true + k = k + 1 + if k < 2 then goto foo end +end +]], +patch = [[ +--- lparser.c 2015/11/02 16:09:30 2.149 ++++ lparser.c 2016/03/03 12:03:37 +@@ -1226,7 +1226,7 @@ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ +- l = newlabelentry(ls, ll, label, line, fs->pc); ++ l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ +]] +} + + +Bug{ +what = [['gmatch' iterator fails when called from a coroutine different +from the one that created it]], +report = [[Nagaev Boris, 2016/03/18]], +since = [[5.3.2]], +fix = nil, +example = [[ +local f = string.gmatch("1 2 3 4 5", "%d+") +print(f()) --> 1 +co = coroutine.wrap(f) +print(co()) --> ??? (should be 2) +]], +patch = [[ +--- lstrlib.c 2015/11/25 16:28:17 1.239 ++++ lstrlib.c 2016/04/11 15:29:41 +@@ -688,6 +688,7 @@ + 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); +]] +} + + +----------------------------------------------------------------- +-- Lua 5.3.3 + + +Bug{ +what = [[expression list with four or more expressions in +a 'for' loop can crash the interpreter]], +report = [[Marco Schöpl, 2016/06/17]], +since = [[5.2]], +fix = nil, +example = [[ +-- the next loop will probably crash the interpreter +repeat until load "for _ in _,_,_,_ do local function _() end" +]], +patch = [[ +--- lparser.c 2016/05/13 19:10:16 2.153 ++++ lparser.c 2016/06/17 19:52:48 +@@ -323,6 +323,8 @@ + luaK_nil(fs, reg, extra); + } + } ++ if (nexps > nvars) ++ ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + + +@@ -1160,11 +1162,8 @@ + int nexps; + checknext(ls, '='); + nexps = explist(ls, &e); +- if (nexps != nvars) { ++ if (nexps != nvars) + adjust_assign(ls, nvars, nexps, &e); +- if (nexps > nvars) +- ls->fs->freereg -= nexps - nvars; /* remove extra values */ +- } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); +]] +} + + +Bug{ +what = [[Checking a format for 'os.date' may read pass the format string]], +report = [[Nagaev Boris, 2016/07/10]], +since = [[5.3.3]], +fix = nil, +example = [[ +This bug does not seem to happen with regular compilers. +It needs an "interceptor" 'memcmp' function that continues +reading memory after a difference is found.]], +patch = [[ +2c2 +< ** $Id: bugs,v 1.158 2017/12/06 18:20:28 roberto Exp roberto $ +--- +> ** $Id: bugs,v 1.158 2017/12/06 18:20:28 roberto Exp roberto $ +263c263,264 +< for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) { +--- +> int convlen = (int)strlen(conv); +> for (option = LUA_STRFTIMEOPTIONS; *option != '\0' && oplen <= convlen; option += oplen) { +]] +} + + +Bug{ +what = [[Lua can generate wrong code in functions with too many constants]], +report = [[Marco Schöpl, 2016/07/17]], +since = [[5.3.3]], +fix = nil, +example = [[See http://lua-users.org/lists/lua-l/2016-07/msg00303.html]], +patch = [[ +--- lcode.c 2016/06/20 19:12:46 2.110 ++++ lcode.c 2016/07/18 15:43:41 +@@ -1018,8 +1018,8 @@ + */ + static void codebinexpval (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { +- int rk1 = luaK_exp2RK(fs, e1); /* both operands are "RK" */ +- int rk2 = luaK_exp2RK(fs, e2); ++ int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ ++ int rk1 = luaK_exp2RK(fs, e1); + freeexps(fs, e1, e2); + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ +]] +} + + +Bug{ +what = [[When a coroutine tries to resume a non-suspended coroutine, +it can do some mess (and break C assertions) before detecting the error]], +report = [[Marco Schöpl, 2016/07/20]], +since = [[ ]], +fix = nil, +example = [[ +-- with C assertions on +A = coroutine.running() +B = coroutine.create(function() coroutine.resume(A) end) +coroutine.resume(B) + +-- or +A = coroutine.wrap(function() pcall(A, _) end) +A() +]], +patch = [[ +]] +} + + +Bug{ +what = [[Wrong code for a goto followed by a label inside an 'if']], +report = [[云风, 2017/04/13]], +since = [[5.2]], +fix = nil, +example = [[ +-- should print 32323232..., but prints only '3' +if true then + goto LBL + ::loop:: + print(2) + ::LBL:: + print(3) + goto loop +end +]], +patch = [[ +--- lparser.c 2017/04/19 17:20:42 2.155.1.1 ++++ lparser.c 2017/04/29 18:11:40 2.155.1.2 +@@ -1392,7 +1392,7 @@ + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ +- skipnoopstat(ls); /* skip other no-op statements */ ++ while (testnext(ls, ';')) {} /* skip semicolons */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ +]] +} + + +Bug{ +what = [[Lua crashes when building sequences with more than 2^30 elements.]], +report = [[Viacheslav Usov, 2017/05/11]], +since = [[ ]], +fix = nil, +example = [[ +-- crashes if machine has enough memory +local t = {} +for i = 1, 0x7fffffff do + t[i] = i +end +]], +patch = [[ +]] +} + + +Bug{ +what = [[Table length computation overflows for sequences larger than +2^31 elements.]], +report = [[Viacheslav Usov, 2017/05/12]], +since = [[ ]], +fix = nil, +example = [[ +-- on a machine with enough memory +local t = {} +for i = 1, 2147483681 do + t[i] = i +end +print(#t) +]], +patch = [[ +]] +} + +Bug{ +what = [[Lua does not check GC when creating error messages]], +report = [[Viacheslav Usov, 2017/07/06]], +since = [[5.3.2]], +fix = nil, +example = [[ +function test() + bob.joe.larry = 23 +end + +-- memory will grow steadly +for i = 1, math.huge do + pcall(test) + if i % 100000 == 0 then + io.write(collectgarbage'count'*1024, "\n") + end +end +]], +patch = [[ +--- ldebug.c 2017/04/19 17:20:42 2.121.1.1 ++++ ldebug.c 2017/07/10 17:08:39 +@@ -653,6 +653,7 @@ + CallInfo *ci = L->ci; + const char *msg; + va_list argp; ++ luaC_checkGC(L); /* error message uses memory */ + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ + va_end(argp); +]] +} + + +Bug{ +what = [[dead keys with nil values can stay in weak tables]], +report = [[云风 Cloud Wu, 2017/08/15]], +since = [[5.2]], +fix = nil, +example = [[ +-- The following chunk, under a memory checker like valgrind, +-- produces a memory access violation. + +local a = setmetatable({}, {__mode = 'kv'}) + +a['ABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz'] = {} +a[next(a)] = nil +collectgarbage() +print(a['BCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz']) +]], +patch = [[ +--- lgc.c 2016/12/22 13:08:50 2.215 ++++ lgc.c 2017/08/31 16:08:23 +@@ -643,8 +643,9 @@ + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ +- removeentry(n); /* and remove entry from table */ + } ++ if (ttisnil(gval(n))) /* is entry empty? */ ++ removeentry(n); /* remove entry from table */ + } + } + } +]] +} + + +Bug{ +what = [['lua_pushcclosure' should not call the garbage collector when +'n' is zero.]], +report = [[Andrew Gierth, 2017/12/05]], +since = [[5.3.3]], +fix = nil, +example = [[ ]], +patch = [[ +--- lapi.c 2017/04/19 17:13:00 2.259.1.1 ++++ lapi.c 2017/12/06 18:14:45 +@@ -533,6 +533,7 @@ + lua_lock(L); + if (n == 0) { + setfvalue(L->top, fn); ++ api_incr_top(L); + } + else { + CClosure *cl; +@@ -546,9 +547,9 @@ + /* does not need barrier because closure is white */ + } + setclCvalue(L, L->top, cl); ++ api_incr_top(L); ++ luaC_checkGC(L); + } +- api_incr_top(L); +- luaC_checkGC(L); + lua_unlock(L); + } +]] +} + + +Bug{ +what = [[memory-allocation error when resizing a table can leave it +in an inconsistent state.]], +report = [[Roberto, 2017/12/08]], +since = [[5.0]], +fix = nil, +example = [[ +local a = {x = 1, y = 1, z = 1} +a[1] = 10 -- goes to the hash part (which has 4 slots) +print(a[1]) --> 10 + +-- assume that the 2nd memory allocation from now fails +pcall(rawset, a, 2, 20) -- forces a rehash + +-- a[1] now exists both in the array part (because the array part +-- grew) and in the hash part (because the allocation of the hash +-- part failed, keeping it as it was). +-- This makes the following traversal goes forever... +for k,v in pairs(a) do print(k,v) end +]], +patch = [[ +]] +} + + + + +--[=[ +Bug{ +what = [[ ]], +report = [[ ]], +since = [[ ]], +fix = nil, +example = [[ ]], +patch = [[ +]] +} +]=] + + diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c new file mode 100644 index 000000000..03c890f7e --- /dev/null +++ b/3rd/lua/lapi.c @@ -0,0 +1,1341 @@ +/* +** $Id: lapi.c,v 2.278 2017/12/06 18:08:03 roberto Exp roberto $ +** Lua API +** See Copyright Notice in lua.h +*/ + +#define lapi_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 "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + + +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) + +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) + +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) + +/* test for upvalue */ +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) + +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) + +#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index") + +#define api_checkstackindex(l, i, o) \ + api_check(l, isstackindex(i, o), "index not in the stack") + + +static TValue *index2value (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + StkId o = ci->func + idx; + api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; + else return s2v(o); + } + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return s2v(L->top + idx); + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + int r = LUA_REGISTRYINDEX; + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(s2v(ci->func))) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(s2v(ci->func)); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; + } + } +} + + +static StkId index2stack (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + StkId o = ci->func + idx; + api_check(L, o < L->top, "unacceptable index"); + return o; + } + else { /* non-positive index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, !ispseudo(idx), "invalid index"); + return L->top + idx; + } +} + + +LUA_API int lua_checkstack (lua_State *L, int n) { + int res; + CallInfo *ci = L->ci; + lua_lock(L); + api_check(L, n >= 0, "negative 'n'"); + if (L->stack_last - L->top > n) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = luaD_growstack(L, n, 0); + } + if (res && ci->top < L->top + n) + ci->top = L->top + n; /* adjust frame top */ + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); + from->top -= n; + for (i = 0; i < n; i++) { + setobjs2s(to, to->top, from->top + i); + to->top++; /* stack already checked by previous 'api_check' */ + } + lua_unlock(to); +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; +} + + + +/* +** basic stack manipulation +*/ + + +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func) + idx; +} + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - (L->ci->func + 1)); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) + setnilvalue(s2v(L->top++)); + L->top = (func + 1) + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + L->top += idx+1; /* 'subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +/* +** Reverse the stack segment from 'from' to 'to' +** (auxiliary to 'lua_rotate') +** Note that we move(copy) only the value inside the stack. +** (We do not move additional fields that may exist.) +*/ +static void reverse (lua_State *L, StkId from, StkId to) { + for (; from < to; from++, to--) { + TValue temp; + setobj(L, &temp, s2v(from)); + setobjs2s(L, from, to); + setobj2s(L, to, &temp); + } +} + + +/* +** Let x = AB, where A is a prefix of length 'n'. Then, +** rotate x n == BA. But BA == (A^r . B^r)^r. +*/ +LUA_API void lua_rotate (lua_State *L, int idx, int n) { + StkId p, t, m; + lua_lock(L); + t = L->top - 1; /* end of stack segment being rotated */ + p = index2stack(L, idx); /* start of segment */ + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ + reverse(L, p, m); /* reverse the prefix with length 'n' */ + reverse(L, m + 1, t); /* reverse the suffix */ + reverse(L, p, t); /* reverse the entire segment */ + lua_unlock(L); +} + + +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr, *to; + lua_lock(L); + fr = index2value(L, fromidx); + to = index2value(L, toidx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (isupvalue(toidx)) /* function upvalue? */ + luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2value(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (isvalid(o) ? ttnov(o) : LUA_TNONE); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); + return ttypename(t); +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isinteger (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return ttisinteger(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + lua_Number n; + const TValue *o = index2value(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttisstring(o) || cvt2str(o)); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (ttisfulluserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + const TValue *o1 = index2value(L, index1); + const TValue *o2 = index2value(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; +} + + +LUA_API void lua_arith (lua_State *L, int op) { + lua_lock(L); + if (op != LUA_OPUNM && op != LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ + else { /* for unary operations, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + api_incr_top(L); + } + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); + L->top--; /* remove second operand */ + lua_unlock(L); +} + + +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { + const TValue *o1; + const TValue *o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2value(L, index1); + o2 = index2value(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; +} + + +LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { + size_t sz = luaO_str2num(s, s2v(L->top)); + if (sz != 0) + api_incr_top(L); + return sz; +} + + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { + lua_Number n; + const TValue *o = index2value(L, idx); + int isnum = tonumber(o, &n); + if (!isnum) + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return n; +} + + +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { + lua_Integer res; + const TValue *o = index2value(L, idx); + int isnum = tointeger(o, &res); + if (!isnum) + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return res; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + TValue *o = index2value(L, idx); + if (!ttisstring(o)) { + if (!cvt2str(o)) { /* not convertible? */ + if (len != NULL) *len = 0; + return NULL; + } + lua_lock(L); /* 'luaO_tostring' may create a new string */ + luaO_tostring(L, o); + luaC_checkGC(L); + o = index2value(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) + *len = vslen(o); + return svalue(o); +} + + +LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + switch (ttype(o)) { + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + switch (ttnov(o)) { + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + const TValue *o = index2value(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(s2v(L->top)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setfltvalue(s2v(L->top), n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setivalue(s2v(L->top), n); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** Pushes on the stack a string with given length. Avoid using 's' when +** 'len' == 0 (as 's' can be NULL in that case), due to later use of +** 'memcmp' and 'memcpy'. +*/ +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; + lua_lock(L); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getstr(ts); +} + + +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + lua_lock(L); + if (s == NULL) + setnilvalue(s2v(L->top)); + else { + TString *ts; + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + s = getstr(ts); /* internal copy's address */ + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return s; +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + lua_lock(L); + if (n == 0) { + setfvalue(s2v(L->top), fn); + api_incr_top(L); + } + else { + CClosure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + cl = luaF_newCclosure(L, n); + cl->f = fn; + L->top -= n; + while (n--) { + setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); + /* does not need barrier because closure is white */ + } + setclCvalue(L, s2v(L->top), cl); + api_incr_top(L); + luaC_checkGC(L); + } + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(s2v(L->top), (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(s2v(L->top), p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, s2v(L->top), L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + } + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API int lua_getglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + +LUA_API int lua_gettable (lua_State *L, int idx) { + const TValue *slot; + TValue *t; + lua_lock(L); + t = index2value(L, idx); + if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { + setobj2s(L, L->top - 1, slot); + } + else + luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { + lua_lock(L); + return auxgetstr(L, index2value(L, idx), k); +} + + +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { + TValue *t; + const TValue *slot; + lua_lock(L); + t = index2value(L, idx); + if (luaV_fastgeti(L, t, n, slot)) { + setobj2s(L, L->top, slot); + } + else { + TValue aux; + setivalue(&aux, n); + luaV_finishget(L, t, &aux, L->top, slot); + } + api_incr_top(L); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API int lua_rawget (lua_State *L, int idx) { + TValue *t; + lua_lock(L); + t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), s2v(L->top - 1))); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { + TValue *t; + lua_lock(L); + t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { + TValue *t; + TValue k; + lua_lock(L); + t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; + lua_lock(L); + t = luaH_new(L); + sethvalue2s(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt; + int res = 0; + lua_lock(L); + obj = index2value(L, objindex); + switch (ttnov(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttnov(obj)]; + break; + } + if (mt != NULL) { + sethvalue2s(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API int lua_getuservalue (lua_State *L, int idx) { + TValue *o; + lua_lock(L); + o = index2value(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + getuservalue(L, uvalue(o), s2v(L->top)); + api_incr_top(L); + lua_unlock(L); + return ttnov(s2v(L->top - 1)); +} + + +/* +** set functions (stack -> Lua) +*/ + +/* +** t[k] = value at the top of the stack (where 'k' is a string) +*/ +static void auxsetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + L->top--; /* pop value */ + } + else { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ +} + + +LUA_API void lua_setglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + +LUA_API void lua_settable (lua_State *L, int idx) { + TValue *t; + const TValue *slot; + lua_lock(L); + api_checknelems(L, 2); + t = index2value(L, idx); + if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + } + else + luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2value(L, idx), k); +} + + +LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { + TValue *t; + const TValue *slot; + lua_lock(L); + api_checknelems(L, 1); + t = index2value(L, idx); + if (luaV_fastgeti(L, t, n, slot)) { + luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + } + else { + TValue aux; + setivalue(&aux, n); + luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); + } + L->top--; /* pop value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + TValue *o; + TValue *slot; + lua_lock(L); + api_checknelems(L, 2); + o = index2value(L, idx); + api_check(L, ttistable(o), "table expected"); + slot = luaH_set(L, hvalue(o), s2v(L->top - 2)); + setobj2t(L, slot, s2v(L->top - 1)); + invalidateTMcache(hvalue(o)); + luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = index2value(L, idx); + api_check(L, ttistable(o), "table expected"); + luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); + luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + TValue *o; + TValue k, *slot; + lua_lock(L); + api_checknelems(L, 1); + o = index2value(L, idx); + api_check(L, ttistable(o), "table expected"); + setpvalue(&k, cast(void *, p)); + slot = luaH_set(L, hvalue(o), &k); + setobj2t(L, slot, s2v(L->top - 1)); + luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2value(L, objindex); + if (ttisnil(s2v(L->top - 1))) + mt = NULL; + else { + api_check(L, ttistable(s2v(L->top - 1)), "table expected"); + mt = hvalue(s2v(L->top - 1)); + } + int t = ttnov(obj); + switch (t) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, uvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: { + G(L)->mt[ttnov(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API void lua_setuservalue (lua_State *L, int idx) { + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = index2value(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + setuservalue(L, uvalue(o), s2v(L->top - 1)); + luaC_barrier(L, gcvalue(o), s2v(L->top - 1)); + L->top--; + lua_unlock(L); +} + + +/* +** 'load' and 'call' functions (run Lua code) +*/ + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) { + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_callnoyield(L, func, nresults); /* just do the call */ + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to 'f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_callnoyield(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2stack(L, errfunc); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->u2.funcidx = savestack(L, c.func); + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + luaD_call(L, c.func, nresults); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname, const char *mode) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ + if (f->nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_barrier(L, f->upvals[0], gt); + } + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = s2v(L->top - 1); + if (isLfunction(o)) + status = luaU_dump(L, getproto(o), writer, data, strip); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ +LUA_API int lua_gc (lua_State *L, int what, ...) { + va_list argp; + int res = 0; + global_State *g = G(L); + lua_lock(L); + va_start(argp, what); + switch (what) { + case LUA_GCSTOP: { + g->gcrunning = 0; + break; + } + case LUA_GCRESTART: { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: { + int data = va_arg(argp, int); + l_mem debt = 1; /* =1 to signal that it did an actual step */ + lu_byte oldrunning = g->gcrunning; + g->gcrunning = 1; /* allow GC to run */ + if (data == 0) { + luaE_setdebt(g, 0); /* do a basic step */ + luaC_step(L); + } + else { /* add 'data' to total debt */ + debt = cast(l_mem, data) * 1024 + g->GCdebt; + luaE_setdebt(g, debt); + luaC_checkGC(L); + } + g->gcrunning = oldrunning; /* restore previous state */ + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + break; + } + case LUA_GCSETPAUSE: { + int data = va_arg(argp, int); + res = getgcparam(g->gcpause); + setgcparam(g->gcpause, data); + break; + } + case LUA_GCSETSTEPMUL: { + int data = va_arg(argp, int); + res = getgcparam(g->gcstepmul); + setgcparam(g->gcstepmul, data); + break; + } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + case LUA_GCGEN: { + int minormul = va_arg(argp, int); + int majormul = va_arg(argp, int); + if (minormul != 0) + g->genminormul = minormul; + if (majormul != 0) + setgcparam(g->genmajormul, majormul); + luaC_changemode(L, KGC_GEN); + break; + } + case LUA_GCINC: { + int pause = va_arg(argp, int); + int stepmul = va_arg(argp, int); + int stepsize = va_arg(argp, int); + if (pause != 0) + setgcparam(g->gcpause, pause); + if (stepmul != 0) + setgcparam(g->gcstepmul, stepmul); + if (stepsize != 0) + g->gcstepsize = stepsize; + luaC_changemode(L, KGC_INC); + break; + } + default: res = -1; /* invalid option */ + } + va_end(argp); + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + TValue *t; + int more; + lua_lock(L); + t = index2value(L, idx); + api_check(L, ttistable(t), "table expected"); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaV_concat(L, n); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API void lua_len (lua_State *L, int idx) { + TValue *t; + lua_lock(L); + t = index2value(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + u = luaS_newudata(L, size); + setuvalue(L, s2v(L->top), u); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getudatamem(u); +} + + + +static const char *aux_upvalue (TValue *fi, int n, TValue **val, + GCObject **owner) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = obj2gco(f); + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (owner) *owner = obj2gco(f->upvals[n - 1]); + name = p->upvalues[n-1].name; + return (name == NULL) ? "(*no name)" : getstr(name); + } + default: return NULL; /* not a closure */ + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ + TValue *fi; + lua_lock(L); + fi = index2value(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner); + if (name) { + L->top--; + setobj(L, val, s2v(L->top)); + luaC_barrier(L, owner, val); + } + lua_unlock(L); + return name; +} + + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + LClosure *f; + TValue *fi = index2value(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + TValue *fi = index2value(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + *up1 = *up2; + luaC_objbarrier(L, f1, *up1); +} + + diff --git a/3rd/lua/lapi.h b/3rd/lua/lapi.h new file mode 100644 index 000000000..77ebb3002 --- /dev/null +++ b/3rd/lua/lapi.h @@ -0,0 +1,24 @@ +/* +** $Id: lapi.h,v 2.10 2017/11/01 18:20:48 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "llimits.h" +#include "lstate.h" + +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") + + +#endif diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c new file mode 100644 index 000000000..2c2610773 --- /dev/null +++ b/3rd/lua/lauxlib.c @@ -0,0 +1,1043 @@ +/* +** $Id: lauxlib.c,v 1.290 2017/04/24 18:06:12 roberto Exp roberto $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + + +/* +** This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#include "lua.h" + +#include "lauxlib.h" + + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 10 /* size of the first part of the stack */ +#define LEVELS2 11 /* size of the second part of the stack */ + + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +/* +** Search for a name for a function in all loaded modules +*/ +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + if (findfield(L, top + 1, 2)) { + const char *name = lua_tostring(L, -1); + if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */ + lua_pushstring(L, name + 3); /* push name without prefix */ + lua_remove(L, -2); /* remove original name */ + } + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (pushglobalfuncname(L, ar)) { /* try first a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else if (*ar->namewhat != '\0') /* is there a name from code? */ + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what != 'C') /* for Lua functions, use */ + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); + else /* nothing left... */ + lua_pushliteral(L, "?"); +} + + +static int lastlevel (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int last = lastlevel(L1); + int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + if (msg) + lua_pushfstring(L, "%s\n", msg); + luaL_checkstack(L, 10, NULL); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (n1-- == 0) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = last - LEVELS2 + 1; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + arg--; /* do not count 'self' */ + if (arg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling '%s' on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to '%s' (%s)", + arg, ar.name, extramsg); +} + + +static int typeerror (lua_State *L, int arg, const char *tname) { + const char *msg; + const char *typearg; /* name for the type of the actual argument */ + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) + typearg = lua_tostring(L, -1); /* use the given type name */ + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) + typearg = "light userdata"; /* special name for messages */ + else + typearg = luaL_typename(L, arg); /* standard name */ + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); + return luaL_argerror(L, arg, msg); +} + + +static void tag_error (lua_State *L, int arg, int tag) { + typeerror(L, arg, lua_typename(L, tag)); +} + + +/* +** The use of 'lua_pushfstring' ensures this function does not +** need reserved stack space when called. +*/ +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushfstring(L, ""); /* else, no information available... */ +} + + +/* +** Again, the use of 'lua_pushvfstring' ensures this function does +** not need reserved stack space when called. (At worst, it generates +** an error with "stack overflow" instead of the given message.) +*/ +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + + +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +#if !defined(l_inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define l_inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define l_inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + l_inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_createtable(L, 0, 2); /* create metatable */ + lua_pushstring(L, tname); + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, arg, def) : + luaL_checkstring(L, arg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, arg, + lua_pushfstring(L, "invalid option '%s'", name)); +} + + +/* +** Ensures the stack has at least 'space' extra slots, raising an error +** if it cannot fulfill the request. (The error handling needs a few +** extra slots to format the error message. In case of an error without +** this extra space, Lua will generate the same 'stack overflow' error, +** but without 'msg'.) +*/ +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { + if (!lua_checkstack(L, space)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } +} + + +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { + if (lua_type(L, arg) != t) + tag_error(L, arg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int arg) { + if (lua_type(L, arg) == LUA_TNONE) + luaL_argerror(L, arg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { + const char *s = lua_tolstring(L, arg, len); + if (!s) tag_error(L, arg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, arg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, arg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { + int isnum; + lua_Number d = lua_tonumberx(L, arg, &isnum); + if (!isnum) + tag_error(L, arg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, arg, def); +} + + +static void interror (lua_State *L, int arg) { + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); + else + tag_error(L, arg, LUA_TNUMBER); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { + int isnum; + lua_Integer d = lua_tointegerx(L, arg, &isnum); + if (!isnum) { + interror(L, arg); + } + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, arg, def); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +/* userdata to box arbitrary data */ +typedef struct UBox { + void *box; + size_t bsize; +} UBox; + + +static void *resizebox (lua_State *L, int idx, size_t newsize) { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox *box = (UBox *)lua_touserdata(L, idx); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (temp == NULL && newsize > 0) { /* allocation error? */ + resizebox(L, idx, 0); /* free buffer */ + luaL_error(L, "not enough memory for buffer allocation"); + } + box->box = temp; + box->bsize = newsize; + return temp; +} + + +static int boxgc (lua_State *L) { + resizebox(L, 1, 0); + return 0; +} + + +static void *newbox (lua_State *L, size_t newsize) { + UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ + lua_pushcfunction(L, boxgc); + lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ + } + lua_setmetatable(L, -2); + return resizebox(L, -1, newsize); +} + + +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->init.b) + + +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + if (buffonstack(B)) + newbuff = (char *)resizebox(L, -1, newsize); + else { /* no buffer yet */ + newbuff = (char *)newbox(L, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) { + resizebox(L, -2, 0); /* delete old buffer */ + lua_remove(L, -2); /* remove its header from the stack */ + } +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->b = B->init.b; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[BUFSIZ]; /* area for reading file */ +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); +} + + +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + +/* }====================================================== */ + + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return LUA_TNIL; + else { + int tt; + lua_pushstring(L, event); + tt = lua_rawget(L, -2); + if (tt == LUA_TNIL) /* is metafield nil? */ + lua_pop(L, 2); /* remove metatable and metafield */ + else + lua_remove(L, -2); /* remove only metatable */ + return tt; /* return metafield type */ + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = lua_absindex(L, obj); + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { + lua_Integer l; + int isnum; + lua_len(L, idx); + l = lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not an integer"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + else { + switch (lua_type(L, idx)) { + case LUA_TNUMBER: { + if (lua_isinteger(L, idx)) + lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); + else + lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); + break; + } + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: { + int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ + const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : + luaL_typename(L, idx); + lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_remove(L, -2); /* remove '__name' */ + break; + } + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1); + if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no LOADED[modname]? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module '%s'", modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove LOADED table */ +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} + +#endif +/* }====================================================== */ + +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + if (lua_getfield(L, idx, fname) == LUA_TTABLE) + return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** Stripped-down 'require': After checking "loaded" table, calls 'openf' +** to open a module, registers the result in 'package.loaded' table and, +** if 'glb' is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, -1, modname); /* LOADED[modname] */ + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of module */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after 'p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { + const lua_Number *v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); +} + diff --git a/3rd/lua/lauxlib.h b/3rd/lua/lauxlib.h new file mode 100644 index 000000000..79d1f30ab --- /dev/null +++ b/3rd/lua/lauxlib.h @@ -0,0 +1,271 @@ +/* +** $Id: lauxlib.h,v 1.132 2017/04/24 18:06:12 roberto Exp roberto $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +/* global table */ +#define LUA_GNAME "_G" + + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + union { + LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ + char b[LUAL_BUFFERSIZE]; /* initial buffer */ + } init; +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/3rd/lua/lbaselib.c b/3rd/lua/lbaselib.c new file mode 100644 index 000000000..00452f2d3 --- /dev/null +++ b/3rd/lua/lbaselib.c @@ -0,0 +1,525 @@ +/* +** $Id: lbaselib.c,v 1.317 2017/06/27 18:32:49 roberto Exp roberto $ +** Basic library +** See Copyright Notice in lua.h +*/ + +#define lbaselib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + size_t l; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tolstring(L, -1, &l); /* get result */ + if (s == NULL) + return luaL_error(L, "'tostring' must return a string to 'print'"); + if (i>1) lua_writestring("\t", 1); + lua_writestring(s, l); + lua_pop(L, 1); /* pop result */ + } + lua_writeline(); + return 0; +} + + +#define SPACECHARS " \f\n\r\t\v" + +static const char *b_str2int (const char *s, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle sign */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return NULL; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : (toupper((unsigned char)*s) - 'A') + 10; + if (digit >= base) return NULL; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + *pn = (lua_Integer)((neg) ? (0u - n) : n); + return s; +} + + +static int luaB_tonumber (lua_State *L) { + if (lua_isnoneornil(L, 2)) { /* standard conversion? */ + luaL_checkany(L, 1); + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ + return 1; + } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_stringtonumber(L, s) == l + 1) + return 1; /* successful conversion to number */ + /* else not a number */ + } + } + else { + size_t l; + const char *s; + lua_Integer n = 0; /* to avoid warnings */ + lua_Integer base = luaL_checkinteger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + if (b_str2int(s, (int)base, &n) == s + l) { + lua_pushinteger(L, n); + return 1; + } /* else not a number */ + } /* else not a number */ + lua_pushnil(L); /* not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = (int)luaL_optinteger(L, 2, 1); + lua_settop(L, 1); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) { + luaL_where(L, level); /* add extra information */ + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "isrunning", "generational", "incremental", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + switch (o) { + case LUA_GCCOUNT: { + int k = lua_gc(L, o); + int b = lua_gc(L, LUA_GCCOUNTB); + lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + int step = (int)luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, step); + lua_pushboolean(L, res); + return 1; + } + case LUA_GCSETPAUSE: + case LUA_GCSETSTEPMUL: { + int p = (int)luaL_optinteger(L, 2, 0); + int previous = lua_gc(L, o, p); + lua_pushinteger(L, previous); + return 1; + } + case LUA_GCISRUNNING: { + int res = lua_gc(L, o); + lua_pushboolean(L, res); + return 1; + } + case LUA_GCGEN: { + int minormul = (int)luaL_optinteger(L, 2, 0); + int majormul = (int)luaL_optinteger(L, 3, 0); + lua_gc(L, o, minormul, majormul); + return 0; + } + case LUA_GCINC: { + int pause = (int)luaL_optinteger(L, 2, 0); + int stepmul = (int)luaL_optinteger(L, 3, 0); + int stepsize = (int)luaL_optinteger(L, 4, 0); + lua_gc(L, o, pause, stepmul, stepsize); + return 0; + } + default: { + int res = lua_gc(L, o); + lua_pushinteger(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); + return 1; +} + + +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + luaL_checkany(L, 1); + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + return pairsmeta(L, "__pairs", 0, luaB_next); +} + + +/* +** Traversal function for 'ipairs' +*/ +static int ipairsaux (lua_State *L) { + lua_Integer i = luaL_checkinteger(L, 2) + 1; + lua_pushinteger(L, i); + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; +} + + +/* +** 'ipairs' function. Returns 'ipairsaux', given "table", 0. +** (The given "table" may not be a table.) +*/ +static int luaB_ipairs (lua_State *L) { +#if defined(LUA_COMPAT_IPAIRS) + return pairsmeta(L, "__ipairs", 1, ipairsaux); +#else + luaL_checkany(L, 1); + lua_pushcfunction(L, ipairsaux); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ + return 3; +#endif +} + + +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else { /* error (message is on top of the stack) */ + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); +} + + +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** Reader for generic 'load' function: 'lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)(ud); /* not used */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); +} + + +static int luaB_load (lua_State *L) { + int status; + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); +} + +/* }====================================================== */ + + +static int dofilecont (lua_State *L, int d1, lua_KContext d2) { + (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ + return lua_gettop(L) - 1; +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); +} + + +static int luaB_assert (lua_State *L) { + if (lua_toboolean(L, 1)) /* condition is true? */ + return lua_gettop(L); /* return all arguments */ + else { /* error */ + luaL_checkany(L, 1); /* there must be a condition */ + lua_remove(L, 1); /* remove it */ + lua_pushliteral(L, "assertion failed!"); /* default message */ + lua_settop(L, 1); /* leave only message (default if no other one) */ + return luaB_error(L); /* call 'error' */ + } +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + lua_Integer i = luaL_checkinteger(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - (int)i; + } +} + + +/* +** Continuation function for 'pcall' and 'xpcall'. Both functions +** already pushed a 'true' before doing the call, so in case of success +** 'finishpcall' only has to return everything in the stack minus +** 'extra' values (where 'extra' is exactly the number of items to be +** ignored). +*/ +static int finishpcall (lua_State *L, int status, lua_KContext extra) { + if (status != LUA_OK && status != LUA_YIELD) { /* error? */ + lua_pushboolean(L, 0); /* first result (false) */ + lua_pushvalue(L, -2); /* error message */ + return 2; /* return false, msg */ + } + else + return lua_gettop(L) - (int)extra; /* return all results */ +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + lua_pushboolean(L, 1); /* first result if no errors */ + lua_insert(L, 1); /* put it in place */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); + return finishpcall(L, status, 0); +} + + +/* +** Do a protected call with error handling. After 'lua_rotate', the +** stack will have ; so, the function passes +** 2 to 'finishpcall' to skip the 2 first values when returning results. +*/ +static int luaB_xpcall (lua_State *L) { + int status; + int n = lua_gettop(L); + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ + lua_pushboolean(L, 1); /* first result */ + lua_pushvalue(L, 1); /* function */ + lua_rotate(L, 3, 2); /* move them below function's arguments */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); + return finishpcall(L, status, 2); +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + /* placeholders */ + {LUA_GNAME, NULL}, + {"_VERSION", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_base (lua_State *L) { + /* open lib into global table */ + lua_pushglobaltable(L); + luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, LUA_GNAME); + /* set global _VERSION */ + lua_pushliteral(L, LUA_VERSION); + lua_setfield(L, -2, "_VERSION"); + return 1; +} + diff --git a/3rd/lua/lbitlib.c b/3rd/lua/lbitlib.c new file mode 100644 index 000000000..63dbbe1d1 --- /dev/null +++ b/3rd/lua/lbitlib.c @@ -0,0 +1,233 @@ +/* +** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp roberto $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if defined(LUA_COMPAT_BITLIB) /* { */ + + +#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +/* +** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must +** be made in two parts to avoid problems when LUA_NBITS is equal to the +** number of bits in a lua_Unsigned.) +*/ +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + + +static lua_Unsigned andaux (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = ~(lua_Unsigned)0; + for (i = 1; i <= n; i++) + r &= checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + lua_Unsigned r = andaux(L); + pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + lua_Unsigned r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r |= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r ^= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + lua_Unsigned r = ~checkunsigned(L, 1); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); +} + + +static int b_arshift (lua_State *L) { + lua_Unsigned r = checkunsigned(L, 1); + lua_Integer i = luaL_checkinteger(L, 2); + if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add sign bit */ + pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, lua_Integer d) { + lua_Unsigned r = checkunsigned(L, 1); + int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ + r = trim(r); + if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ + r = (r << i) | (r >> (LUA_NBITS - i)); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkinteger(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkinteger(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + lua_Integer f = luaL_checkinteger(L, farg); + lua_Integer w = luaL_optinteger(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = (int)w; + return (int)f; +} + + +static int b_extract (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + lua_Unsigned v = trim(checkunsigned(L, 2)); + int f = fieldargs(L, 3, &w); + lua_Unsigned m = mask(w); + r = (r & ~(m << f)) | ((v & m) << f); + pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + + +#else /* }{ */ + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + return luaL_error(L, "library 'bit32' has been deprecated"); +} + +#endif /* } */ diff --git a/3rd/lua/lcode.c b/3rd/lua/lcode.c new file mode 100644 index 000000000..1eae475ab --- /dev/null +++ b/3rd/lua/lcode.c @@ -0,0 +1,1641 @@ +/* +** $Id: lcode.c,v 2.147 2017/12/22 14:16:46 roberto Exp roberto $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#define lcode_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* Maximum number of registers in a Lua function (must fit in 8 bits) */ +#define MAXREGS 255 + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int codesJ (FuncState *fs, OpCode o, int sj, int k); + + +/* +** If expression is a numeric constant, fills 'v' with its value +** and returns 1. Otherwise, returns 0. +*/ +static int tonumeral(const expdesc *e, TValue *v) { + if (hasjumps(e)) + return 0; /* not a numeral */ + switch (e->k) { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setfltvalue(v, e->u.nval); + return 1; + default: return 0; + } +} + + +/* +** Create a OP_LOADNIL instruction, but try to optimize: if the previous +** instruction is also OP_LOADNIL and ranges are compatible, adjust +** range of previous instruction instead of emitting a new one. (For +** instance, 'local a; local b' will generate a single opcode.) +*/ +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + int l = from + n - 1; /* last register to set nil */ + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ + int pfrom = GETARG_A(*previous); /* get previous range */ + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +} + + +/* +** Gets the destination address of a jump instruction. Used to traverse +** a list of jumps. +*/ +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sJ(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +/* +** Fix jump instruction at position 'pc' to jump to 'dest'. +** (Jump addresses are relative in Lua) +*/ +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + lua_assert(dest != NO_JUMP); + if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ)) + luaX_syntaxerror(fs->ls, "control structure too long"); + lua_assert(GET_OPCODE(*jmp) == OP_JMP); + SETARG_sJ(*jmp, offset); +} + + +/* +** Concatenate jump-list 'l2' into jump-list 'l1' +*/ +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; /* nothing to concatenate? */ + else if (*l1 == NO_JUMP) /* no original list? */ + *l1 = l2; /* 'l1' points to 'l2' */ + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); /* last element links to 'l2' */ + } +} + + +/* +** Create a jump instruction and return its position, so its destination +** can be fixed later (with 'fixjump'). +*/ +int luaK_jump (FuncState *fs) { + return codesJ(fs, OP_JMP, NO_JUMP, 0); +} + + +/* +** Code a 'return' instruction +*/ +void luaK_ret (FuncState *fs, int first, int nret) { + switch (nret) { + case 0: + luaK_codeABC(fs, OP_RETURN0, 0, 0, 0); + break; + case 1: + luaK_codeABC(fs, OP_RETURN1, first, 0, 0); + break; + default: + luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0); + break; + } +} + + +/* +** Code a "conditional jump", that is, a test or comparison opcode +** followed by a jump. Return jump position. +*/ +static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { + luaK_codeABCk(fs, op, A, B, C, k); + return luaK_jump(fs); +} + + +/* +** returns current 'pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +/* +** Returns the position of the instruction "controlling" a given +** jump (that is, its condition), or the jump itself if it is +** unconditional. +*/ +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** Patch destination register for a TESTSET instruction. +** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). +** Otherwise, if 'reg' is not 'NO_REG', set it as the destination +** register. Otherwise, change instruction to a simple 'TEST' (produces +** no register value) +*/ +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else { + /* no register to put value or register already has the value; + change instruction to simple test */ + *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); + } + return 1; +} + + +/* +** Traverse a list of tests ensuring no one produces a value +*/ +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +/* +** Traverse a list of tests, patching their destination address and +** registers: tests producing values jump to 'vtarget' (and put their +** values in 'reg'), other tests jump to 'dtarget'. +*/ +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +/* +** Path all jumps in 'list' to jump to 'target'. +** (The assert means that we cannot fix a jump to a forward address +** because we only know addresses once code is generated.) +*/ +void luaK_patchlist (FuncState *fs, int list, int target) { + lua_assert(target <= fs->pc); + patchlistaux(fs, list, target, NO_REG, target); +} + + +void luaK_patchtohere (FuncState *fs, int list) { + int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_patchlist(fs, list, hr); +} + + +/* +** Correct a jump list to jump to 'target'. If 'hasclose' is true, +** 'target' contains an OP_CLOSE instruction (see first assert). +** Only jumps with the 'k' arg true need that close; other jumps +** avoid it jumping to the next instruction. +*/ +void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { + lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE); + while (list != NO_JUMP) { + int next = getjump(fs, list); + lua_assert(!GETARG_k(fs->f->code[list]) || hasclose); + patchtestreg(fs, list, NO_REG); /* do not generate values */ + if (!hasclose || GETARG_k(fs->f->code[list])) + fixjump(fs, list, target); + else /* there is a CLOSE instruction but jump does not need it */ + fixjump(fs, list, target + 1); /* avoid CLOSE instruction */ + list = next; + } +} + + +/* +** Mark (using the 'k' arg) all jumps in 'list' to close upvalues. Mark +** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE +** instructions. +*/ +void luaK_patchclose (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP); + SETARG_k(fs->f->code[list], 1); + } +} + + +#if !defined(MAXIWTHABS) +#define MAXIWTHABS 120 +#endif + +/* +** Save line info for a new instruction. If difference from last line +** does not fit in a byte, of after that many instructions, save a new +** absolute line info; (in that case, the special value 'ABSLINEINFO' +** in 'lineinfo' signals the existence of this absolute information.) +** Otherwise, store the difference from last line in 'lineinfo'. +*/ +static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { + int linedif = line - fs->previousline; + if (abs(linedif) >= 0x80 || fs->iwthabs++ > MAXIWTHABS) { + luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, + f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); + f->abslineinfo[fs->nabslineinfo].pc = pc; + f->abslineinfo[fs->nabslineinfo++].line = line; + linedif = ABSLINEINFO; /* signal there is absolute information */ + fs->iwthabs = 0; /* restart counter */ + } + luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, + MAX_INT, "opcodes"); + f->lineinfo[pc] = linedif; + fs->previousline = line; /* last line saved */ +} + + +/* +** Emit instruction 'i', checking for array sizes and saving also its +** line information. Return 'i' position. +*/ +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + savelineinfo(fs, f, fs->pc, fs->ls->lastline); + return fs->pc++; +} + + +/* +** Format and emit an 'iABC' instruction. (Assertions check consistency +** of parameters versus opcode.) +*/ +int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { + lua_assert(getOpMode(o) == iABC); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && + c <= MAXARG_C && (k & ~1) == 0); + return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); +} + + +#define codeABsC(fs,o,a,b,c,k) luaK_codeABCk(fs,o,a,b,((c) + OFFSET_sC),k) + + + +/* +** Format and emit an 'iABx' instruction. +*/ +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +/* +** Format and emit an 'iAsBx' instruction. +*/ +int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { + unsigned int b = bc + OFFSET_sBx; + lua_assert(getOpMode(o) == iAsBx); + lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, b)); +} + + +/* +** Format and emit an 'isJ' instruction. +*/ +static int codesJ (FuncState *fs, OpCode o, int sj, int k) { + unsigned int j = sj + OFFSET_sJ; + lua_assert(getOpMode(o) == isJ); + lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); + return luaK_code(fs, CREATE_sJ(o, j, k)); +} + + +/* +** Emit an "extra argument" instruction (format 'iAx') +*/ +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +/* +** Emit a "load constant" instruction, using either 'OP_LOADK' +** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' +** instruction with "extra argument". +*/ +static int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + +/* +** Check register-stack level, keeping track of its maximum size +** in field 'maxstacksize' +*/ +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXREGS) + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +/* +** Reserve 'n' registers in register stack +*/ +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +/* +** Free register 'reg', if it is neither a constant index nor +** a local variable. +) +*/ +static void freereg (FuncState *fs, int reg) { + if (reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +/* +** Free two registers in proper order +*/ +static void freeregs (FuncState *fs, int r1, int r2) { + if (r1 > r2) { + freereg(fs, r1); + freereg(fs, r2); + } + else { + freereg(fs, r2); + freereg(fs, r1); + } +} + + +/* +** Free register used by expression 'e' (if any) +*/ +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.info); +} + + +/* +** Free registers used by expressions 'e1' and 'e2' (if any) in proper +** order. +*/ +static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { + int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; + int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; + freeregs(fs, r1, r2); +} + + +/* +** Add constant 'v' to prototype's list of constants (field 'k'). +** Use scanner's table to cache position of constants in constant list +** and try to reuse constants. Because some values should not be used +** as keys (nil cannot be a key, integer keys can collapse with float +** keys), the caller must provide a useful 'key' for indexing the cache. +*/ +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + Proto *f = fs->f; + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ + int k, oldsize; + if (ttisinteger(idx)) { /* is there an index there? */ + k = cast_int(ivalue(idx)); + /* correct value? (warning: must distinguish floats from integers!) */ + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && + luaV_rawequalobj(&f->k[k], v)) + return k; /* reuse index */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setivalue(idx, k); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +/* +** Add a string to list of constants and return its index. +*/ +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); /* use string itself as key */ +} + + +/* +** Add an integer to list of constants and return its index. +** Integers use userdata as keys to avoid collision with floats with +** same value; conversion to 'void*' is used only for hashing, so there +** are no "precision" problems. +*/ +static int luaK_intK (FuncState *fs, lua_Integer n) { + TValue k, o; + setpvalue(&k, cast(void*, cast(size_t, n))); + setivalue(&o, n); + return addk(fs, &k, &o); +} + +/* +** Add a float to list of constants and return its index. +*/ +static int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setfltvalue(&o, r); + return addk(fs, &o, &o); /* use number itself as key */ +} + + +/* +** Add a boolean to list of constants and return its index. +*/ +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); /* use boolean itself as key */ +} + + +/* +** Add nil to list of constants and return its index. +*/ +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->ls->L, &k, fs->ls->h); + return addk(fs, &k, &v); +} + + +/* +** Check whether 'i' can be stored in an 'sC' operand. +** Equivalent to (0 <= i + OFFSET_sC && i + OFFSET_sC <= MAXARG_C) +** but without risk of overflows in the addition. +*/ +static int fitsC (lua_Integer i) { + return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC); +} + + +/* +** Check whether 'i' can be stored in an 'sBx' operand. +*/ +static int fitsBx (lua_Integer i) { + return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx); +} + + +void luaK_int (FuncState *fs, int reg, lua_Integer i) { + if (fitsBx(i)) + luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i)); + else + luaK_codek(fs, reg, luaK_intK(fs, i)); +} + + +static int floatI (lua_Number f, lua_Integer *fi) { + TValue v; + setfltvalue(&v, f); + return (luaV_flttointeger(&v, fi, 0) && fitsBx(*fi)); +} + + +static void luaK_float (FuncState *fs, int reg, lua_Number f) { + lua_Integer fi; + if (floatI(f, &fi)) + luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); + else + luaK_codek(fs, reg, luaK_numberK(fs, f)); +} + + +/* +** Fix an expression to return the number of results 'nresults'. +** Either 'e' is a multi-ret expression (function call or vararg) +** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). +*/ +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + Instruction *pc = &getinstruction(fs, e); + if (e->k == VCALL) /* expression is an open function call? */ + SETARG_C(*pc, nresults + 1); + else if (e->k == VVARARG) { + SETARG_C(*pc, nresults + 1); + SETARG_A(*pc, fs->freereg); + luaK_reserveregs(fs, 1); + } + else lua_assert(nresults == LUA_MULTRET); +} + + +/* +** Fix an expression to return one result. +** If expression is not a multi-ret expression (function call or +** vararg), it already returns one result, so nothing needs to be done. +** Function calls become VNONRELOC expressions (as its result comes +** fixed in the base register of the call), while vararg expressions +** become VRELOC (as OP_VARARG puts its results where it wants). +** (Calls are created returning one result, so that does not need +** to be fixed.) +*/ +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + /* already returns 1 value */ + lua_assert(GETARG_C(getinstruction(fs, e)) == 2); + e->k = VNONRELOC; /* result has fixed position */ + e->u.info = GETARG_A(getinstruction(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_C(getinstruction(fs, e), 2); + e->k = VRELOC; /* can relocate its simple result */ + } +} + + +/* +** Ensure that expression 'e' is not a variable. +*/ +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { /* already in a register */ + e->k = VNONRELOC; /* becomes a non-relocatable value */ + break; + } + case VUPVAL: { /* move value to some (pending) register */ + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOC; + break; + } + case VINDEXUP: { + e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXI: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXSTR: { + freereg(fs, e->u.ind.t); + e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VINDEXED: { + freeregs(fs, e->u.ind.t, e->u.ind.idx); + e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOC; + break; + } + case VVARARG: case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +/* +** Ensures expression value is in register 'reg' (and therefore +** 'e' will become a non-relocatable expression). +*/ +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codek(fs, reg, e->u.info); + break; + } + case VKFLT: { + luaK_float(fs, reg, e->u.nval); + break; + } + case VKINT: { + luaK_int(fs, reg, e->u.ival); + break; + } + case VRELOC: { + Instruction *pc = &getinstruction(fs, e); + SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ + break; + } + case VNONRELOC: { + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: { + lua_assert(e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensures expression value is in any register. +*/ +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { /* no fixed register yet? */ + luaK_reserveregs(fs, 1); /* get a register */ + discharge2reg(fs, e, fs->freereg-1); /* put value there */ + } +} + + +static int code_loadbool (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +/* +** check whether list has any jump that do not produce a value +** or produce an inverted value +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in register 'reg'. +** If expression has jumps, need to patch these jumps either to +** its final position or to "load" instructions (for those tests +** that do not produce values). +*/ +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) /* expression itself is a test? */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_loadbool(fs, reg, 0, 1); + p_t = code_loadbool(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in next available register. +*/ +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in some (any) register and return that register. +*/ +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { /* expression already has a register? */ + if (!hasjumps(e)) /* no jumps? */ + return e->u.info; /* result is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put final result in it */ + return e->u.info; + } + } + luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ + return e->u.info; +} + + +/* +** Ensures final expression result is either in a register or in an +** upvalue. +*/ +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + +/* +** Ensures final expression result is either in a register or it is +** a constant. +*/ +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +/* +** Ensures final expression result is in a valid R/K index +** (that is, it is either in a register or in 'k' with an index +** in the range of R/K indices). +** Returns 1 if expression is K, 0 otherwise. +*/ +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { /* move constants to 'k' */ + case VTRUE: e->u.info = boolK(fs, 1); goto vk; + case VFALSE: e->u.info = boolK(fs, 0); goto vk; + case VNIL: e->u.info = nilK(fs); goto vk; + case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; + case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; + case VK: + vk: + e->k = VK; + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ + return 1; + else break; + default: break; + } + /* not a constant in the right range: put it in a register */ + luaK_exp2anyreg(fs, e); + return 0; +} + + +static void codeABRK (FuncState *fs, OpCode o, int a, int b, + expdesc *ec) { + int k = luaK_exp2RK(fs, ec); + luaK_codeABCk(fs, o, a, b, ec->u.info, k); +} + + +/* +** Generate code to store result of expression 'ex' into variable 'var'. +*/ +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXUP: { + codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXI: { + codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXSTR: { + codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex); + break; + } + case VINDEXED: { + codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex); + break; + } + default: lua_assert(0); /* invalid var kind to store */ + } + freeexp(fs, ex); +} + + +/* +** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). +*/ +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + codeABRK(fs, OP_SELF, e->u.info, ereg, key); + freeexp(fs, key); +} + + +/* +** Negate condition 'e' (where 'e' is a comparison). +*/ +static void negatecondition (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); +} + + +/* +** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' +** is true, code will jump if 'e' is true.) Return jump position. +** Optimize when 'e' is 'not' something, inverting the condition +** and removing the 'not'. +*/ +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOC) { + Instruction ie = getinstruction(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); +} + + +/* +** Emit code to go through if 'e' is true, jump otherwise. +*/ +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { /* condition? */ + negatecondition(fs, e); /* jump when it is false */ + pc = e->u.info; /* save jump position */ + break; + } + case VK: case VKFLT: case VKINT: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 0); /* jump when false */ + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ + luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ + e->t = NO_JUMP; +} + + +/* +** Emit code to go through if 'e' is false, jump otherwise. +*/ +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + pc = e->u.info; /* already jump if true */ + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 1); /* jump if true */ + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ + luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ + e->f = NO_JUMP; +} + + +/* +** Code 'not e', doing constant folding. +*/ +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; /* true == not nil == not false */ + break; + } + case VK: case VKFLT: case VKINT: case VTRUE: { + e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ + break; + } + case VJMP: { + negatecondition(fs, e); + break; + } + case VRELOC: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOC; + break; + } + default: lua_assert(0); /* cannot happen */ + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); /* values are useless when negated */ + removevalues(fs, e->t); +} + + +/* +** Check whether expression 'e' is a small literal string +*/ +static int isKstr (FuncState *fs, expdesc *e) { + return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && + ttisshrstring(&fs->f->k[e->u.info])); +} + +/* +** Check whether expression 'e' is a literal integer. +*/ +int luaK_isKint (expdesc *e) { + return (e->k == VKINT && !hasjumps(e)); +} + + +/* +** Check whether expression 'e' is a literal integer in +** proper range to fit in register C +*/ +static int isCint (expdesc *e) { + return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C)); +} + + +/* +** Check whether expression 'e' is a literal integer in +** proper range to fit in register sC +*/ +static int isSCint (expdesc *e) { + return luaK_isKint(e) && fitsC(e->u.ival); +} + + +/* +** Check whether expression 'e' is a literal integer or float in +** proper range to fit in register sC +*/ +static int isSCnumber (expdesc *e, lua_Integer *i) { + if (e->k == VKINT) + *i = e->u.ival; + else if (!(e->k == VKFLT && floatI(e->u.nval, i))) + return 0; /* not a number */ + if (!hasjumps(e) && fitsC(*i)) { + *i += OFFSET_sC; + return 1; + } + else + return 0; +} + + +/* +** Create expression 't[k]'. 't' must have its final result already in a +** register or upvalue. Upvalues can only be indexed by literal strings. +** Keys can be literal strings in the constant table or arbitrary +** values in registers. +*/ +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); + if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */ + luaK_exp2anyreg(fs, t); /* put it in a register */ + t->u.ind.t = t->u.info; /* register or upvalue index */ + if (t->k == VUPVAL) { + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXUP; + } + else if (isKstr(fs, k)) { + t->u.ind.idx = k->u.info; /* literal string */ + t->k = VINDEXSTR; + } + else if (isCint(k)) { + t->u.ind.idx = cast_int(k->u.ival); /* integer constant in proper range */ + t->k = VINDEXI; + } + else { + t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ + t->k = VINDEXED; + } +} + + +/* +** Return false if folding can raise an error. +** Bitwise operations need operands convertible to integers; division +** operations cannot have 0 as divisor. +*/ +static int validop (int op, TValue *v1, TValue *v2) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ + lua_Integer i; + return (tointegerns(v1, &i) && tointegerns(v2, &i)); + } + case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ + return (nvalue(v2) != 0); + default: return 1; /* everything else is valid */ + } +} + + +/* +** Try to "constant-fold" an operation; return 1 iff successful. +** (In this case, 'e1' has the final result.) +*/ +static int constfolding (FuncState *fs, int op, expdesc *e1, + const expdesc *e2) { + TValue v1, v2, res; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) + return 0; /* non-numeric operands or not safe to fold */ + luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ + if (ttisinteger(&res)) { + e1->k = VKINT; + e1->u.ival = ivalue(&res); + } + else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ + lua_Number n = fltvalue(&res); + if (luai_numisnan(n) || n == 0) + return 0; + e1->k = VKFLT; + e1->u.nval = n; + } + return 1; +} + + +/* +** Emit code for unary expressions that "produce values" +** (everything but 'not'). +** Expression to produce final result will be encoded in 'e'. +*/ +static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { + int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ + e->k = VRELOC; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, + int pc, int line) { + freeexps(fs, e1, e2); + e1->u.info = pc; + e1->k = VRELOC; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for binary expressions that "produce values" +** (everything but logical operators 'and'/'or' and comparison +** operators). +** Expression to produce final result will be encoded in 'e1'. +** Because 'luaK_exp2anyreg' can free registers, its calls must be +** in "stack order" (that is, first on 'e2', which may have more +** recent registers to be released). +*/ +static void codebinexpval (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ + int v1 = luaK_exp2anyreg(fs, e1); + int pc = luaK_codeABC(fs, op, 0, v1, v2); /* generate opcode */ + finishbinexpval(fs, e1, e2, pc, line); +} + + +/* +** Code binary operators ('+', '-', ...) with immediate operands. +*/ +static void codebini (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int k, int line) { + int v2 = cast_int(e2->u.ival); /* immediate operand */ + int v1 = luaK_exp2anyreg(fs, e1); + int pc = codeABsC(fs, op, 0, v1, v2, k); /* generate opcode */ + finishbinexpval(fs, e1, e2, pc, line); +} + + +/* +** Code arithmetic operators ('+', '-', ...). If second operand is a +** constant in the proper range, use variant opcodes with immediate +** operands. +*/ +static void codearith (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int flip, int line) { + if (!isSCint(e2)) + codebinexpval(fs, op, e1, e2, line); /* use standard operators */ + else /* use immediate operators */ + codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); +} + + +static void swapexps (expdesc *e1, expdesc *e2) { + expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ +} + + +/* +** Code commutative operators ('+', '*'). If first operand is a +** constant, change order of operands to use immediate operator. +*/ +static void codecommutative (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + int flip = 0; + if (isSCint(e1)) { + swapexps(e1, e2); + flip = 1; + } + codearith(fs, op, e1, e2, flip, line); +} + + +/* +** Code bitwise operations; they are all associative, so the function +** tries to put an integer constant as the 2nd operand (a K operand). +*/ +static void codebitwise (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int line) { + int inv = 0; + int v1, v2, pc; + OpCode op; + if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { + swapexps(e1, e2); /* 'e2' will be the constant operand */ + inv = 1; + } + else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ + op = cast(OpCode, opr - OPR_BAND + OP_BAND); + codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ + return; + } + v1 = luaK_exp2anyreg(fs, e1); + v2 = e2->u.info; /* index in K array */ + op = cast(OpCode, opr - OPR_BAND + OP_BANDK); + lua_assert(ttisinteger(&fs->f->k[v2])); + pc = luaK_codeABCk(fs, op, 0, v1, v2, inv); + finishbinexpval(fs, e1, e2, pc, line); +} + + +/* +** Code shift operators. If second operand is constant, use immediate +** operand (negating it if shift is in the other direction). +*/ +static void codeshift (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + if (isSCint(e2)) { + int changedir = 0; + if (op == OP_SHL) { + changedir = 1; + e2->u.ival = -(e2->u.ival); + } + codebini(fs, OP_SHRI, e1, e2, changedir, line); + } + else + codebinexpval(fs, op, e1, e2, line); +} + + +/* +** Emit code for order comparisons. +** When the first operand is an integral value in the proper range, +** change (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) so that +** it can use an immediate operand. In this case, C indicates this +** change, for cases that cannot assume a total order (NaN and +** metamethods). +*/ +static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + int r1, r2; + int cond = 1; + int C = 0; + lua_Integer im; + if (isSCnumber(e2, &im)) { + /* use immediate operand */ + r1 = luaK_exp2anyreg(fs, e1); + r2 = cast_int(im); + op = cast(OpCode, (op - OP_LT) + OP_LTI); + } + else if (isSCnumber(e1, &im)) { + /* transform (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) */ + r1 = luaK_exp2anyreg(fs, e2); + r2 = cast_int(im); + op = (op == OP_LT) ? OP_LEI : OP_LTI; + cond = 0; /* negate original test */ + C = 1; /* indication that it used the transformations */ + } + else { /* regular case, compare two registers */ + r1 = luaK_exp2anyreg(fs, e1); + r2 = luaK_exp2anyreg(fs, e2); + } + freeexps(fs, e1, e2); + e1->u.info = condjump(fs, op, r1, r2, C, cond); + e1->k = VJMP; +} + + +/* +** Emit code for equality comparisons ('==', '~='). +** 'e1' was already put as RK by 'luaK_infix'. +*/ +static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { + int r1, r2; + lua_Integer im; + OpCode op; + if (e1->k != VNONRELOC) { + lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); + swapexps(e1, e2); + } + r1 = luaK_exp2anyreg(fs, e1); /* 1nd expression must be in register */ + if (isSCnumber(e2, &im)) { + op = OP_EQI; + r2 = cast_int(im); /* immediate operand */ + } + else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + op = OP_EQK; + r2 = e2->u.info; /* constant index */ + } + else { + op = OP_EQ; /* will compare two registers */ + r2 = luaK_exp2anyreg(fs, e2); + } + freeexps(fs, e1, e2); + e1->u.info = condjump(fs, op, r1, r2, 0, (opr == OPR_EQ)); + e1->k = VJMP; +} + + +/* +** Apply prefix operation 'op' to expression 'e'. +*/ +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; + switch (op) { + case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ + if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + break; + /* FALLTHROUGH */ + case OPR_LEN: + codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + break; + case OPR_NOT: codenot(fs, e); break; + default: lua_assert(0); + } +} + + +/* +** Process 1st operand 'v' of binary operation 'op' before reading +** 2nd operand. +*/ +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ + break; + } + case OPR_ADD: case OPR_SUB: + case OPR_MUL: case OPR_DIV: case OPR_IDIV: + case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!tonumeral(v, NULL)) + luaK_exp2anyreg(fs, v); + /* else keep numeral, which may be folded with 2nd operand */ + break; + } + case OPR_EQ: case OPR_NE: { + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be an immediate operand */ + break; + } + case OPR_LT: case OPR_LE: + case OPR_GT: case OPR_GE: { + lua_Integer dummy; + if (!isSCnumber(v, &dummy)) + luaK_exp2anyreg(fs, v); + /* else keep numeral, which may be an immediate operand */ + break; + } + default: lua_assert(0); + } +} + + +/* +** Finalize code for binary operation, after reading 2nd operand. +** For '(a .. b .. c)' (which is '(a .. (b .. c))', because +** concatenation is right associative), merge second CONCAT into first +** one. +*/ +void luaK_posfix (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int line) { + switch (opr) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOC && + GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getinstruction(fs, e2), e1->u.info); + e1->k = VRELOC; e1->u.info = e2->u.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codebinexpval(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: case OPR_MUL: { + if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) + codecommutative(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); + break; + } + case OPR_SUB: case OPR_DIV: + case OPR_IDIV: case OPR_MOD: case OPR_POW: { + if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) + codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); + break; + } + case OPR_BAND: case OPR_BOR: case OPR_BXOR: { + if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) + codebitwise(fs, opr, e1, e2, line); + break; + } + case OPR_SHL: { + if (!constfolding(fs, LUA_OPSHL, e1, e2)) { + if (isSCint(e1)) { + swapexps(e1, e2); + codebini(fs, OP_SHLI, e1, e2, 1, line); + } + else + codeshift(fs, OP_SHL, e1, e2, line); + } + break; + } + case OPR_SHR: { + if (!constfolding(fs, LUA_OPSHR, e1, e2)) + codeshift(fs, OP_SHR, e1, e2, line); + break; + } + case OPR_EQ: case OPR_NE: { + codeeq(fs, opr, e1, e2); + break; + } + case OPR_LT: case OPR_LE: { + OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); + codeorder(fs, op, e1, e2); + break; + } + case OPR_GT: case OPR_GE: { + /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ + OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); + swapexps(e1, e2); + codeorder(fs, op, e1, e2); + break; + } + default: lua_assert(0); + } +} + + +/* +** Change line information associated with current position. If that +** information is absolute, just change it and correct 'previousline'. +** Otherwise, restore 'previousline' to its value before saving the +** current position and than saves the line information again, with the +** new line. +*/ +void luaK_fixline (FuncState *fs, int line) { + Proto *f = fs->f; + if (f->lineinfo[fs->pc - 1] == ABSLINEINFO) { + lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == fs->pc - 1); + f->abslineinfo[fs->nabslineinfo - 1].line = line; + fs->previousline = line; + } + else { + fs->previousline -= f->lineinfo[fs->pc - 1]; /* undo previous info. */ + savelineinfo(fs, f, fs->pc - 1, line); /* redo it */ + } +} + + +/* +** Emit a SETLIST instruction. +** 'base' is register that keeps table; +** 'nelems' is #table plus those to be stored now; +** 'tostore' is number of values (in registers 'base + 1',...) to add to +** table (or LUA_MULTRET to add up to stack top). +*/ +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else if (c <= MAXARG_Ax) { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } + else + luaX_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ +} + + +/* +** return the final target of a jump (skipping jumps to jumps) +*/ +static int finaltarget (Instruction *code, int i) { + int count; + for (count = 0; count < 100; count++) { /* avoid infinite loops */ + Instruction pc = code[i]; + if (GET_OPCODE(pc) != OP_JMP) + break; + else + i += GETARG_sJ(pc) + 1; + } + return i; +} + + +/* +** Do a final pass over the code of a function, doing small peephole +** optimizations and adjustments. +*/ +void luaK_finish (FuncState *fs) { + int i; + Proto *p = fs->f; + for (i = 0; i < fs->pc; i++) { + Instruction *pc = &p->code[i]; + lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); + switch (GET_OPCODE(*pc)) { + case OP_RETURN: case OP_RETURN0: case OP_RETURN1: + case OP_TAILCALL: { + if (p->sizep > 0) + SETARG_k(*pc, 1); /* signal that they must close upvalues */ + break; + } + case OP_JMP: { + int target = finaltarget(p->code, i); + fixjump(fs, i, target); + break; + } + default: break; + } + } +} diff --git a/3rd/lua/lcode.h b/3rd/lua/lcode.h new file mode 100644 index 000000000..beeba54f5 --- /dev/null +++ b/3rd/lua/lcode.h @@ -0,0 +1,94 @@ +/* +** $Id: lcode.h,v 1.69 2017/11/30 13:29:18 roberto Exp roberto $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums (ORDER OP) +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, + OPR_DIV, + OPR_IDIV, + OPR_BAND, OPR_BOR, OPR_BXOR, + OPR_SHL, OPR_SHR, + OPR_CONCAT, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0) + + +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +/* get (pointer to) instruction of given 'expdesc' */ +#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) + + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); +LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, + int B, int C, int k); +LUAI_FUNC int luaK_isKint (expdesc *e); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +LUAI_FUNC void luaK_finish (FuncState *fs); + + +#endif diff --git a/3rd/lua/lcorolib.c b/3rd/lua/lcorolib.c new file mode 100644 index 000000000..49a3cf28d --- /dev/null +++ b/3rd/lua/lcorolib.c @@ -0,0 +1,167 @@ +/* +** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp roberto $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + +#define lcorolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static lua_State *getco (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "thread expected"); + return co; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status, nres; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg, &nres); + if (status == LUA_OK || status == LUA_YIELD) { + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = getco(L); + int r; + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + 'resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = getco(L); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_yieldable (lua_State *L) { + lua_pushboolean(L, lua_isyieldable(L)); + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {"isyieldable", luaB_yieldable}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/3rd/lua/lctype.c b/3rd/lua/lctype.c new file mode 100644 index 000000000..367640c66 --- /dev/null +++ b/3rd/lua/lctype.c @@ -0,0 +1,55 @@ +/* +** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp roberto $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lprefix.h" + + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/3rd/lua/lctype.h b/3rd/lua/lctype.h new file mode 100644 index 000000000..5dc17013c --- /dev/null +++ b/3rd/lua/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.11 2011/06/27 18:22:46 roberto Exp roberto $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/3rd/lua/ldblib.c b/3rd/lua/ldblib.c new file mode 100644 index 000000000..0bcd2e9e9 --- /dev/null +++ b/3rd/lua/ldblib.c @@ -0,0 +1,456 @@ +/* +** $Id: ldblib.c,v 1.150 2015/11/19 19:16:22 roberto Exp roberto $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + +#define ldblib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** The hook table at registry[&HOOKKEY] maps threads to their current +** hook function. (We only need the unique address of 'HOOKKEY'.) +*/ +static const int HOOKKEY = 0; + + +/* +** If L1 != L, L1 can be in any state, and therefore there are no +** guarantees about its stack space; any push in L1 must be +** checked. +*/ +static void checkstack (lua_State *L, lua_State *L1, int n) { + if (L != L1 && !lua_checkstack(L1, n)) + luaL_error(L, "stack overflow"); +} + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ +} + + +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); + return 1; +} + + +static int db_setuservalue (lua_State *L) { + luaL_checktype(L, 1, LUA_TUSERDATA); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_setuservalue(L, 1); + return 1; +} + + +/* +** Auxiliary function used by several library functions: check for +** an optional thread as function's first argument and set 'arg' with +** 1 if this argument is present (so that functions can skip it to +** access their other arguments) +*/ +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; /* function will operate over current thread */ + } +} + + +/* +** Variations of 'lua_settable', used by 'db_getinfo' to put results +** from 'lua_getinfo' into result table. Key is always a string; +** value can be a string, an int, or a boolean. +*/ +static void settabss (lua_State *L, const char *k, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, k); +} + +static void settabsi (lua_State *L, const char *k, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, k); +} + +static void settabsb (lua_State *L, const char *k, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, k); +} + + +/* +** In function 'db_getinfo', the call to 'lua_getinfo' may push +** results on the stack; later it creates the result table to put +** these objects. Function 'treatstackoption' puts the result from +** 'lua_getinfo' on top of the result table so that it can call +** 'lua_setfield'. +*/ +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) + lua_rotate(L, -2, 1); /* exchange object and table */ + else + lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lua_setfield(L, -2, fname); /* put object into table */ +} + + +/* +** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. +*/ +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnStu"); + checkstack(L, L1, 3); + if (lua_isfunction(L, arg + 1)) { /* info about a function? */ + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lua_xmove(L, L1, 1); + } + else { /* stack level */ + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_newtable(L); /* table to collect results */ + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) { + settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; /* return only name (there is no value) */ + } + else { /* stack-level argument */ + int level = (int)luaL_checkinteger(L, arg + 1); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + checkstack(L, L1, 1); + name = lua_getlocal(L1, &ar, nvar); + if (name) { + lua_xmove(L1, L, 1); /* move local value */ + lua_pushstring(L, name); /* push name */ + lua_rotate(L, -2, 1); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + const char *name; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + int level = (int)luaL_checkinteger(L, arg + 1); + int nvar = (int)luaL_checkinteger(L, arg + 2); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + checkstack(L, L1, 1); + lua_xmove(L, L1, 1); + name = lua_setlocal(L1, &ar, nvar); + if (name == NULL) + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ + lua_pushstring(L, name); + return 1; +} + + +/* +** get (if 'get' is true) or set an upvalue from a closure +*/ +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); /* no-op if get is false */ + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + +/* +** Check whether a given upvalue from a given closure exists and +** returns its index +*/ +static int checkupval (lua_State *L, int argf, int argnup) { + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ + luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, + "invalid upvalue index"); + return nup; +} + + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +/* +** Call hook function registered at hook table for the current +** thread (if there is one) +*/ +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + lua_pushthread(L); + if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); /* push current line */ + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); /* call hook function */ + } +} + + +/* +** Convert a string mask (for 'sethook') into a bit mask +*/ +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +/* +** Convert a bit mask (for 'gethook') into a string mask +*/ +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { /* no hook? */ + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = (int)luaL_optinteger(L, arg + 3, 0); + func = hookf; mask = makemask(smask, count); + } + if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { + lua_createtable(L, 0, 2); /* create a hook table */ + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ + lua_pushvalue(L, arg + 1); /* value (hook function) */ + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ + lua_sethook(L1, func, mask, count); + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook == NULL) /* no hook? */ + lua_pushnil(L); + else if (hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { /* hook table must exist */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ + lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + lua_writestringerror("%s", "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) + lua_writestringerror("%s\n", lua_tostring(L, -1)); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +static int db_traceback (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); + return 1; +} + diff --git a/3rd/lua/ldebug.c b/3rd/lua/ldebug.c new file mode 100644 index 000000000..523356004 --- /dev/null +++ b/3rd/lua/ldebug.c @@ -0,0 +1,798 @@ +/* +** $Id: ldebug.c,v 2.150 2017/12/20 14:58:05 roberto Exp roberto $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + +#define ldebug_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) + + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue(s2v((ci)->func))) + + +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name); + + +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +} + + +/* +** Get a "base line" to find the line corresponding to an instruction. +** For that, search the array of absolute line info for the largest saved +** instruction smaller or equal to the wanted instruction. A special +** case is when there is no absolute info or the instruction is before +** the first absolute one. +*/ +static int getbaseline (Proto *f, int pc, int *basepc) { + if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) { + *basepc = -1; /* start from the beginning */ + return f->linedefined; + } + else { + unsigned int i; + if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc) + i = f->sizeabslineinfo - 1; /* instruction is after last saved one */ + else { /* binary search */ + unsigned int j = f->sizeabslineinfo - 1; /* pc < anchorlines[j] */ + i = 0; /* abslineinfo[i] <= pc */ + while (i < j - 1) { + unsigned int m = (j + i) / 2; + if (pc >= f->abslineinfo[m].pc) + i = m; + else + j = m; + } + } + *basepc = f->abslineinfo[i].pc; + return f->abslineinfo[i].line; + } +} + + +/* +** Get the line corresponding to instruction 'pc' in function 'f'; +** first gets a base line and from there does the increments until +** the desired instruction. +*/ +int luaG_getfuncline (Proto *f, int pc) { + if (f->lineinfo == NULL) /* no debug information? */ + return -1; + else { + int basepc; + int baseline = getbaseline(f, pc, &basepc); + while (basepc++ < pc) { /* walk until given instruction */ + lua_assert(f->lineinfo[basepc] != ABSLINEINFO); + baseline += f->lineinfo[basepc]; /* correct line */ + } + return baseline; + } +} + + +static int currentline (CallInfo *ci) { + return luaG_getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** This function can be called asynchronously (e.g. during a signal), +** under "reasonable" assumptions. A new 'ci' is completely linked +** in the list before it becomes part of the "active" list, and +** we assume that pointers are atomic (see comment in next function). +** (If we traverse one more item, there is no problem. If we traverse +** one less item, the worst that can happen is that the signal will +** not interrupt the script.) +*/ +static void settraps (CallInfo *ci) { + for (; ci != NULL; ci = ci->previous) + if (isLua(ci)) + ci->u.l.trap = 1; +} + + +/* +** This function can be called asynchronously (e.g. during a signal), +** under "reasonable" assumptions. +** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by +** 'resethookcount') are for debug only, and it is no problem if they +** get arbitrary values (causes at most one wrong hook call). 'hookmask' +** is an atomic value. We assume that pointers are atomic too (e.g., gcc +** ensures that for all platforms where it runs). Moreover, 'hook' is +** always checked before being called (see 'luaD_hook'). +*/ +LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + if (mask & (LUA_MASKLINE | LUA_MASKCOUNT)) + settraps(L->ci); /* to trace inside 'luaV_execute' */ +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + StkId base = ci->func + 1; + const char *name = (isLua(ci)) + ? luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)) + : NULL; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ + else + return NULL; /* no name */ + } + *pos = base + (n - 1); + return name; +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + lua_lock(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = NULL; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, L->top, pos); + api_incr_top(L); + } + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = NULL; /* to avoid warnings */ + const char *name; + lua_lock(L); + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (noLuaClosure(cl)) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static int nextline (Proto *p, int currentline, int pc) { + if (p->lineinfo[pc] != ABSLINEINFO) + return currentline + p->lineinfo[pc]; + else + return luaG_getfuncline(p, pc); +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (noLuaClosure(f)) { + setnilvalue(s2v(L->top)); + api_incr_top(L); + } + else { + int i; + TValue v; + Proto *p = f->l.p; + int currentline = p->linedefined; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue2s(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < p->sizelineinfo; i++) { /* for all lines with code */ + currentline = nextline(p, currentline, i); + luaH_setint(L, t, currentline, &v); /* table[line] = true */ + } + } +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + if (ci == NULL) /* no 'ci'? */ + return NULL; /* no info */ + else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ + *name = "__gc"; + return "metamethod"; /* report it as such */ + } + /* calling function is a known Lua function? */ + else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + return funcnamefromcode(L, ci->previous, name); + else return NULL; /* no way to find a name */ +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams + f->l.p->is_vararg; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': { + ar->namewhat = getfuncname(L, ci, &ar->name); + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *cl; + CallInfo *ci; + TValue *func; + lua_lock(L); + if (*what == '>') { + ci = NULL; + func = s2v(L->top - 1); + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else { + ci = ar->i_ci; + func = s2v(ci->func); + lua_assert(ttisfunction(func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) { + setobj2s(L, L->top, func); + api_incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); + + +/* +** Find a "name" for the constant 'c'. +*/ +static void kname (Proto *p, int c, const char **name) { + TValue *kvalue = &p->k[c]; + *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?"; +} + + +/* +** Find a "name" for the register 'c'. +*/ +static void rname (Proto *p, int pc, int c, const char **name) { + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (!(what && *what == 'c')) /* did not find a constant name? */ + *name = "?"; +} + + +/* +** Find a "name" for a 'C' value in an RK instruction. +*/ +static void rkname (Proto *p, int pc, Instruction i, const char **name) { + int c = GETARG_C(i); /* key index */ + if (GETARG_k(i)) /* is 'c' a constant? */ + kname(p, c, name); + else /* 'c' is a register */ + rname(p, pc, c, name); +} + + +static int filterpc (int pc, int jmptarget) { + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ +} + + +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int change; /* true if current instruction changed 'reg' */ + switch (op) { + case OP_LOADNIL: { /* set registers from 'a' to 'a+b' */ + int b = GETARG_B(i); + change = (a <= reg && reg <= a + b); + break; + } + case OP_TFORCALL: { /* affect all regs above its base */ + change = (reg >= a + 2); + break; + } + case OP_CALL: + case OP_TAILCALL: { /* affect all registers above base */ + change = (reg >= a); + break; + } + case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */ + int b = GETARG_sJ(i); + int dest = pc + 1 + b; + /* jump does not skip 'lastpc' and is larger than current one? */ + if (dest <= lastpc && dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ + change = 0; + break; + } + default: /* any instruction that sets A */ + change = (testAMode(op) && reg == a); + break; + } + if (change) + setreg = filterpc(pc, jmptarget); + } + return setreg; +} + + +/* +** Check whether table being indexed by instruction 'i' is the +** environment '_ENV' +*/ +static const char *gxf (Proto *p, int pc, Instruction i, int isup) { + int t = GETARG_B(i); /* table index */ + const char *name; /* name of indexed variable */ + if (isup) /* is an upvalue? */ + name = upvalname(p, t); + else + getobjname(p, pc, t, &name); + return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; +} + + + const char *getobjname (Proto *p, int lastpc, int reg, const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 1); + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + rname(p, pc, k, name); + return gxf(p, pc, i, 0); + } + case OP_GETI: { + *name = "integer index"; + return "field"; + } + case OP_GETFIELD: { + int k = GETARG_C(i); /* key index */ + kname(p, k, name); + return gxf(p, pc, i, 0); + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + rkname(p, pc, i, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ +} + + +/* +** Try to find a name for a function based on the code that called it. +** (Only works when function was called by a Lua function.) +** Returns what the name is (e.g., "for iterator", "method", +** "metamethod") and sets '*name' to point to the name. +*/ +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name) { + TMS tm = (TMS)0; /* (initial value avoids warnings) */ + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ + *name = "?"; + return "hook"; + } + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + return getobjname(p, pc, GETARG_A(i), name); /* get function name */ + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* other instructions can do calls through metamethods */ + case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: + case OP_GETI: case OP_GETFIELD: + tm = TM_INDEX; + break; + case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: + tm = TM_NEWINDEX; + break; + case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI: + case OP_POWI: case OP_DIVI: case OP_IDIVI: + case OP_BANDK: case OP_BORK: case OP_BXORK: { + int offset = GET_OPCODE(i) - OP_ADDI; /* ORDER OP */ + tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ + break; + } + case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: + case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: + case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { + int offset = GET_OPCODE(i) - OP_ADD; /* ORDER OP */ + tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ + break; + } + case OP_UNM: tm = TM_UNM; break; + case OP_BNOT: tm = TM_BNOT; break; + case OP_LEN: tm = TM_LEN; break; + case OP_CONCAT: tm = TM_CONCAT; break; + case OP_EQ: tm = TM_EQ; break; + case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: + *name = "order"; /* '<=' can call '__lt', etc. */ + return "metamethod"; + case OP_SHRI: case OP_SHLI: + *name = "shift"; + return "metamethod"; + default: + return NULL; /* cannot find a reasonable name */ + } + *name = getstr(G(L)->tmname[tm]) + 2; + return "metamethod"; +} + +/* }====================================================== */ + + + +/* +** The subtraction of two potentially unrelated pointers is +** not ISO C, but it should not crash a program; the subsequent +** checks are ISO C and ensure a correct result. +*/ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId base = ci->func + 1; + ptrdiff_t i = cast(StkId, o) - base; + return (0 <= i && i < (ci->top - base) && s2v(base + i) == o); +} + + +/* +** Checks whether value 'o' came from an upvalue. (That can only happen +** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on +** upvalues.) +*/ +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +static const char *varinfo (lua_State *L, const TValue *o) { + const char *name = NULL; /* to avoid warnings */ + CallInfo *ci = L->ci; + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(cast(StkId, o) - (ci->func + 1)), &name); + } + return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *t = luaT_objtypename(L, o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); +} + + +l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; + luaG_typeerror(L, p1, "concatenate"); +} + + +l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, const char *msg) { + if (!ttisnumber(p1)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ + luaG_typeerror(L, p2, msg); +} + + +/* +** Error when both values are convertible to numbers, but not to integers +*/ +l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { + lua_Integer temp; + if (!tointegerns(p1, &temp)) + p2 = p1; + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); +} + + +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_objtypename(L, p1); + const char *t2 = luaT_objtypename(L, p2); + if (strcmp(t1, t2) == 0) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +} + + +/* add src:line information to 'msg' */ +const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, + int line) { + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +} + + +l_noret luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + L->top++; /* assume EXTRA_STACK */ + luaE_incCcalls(L); + luaD_callnoyield(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + CallInfo *ci = L->ci; + const char *msg; + va_list argp; + luaC_checkGC(L); /* error message uses memory */ + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ + va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); + luaG_errormsg(L); +} + + +/* +** Check whether new instruction 'newpc' is in a different line from +** previous instruction 'oldpc'. +*/ +static int changedline (Proto *p, int oldpc, int newpc) { + while (oldpc++ < newpc) { + if (p->lineinfo[oldpc] != 0) + return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc)); + } + return 0; /* no line changes in the way */ +} + + +void luaG_traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); + if (counthook) + resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return; /* no line hook and count != 0; nothing to be done */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (!isIT(*(ci->u.l.savedpc - 1))) + L->top = ci->top; /* prepare top */ + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + const Instruction *npc = ci->u.l.savedpc; + int npci = pcRel(npc, p); + if (npci == 0 || /* call linehook when enter a new function, */ + npc <= L->oldpc || /* when jump back (loop), or when */ + changedline(p, pcRel(L->oldpc, p), npci)) { /* enter new line */ + int newline = luaG_getfuncline(p, npci); /* new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = npc; + } + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + luaD_throw(L, LUA_YIELD); + } +} + diff --git a/3rd/lua/ldebug.h b/3rd/lua/ldebug.h new file mode 100644 index 000000000..9062f4bd0 --- /dev/null +++ b/3rd/lua/ldebug.h @@ -0,0 +1,43 @@ +/* +** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp roberto $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + +/* +** mark for entries in 'lineinfo' array that has absolute information in +** 'abslineinfo' array +*/ +#define ABSLINEINFO (-0x80) + +LUAI_FUNC int luaG_getfuncline (Proto *f, int pc); +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, + const char *msg); +LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, + TString *src, int line); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); +LUAI_FUNC void luaG_traceexec (lua_State *L); + + +#endif diff --git a/3rd/lua/ldo.c b/3rd/lua/ldo.c new file mode 100644 index 000000000..1abd105c8 --- /dev/null +++ b/3rd/lua/ldo.c @@ -0,0 +1,801 @@ +/* +** $Id: ldo.c,v 2.184 2017/12/28 14:17:09 roberto Exp roberto $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#define ldo_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + +#define errorstatus(s) ((s) > LUA_YIELD) + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By +** default, Lua handles errors with exceptions when compiling as +** C++ code, with _longjmp/_setjmp when asked to use them, and with +** longjmp/setjmp otherwise. +*/ +#if !defined(LUAI_THROW) /* { */ + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ + +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) \ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_POSIX) /* }{ */ + +/* in POSIX, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else /* }{ */ + +/* ISO C handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif /* } */ + +#endif /* } */ + + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { /* memory error? */ + TString *memerrmsg = luaS_newliteral(L, MEMERRMSG); + setsvalue2s(L, oldtop, memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + default: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else { /* thread has no error handler */ + global_State *g = G(L); + L->status = cast_byte(errcode); /* mark it as dead */ + if (g->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (g->panic) { /* panic function? */ + seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ + if (L->ci->top < L->top) + L->ci->top = L->top; /* pushing msg. can break this invariant */ + lua_unlock(L); + g->panic(L); /* call panic function (last chance to jump out) */ + } + abort(); + } + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls - L->nci; + struct lua_longjmp lj; + lj.status = LUA_OK; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls + L->nci; + return lj.status; +} + +/* }====================================================== */ + + +/* +** {================================================================== +** Stack reallocation +** =================================================================== +*/ +static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { + CallInfo *ci; + UpVal *up; + if (oldstack == newstack) + return; /* stack address did not change */ + L->top = (L->top - oldstack) + newstack; + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v = s2v((uplevel(up) - oldstack) + newstack); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top = (ci->top - oldstack) + newstack; + ci->func = (ci->func - oldstack) + newstack; + if (isLua(ci)) + ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ + } +} + + +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + +int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { + int lim = L->stacksize; + StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + if (newstack == NULL) { /* reallocation failed? */ + if (raiseerror) + luaM_error(L); + else return 0; /* do not raise an error */ + } + for (; lim < newsize; lim++) + setnilvalue(s2v(newstack + lim)); /* erase new segment */ + correctstack(L, L->stack, newstack); + L->stack = newstack; + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; + return 1; +} + + +/* +** Try to grow the stack by at least 'n' elements. when 'raiseerror' +** is true, raises any error; otherwise, return 0 in case of errors. +*/ +int luaD_growstack (lua_State *L, int n, int raiseerror) { + int size = L->stacksize; + int newsize = 2 * size; /* tentative new size */ + if (size > LUAI_MAXSTACK) { /* need more space after extra size? */ + if (raiseerror) + luaD_throw(L, LUA_ERRERR); /* error inside message handler */ + else return 0; + } + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ + newsize = LUAI_MAXSTACK; + if (newsize < needed) /* but must respect what was asked for */ + newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + /* add extra size to be able to handle the error message */ + luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); + if (raiseerror) + luaG_runerror(L, "stack overflow"); + else return 0; + } + } /* else no errors */ + return luaD_reallocstack(L, newsize, raiseerror); +} + + +static int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + if (lim < ci->top) lim = ci->top; + } + lua_assert(lim <= L->stack_last); + return cast_int(lim - L->stack) + 1; /* part of stack in use */ +} + + +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) + goodsize = LUAI_MAXSTACK; /* respect stack limit */ + /* if thread is currently not handling a stack overflow and its + good size is smaller than current size, shrink its stack */ + if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && + goodsize < L->stacksize) + luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ + else /* don't change stack */ + condmovestack(L,{},{}); /* (change only for debugging) */ + luaE_shrinkCI(L); /* shrink CI list */ +} + + +void luaD_inctop (lua_State *L) { + luaD_checkstack(L, 1); + L->top++; +} + +/* }================================================================== */ + + +/* +** Call a hook for the given event. Make sure there is a hook to be +** called. (Both 'L->hook' and 'L->hookmask', which triggers this +** function, can be changed asynchronously by signals.) +*/ +void luaD_hook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { /* make sure there is a hook */ + CallInfo *ci = L->ci; + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + if (L->top + LUA_MINSTACK > ci->top) + ci->top = L->top + LUA_MINSTACK; + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } +} + + +static void hookcall (lua_State *L, CallInfo *ci, int istail) { + int hook; + ci->u.l.trap = 1; + if (!(L->hookmask & LUA_MASKCALL)) + return; /* some other hook */ + L->top = ci->top; /* prepare top */ + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (istail) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + else + hook = LUA_HOOKCALL; + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ +} + + +static void rethook (lua_State *L, CallInfo *ci) { + if (isLuacode(ci)) + L->top = ci->top; /* prepare top */ + if (L->hookmask & LUA_MASKRET) /* is return hook on? */ + luaD_hook(L, LUA_HOOKRET, -1); /* call it */ + if (isLua(ci->previous)) + L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */ +} + + +/* +** Check whether __call metafield of 'func' is a function. If so, put +** it in stack below original 'func' so that 'luaD_call' can call +** it. Raise an error if __call metafield is not a function. +*/ +StkId luaD_tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); + StkId p; + if (!ttisfunction(tm)) + luaG_typeerror(L, s2v(func), "call"); + /* Open a hole inside the stack at 'func' */ + checkstackp(L, 1, func); /* ensure space for metamethod */ + for (p = L->top; p > func; p--) + setobjs2s(L, p, p-1); + L->top++; + setobj2s(L, func, tm); /* metamethod is the new function to be called */ + return func; +} + + +/* +** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. +** Handle most typical cases (zero results for commands, one result for +** expressions, multiple results for tail calls/single parameters) +** separated. +*/ +static void moveresults (lua_State *L, StkId firstResult, StkId res, + int nres, int wanted) { + switch (wanted) { /* handle typical cases separately */ + case 0: break; /* nothing to move */ + case 1: { /* one result needed */ + if (nres == 0) /* no results? */ + setnilvalue(s2v(res)); /* adjust with nil */ + else + setobjs2s(L, res, firstResult); /* move it to proper place */ + break; + } + case LUA_MULTRET: { + int i; + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + wanted = nres; /* it wanted what it had */ + break; + } + default: { + int i; + if (wanted <= nres) { /* enough results? */ + for (i = 0; i < wanted; i++) /* move wanted results to correct place */ + setobjs2s(L, res + i, firstResult + i); + } + else { /* not enough results; use all of them plus nils */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(s2v(res + i)); + } + break; + } + } + L->top = res + wanted; /* top points after the last result */ +} + + +/* +** Finishes a function call: calls hook if necessary, removes CallInfo, +** moves current number of results to proper place; returns 0 iff call +** wanted multiple (variable number of) results. +*/ +void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { + if (L->hookmask) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + rethook(L, ci); + firstResult = restorestack(L, fr); + } + L->ci = ci->previous; /* back to caller */ + /* move results to proper place */ + moveresults(L, firstResult, ci->func, nres, ci->nresults); +} + + + +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) + + +/* +** Prepare a function for a tail call, building its call info on top +** of the current call info. 'n' is the number of arguments plus 1 +** (so that it includes the function itself). +*/ +void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) { + Proto *p = clLvalue(s2v(func))->p; + int fsize = p->maxstacksize; /* frame size */ + int i; + for (i = 0; i < n; i++) /* move down function and arguments */ + setobjs2s(L, ci->func + i, func + i); + checkstackp(L, fsize, func); + for (; i <= p->numparams; i++) + setnilvalue(s2v(ci->func + i)); /* complete missing arguments */ + if (p->is_vararg) { + L->top -= (func - ci->func); /* move down top */ + luaT_adjustvarargs(L, p, n - 1); + } + ci->top = ci->func + 1 + fsize; /* top for new function */ + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus |= CIST_TAIL; + if (L->hookmask) + hookcall(L, ci, 1); +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nresults) { + lua_CFunction f; + TValue *funcv = s2v(func); + CallInfo *ci; + switch (ttype(funcv)) { + case LUA_TCCL: /* C closure */ + f = clCvalue(funcv)->f; + goto Cfunc; + case LUA_TLCF: /* light C function */ + f = fvalue(funcv); + Cfunc: { + int n; /* number of returns */ + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = CIST_C; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); + break; + } + case LUA_TLCL: { /* Lua function: prepare its call */ + Proto *p = clLvalue(funcv)->p; + int n = cast_int(L->top - func) - 1; /* number of real arguments */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + for (; n < p->numparams; n++) + setnilvalue(s2v(L->top++)); /* complete missing arguments */ + if (p->is_vararg) + luaT_adjustvarargs(L, p, n); + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->top = func + 1 + fsize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = 0; + if (L->hookmask) + hookcall(L, ci, 0); + luaV_execute(L, ci); /* run the function */ + break; + } + default: { /* not a function */ + func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ + luaD_call(L, func, nresults); /* now it must be a function */ + break; + } + } +} + + +/* +** Similar to 'luaD_call', but does not allow yields during the call +*/ +void luaD_callnoyield (lua_State *L, StkId func, int nResults) { + L->nny++; + luaD_call(L, func, nResults); + L->nny--; +} + + +/* +** Completes the execution of an interrupted C function, calling its +** continuation function. +*/ +static void finishCcall (lua_State *L, int status) { + CallInfo *ci = L->ci; + int n; + /* must have a continuation and must be able to call it */ + lua_assert(ci->u.c.k != NULL && L->nny == 0); + /* error status can only happen in a protected call */ + lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ + L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ + } + /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already + handled */ + adjustresults(L, ci->nresults); + lua_unlock(L); + n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_call' */ +} + + +/* +** Executes "full continuation" (everything in the stack) of a +** previously interrupted coroutine until the stack is empty (or another +** interruption long-jumps out of the loop). If the coroutine is +** recovering from an error, 'ud' points to the error status, which must +** be passed to the first continuation function (otherwise the default +** status is LUA_YIELD). +*/ +static void unroll (lua_State *L, void *ud) { + CallInfo *ci; + if (ud != NULL) /* error status? */ + finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ + while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ + if (!isLua(ci)) /* C function? */ + finishCcall(L, LUA_YIELD); /* complete its execution */ + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L, ci); /* execute down to higher C 'boundary' */ + } + } +} + + +/* +** Try to find a suspended protected call (a "recover point") for the +** given thread. +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +/* +** Recovers from an error in a coroutine. Finds a recover point (if +** there is one) and completes the execution of the interrupted +** 'luaD_pcall'. If there is no recover point, returns zero. +*/ +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->u2.funcidx); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + return 1; /* continue running the coroutine */ +} + + +/* +** Signal an error in the call to 'lua_resume', not in the execution +** of the coroutine itself. (Such errors should not be handled by any +** coroutine error handler and should not kill the coroutine.) +*/ +static int resume_error (lua_State *L, const char *msg, int narg) { + L->top -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +/* +** Do the work for 'lua_resume' in protected mode. Most of the work +** depends on the status of the coroutine: initial state, suspended +** inside a hook, or regularly suspended (optionally with a continuation +** function), plus erroneous cases: non-suspended coroutine or dead +** coroutine. +*/ +static void resume (lua_State *L, void *ud) { + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ + CallInfo *ci = L->ci; + if (L->status == LUA_OK) { /* starting a coroutine? */ + luaD_call(L, firstArg - 1, LUA_MULTRET); + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = LUA_OK; /* mark that it is running (again) */ + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L, ci); /* just continue running Lua code */ + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation function? */ + lua_unlock(L); + n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_call' */ + } + unroll(L, NULL); /* run continuation */ + } +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, + int *nresults) { + int status; + unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ + lua_lock(L); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (L->ci != &L->base_ci) /* not in base level? */ + return resume_error(L, "cannot resume non-suspended coroutine", nargs); + } + else if (L->status != LUA_YIELD) + return resume_error(L, "cannot resume dead coroutine", nargs); + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow", nargs); + luai_userstateresume(L, nargs); + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* continue running after recoverable errors */ + while (errorstatus(status) && recover(L, status)) { + /* unroll continuation */ + status = luaD_rawrunprotected(L, unroll, &status); + } + if (errorstatus(status)) { /* unrecoverable error? */ + L->status = cast_byte(status); /* mark thread as 'dead' */ + seterrorobj(L, status, L->top); /* push error message */ + L->ci->top = L->top; + } + else lua_assert(status == L->status); /* normal end or yield */ + } + *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield + : L->top - (L->ci->func + 1); + L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; + // lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); + lua_unlock(L); + return status; +} + + +LUA_API int lua_isyieldable (lua_State *L) { + return (L->nny == 0); +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k) { + CallInfo *ci = L->ci; + luai_userstateyield(L, nresults); + lua_lock(L); + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + if (isLua(ci)) { /* inside a hook? */ + lua_assert(!isLuacode(ci)); + api_check(L, k == NULL, "hooks cannot continue after yielding"); + ci->u2.nyield = 0; /* no results */ + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->u2.nyield = nresults; /* save number of results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != LUA_OK) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; + L->allowhook = old_allowhooks; + L->nny = old_nny; + luaD_shrinkstack(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to 'f_parser' */ + ZIO *z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; + const char *name; +}; + + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is '%s')", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + +static void f_parser (lua_State *L, void *ud) { + LClosure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luaF_initupvals(L, cl); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { + struct SParser p; + int status; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; + return status; +} + + diff --git a/3rd/lua/ldo.h b/3rd/lua/ldo.h new file mode 100644 index 000000000..765f6cef5 --- /dev/null +++ b/3rd/lua/ldo.h @@ -0,0 +1,68 @@ +/* +** $Id: ldo.h,v 2.37 2017/12/08 17:28:25 roberto Exp roberto $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +/* +** Macro to check stack size and grow stack if needed. Parameters +** 'pre'/'pos' allow the macro to preserve a pointer into the +** stack across reallocations, doing the work only when needed. +** 'condmovestack' is used in heavy tests to force a stack reallocation +** at every check. +*/ +#define luaD_checkstackaux(L,n,pre,pos) \ + if (L->stack_last - L->top <= (n)) \ + { pre; luaD_growstack(L, n, 1); pos; } \ + else { condmovestack(L,pre,pos); } + +/* In general, 'pre'/'pos' are empty (nothing to save) */ +#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) + + + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((StkId)((char *)L->stack + (n))) + + +/* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* type of protected functions, to be ran by 'runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); +LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); +LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, + int nres); +LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); +LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); +LUAI_FUNC void luaD_inctop (lua_State *L); + +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +#endif + diff --git a/3rd/lua/ldump.c b/3rd/lua/ldump.c new file mode 100644 index 000000000..4d3f64357 --- /dev/null +++ b/3rd/lua/ldump.c @@ -0,0 +1,230 @@ +/* +** $Id: ldump.c,v 2.39 2017/06/27 14:21:12 roberto Exp roberto $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define ldump_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + + +typedef struct { + lua_State *L; + lua_Writer writer; + void *data; + int strip; + int status; +} DumpState; + + +/* +** All high-level dumps go through DumpVector; you can change it to +** change the endianness of the result +*/ +#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) + +#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) + + +static void DumpBlock (const void *b, size_t size, DumpState *D) { + if (D->status == 0 && size > 0) { + lua_unlock(D->L); + D->status = (*D->writer)(D->L, b, size, D->data); + lua_lock(D->L); + } +} + + +#define DumpVar(x,D) DumpVector(&x,1,D) + + +static void DumpByte (int y, DumpState *D) { + lu_byte x = (lu_byte)y; + DumpVar(x, D); +} + + +/* DumpInt Buff Size */ +#define DIBS ((sizeof(size_t) * 8 / 7) + 1) + +static void DumpSize (size_t x, DumpState *D) { + lu_byte buff[DIBS]; + int n = 0; + do { + buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ + x >>= 7; + } while (x != 0); + buff[DIBS - 1] |= 0x80; /* mark last byte */ + DumpVector(buff + DIBS - n, n, D); +} + + +static void DumpInt (int x, DumpState *D) { + DumpSize(x, D); +} + + +static void DumpNumber (lua_Number x, DumpState *D) { + DumpVar(x, D); +} + + +static void DumpInteger (lua_Integer x, DumpState *D) { + DumpVar(x, D); +} + + +static void DumpString (const TString *s, DumpState *D) { + if (s == NULL) + DumpSize(0, D); + else { + size_t size = tsslen(s); + const char *str = getstr(s); + DumpSize(size + 1, D); + DumpVector(str, size, D); + } +} + + +static void DumpCode (const Proto *f, DumpState *D) { + DumpInt(f->sizecode, D); + DumpVector(f->code, f->sizecode, D); +} + + +static void DumpFunction(const Proto *f, TString *psource, DumpState *D); + +static void DumpConstants (const Proto *f, DumpState *D) { + int i; + int n = f->sizek; + DumpInt(n, D); + for (i = 0; i < n; i++) { + const TValue *o = &f->k[i]; + DumpByte(ttype(o), D); + switch (ttype(o)) { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpByte(bvalue(o), D); + break; + case LUA_TNUMFLT: + DumpNumber(fltvalue(o), D); + break; + case LUA_TNUMINT: + DumpInteger(ivalue(o), D); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + DumpString(tsvalue(o), D); + break; + default: lua_assert(0); + } + } +} + + +static void DumpProtos (const Proto *f, DumpState *D) { + int i; + int n = f->sizep; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpFunction(f->p[i], f->source, D); +} + + +static void DumpUpvalues (const Proto *f, DumpState *D) { + int i, n = f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpByte(f->upvalues[i].instack, D); + DumpByte(f->upvalues[i].idx, D); + } +} + + +static void DumpDebug (const Proto *f, DumpState *D) { + int i, n; + n = (D->strip) ? 0 : f->sizelineinfo; + DumpInt(n, D); + DumpVector(f->lineinfo, n, D); + n = (D->strip) ? 0 : f->sizeabslineinfo; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpInt(f->abslineinfo[i].pc, D); + DumpInt(f->abslineinfo[i].line, D); + } + n = (D->strip) ? 0 : f->sizelocvars; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpString(f->locvars[i].varname, D); + DumpInt(f->locvars[i].startpc, D); + DumpInt(f->locvars[i].endpc, D); + } + n = (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpString(f->upvalues[i].name, D); +} + + +static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { + if (D->strip || f->source == psource) + DumpString(NULL, D); /* no debug info or same source as its parent */ + else + DumpString(f->source, D); + DumpInt(f->linedefined, D); + DumpInt(f->lastlinedefined, D); + DumpByte(f->numparams, D); + DumpByte(f->is_vararg, D); + DumpByte(f->maxstacksize, D); + DumpCode(f, D); + DumpConstants(f, D); + DumpUpvalues(f, D); + DumpProtos(f, D); + DumpDebug(f, D); +} + + +static void DumpHeader (DumpState *D) { + DumpLiteral(LUA_SIGNATURE, D); + DumpByte(LUAC_VERSION, D); + DumpByte(LUAC_FORMAT, D); + DumpLiteral(LUAC_DATA, D); + DumpByte(sizeof(int), D); + DumpByte(sizeof(size_t), D); + DumpByte(sizeof(Instruction), D); + DumpByte(sizeof(lua_Integer), D); + DumpByte(sizeof(lua_Number), D); + DumpInteger(LUAC_INT, D); + DumpNumber(LUAC_NUM, D); +} + + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, + int strip) { + DumpState D; + D.L = L; + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + DumpHeader(&D); + DumpByte(f->sizeupvalues, &D); + DumpFunction(f, NULL, &D); + return D.status; +} + diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c new file mode 100644 index 000000000..307a857bd --- /dev/null +++ b/3rd/lua/lfunc.c @@ -0,0 +1,165 @@ +/* +** $Id: lfunc.c,v 2.50 2017/06/27 11:35:31 roberto Exp roberto $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#define lfunc_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +CClosure *luaF_newCclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); + CClosure *c = gco2ccl(o); + c->nupvalues = cast_byte(n); + return c; +} + + +LClosure *luaF_newLclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); + LClosure *c = gco2lcl(o); + c->p = NULL; + c->nupvalues = cast_byte(n); + while (n--) c->upvals[n] = NULL; + return c; +} + +/* +** fill a closure with new closed upvalues +*/ +void luaF_initupvals (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + GCObject *o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal)); + UpVal *uv = gco2upv(o); + uv->v = &uv->u.value; /* make it closed */ + setnilvalue(uv->v); + cl->upvals[i] = uv; + luaC_objbarrier(L, cl, o); + } +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + UpVal **pp = &L->openupval; + GCObject *o; + UpVal *p; + UpVal *uv; + lua_assert(isintwups(L) || L->openupval == NULL); + while ((p = *pp) != NULL && uplevel(p) >= level) { + if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */ + return p; /* return it */ + pp = &p->u.open.next; + } + /* not found: create a new upvalue between 'pp' and 'p' */ + o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal)); + uv = gco2upv(o); + uv->u.open.next = p; /* link it to list of open upvalues */ + uv->u.open.previous = pp; + if (p) + p->u.open.previous = &uv->u.open.next; + *pp = uv; + uv->v = s2v(level); /* current value lives in the stack */ + if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ + L->twups = G(L)->twups; /* link it to the list */ + G(L)->twups = L; + } + return uv; +} + + +void luaF_unlinkupval (UpVal *uv) { + lua_assert(upisopen(uv)); + *uv->u.open.previous = uv->u.open.next; + if (uv->u.open.next) + uv->u.open.next->u.open.previous = uv->u.open.previous; +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + while (L->openupval != NULL && + (uv = L->openupval, uplevel(uv) >= level)) { + TValue *slot = &uv->u.value; /* new position for value */ + luaF_unlinkupval(uv); + setobj(L, slot, uv->v); /* move value to upvalue slot */ + uv->v = slot; /* now current value lives here */ + if (!iswhite(uv)) + gray2black(uv); /* closed upvalues cannot be gray */ + luaC_barrier(L, uv, slot); + } +} + + +Proto *luaF_newproto (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); + Proto *f = gco2p(o); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->cachemiss = 0; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->abslineinfo = NULL; + f->sizeabslineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); +} + + +/* +** Look for n-th local variable at line 'line' in function 'func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/3rd/lua/lfunc.h b/3rd/lua/lfunc.h new file mode 100644 index 000000000..b7d758694 --- /dev/null +++ b/3rd/lua/lfunc.h @@ -0,0 +1,57 @@ +/* +** $Id: lfunc.h,v 2.17 2017/05/04 13:32:01 roberto Exp roberto $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +/* test whether thread is in 'twups' list */ +#define isintwups(L) (L->twups != L) + + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in a VM register.) +*/ +#define MAXUPVAL 255 + + +#define upisopen(up) ((up)->v != &(up)->u.value) + + +#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) + + +/* +** maximum number of misses before giving up the cache of closures +** in prototypes +*/ +#define MAXMISS 10 + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); +LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); +LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_unlinkupval (UpVal *uv); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c new file mode 100644 index 000000000..d02dc031c --- /dev/null +++ b/3rd/lua/lgc.c @@ -0,0 +1,1558 @@ +/* +** $Id: lgc.c,v 2.243 2017/12/20 14:58:05 roberto Exp roberto $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#define lgc_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +/* +** Maximum number of elements to sweep in each single step. +** (Large enough to dissipate fixed overheads but small enough +** to allow small steps for the collector.) +*/ +#define GCSWEEPMAX 100 + +/* +** Maximum number of finalizers to call in each single step. +*/ +#define GCFINMAX 10 + + +/* +** Cost of calling one finalizer. +*/ +#define GCFINALIZECOST 50 + + +/* +** The equivalent, in bytes, of one unit of "work" (visiting a slot, +** sweeping an object, etc.) +*/ +#define WORK2MEM sizeof(TValue) + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + + +/* mask to erase all color bits (plus gen. related stuff) */ +#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS | AGEBITS)) + + +/* macro to erase all color bits then sets only the current white bit */ +#define makewhite(g,x) \ + (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) + +#define white2gray(x) resetbits(x->marked, WHITEBITS) +#define black2gray(x) resetbit(x->marked, BLACKBIT) + + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n))) + + +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) + + +#define markvalue(g,o) { checkconsistency(o); \ + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } + +#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } + +/* +** mark an object that can be NULL (either because it is really optional, +** or it was stripped as debug info, or inside an uncompleted structure) +*/ +#define markobjectN(g,t) { if (t) markobject(g,t); } + +static void reallymarkobject (global_State *g, GCObject *o); +static lu_mem atomic (lua_State *L); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + + +/* +** link collectable object 'o' into list pointed by 'p' +*/ +#define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) + + +/* +** Clear keys for empty entries in tables. If entry is empty +** and its key is not marked, mark its entry as dead. This allows the +** collection of the key, but keeps its entry in the table (its removal +** could break a chain). Other places never manipulate dead keys, +** because its associated nil value is enough to signal that the entry +** is logically empty. +*/ +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (keyiswhite(n)) + setdeadkey(n); /* unused and unmarked key; remove it */ +} + + +/* +** tells whether a key or value can be cleared from a weak +** table. Non-collectable objects are never removed from weak +** tables. Strings behave as 'values', so are never removed too. for +** other objects: if really collected, cannot keep them; for objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const GCObject *o) { + if (o == NULL) return 0; /* non-collectable value */ + else if (novariant(o->tt) == LUA_TSTRING) { + markobject(g, o); /* strings are 'values', so are never weak */ + return 0; + } + else return iswhite(o); +} + + +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. (If in sweep phase, clear the black +** object to white [sweep it] to avoid other barrier calls for this +** same object.) +*/ +void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + if (keepinvariant(g)) { /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + if (isold(o)) { + lua_assert(!isold(v)); /* white object could not be old */ + setage(v, G_OLD0); /* restore generational invariant */ + } + } + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. +*/ +void luaC_barrierback_ (lua_State *L, Table *t) { + global_State *g = G(L); + lua_assert(isblack(t) && !isdead(g, t)); + lua_assert(g->gckind != KGC_GEN || (isold(t) && getage(t) != G_TOUCHED1)); + if (getage(t) != G_TOUCHED2) /* not already in gray list? */ + linkgclist(t, g->grayagain); /* link it in 'grayagain' */ + black2gray(t); /* make table gray (again) */ + setage(t, G_TOUCHED1); /* touched in current cycle */ +} + + +/* +** Barrier for prototype's cache of closures. For an 'old1' +** object, making it gray stops it from being visited by 'markold', +** so it is linked in the 'grayagain' list to ensure it will be +** visited. Otherwise, it goes to 'protogray', as only its 'cache' field +** needs to be revisited. (A prototype to be in this barrier must be +** already finished, so its other fields cannot change and do not need +** to be revisited.) +*/ +LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p) { + global_State *g = G(L); + lua_assert(g->gckind != KGC_GEN || isold(p)); + if (getage(p) == G_OLD1) /* still need to be visited? */ + linkgclist(p, g->grayagain); /* link it in 'grayagain' */ + else + linkgclist(p, g->protogray); /* link it in 'protogray' */ + black2gray(p); /* make prototype gray (to avoid other barriers) */ +} + + +void luaC_fix (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ + white2gray(o); /* they will be gray forever */ + setage(o, G_OLD); /* and old forever */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ + g->fixedgc = o; +} + + +/* +** create a new collectable object (with given type and size) and link +** it to 'allgc' list. +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + global_State *g = G(L); + GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; + g->allgc = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** Mark an object. Userdata, strings, and closed upvalues are visited +** and turned black here. Other objects are marked gray and added +** to appropriate list to be visited (and turned black) later. (Open +** upvalues are already linked in 'headuv' list. They are kept gray +** to avoid barriers, as their values will be revisited by the thread.) +*/ +static void reallymarkobject (global_State *g, GCObject *o) { + reentry: + white2gray(o); + switch (o->tt) { + case LUA_TSHRSTR: + case LUA_TLNGSTR: { + gray2black(o); + break; + } + case LUA_TUSERDATA: { + TValue uvalue; + markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ + gray2black(o); + getuservalue(g->mainthread, gco2u(o), &uvalue); + if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ + o = gcvalue(&uvalue); + goto reentry; + } + break; + } + case LUA_TUPVAL: { + UpVal *uv = gco2upv(o); + if (!upisopen(uv)) /* open upvalues are kept gray */ + gray2black(o); + markvalue(g, uv->v); /* mark its content */ + break; + } + case LUA_TLCL: { + linkgclist(gco2lcl(o), g->gray); + break; + } + case LUA_TCCL: { + linkgclist(gco2ccl(o), g->gray); + break; + } + case LUA_TTABLE: { + linkgclist(gco2t(o), g->gray); + break; + } + case LUA_TTHREAD: { + linkgclist(gco2th(o), g->gray); + break; + } + case LUA_TPROTO: { + linkgclist(gco2p(o), g->gray); + break; + } + default: lua_assert(0); break; + } +} + + +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobjectN(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static lu_mem markbeingfnz (global_State *g) { + GCObject *o; + lu_mem count = 0; + for (o = g->tobefnz; o != NULL; o = o->next) { + count++; + markobject(g, o); + } + return count; +} + + +/* +** Mark all values stored in marked open upvalues from non-marked threads. +** (Values from marked threads were already marked when traversing the +** thread.) Remove from the list threads that no longer have upvalues and +** not-marked threads. +*/ +static int remarkupvals (global_State *g) { + lua_State *thread; + lua_State **p = &g->twups; + int work = 0; + while ((thread = *p) != NULL) { + work++; + lua_assert(!isblack(thread)); /* threads are never black */ + if (isgray(thread) && thread->openupval != NULL) + p = &thread->twups; /* keep marked thread with upvalues in the list */ + else { /* thread is not marked or without upvalues */ + UpVal *uv; + *p = thread->twups; /* remove thread from the list */ + thread->twups = thread; /* mark that it is out of list */ + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { + work++; + if (!iswhite(uv)) /* upvalue already visited? */ + markvalue(g, uv->v); /* mark its value */ + } + } + } + return work; +} + + +/* +** mark root set and reset all gray lists, to start a new collection +*/ +static void restartcollection (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = g->protogray = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +/* +** Traverse a table with weak values and link it to proper list. During +** propagate phase, keep it in 'grayagain' list, to be revisited in the +** atomic phase. In the atomic phase, if table has any white value, +** put it in 'weak' list, to be cleared. +*/ +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (it is not + worth traversing it now just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!keyisnil(n)); + markkey(g, n); + if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (g->gcstate == GCSatomic && hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ + else + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ +} + + +/* +** Traverse an ephemeron table and link it to proper list. Returns true +** iff any object was marked during this traversal (which implies that +** convergence has to continue). During propagation phase, keep table +** in 'grayagain' list, to be visited again in the atomic phase. In +** the atomic phase, if table has any white->white entry, it has to +** be revisited during ephemeron convergence (as that key may turn +** black). Otherwise, if it has any white key, table has to be cleared +** (in the atomic phase). In generational mode, it (like all visited +** tables) must be kept in some gray list for post-processing. +*/ +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int hasww = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + unsigned int i; + /* traverse array part */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + hasww = 1; /* white-white entry */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + /* link table into proper list */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasww) /* table has white->white entries? */ + linkgclist(h, g->ephemeron); /* have to propagate again */ + else if (hasclears) /* table has white keys? */ + linkgclist(h, g->allweak); /* may have to clean white keys */ + else if (g->gckind == KGC_GEN) + linkgclist(h, g->grayagain); /* keep it in some list */ + else + gray2black(h); + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!keyisnil(n)); + markkey(g, n); + markvalue(g, gval(n)); + } + } + if (g->gckind == KGC_GEN) { + linkgclist(h, g->grayagain); /* keep it in some gray list */ + black2gray(h); + } +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobjectN(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + black2gray(h); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linkgclist(h, g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return 1 + h->sizearray + 2 * allocsizenode(h); +} + + +/* +** Check the cache of a prototype, to keep invariants. If the +** cache is white, clear it. (A cache should not prevent the +** collection of its reference.) Otherwise, if in generational +** mode, check the generational invariant. If the cache is old, +** everything is ok. If the prototype is 'old0', everything +** is ok too. (It will naturally be visited again.) If the +** prototype is older than 'old0', then its cache (which is new) +** must be visited again in the next collection, so the prototype +** goes to the 'protogray' list. (If the prototype has a cache, +** it is already immutable and does not need other barriers; +** then, it can become gray without problems for its other fields.) +*/ +static void checkprotocache (global_State *g, Proto *p) { + if (p->cache) { + if (iswhite(p->cache)) + p->cache = NULL; /* allow cache to be collected */ + else if (g->gckind == KGC_GEN && !isold(p->cache) && getage(p) >= G_OLD1) { + linkgclist(p, g->protogray); /* link it in 'protogray' */ + black2gray(p); /* make prototype gray */ + } + } + p->cachemiss = 0; /* restart counting */ +} + + +/* +** Traverse a prototype. (While a prototype is being build, its +** arrays can be larger than needed; the extra slots are filled with +** NULL, so the use of 'markobjectN') +*/ +static int traverseproto (global_State *g, Proto *f) { + int i; + checkprotocache(g, f); + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobjectN(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; +} + + +static int traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return 1 + cl->nupvalues; +} + +/* +** Traverse a Lua closure, marking its prototype and its upvalues. +** (Both can be NULL while closure is being created.) +*/ +static int traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobjectN(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ + UpVal *uv = cl->upvals[i]; + markobjectN(g, uv); /* mark upvalue */ + } + return 1 + cl->nupvalues; +} + + +/* +** Traverse a thread, marking the elements in the stack up to its top +** and cleaning the rest of the stack in the final traversal. +** That ensures that the entire stack have valid (non-dead) objects. +*/ +static int traversethread (global_State *g, lua_State *th) { + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + lua_assert(g->gcstate == GCSatomic || + th->openupval == NULL || isintwups(th)); + for (; o < th->top; o++) /* mark live elements in the stack */ + markvalue(g, s2v(o)); + if (g->gcstate == GCSatomic) { /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(s2v(o)); + /* 'remarkupvals' may have removed thread from 'twups' list */ + if (!isintwups(th) && th->openupval != NULL) { + th->twups = g->twups; /* link it back to the list */ + g->twups = th; + } + } + else if (!g->gcemergency) + luaD_shrinkstack(th); /* do not change stack in emergency cycle */ + return 1 + th->stacksize; +} + + +/* +** traverse one gray object, turning it to black (except for threads, +** which are always gray). +*/ +static lu_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + gray2black(o); + switch (o->tt) { + case LUA_TTABLE: { + Table *h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + return traversetable(g, h); + } + case LUA_TLCL: { + LClosure *cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + return traverseLclosure(g, cl); + } + case LUA_TCCL: { + CClosure *cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + return traverseCclosure(g, cl); + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; /* remove from 'gray' list */ + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ + black2gray(o); + return traversethread(g, th); + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; /* remove from 'gray' list */ + return traverseproto(g, p); + } + default: lua_assert(0); return 0; + } +} + + +static lu_mem propagateall (global_State *g) { + lu_mem tot = 0; + while (g->gray) + tot += propagatemark(g); + return tot; +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables may return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + +static void clearprotolist (global_State *g) { + GCObject *p = g->protogray; + g->protogray = NULL; + while (p != NULL) { + Proto *pp = gco2p(p); + GCObject *next = pp->gclist; + lua_assert(isgray(pp) && (pp->cache != NULL || pp->cachemiss >= MAXMISS)); + gray2black(pp); + checkprotocache(g, pp); + p = next; + } +} + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' +*/ +static void clearkeys (global_State *g, GCObject *l) { + for (; l; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) /* unmarked key? */ + setnilvalue(gval(n)); /* clear value */ + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove it from table */ + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, gcvalueN(o))) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ + setnilvalue(gval(n)); /* clear value */ + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove it from table */ + } + } +} + + +static void freeupval (lua_State *L, UpVal *uv) { + if (upisopen(uv)) + luaF_unlinkupval(uv); + luaM_free(L, uv); +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->tt) { + case LUA_TPROTO: + luaF_freeproto(L, gco2p(o)); + break; + case LUA_TUPVAL: + freeupval(L, gco2upv(o)); + break; + case LUA_TLCL: + luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); + break; + case LUA_TCCL: + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + break; + case LUA_TTABLE: + luaH_free(L, gco2t(o)); + break; + case LUA_TTHREAD: + luaE_freethread(L, gco2th(o)); + break; + case LUA_TUSERDATA: + luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + case LUA_TSHRSTR: + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; + case LUA_TLNGSTR: + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); + break; + default: lua_assert(0); + } +} + + +/* +** sweep at most 'countin' elements from a list of GCObjects erasing dead +** objects, where a dead object is one marked with the old (non current) +** white; change all non-dead objects back to white, preparing for next +** collection cycle. Return where to continue the traversal or NULL if +** list is finished. ('*countout' gets the number of elements traversed.) +*/ +static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, + int *countout) { + global_State *g = G(L); + int ow = otherwhite(g); + int i; + int white = luaC_white(g); /* current white */ + for (i = 0; *p != NULL && i < countin; i++) { + GCObject *curr = *p; + int marked = curr->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* change mark to 'white' */ + curr->marked = cast_byte((marked & maskcolors) | white); + p = &curr->next; /* go to next element */ + } + } + if (countout) + *countout = i; /* number of elements traversed */ + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p) { + GCObject **old = p; + do { + p = sweeplist(L, p, 1, NULL); + } while (p == old); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +/* +** If possible, shrink string table. +*/ +static void checkSizes (lua_State *L, global_State *g) { + if (!g->gcemergency) { + l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + luaS_resize(L, g->strt.size / 2); + g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ + } +} + + +/* +** Get the next udata to be finalized from the 'tobefnz' list, and +** link it back into the 'allgc' list. +*/ +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(tofinalize(o)); + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ + if (issweepphase(g)) + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_callnoyield(L, L->top - 2, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { + global_State *g = G(L); + const TValue *tm; + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error object? */ + const char *msg = (ttisstring(s2v(L->top - 1))) + ? svalue(s2v(L->top - 1)) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } + } +} + + +/* +** Call a few finalizers +*/ +static int runafewfinalizers (lua_State *L, int n) { + global_State *g = G(L); + int i; + for (i = 0; i < n && g->tobefnz; i++) + GCTM(L, 1); /* call one finalizer */ + return i; +} + + +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L) { + global_State *g = G(L); + while (g->tobefnz) + GCTM(L, 0); +} + + +/* +** find last 'next' field in list 'p' list (to add elements in its end) +*/ +static GCObject **findlast (GCObject **p) { + while (*p != NULL) + p = &(*p)->next; + return p; +} + + +/* +** Move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized). +** (Note that objects after 'finobjold' cannot be white, so they +** don't need to be traversed. In incremental mode, 'finobjold' is NULL, +** so the whole list is traversed.) +*/ +static void separatetobefnz (global_State *g, int all) { + GCObject *curr; + GCObject **p = &g->finobj; + GCObject **lastnext = findlast(&g->tobefnz); + while ((curr = *p) != g->finobjold) { /* traverse all finalizable objects */ + lua_assert(tofinalize(curr)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &curr->next; /* don't bother with it */ + else { + if (curr == g->finobjsur) /* removing 'finobjsur'? */ + g->finobjsur = curr->next; /* correct it */ + *p = curr->next; /* remove 'curr' from 'finobj' list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &curr->next; + } + } +} + + +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (tofinalize(o) || /* obj. is already marked... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + if (issweepphase(g)) { + makewhite(g, o); /* "sweep" object 'o' */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ + } + else { /* correct pointers into 'allgc' list, if needed */ + if (o == g->survival) + g->survival = o->next; + if (o == g->old) + g->old = o->next; + if (o == g->reallyold) + g->reallyold = o->next; + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in 'finobj' list */ + g->finobj = o; + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generational Collector +** ======================================================= +*/ + + +/* mask to erase all color bits, not changing gen-related stuff */ +#define maskgencolors (~(bitmask(BLACKBIT) | WHITEBITS)) + + +/* +** Sweep a list of objects, deleting dead ones and turning +** the non dead to old (without changing their colors). +*/ +static void sweep2old (lua_State *L, GCObject **p) { + GCObject *curr; + while ((curr = *p) != NULL) { + if (iswhite(curr)) { /* is 'curr' dead? */ + lua_assert(isdead(G(L), curr)); + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* all surviving objects become old */ + setage(curr, G_OLD); + p = &curr->next; /* go to next element */ + } + } +} + + +/* +** Sweep for generational mode. Delete dead objects. (Because the +** collection is not incremental, there are no "new white" objects +** during the sweep. So, any white object must be dead.) For +** non-dead objects, advance their ages and clear the color of +** new objects. (Old objects keep their colors.) +*/ +static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, + GCObject *limit) { + static lu_byte nextage[] = { + G_SURVIVAL, /* from G_NEW */ + G_OLD1, /* from G_SURVIVAL */ + G_OLD1, /* from G_OLD0 */ + G_OLD, /* from G_OLD1 */ + G_OLD, /* from G_OLD (do not change) */ + G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ + G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ + }; + int white = luaC_white(g); + GCObject *curr; + while ((curr = *p) != limit) { + if (iswhite(curr)) { /* is 'curr' dead? */ + lua_assert(!isold(curr) && isdead(g, curr)); + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* correct mark and age */ + if (getage(curr) == G_NEW) + curr->marked = cast_byte((curr->marked & maskgencolors) | white); + setage(curr, nextage[getage(curr)]); + p = &curr->next; /* go to next element */ + } + } + return p; +} + + +/* +** Traverse a list making all its elements white and clearing their +** age. +*/ +static void whitelist (global_State *g, GCObject *p) { + int white = luaC_white(g); + for (; p != NULL; p = p->next) + p->marked = cast_byte((p->marked & maskcolors) | white); +} + + +/* +** Correct a list of gray objects. Because this correction is +** done after sweeping, young objects can be white and still +** be in the list. They are only removed. +** For tables, advance 'touched1' to 'touched2'; 'touched2' objects +** become regular old and are removed from the list. +** For threads, just remove white ones from the list. +*/ +static GCObject **correctgraylist (GCObject **p) { + GCObject *curr; + while ((curr = *p) != NULL) { + switch (curr->tt) { + case LUA_TTABLE: { + Table *h = gco2t(curr); + if (getage(h) == G_TOUCHED1) { /* touched in this cycle? */ + lua_assert(isgray(h)); + gray2black(h); /* make it black, for next barrier */ + changeage(h, G_TOUCHED1, G_TOUCHED2); + p = &h->gclist; /* go to next element */ + } + else { + if (!iswhite(h)) { + lua_assert(isold(h)); + if (getage(h) == G_TOUCHED2) + changeage(h, G_TOUCHED2, G_OLD); + gray2black(h); /* make it black */ + } + *p = h->gclist; /* remove 'curr' from gray list */ + } + break; + } + case LUA_TTHREAD: { + lua_State *th = gco2th(curr); + lua_assert(!isblack(th)); + if (iswhite(th)) /* new object? */ + *p = th->gclist; /* remove from gray list */ + else /* old threads remain gray */ + p = &th->gclist; /* go to next element */ + break; + } + default: lua_assert(0); /* nothing more could be gray here */ + } + } + return p; +} + + +/* +** Correct all gray lists, coalescing them into 'grayagain'. +*/ +static void correctgraylists (global_State *g) { + GCObject **list = correctgraylist(&g->grayagain); + *list = g->weak; g->weak = NULL; + list = correctgraylist(list); + *list = g->allweak; g->allweak = NULL; + list = correctgraylist(list); + *list = g->ephemeron; g->ephemeron = NULL; + correctgraylist(list); +} + + +/* +** Mark 'old1' objects when starting a new young collection. +** Gray objects are already in some gray list, and so will be visited +** in the atomic step. +*/ +static void markold (global_State *g, GCObject *from, GCObject *to) { + GCObject *p; + for (p = from; p != to; p = p->next) { + if (getage(p) == G_OLD1) { + lua_assert(!iswhite(p)); + if (isblack(p)) { + black2gray(p); /* should be '2white', but gray works too */ + reallymarkobject(g, p); + } + } + } +} + + +/* +** Finish a young-generation collection. +*/ +static void finishgencycle (lua_State *L, global_State *g) { + correctgraylists(g); + checkSizes(L, g); + g->gcstate = GCSpropagate; /* skip restart */ + callallpendingfinalizers(L); +} + + +/* +** Does a young collection. First, mark 'old1' objects. (Only survival +** and "recent old" lists can contain 'old1' objects. New lists cannot +** contain 'old1' objects, at most 'old0' objects that were already +** visited when marked old.) Then does the atomic step. Then, +** sweep all lists and advance pointers. Finally, finish the collection. +*/ +static void youngcollection (lua_State *L, global_State *g) { + GCObject **psurvival; /* to point to first non-dead survival object */ + lua_assert(g->gcstate == GCSpropagate); + markold(g, g->survival, g->reallyold); + markold(g, g->finobj, g->finobjrold); + atomic(L); + + /* sweep nursery and get a pointer to its last live element */ + psurvival = sweepgen(L, g, &g->allgc, g->survival); + /* sweep 'survival' and 'old' */ + sweepgen(L, g, psurvival, g->reallyold); + g->reallyold = g->old; + g->old = *psurvival; /* 'survival' survivals are old now */ + g->survival = g->allgc; /* all news are survivals */ + + /* repeat for 'finobj' lists */ + psurvival = sweepgen(L, g, &g->finobj, g->finobjsur); + /* sweep 'survival' and 'old' */ + sweepgen(L, g, psurvival, g->finobjrold); + g->finobjrold = g->finobjold; + g->finobjold = *psurvival; /* 'survival' survivals are old now */ + g->finobjsur = g->finobj; /* all news are survivals */ + + sweepgen(L, g, &g->tobefnz, NULL); + + finishgencycle(L, g); +} + + +/* +** Enter generational mode. Must go until the end of an atomic cycle +** to ensure that all threads are in the gray list. Then, turn all +** objects into old and finishes the collection. +*/ +static void entergen (lua_State *L, global_State *g) { + luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ + atomic(L); + /* sweep all elements making them old */ + sweep2old(L, &g->allgc); + /* everything alive now is old */ + g->reallyold = g->old = g->survival = g->allgc; + + /* repeat for 'finobj' lists */ + sweep2old(L, &g->finobj); + g->finobjrold = g->finobjold = g->finobjsur = g->finobj; + + sweep2old(L, &g->tobefnz); + + finishgencycle(L, g); + g->gckind = KGC_GEN; + g->GCestimate = gettotalbytes(g); /* base for memory control */ +} + + +/* +** Enter incremental mode. Turn all objects white, make all +** intermediate lists point to NULL (to avoid invalid pointers), +** and go to pause state. +*/ +static void enterinc (global_State *g) { + whitelist(g, g->allgc); + g->reallyold = g->old = g->survival = NULL; + whitelist(g, g->finobj); + g->finobjrold = g->finobjold = g->finobjsur = NULL; + lua_assert(g->tobefnz == NULL); /* no need to sweep */ + g->gcstate = GCSpause; + g->gckind = KGC_INC; +} + + +/* +** Change collector mode to 'newmode'. +*/ +void luaC_changemode (lua_State *L, int newmode) { + global_State *g = G(L); + if (newmode != g->gckind) { + if (newmode == KGC_GEN) /* entering generational mode? */ + entergen(L, g); + else + enterinc(g); /* entering incremental mode */ + } +} + + +/* +** Does a full collection in generational mode. +*/ +static void fullgen (lua_State *L, global_State *g) { + enterinc(g); + entergen(L, g); +} + + +/* +** Does a generational "step". If memory grows 'genmajormul'% larger +** than last major collection (kept in 'g->GCestimate'), does a major +** collection. Otherwise, does a minor collection and set debt to make +** another collection when memory grows 'genminormul'% larger. +** 'GCdebt <= 0' means an explicit call to GC step with "size" zero; +** in that case, always do a minor collection. +*/ +static void genstep (lua_State *L, global_State *g) { + lu_mem majorbase = g->GCestimate; + int majormul = getgcparam(g->genmajormul); + if (g->GCdebt > 0 && + gettotalbytes(g) > (majorbase / 100) * (100 + majormul)) { + fullgen(L, g); + } + else { + lu_mem mem; + youngcollection(L, g); + mem = gettotalbytes(g); + luaE_setdebt(g, -(cast(l_mem, (mem / 100)) * g->genminormul)); + g->GCestimate = majorbase; /* preserve base value */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** Set the "time" to wait before starting a new GC cycle; cycle will +** start when memory use hits the threshold of ('estimate' * pause / +** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, +** because Lua cannot even start with less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + int pause = getgcparam(g->gcpause); + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (pause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * pause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + if (debt > 0) debt = 0; + luaE_setdebt(g, debt); +} + + +/* +** Enter first sweep phase. +** The call to 'sweeptolive' makes the pointer point to an object +** inside the list (instead of to the header), so that the real sweep do +** not need to skip objects created between "now" and the start of the +** real sweep. +*/ +static void entersweep (lua_State *L) { + global_State *g = G(L); + g->gcstate = GCSswpallgc; + lua_assert(g->sweepgc == NULL); + g->sweepgc = sweeptolive(L, &g->allgc); +} + + +/* +** Delete all objects in list 'p' until (but not including) object +** 'limit'. +*/ +static void deletelist (lua_State *L, GCObject *p, GCObject *limit) { + while (p != limit) { + GCObject *next = p->next; + freeobj(L, p); + p = next; + } +} + + +/* +** Call all finalizers of the objects in the given Lua state, and +** then free all objects, except for the main thread. +*/ +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + luaC_changemode(L, KGC_INC); + separatetobefnz(g, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L); + deletelist(L, g->allgc, obj2gco(g->mainthread)); + deletelist(L, g->finobj, NULL); + deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); +} + + +static lu_mem atomic (lua_State *L) { + global_State *g = G(L); + lu_mem work = 0; + GCObject *origweak, *origall; + GCObject *grayagain = g->grayagain; /* save original list */ + g->grayagain = NULL; + lua_assert(g->ephemeron == NULL && g->weak == NULL); + lua_assert(!iswhite(g->mainthread)); + g->gcstate = GCSatomic; + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark global metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + work += remarkupvals(g); + work += propagateall(g); /* propagate changes */ + g->gray = grayagain; + work += propagateall(g); /* traverse 'grayagain' list */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* Clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + separatetobefnz(g, 0); /* separate objects to be finalized */ + work += markbeingfnz(g); /* mark objects that will be finalized */ + work += propagateall(g); /* remark, to propagate 'resurrection' */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak); /* clear keys from all 'allweak' tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + luaS_clearcache(g); + clearprotolist(g); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + lua_assert(g->gray == NULL); + return work; /* estimate of slots marked by 'atomic' */ +} + + +static int sweepstep (lua_State *L, global_State *g, + int nextstate, GCObject **nextlist) { + if (g->sweepgc) { + l_mem olddebt = g->GCdebt; + int count; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count); + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + return count; + } + else { /* enter next state */ + g->gcstate = nextstate; + g->sweepgc = nextlist; + return 0; /* no work done */ + } +} + + +static lu_mem singlestep (lua_State *L) { + global_State *g = G(L); + switch (g->gcstate) { + case GCSpause: { + restartcollection(g); + g->gcstate = GCSpropagate; + return 1; + } + case GCSpropagate: { + if (g->gray == NULL) { /* no more gray objects? */ + g->gcstate = GCSenteratomic; /* finish propagate phase */ + return 0; + } + else + return propagatemark(g); /* traverse one gray object */ + } + case GCSenteratomic: { + lu_mem work = propagateall(g); /* make sure gray list is empty */ + work += atomic(L); /* work is what was traversed by 'atomic' */ + entersweep(L); + g->GCestimate = gettotalbytes(g); /* first estimate */; + return work; + } + case GCSswpallgc: { /* sweep "regular" objects */ + return sweepstep(L, g, GCSswpfinobj, &g->finobj); + } + case GCSswpfinobj: { /* sweep objects with finalizers */ + return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + } + case GCSswptobefnz: { /* sweep objects to be finalized */ + return sweepstep(L, g, GCSswpend, NULL); + } + case GCSswpend: { /* finish sweeps */ + checkSizes(L, g); + g->gcstate = GCScallfin; + return 0; + } + case GCScallfin: { /* call remaining finalizers */ + if (g->tobefnz && !g->gcemergency) { + int n = runafewfinalizers(L, GCFINMAX); + return n * GCFINALIZECOST; + } + else { /* emergency mode or no more finalizers */ + g->gcstate = GCSpause; /* finish collection */ + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { + global_State *g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); +} + + +/* +** Performs a basic incremental step. The debt and step size are +** converted from bytes to "units of work"; then the function loops +** running single steps until adding that many units of work or +** finishing a cycle (pause state). Finally, it sets the debt that +** controls when next step will be performed. +*/ +static void incstep (lua_State *L, global_State *g) { + int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ + l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; + l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem)) + ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul + : MAX_LMEM; /* overflow; keep maximum value */ + do { /* repeat until pause or enough "credit" (negative debt) */ + lu_mem work = singlestep(L); /* perform one single step */ + debt -= work; + } while (debt > -stepsize && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g); /* pause until next cycle */ + else { + debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ + luaE_setdebt(g, debt); + } +} + +/* +** performs a basic GC step if collector is running +*/ +void luaC_step (lua_State *L) { + global_State *g = G(L); + if (g->gcrunning) { /* running? */ + if (g->gckind == KGC_INC) + incstep(L, g); + else + genstep(L, g); + } +} + + +/* +** Perform a full collection in incremental mode. +** Before running the collection, check 'keepinvariant'; if it is true, +** there may be some objects marked as black, so the collector has +** to sweep all objects to turn them back to white (as white has not +** changed, nothing will be collected). +*/ +static void fullinc (lua_State *L, global_State *g) { + if (keepinvariant(g)) /* black objects? */ + entersweep(L); /* sweep everything to turn them back to white */ + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ + /* estimate must be correct after a full GC cycle */ + lua_assert(g->GCestimate == gettotalbytes(g)); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + setpause(g); +} + + +/* +** Performs a full GC cycle; if 'isemergency', set a flag to avoid +** some operations which could change the interpreter state in some +** unexpected ways (running finalizers and shrinking some structures). +*/ +void luaC_fullgc (lua_State *L, int isemergency) { + global_State *g = G(L); + lua_assert(!g->gcemergency); + g->gcemergency = isemergency; /* set flag */ + if (g->gckind == KGC_INC) + fullinc(L, g); + else + fullgen(L, g); + g->gcemergency = 0; +} + +/* }====================================================== */ + + diff --git a/3rd/lua/lgc.h b/3rd/lua/lgc.h new file mode 100644 index 000000000..5113e922f --- /dev/null +++ b/3rd/lua/lgc.h @@ -0,0 +1,182 @@ +/* +** $Id: lgc.h,v 2.98 2017/05/26 19:14:29 roberto Exp roberto $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpropagate 0 +#define GCSenteratomic 1 +#define GCSatomic 2 +#define GCSswpallgc 3 +#define GCSswpfinobj 4 +#define GCSswptobefnz 5 +#define GCSswpend 6 +#define GCScallfin 7 +#define GCSpause 8 + + +#define issweepphase(g) \ + (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) + + +/* +** macro to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. +*/ + +#define keepinvariant(g) ((g)->gcstate <= GCSatomic) + + +/* +** some useful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) + + +/* +** Layout for bit use in 'marked' field. First three bits are +** used for object "age" in generational mode. +*/ +#define WHITE0BIT 3 /* object is white (type 0) */ +#define WHITE1BIT 4 /* object is white (type 1) */ +#define BLACKBIT 5 /* object is black */ +#define FINALIZEDBIT 6 /* object has been marked for finalization */ +#define TESTGRAYBIT 7 /* used by tests (luaL_checkmemory) */ + + +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) testbits((x)->marked, WHITEBITS) +#define isblack(x) testbit((x)->marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) + +#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) + +#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) ((m) & (ow)) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) + +#define changewhite(x) ((x)->marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->marked, BLACKBIT) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +/* object age in generational mode */ +#define G_NEW 0 /* created in current cycle */ +#define G_SURVIVAL 1 /* created in previous cycle */ +#define G_OLD0 2 /* marked old by frw. barrier in this cycle */ +#define G_OLD1 3 /* first full cycle as old */ +#define G_OLD 4 /* really old object (not to be visited) */ +#define G_TOUCHED1 5 /* old object touched this cycle */ +#define G_TOUCHED2 6 /* old object touched in previous cycle */ + +#define AGEBITS 7 /* all age bits (111) */ + +#define getage(o) ((o)->marked & AGEBITS) +#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a)) +#define isold(o) (getage(o) > G_SURVIVAL) + +#define changeage(o,f,t) \ + check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) + + +/* Default Values for GC parameters */ +#define LUAI_GENMAJORMUL 100 +#define LUAI_GENMINORMUL 12 + +/* wait memory to double before starting new cycle */ +#define LUAI_GCPAUSE 200 /* 200% */ + +/* +** gc parameters are stored divided by 4 to allow a maximum value larger +** than 1000 in an 'lu_byte'. +*/ +#define getgcparam(p) ((p) * 4) +#define setgcparam(p,v) ((p) = (v) / 4) + +#define LUAI_GCMUL 100 + +/* how much to allocate before next GC step (log2) */ +#define LUAI_GCSTEPSIZE 13 /* 8 KB */ + + +/* +** Does one step of collection when debt becomes positive. 'pre'/'pos' +** allows some adjustments to be done only when needed. macro +** 'condchangemem' is used only for heavy tests (forcing a full +** GC cycle on every opportunity) +*/ +#define luaC_condGC(L,pre,pos) \ + { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos); } + +/* more often than not, 'pre'/'pos' are empty */ +#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) + + +#define luaC_barrier(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_objbarrier(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) + +#define luaC_protobarrier(L,p,o) \ + (isblack(p) ? luaC_protobarrier_(L,p) : cast_void(0)) + +LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); +LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); + + +#endif diff --git a/3rd/lua/linit.c b/3rd/lua/linit.c new file mode 100644 index 000000000..3c2b6023b --- /dev/null +++ b/3rd/lua/linit.c @@ -0,0 +1,68 @@ +/* +** $Id: linit.c,v 1.39 2016/12/04 20:17:24 roberto Exp roberto $ +** Initialization of libraries for lua.c and other clients +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +** +** You can also *preload* libraries, so that a later 'require' can +** open the library, which is already linked to the application. +** For that, do the following code: +** +** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); +** lua_pushcfunction(L, luaopen_modname); +** lua_setfield(L, -2, modname); +** lua_pop(L, 1); // remove PRELOAD table +*/ + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {LUA_GNAME, luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_UTF8LIBNAME, luaopen_utf8}, + {LUA_DBLIBNAME, luaopen_debug}, +#if defined(LUA_COMPAT_BITLIB) + {LUA_BITLIBNAME, luaopen_bit32}, +#endif + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib; + /* "require" functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } +} + diff --git a/3rd/lua/liolib.c b/3rd/lua/liolib.c new file mode 100644 index 000000000..f3c914d7f --- /dev/null +++ b/3rd/lua/liolib.c @@ -0,0 +1,780 @@ +/* +** $Id: liolib.c,v 2.153 2017/11/16 13:19:06 roberto Exp roberto $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + +#define liolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#if !defined(l_checkmode) + +/* accepted extensions to 'mode' in 'fopen' */ +#if !defined(L_MODEEXT) +#define L_MODEEXT "b" +#endif + +/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ +static int l_checkmode (const char *mode) { + return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && + (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ + (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ +} + +#endif + +/* +** {====================================================== +** l_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(l_popen) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) +#define l_pclose(L,file) (pclose(file)) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#define l_popen(L,c,m) (_popen(c,m)) +#define l_pclose(L,file) (_pclose(file)) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_popen(L,c,m) \ + ((void)((void)c, m), \ + luaL_error(L, "'popen' not supported"), \ + (FILE*)0) +#define l_pclose(L,file) ((void)L, (void)file, -1) + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#if !defined(l_getc) /* { */ + +#if defined(LUA_USE_POSIX) +#define l_getc(f) getc_unlocked(f) +#define l_lockfile(f) flockfile(f) +#define l_unlockfile(f) funlockfile(f) +#else +#define l_getc(f) getc(f) +#define l_lockfile(f) ((void)0) +#define l_unlockfile(f) ((void)0) +#endif + +#endif /* } */ + + +/* +** {====================================================== +** l_fseek: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(l_fseek) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ + +/* Windows (but not DDK) and Visual C++ 2005 or higher */ +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else /* }{ */ + +/* ISO C definitions */ +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) + + +static int io_type (lua_State *L) { + LStream *p; + luaL_checkany(L, 1); + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + lua_pushnil(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + +static FILE *tofile (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; +} + + +/* +** When creating file handles, always creates a 'closed' file handle +** before opening the actual file; so, if there is a memory error, the +** handle is in a consistent state. +*/ +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; +} + + +/* +** Calls the 'close' function from a file handle. The 'volatile' avoids +** a bug in some versions of the Clang compiler (e.g., clang 3.0 for +** 32 bits). +*/ +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + volatile lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ +} + + +static int f_close (lua_State *L) { + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + return f_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); +} + + +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; +} + + +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, l_pclose(L, p->f)); +} + + +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newprefile(L); + p->f = l_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); + return p->f; +} + + +static int g_iofile (lua_State *L, const char *f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +/* +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit +** in the limit for upvalues of a closure) +*/ +#define MAXARGLINE 250 + +static void aux_lines (lua_State *L, int toclose) { + int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ + lua_pushcclosure(L, io_readline, 3 + n); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else { /* open a new file */ + const char *filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); + return 1; +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + + +/* auxiliary structure used by 'read_number' */ +typedef struct { + FILE *f; /* file being read */ + int c; /* current character (look ahead) */ + int n; /* number of elements in buffer 'buff' */ + char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ +} RN; + + +/* +** Add current char to buffer (if not out of space) and read next one +*/ +static int nextc (RN *rn) { + if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ + rn->buff[0] = '\0'; /* invalidate result */ + return 0; /* fail */ + } + else { + rn->buff[rn->n++] = rn->c; /* save current char */ + rn->c = l_getc(rn->f); /* read next one */ + return 1; + } +} + + +/* +** Accept current char if it is in 'set' (of size 2) +*/ +static int test2 (RN *rn, const char *set) { + if (rn->c == set[0] || rn->c == set[1]) + return nextc(rn); + else return 0; +} + + +/* +** Read a sequence of (hex)digits +*/ +static int readdigits (RN *rn, int hex) { + int count = 0; + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + count++; + return count; +} + + +/* +** Read a number: first reads a valid prefix of a numeral into a buffer. +** Then it calls 'lua_stringtonumber' to check whether the format is +** correct and to convert it to a Lua number +*/ +static int read_number (lua_State *L, FILE *f) { + RN rn; + int count = 0; + int hex = 0; + char decp[2]; + rn.f = f; rn.n = 0; + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '.'; /* always accept a dot */ + l_lockfile(rn.f); + do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ + test2(&rn, "-+"); /* optional sign */ + if (test2(&rn, "00")) { + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ + else count = 1; /* count initial '0' as a valid digit */ + } + count += readdigits(&rn, hex); /* integral part */ + if (test2(&rn, decp)) /* decimal point? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ + test2(&rn, "-+"); /* exponent sign */ + readdigits(&rn, 0); /* exponent digits */ + } + ungetc(rn.c, rn.f); /* unread look-ahead char */ + l_unlockfile(rn.f); + rn.buff[rn.n] = '\0'; /* finish string */ + if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ + return 1; /* ok */ + else { /* invalid format */ + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); /* no-op when c == EOF */ + lua_pushliteral(L, ""); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f, int chop) { + luaL_Buffer b; + int c = '\0'; + luaL_buffinit(L, &b); + while (c != EOF && c != '\n') { /* repeat until end of line */ + char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ + int i = 0; + l_lockfile(f); /* no memory errors can happen inside the lock */ + while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') + buff[i++] = c; + l_unlockfile(f); + luaL_addsize(&b, i); + } + if (!chop && c == '\n') /* want a newline and have one? */ + luaL_addchar(&b, c); /* add ending newline to result */ + luaL_pushresult(&b); /* close buffer */ + /* return ok if read something (either a newline or something else) */ + return (c == '\n' || lua_rawlen(L, -1) > 0); +} + + +static void read_all (lua_State *L, FILE *f) { + size_t nr; + luaL_Buffer b; + luaL_buffinit(L, &b); + do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ + char *p = luaL_prepbuffer(&b); + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); + luaL_addsize(&b, nr); + } while (nr == LUAL_BUFFERSIZE); + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int nresults, success; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f, 1); + nresults = 1; + } + else { + success = 1; + nresults = 0; + for (; nargs-- && success; first++) { + luaL_checkstack(L, LUA_MINSTACK, "too many arguments"); + if (lua_type(L, first) == LUA_TNUMBER) { + size_t l = (size_t)luaL_checkinteger(L, first); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + nresults++; + } + else { + const char *p = luaL_checkstring(L, first); + if (*p == '*') p++; /* skip optional '*' (for compatibility) */ + for (; success && *p != '\0'; p++) { + nresults++; + switch (*p) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, first, "invalid format"); + } + } + } + } + } + if (ferror(f)) + return luaL_fileresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return nresults; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + luaL_checkstack(L, n, "too many arguments"); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (lua_toboolean(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - arg; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, + (LUAI_UACINT)lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, + (LUAI_UACNUMBER)lua_tonumber(L, arg)); + status = status && (len > 0); + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + lua_Integer p3 = luaL_optinteger(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Integer)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (op) + return luaL_fileresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, (lua_Integer)l_ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); + return luaL_fileresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +} + + +/* +** functions for 'io' library +*/ +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +/* +** methods for file handles +*/ +static const luaL_Reg flib[] = { + {"close", f_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ +} + + +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; +} + diff --git a/3rd/lua/llex.c b/3rd/lua/llex.c new file mode 100644 index 000000000..eaa400fad --- /dev/null +++ b/3rd/lua/llex.c @@ -0,0 +1,565 @@ +/* +** $Id: llex.c,v 2.97 2017/06/09 16:48:44 roberto Exp roberto $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#define llex_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", + "", "", "", "" +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static l_noret lexerror (LexState *ls, const char *msg, int token); + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZE/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ + luaC_fix(L, obj2gco(e)); /* never collect this name */ + for (i=0; iextra = cast_byte(i+1); /* reserved word */ + } +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + lua_assert(token == cast_uchar(token)); + return luaO_pushfstring(ls->L, "'%c'", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, "'%s'", s); + else /* names, strings, and numerals */ + return s; + } +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: case TK_STRING: + case TK_FLT: case TK_INT: + save(ls, '\0'); + return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + + +static l_noret lexerror (LexState *ls, const char *msg, int token) { + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); +} + + +/* +** creates a new string and anchors it in scanner's table so that +** it will not be collected until the end of the compilation +** (by that time it should be anchored somewhere) +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TValue *o; /* entry for 'str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->h, s2v(L->top - 1)); + if (ttisnil(o)) { /* not in use yet? */ + /* boolean value does not need GC barrier; + table is not a metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + else { /* string already present */ + ts = keystrval(nodefromval(o)); /* re-use value previously stored */ + } + L->top--; /* remove string from stack */ + return ts; +} + + +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip '\n' or '\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip '\n\r' or '\r\n' */ + if (++ls->linenumber >= MAX_INT) + lexerror(ls, "chunk has too many lines", 0); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->t.token = 0; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +static int check_next1 (LexState *ls, int c) { + if (ls->current == c) { + next(ls); + return 1; + } + else return 0; +} + + +/* +** Check whether current char is in set 'set' (with two chars) and +** saves it +*/ +static int check_next2 (LexState *ls, const char *set) { + lua_assert(set[2] == '\0'); + if (ls->current == set[0] || ls->current == set[1]) { + save_and_next(ls); + return 1; + } + else return 0; +} + + +/* LUA_NUMBER */ +/* +** this function is quite liberal in what it accepts, as 'luaO_str2num' +** will reject ill-formed numerals. +*/ +static int read_numeral (LexState *ls, SemInfo *seminfo) { + TValue obj; + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next2(ls, expo)) /* exponent part? */ + check_next2(ls, "-+"); /* optional exponent sign */ + if (lisxdigit(ls->current)) + save_and_next(ls); + else if (ls->current == '.') + save_and_next(ls); + else break; + } + save(ls, '\0'); + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ + lexerror(ls, "malformed number", TK_FLT); + if (ttisinteger(&obj)) { + seminfo->i = ivalue(&obj); + return TK_INT; + } + else { + lua_assert(ttisfloat(&obj)); + seminfo->r = fltvalue(&obj); + return TK_FLT; + } +} + + +/* +** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return +** its number of '='s; otherwise, return a negative number (-1 iff there +** are no '='s after initial bracket) +*/ +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int line = ls->linenumber; /* initial line (for error message) */ + save_and_next(ls); /* skip 2nd '[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: { /* error */ + const char *what = (seminfo ? "string" : "comment"); + const char *msg = luaO_pushfstring(ls->L, + "unfinished long %s (starting at line %d)", what, line); + lexerror(ls, msg, TK_EOS); + break; /* to avoid warnings */ + } + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd ']' */ + goto endloop; + } + break; + } + case '\n': case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void esccheck (LexState *ls, int c, const char *msg) { + if (!c) { + if (ls->current != EOZ) + save_and_next(ls); /* add current to buffer for error message */ + lexerror(ls, msg, TK_STRING); + } +} + + +static int gethexa (LexState *ls) { + save_and_next(ls); + esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); + return luaO_hexavalue(ls->current); +} + + +static int readhexaesc (LexState *ls) { + int r = gethexa(ls); + r = (r << 4) + gethexa(ls); + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ + return r; +} + + +static unsigned long readutf8esc (LexState *ls) { + unsigned long r; + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ + save_and_next(ls); /* skip 'u' */ + esccheck(ls, ls->current == '{', "missing '{'"); + r = gethexa(ls); /* must have at least one digit */ + while ((save_and_next(ls), lisxdigit(ls->current))) { + i++; + r = (r << 4) + luaO_hexavalue(ls->current); + esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); + } + esccheck(ls, ls->current == '}', "missing '}'"); + next(ls); /* skip '}' */ + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ + return r; +} + + +static void utf8esc (LexState *ls) { + char buff[UTF8BUFFSZ]; + int n = luaO_utf8esc(buff, readutf8esc(ls)); + for (; n > 0; n--) /* add 'buff' to string */ + save(ls, buff[UTF8BUFFSZ - n]); +} + + +static int readdecesc (LexState *ls) { + int i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + r = 10*r + ls->current - '0'; + save_and_next(ls); + } + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + save_and_next(ls); /* keep '\\' for error messages */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case 'u': utf8esc(ls); goto no_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); + } + goto no_save; + } + default: { + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); + c = readdecesc(ls); /* digital escape '\ddd' */ + goto only_save; + } + } + read_save: + next(ls); + /* go through */ + only_save: + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + save(ls, c); + /* go through */ + no_save: break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep != -1) /* '[=...' missing second bracket */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; + } + case '=': { + next(ls); + if (check_next1(ls, '=')) return TK_EQ; + else return '='; + } + case '<': { + next(ls); + if (check_next1(ls, '=')) return TK_LE; + else if (check_next1(ls, '<')) return TK_SHL; + else return '<'; + } + case '>': { + next(ls); + if (check_next1(ls, '=')) return TK_GE; + else if (check_next1(ls, '>')) return TK_SHR; + else return '>'; + } + case '/': { + next(ls); + if (check_next1(ls, '/')) return TK_IDIV; + else return '/'; + } + case '~': { + next(ls); + if (check_next1(ls, '=')) return TK_NE; + else return '~'; + } + case ':': { + next(ls); + if (check_next1(ls, ':')) return TK_DBCOLON; + else return ':'; + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next1(ls, '.')) { + if (check_next1(ls, '.')) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + else return read_numeral(ls, seminfo); + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + return read_numeral(ls, seminfo); + } + case EOZ: { + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->extra - 1 + FIRST_RESERVED; + else { + return TK_NAME; + } + } + else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +int luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/3rd/lua/llex.h b/3rd/lua/llex.h new file mode 100644 index 000000000..a50b68735 --- /dev/null +++ b/3rd/lua/llex.h @@ -0,0 +1,85 @@ +/* +** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp roberto $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + + +#if !defined(LUA_ENV) +#define LUA_ENV "_ENV" +#endif + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, + TK_SHL, TK_SHR, + TK_DBCOLON, TK_EOS, + TK_FLT, TK_INT, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + lua_Integer i; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +/* state of the lexer plus state of the parser when shared by all + functions */ +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token 'consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* current function (parser) */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + Table *h; /* to avoid collection/reuse strings */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ + TString *source; /* current source name */ + TString *envn; /* environment variable name */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source, int firstchar); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/3rd/lua/llimits.h b/3rd/lua/llimits.h new file mode 100644 index 000000000..a9295645b --- /dev/null +++ b/3rd/lua/llimits.h @@ -0,0 +1,316 @@ +/* +** $Id: llimits.h,v 1.147 2017/12/11 18:53:53 roberto Exp roberto $ +** Limits, basic types, and some other 'installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + +/* +** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count +** the total memory used by Lua (in bytes). Usually, 'size_t' and +** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. +*/ +#if defined(LUAI_MEM) /* { external definitions? */ +typedef LUAI_UMEM lu_mem; +typedef LUAI_MEM l_mem; +#elif LUAI_BITSINT >= 32 /* }{ */ +typedef size_t lu_mem; +typedef ptrdiff_t l_mem; +#else /* 16-bit ints */ /* }{ */ +typedef unsigned long lu_mem; +typedef long l_mem; +#endif /* } */ + + +/* chars used as small naturals (so that 'char' is reserved for characters) */ +typedef unsigned char lu_byte; +typedef signed char ls_byte; + + +/* maximum value for size_t */ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +/* maximum size visible for Lua (must be representable in a lua_Integer */ +#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ + : (size_t)(LUA_MAXINTEGER)) + + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) + +#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) + + +#define MAX_INT INT_MAX /* maximum value of an int */ + + +/* +** floor of the log2 of the maximum signed value for integral type 't'. +** (That is, maximum 'n' such that '2^n' fits in the given signed type.) +*/ +#define log2maxs(t) (sizeof(t) * 8 - 2) + + +/* +** conversion of pointer to unsigned integer: +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) + + + +/* types of 'usual argument conversions' for lua_Number and lua_Integer */ +typedef LUAI_UACNUMBER l_uacNumber; +typedef LUAI_UACINT l_uacInt; + + +/* internal assertions for in-house debugging */ +#if defined(lua_assert) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) +#else +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) +#endif + +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) +#define luai_apicheck(l,e) lua_assert(e) +#endif + +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +/* macro to avoid warnings about unused variables */ +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) +#endif + + +/* type casts (a macro highlights casts in the code) */ +#define cast(t, exp) ((t)(exp)) + +#define cast_void(i) cast(void, (i)) +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* cast a signed lua_Integer to lua_Unsigned */ +#if !defined(l_castS2U) +#define l_castS2U(i) ((lua_Unsigned)(i)) +#endif + +/* +** cast a lua_Unsigned to a signed lua_Integer; this cast is +** not strict ISO C, but two-complement architectures should +** work fine. +*/ +#if !defined(l_castU2S) +#define l_castU2S(i) ((lua_Integer)(i)) +#endif + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) && _MSC_VER >= 1200 +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + + + +/* +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int. It must also +** be compatible with the size of the C stack.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 2200 +#endif + + + +/* +** type for virtual-machine instructions; +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +#if LUAI_BITSINT >= 32 +typedef unsigned int Instruction; +#else +typedef unsigned long Instruction; +#endif + + + +/* +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + + +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 128 +#endif + + +/* +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set (M == 1 +** makes a direct cache.) +*/ +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 +#endif + + +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + + +/* +** macros that are executed whenever program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + + + +/* +** The luai_num* macros define the primitive operations over numbers. +*/ + +/* floor division (defined as 'floor(a/b)') */ +#if !defined(luai_numidiv) +#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) +#endif + +/* float division */ +#if !defined(luai_numdiv) +#define luai_numdiv(L,a,b) ((a)/(b)) +#endif + +/* +** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when +** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of +** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) +** ~= floor(a/b)'. That happens when the division has a non-integer +** negative result, which is equivalent to the test below. +*/ +#if !defined(luai_nummod) +#define luai_nummod(L,a,b,m) \ + { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } +#endif + +/* exponentiation */ +#if !defined(luai_numpow) +#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) +#endif + +/* the others are quite standard operations */ +#if !defined(luai_numadd) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + + + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L,pre,pos) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L,pre,pos) \ + { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_, 0); pos; } +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L,pre,pos) ((void)0) +#else +#define condchangemem(L,pre,pos) \ + { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } +#endif + +#endif diff --git a/3rd/lua/lmathlib.c b/3rd/lua/lmathlib.c new file mode 100644 index 000000000..e0240c9b5 --- /dev/null +++ b/3rd/lua/lmathlib.c @@ -0,0 +1,410 @@ +/* +** $Id: lmathlib.c,v 1.118 2016/12/20 18:37:00 roberto Exp roberto $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + +#define lmathlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (l_mathop(3.141592653589793238462643383279502884)) + + +#if !defined(l_rand) /* { */ +#if defined(LUA_USE_POSIX) +#define l_rand() random() +#define l_srand(x) srandom(x) +#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */ +#else +#define l_rand() rand() +#define l_srand(x) srand(x) +#define L_RANDMAX RAND_MAX +#endif +#endif /* } */ + + +static int math_abs (lua_State *L) { + if (lua_isinteger(L, 1)) { + lua_Integer n = lua_tointeger(L, 1); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); + lua_pushinteger(L, n); + } + else + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_Number y = luaL_checknumber(L, 1); + lua_Number x = luaL_optnumber(L, 2, 1); + lua_pushnumber(L, l_mathop(atan2)(y, x)); + return 1; +} + + +static int math_toint (lua_State *L) { + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (valid) + lua_pushinteger(L, n); + else { + luaL_checkany(L, 1); + lua_pushnil(L); /* value is not convertible to integer */ + } + return 1; +} + + +static void pushnumint (lua_State *L, lua_Number d) { + lua_Integer n; + if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ + lua_pushinteger(L, n); /* result is integer */ + else + lua_pushnumber(L, d); /* result is float */ +} + + +static int math_floor (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_ceil (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own ceil */ + else { + lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_fmod (lua_State *L) { + if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { + lua_Integer d = lua_tointeger(L, 2); + if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ + luaL_argcheck(L, d != 0, 2, "zero"); + lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ + } + else + lua_pushinteger(L, lua_tointeger(L, 1) % d); + } + else + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + + +/* +** next function does not use 'modf', avoiding problems with 'double*' +** (which is not compatible with 'float*') when lua_Number is not +** 'double'. +*/ +static int math_modf (lua_State *L) { + if (lua_isinteger(L ,1)) { + lua_settop(L, 1); /* number is its own integer part */ + lua_pushnumber(L, 0); /* no fractional part */ + } + else { + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); + pushnumint(L, ip); + /* fractional part (test needed for inf/-inf) */ + lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); + } + return 2; +} + + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; +} + + +static int math_ult (lua_State *L) { + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); + return 1; +} + +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); +#if !defined(LUA_USE_C89) + if (base == l_mathop(2.0)) + res = l_mathop(log2)(x); else +#endif + if (base == l_mathop(10.0)) + res = l_mathop(log10)(x); + else + res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); + return 1; +} + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imin = 1; /* index of current minimum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, i, imin, LUA_OPLT)) + imin = i; + } + lua_pushvalue(L, imin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imax = 1; /* index of current maximum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, imax, i, LUA_OPLT)) + imax = i; + } + lua_pushvalue(L, imax); + return 1; +} + +/* +** This function uses 'double' (instead of 'lua_Number') to ensure that +** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' +** will keep full precision (ensuring that 'r' is always less than 1.0.) +*/ +static int math_random (lua_State *L) { + lua_Integer low, up; + double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ + return 1; + } + case 1: { /* only upper limit */ + low = 1; + up = luaL_checkinteger(L, 1); + break; + } + case 2: { /* lower and upper limits */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + /* random integer in the interval [low, up] */ + luaL_argcheck(L, low <= up, 1, "interval is empty"); + luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, + "interval too large"); + r *= (double)(up - low) + 1.0; + lua_pushinteger(L, (lua_Integer)r + low); + return 1; +} + + +static int math_randomseed (lua_State *L) { + l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); + (void)l_rand(); /* discard first value to avoid undesirable correlations */ + return 0; +} + + +static int math_type (lua_State *L) { + if (lua_type(L, 1) == LUA_TNUMBER) { + if (lua_isinteger(L, 1)) + lua_pushliteral(L, "integer"); + else + lua_pushliteral(L, "float"); + } + else { + luaL_checkany(L, 1); + lua_pushnil(L); + } + return 1; +} + + +/* +** {================================================================== +** Deprecated functions (for compatibility only) +** =================================================================== +*/ +#if defined(LUA_COMPAT_MATHLIB) + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = (int)luaL_checkinteger(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} + +#endif +/* }================================================================== */ + + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"tointeger", math_toint}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"ult", math_ult}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tan", math_tan}, + {"type", math_type}, +#if defined(LUA_COMPAT_MATHLIB) + {"atan2", math_atan}, + {"cosh", math_cosh}, + {"sinh", math_sinh}, + {"tanh", math_tanh}, + {"pow", math_pow}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, +#endif + /* placeholders */ + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, (lua_Number)HUGE_VAL); + lua_setfield(L, -2, "huge"); + lua_pushinteger(L, LUA_MAXINTEGER); + lua_setfield(L, -2, "maxinteger"); + lua_pushinteger(L, LUA_MININTEGER); + lua_setfield(L, -2, "mininteger"); + return 1; +} + diff --git a/3rd/lua/lmem.c b/3rd/lua/lmem.c new file mode 100644 index 000000000..ecafef493 --- /dev/null +++ b/3rd/lua/lmem.c @@ -0,0 +1,169 @@ +/* +** $Id: lmem.c,v 1.94 2017/12/08 17:28:25 roberto Exp roberto $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#define lmem_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + +#if defined(HARDMEMTESTS) +#define hardtest(L,os,s) /* force a GC whenever possible */ \ + if ((s) > (os) && (G(L))->gcrunning) luaC_fullgc(L, 1); +#else +#define hardtest(L,os,s) ((void)0) +#endif + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** ('osize' is the old size, 'nsize' is the new size) +** +** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no +** matter 'x'). +** +** * frealloc(ud, p, x, 0) frees the block 'p' +** (in this specific case, frealloc must return NULL); +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ISO C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, + int size_elems, int limit, const char *what) { + void *newblock; + int size = *psize; + if (nelems + 1 <= size) /* does one extra element still fit? */ + return block; /* nothing to be done */ + if (size >= limit / 2) { /* cannot double it? */ + if (size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + size = limit; /* still have at least one free place */ + } + else { + size *= 2; + if (size < MINSIZEARRAY) + size = MINSIZEARRAY; /* minimum size */ + } + lua_assert(nelems + 1 <= size && size <= limit); + /* 'limit' ensures that multiplication will not overflow */ + newblock = luaM_realloc_(L, block, cast(size_t, *psize) * size_elems, + cast(size_t, size) * size_elems); + if (newblock == NULL) + luaM_error(L); + *psize = size; /* update only when everything else is OK */ + return newblock; +} + + +void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, + int final_n, int size_elem) { + global_State *g = G(L); + void *newblock; + size_t oldsize = cast(size_t, (*size) * size_elem); + size_t newsize = cast(size_t, final_n * size_elem); + lua_assert(newsize <= oldsize); + newblock = (*g->frealloc)(g->ud, block, oldsize, newsize); + if (newblock == NULL && final_n > 0) /* allocation failed? */ + luaM_error(L); + else { + g->GCdebt += newsize - oldsize; + *size = final_n; + return newblock; + } +} + + +l_noret luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); +} + + +/* +** Free memory +*/ +void luaM_free_ (lua_State *L, void *block, size_t osize) { + global_State *g = G(L); + lua_assert((block == 0) == (block == NULL)); + (*g->frealloc)(g->ud, block, osize, 0); + g->GCdebt -= osize; +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + hardtest(L, osize, nsize); + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + /* Is state fully built? Not shrinking a block? */ + if (g->version && nsize > osize) { + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + return NULL; + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - osize; + return newblock; +} + + +void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, + size_t nsize) { + void *newblock = luaM_realloc_(L, block, osize, nsize); + if (newblock == NULL && nsize > 0) /* allocation failed? */ + luaM_error(L); + return newblock; +} + + +void *luaM_malloc_ (lua_State *L, size_t size, int tag) { + hardtest(L, 0, size); + if (size == 0) + return NULL; /* that's all */ + else { + global_State *g = G(L); + void *newblock = (*g->frealloc)(g->ud, NULL, tag, size); + if (newblock == NULL) { + if (g->version) { /* is state fully built? */ + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */ + } + if (newblock == NULL) + luaM_error(L); + } + g->GCdebt += size; + return newblock; + } +} diff --git a/3rd/lua/lmem.h b/3rd/lua/lmem.h new file mode 100644 index 000000000..e98aabdbd --- /dev/null +++ b/3rd/lua/lmem.h @@ -0,0 +1,91 @@ +/* +** $Id: lmem.h,v 1.45 2017/12/07 18:59:52 roberto Exp roberto $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + + +#define luaM_error(L) luaD_throw(L, LUA_ERRMEM) + + +/* +** This macro tests whether it is safe to multiply 'n' by the size of +** type 't' without overflows. Because 'e' is always constant, it avoids +** the runtime division MAX_SIZET/(e). +** (The macro is somewhat complex to avoid warnings: The 'sizeof' +** comparison avoids a runtime comparison when overflow cannot occur. +** The compiler should be able to optimize the real test by itself, but +** when it does it, it may give a warning about "comparison is always +** false due to limited range of data type"; the +1 tricks the compiler, +** avoiding this warning but also this optimization.) +*/ +#define luaM_testsize(n,e) \ + (sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) + +#define luaM_checksize(L,n,e) \ + (luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0)) + + +/* +** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that +** the result is not larger than 'n' and cannot overflow a 'size_t' +** when multiplied by the size of type 't'. (Assumes that 'n' is an +** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.) +*/ +#define luaM_limitN(n,t) \ + ((cast(size_t, n) > MAX_SIZET/sizeof(t)) ? (MAX_SIZET/sizeof(t)) : (n)) + +/* +** Arrays of chars do not need any test +*/ +#define luaM_reallocvchar(L,b,on,n) \ + cast(char *, luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) + +#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) +#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) +#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) + +#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) +#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) +#define luaM_newvectorchecked(L,n,t) \ + (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) + +#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ + luaM_limitN(limit,t),e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + (cast(t *, luaM_realloc_(L, v, cast(size_t, oldn) * sizeof(t), \ + cast(size_t, n) * sizeof(t)))) + +#define luaM_shrinkvector(L,v,size,fs,t) \ + ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) + +LUAI_FUNC l_noret luaM_toobig (lua_State *L); + +/* not to be called directly */ +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, + int *size, int size_elem, int limit, + const char *what); +LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, + int final_n, int size_elem); +LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); + +#endif + diff --git a/3rd/lua/loadlib.c b/3rd/lua/loadlib.c new file mode 100644 index 000000000..176330428 --- /dev/null +++ b/3rd/lua/loadlib.c @@ -0,0 +1,790 @@ +/* +** $Id: loadlib.c,v 1.130 2017/01/12 17:14:26 roberto Exp roberto $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. +*/ + +#define loadlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +/* +** unique key for table in the registry that keeps handles +** for all loaded C libraries +*/ +static const int CLIBS = 0; + +#define LIB_FAIL "open" + + +#define setprogdir(L) ((void)0) + + +/* +** system-dependent functions +*/ + +/* +** unload library 'lib' +*/ +static void lsys_unloadlib (void *lib); + +/* +** load C library in file 'path'. If 'seeglb', load with all names in +** the library global. +** Returns the library; in case of error, returns NULL plus an +** error string in the stack. +*/ +static void *lsys_load (lua_State *L, const char *path, int seeglb); + +/* +** Try to find a function named 'sym' in library 'lib'. +** Returns the function; in case of error, returns NULL plus an +** error string in the stack. +*/ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); + + + + +#if defined(LUA_USE_DLOPEN) /* { */ +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +/* +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. +** (The '__extension__' in gnu compilers is only to avoid warnings.) +*/ +#if defined(__GNUC__) +#define cast_func(p) (__extension__ (lua_CFunction)(p)) +#else +#define cast_func(p) ((lua_CFunction)(p)) +#endif + + +static void lsys_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = cast_func(dlsym(lib, sym)); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) /* }{ */ +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + +#undef setprogdir + + +/* +** Replace in the path (on the top of the stack) any occurrence +** of LUA_EXEC_DIR with the executable's path. +*/ +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; /* cut name on the last '\\' to get the path */ + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void lsys_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + +#else /* }{ */ +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void lsys_unloadlib (void *lib) { + (void)(lib); /* not used */ +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif /* } */ + + +/* +** {================================================================== +** Set Paths +** =================================================================== +*/ + +/* +** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH_VAR) +#define LUA_PATH_VAR "LUA_PATH" +#endif + +#if !defined(LUA_CPATH_VAR) +#define LUA_CPATH_VAR "LUA_CPATH" +#endif + + +#define AUXMARK "\1" /* auxiliary mark */ + + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +/* +** Set a path +*/ +static void setpath (lua_State *L, const char *fieldname, + const char *envname, + const char *dft) { + const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); + const char *path = getenv(nver); /* use versioned name */ + if (path == NULL) /* no environment variable? */ + path = getenv(envname); /* try unversioned name */ + if (path == NULL || noenv(L)) /* no environment variable? */ + lua_pushstring(L, dft); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); + luaL_gsub(L, path, AUXMARK, dft); + lua_remove(L, -2); /* remove result from 1st 'gsub' */ + } + setprogdir(L); + lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ + lua_pop(L, 1); /* pop versioned variable name */ +} + +/* }================================================================== */ + + +/* +** return registry.CLIBS[path] +*/ +static void *checkclib (lua_State *L, const char *path) { + void *plib; + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; +} + + +/* +** registry.CLIBS[path] = plib -- for queries +** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries +*/ +static void addtoclib (lua_State *L, const char *path, void *plib) { + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib +** handles in list CLIBS +*/ +static int gctm (lua_State *L) { + lua_Integer n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + lsys_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; +} + + + +/* error codes for 'lookforfunc' */ +#define ERRLIB 1 +#define ERRFUNC 2 + +/* +** Look for a C function named 'sym' in a dynamically loaded library +** 'path'. +** First, check whether the library is already loaded; if not, try +** to load it. +** Then, if 'sym' is '*', return true (as library has been loaded). +** Otherwise, look for symbol 'sym' in the library and push a +** C function with that symbol. +** Return 0 and 'true' or a function in the stack; in case of +** errors, return an error code and an error message in the stack. +*/ +static int lookforfunc (lua_State *L, const char *path, const char *sym) { + void *reg = checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ + if (reg == NULL) return ERRLIB; /* unable to load library */ + addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else { + lua_CFunction f = lsys_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = lookforfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + luaL_buffinit(L, &msg); + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename = luaL_gsub(L, lua_tostring(L, -1), + LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file '%s'", filename); + lua_remove(L, -2); /* remove file name */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ + } + luaL_pushresult(&msg); /* create error message */ + return NULL; /* not found */ +} + + +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, "'package.%s' must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int searcher_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +} + + +/* +** Try to find a load function for module 'modname' at file 'filename'. +** First, change '.' to '_' in 'modname'; then, if 'modname' has +** the form X-Y (that is, it has an "ignore mark"), build a function +** name "luaopen_X" and look for it. (For compatibility, if that +** fails, it also tries "luaopen_Y".) If there is no ignore mark, +** look for a function named "luaopen_modname". +*/ +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *openfunc; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); +} + + +static int searcher_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); +} + + +static int searcher_Croot (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; +} + + +static int searcher_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + /* push 'package.searchers' to index 3 in the stack */ + if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) + luaL_error(L, "'package.searchers' must be a table"); + luaL_buffinit(L, &msg); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, 2, name); /* LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* LOADED[name] = returned value */ + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +/* +** changes the environment variable of calling function +*/ +static void set_env (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, "'module' not called from a Lua function"); + lua_pushvalue(L, -2); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module table */ + /* check whether table already has a _NAME field */ + if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) + lua_pop(L, 1); /* table is an initialized module */ + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + set_env(L); + dooptions(L, lastarg); + return 1; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushglobaltable(L); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + +#endif +/* }====================================================== */ + + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) + {"seeall", ll_seeall}, +#endif + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) + {"module", ll_module}, +#endif + {"require", ll_require}, + {NULL, NULL} +}; + + +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with predefined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i+1); + } +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ +} + + +/* +** create table CLIBS to keep track of loaded C libraries, +** setting a finalizer to close all libraries when closing state. +*/ +static void createclibstable (lua_State *L) { + lua_newtable(L); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create 'package' table */ + createsearcherstable(L); + /* set paths */ + setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); + setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_setfield(L, -2, "loaded"); + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ +} + diff --git a/3rd/lua/lobject.c b/3rd/lua/lobject.c new file mode 100644 index 000000000..c7d4c06a6 --- /dev/null +++ b/3rd/lua/lobject.c @@ -0,0 +1,528 @@ +/* +** $Id: lobject.c,v 2.121 2017/11/23 19:29:04 roberto Exp roberto $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#define lobject_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= (8 << 4)) { /* coarse steps */ + x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ + e += 4; + } + while (x >= (8 << 1)) { /* fine steps */ + x = (x + 1) >> 1; /* x = ceil(x / 2) */ + e++; + } + return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); +} + + +/* +** Computes ceil(log2(x)) +*/ +int luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = 0; + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, + lua_Integer v2) { + switch (op) { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB:return intop(-, v1, v2); + case LUA_OPMUL:return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPIDIV: return luaV_div(L, v1, v2); + case LUA_OPBAND: return intop(&, v1, v2); + case LUA_OPBOR: return intop(|, v1, v2); + case LUA_OPBXOR: return intop(^, v1, v2); + case LUA_OPSHL: return luaV_shiftl(v1, v2); + case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPUNM: return intop(-, 0, v1); + case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); + default: lua_assert(0); return 0; + } +} + + +static lua_Number numarith (lua_State *L, int op, lua_Number v1, + lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(L, v1, v2); + case LUA_OPSUB: return luai_numsub(L, v1, v2); + case LUA_OPMUL: return luai_nummul(L, v1, v2); + case LUA_OPDIV: return luai_numdiv(L, v1, v2); + case LUA_OPPOW: return luai_numpow(L, v1, v2); + case LUA_OPIDIV: return luai_numidiv(L, v1, v2); + case LUA_OPUNM: return luai_numunm(L, v1); + case LUA_OPMOD: { + lua_Number m; + luai_nummod(L, v1, v2, m); + return m; + } + default: lua_assert(0); return 0; + } +} + + +int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, + TValue *res) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: + case LUA_OPBNOT: { /* operate only on integers */ + lua_Integer i1; lua_Integer i2; + if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) { + setivalue(res, intarith(L, op, i1, i2)); + return 1; + } + else return 0; /* fail */ + } + case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ + lua_Number n1; lua_Number n2; + if (tonumberns(p1, n1) && tonumberns(p2, n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return 1; + } + else return 0; /* fail */ + } + default: { /* other operations */ + lua_Number n1; lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2)) { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return 1; + } + else if (tonumberns(p1, n1) && tonumberns(p2, n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return 1; + } + else return 0; /* fail */ + } + } +} + + +void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, + StkId res) { + if (!luaO_rawarith(L, op, p1, p2, s2v(res))) { + /* could not perform raw operation; try metamethod */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); + } +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return (ltolower(c) - 'a') + 10; +} + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + + +/* +** {================================================================== +** Lua's implementation for 'lua_strx2number' +** =================================================================== +*/ + +#if !defined(lua_strx2number) + +/* maximum number of significant digits to read (to avoid overflows + even with single floats) */ +#define MAXSIGDIG 30 + +/* +** convert a hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + int dot = lua_getlocaledecpoint(); + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ + int neg; /* 1 if number is negative */ + int hasdot = 0; /* true after seen a dot */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check sign */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + for (s += 2; ; s++) { /* skip '0x' and read numeral */ + if (*s == dot) { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; + } + else if (lisxdigit(cast_uchar(*s))) { + if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ + nosigdig++; + else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(*s); + else e++; /* too many digits; ignore, but still count for exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ + } + else break; /* neither a dot nor a digit */ + } + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ + *endptr = cast(char *, s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; /* exponent value */ + int neg1; /* exponent sign */ + s++; /* skip 'p' */ + neg1 = isneg(&s); /* sign */ + if (!lisdigit(cast_uchar(*s))) + return 0.0; /* invalid; must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + *endptr = cast(char *, s); /* valid up to here */ + } + if (neg) r = -r; + return l_mathop(ldexp)(r, e); +} + +#endif +/* }====================================================== */ + + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + +static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { + char *endptr; + *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ + : lua_str2number(s, &endptr); + if (endptr == s) return NULL; /* nothing recognized? */ + while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ + return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ +} + + +/* +** Convert string 's' to a Lua number (put in 'result'). Return NULL +** on fail or the address of the ending '\0' on success. +** 'pmode' points to (and 'mode' contains) special things in the string: +** - 'x'/'X' means a hexadecimal numeral +** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) +** - '.' just optimizes the search for the common case (nothing special) +** This function accepts both the current locale or a dot as the radix +** mark. If the conversion fails, it may mean number has a dot but +** locale accepts something else. In that case, the code copies 's' +** to a buffer (because 's' is read-only), changes the dot to the +** current locale radix mark, and tries to convert again. +*/ +static const char *l_str2d (const char *s, lua_Number *result) { + const char *endptr; + const char *pmode = strpbrk(s, ".xXnN"); + int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; + if (mode == 'n') /* reject 'inf' and 'nan' */ + return NULL; + endptr = l_str2dloc(s, result, mode); /* try to convert */ + if (endptr == NULL) { /* failed? may be a different locale */ + char buff[L_MAXLENNUM + 1]; + const char *pdot = strchr(s, '.'); + if (strlen(s) > L_MAXLENNUM || pdot == NULL) + return NULL; /* string too long or no dot; fail */ + strcpy(buff, s); /* copy string to buffer */ + buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ + endptr = l_str2dloc(buff, result, mode); /* try again */ + if (endptr != NULL) + endptr = s + (endptr - buff); /* make relative to 's' */ + } + return endptr; +} + + +#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) +#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) + +static const char *l_str2int (const char *s, lua_Integer *result) { + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { /* hex? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) { + a = a * 16 + luaO_hexavalue(*s); + empty = 0; + } + } + else { /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) { + int d = *s - '0'; + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return NULL; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ + else { + *result = l_castU2S((neg) ? 0u - a : a); + return s; + } +} + + +size_t luaO_str2num (const char *s, TValue *o) { + lua_Integer i; lua_Number n; + const char *e; + if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ + setivalue(o, i); + } + else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ + setfltvalue(o, n); + } + else + return 0; /* conversion failed */ + return (e - s) + 1; /* success; return string size */ +} + + +int luaO_utf8esc (char *buff, unsigned long x) { + int n = 1; /* number of bytes put in buffer (backwards) */ + lua_assert(x <= 0x10FFFF); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = cast(char, x); + else { /* need continuation bytes */ + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ + do { /* add continuation bytes */ + buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ + } + return n; +} + + +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +/* +** Convert a number object to a string +*/ +void luaO_tostring (lua_State *L, TValue *obj) { + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); + else { + len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); +#if !defined(LUA_COMPAT_FLOATSTRING) + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } +#endif + } + setsvalue(L, obj, luaS_newlstr(L, buff, len)); +} + + +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + luaD_inctop(L); +} + + +/* +** this function handles only '%d', '%c', '%f', '%p', and '%s' + conventional formats, plus Lua-specific '%I' and '%U' +*/ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 0; + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + pushstr(L, fmt, e - fmt); + switch (*(e+1)) { + case 's': { /* zero-terminated string */ + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s, strlen(s)); + break; + } + case 'c': { /* an 'int' as a character */ + char buff = cast(char, va_arg(argp, int)); + if (lisprint(cast_uchar(buff))) + pushstr(L, &buff, 1); + else /* non-printable character; print its code */ + luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); + break; + } + case 'd': { /* an 'int' */ + setivalue(s2v(L->top), va_arg(argp, int)); + goto top2str; + } + case 'I': { /* a 'lua_Integer' */ + setivalue(s2v(L->top), cast(lua_Integer, va_arg(argp, l_uacInt))); + goto top2str; + } + case 'f': { /* a 'lua_Number' */ + setfltvalue(s2v(L->top), cast_num(va_arg(argp, l_uacNumber))); + top2str: /* convert the top element to a string */ + luaD_inctop(L); + luaO_tostring(L, s2v(L->top - 1)); + break; + } + case 'p': { /* a pointer */ + char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ + void *p = va_arg(argp, void *); + int l = lua_pointer2str(buff, sizeof(buff), p); + pushstr(L, buff, l); + break; + } + case 'U': { /* an 'int' as a UTF-8 sequence */ + char buff[UTF8BUFFSZ]; + int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); + pushstr(L, buff + UTF8BUFFSZ - l, l); + break; + } + case '%': { + pushstr(L, "%", 1); + break; + } + default: { + luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", + *(e + 1)); + } + } + n += 2; + fmt = e+2; + } + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); + return svalue(s2v(L->top - 1)); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + diff --git a/3rd/lua/lobject.h b/3rd/lua/lobject.h new file mode 100644 index 000000000..c7b6be18d --- /dev/null +++ b/3rd/lua/lobject.h @@ -0,0 +1,646 @@ +/* +** $Id: lobject.h,v 2.130 2017/11/07 13:25:26 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 +*/ + + +/* +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Variant tags for strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ + + +/* Variant tags for numbers */ +#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ +#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + + +/* +** Common type for all collectable objects +*/ +typedef struct GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common type has only the common header +*/ +struct GCObject { + CommonHeader; +}; + + + + +/* +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. +*/ + +/* +** Union of all Lua values +*/ +typedef union Value { + 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; + + +#define TValuefields Value value_; lu_byte tt_ + + +typedef struct TValue { + TValuefields; +} TValue; + + + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) +#define valraw(o) (&val_(o)) + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttyperaw(t) ((t) & 0x3F) +#define ttype(o) ttyperaw(rttype(o)) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttnov(o) (novariant(rttype(o))) + + +/* Macros to test type */ +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttnov(o) == (t)) +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_TNUMFLT) +#define ttisinteger(o) checktag((o), LUA_TNUMINT) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) + + +/* +** Macros to access unstructured values (may come both from +** 'TValue's and table keys) +*/ +#define ivalueraw(v) ((v).i) +#define fltvalueraw(v) ((v).n) +#define gcvalueraw(v) ((v).gc) +#define pvalueraw(v) ((v).p) +#define tsvalueraw(v) (gco2ts((v).gc)) +#define fvalueraw(v) ((v).f) +#define bvalueraw(v) ((v).b) + + +/* Macros to access values */ +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) +#define nvalue(o) check_exp(ttisnumber(o), \ + (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) +#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) +#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) +#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) +#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + + +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* +** Protected access to objects in values +*/ +#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) + + +/* Macros for internal tests */ +#define righttt(obj) (ttype(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 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); } + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } + +#define setpvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } + +#define setbvalue(obj,x) \ + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io = (obj); GCObject *i_g=(x); \ + val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } + +#define setsvalue(L,obj,x) \ + { TValue *io = (obj); TString *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ + checkliveness(L,io); } + +#define setuvalue(L,obj,x) \ + { TValue *io = (obj); Udata *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(L,io); } + +#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 setclLvalue(L,obj,x) \ + { TValue *io = (obj); LClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(L,io); } + +#define setclCvalue(L,obj,x) \ + { TValue *io = (obj); CClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(L,io); } + +#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 setobj(L,obj1,obj2) \ + { TValue *io1=(obj1); const TValue *io2=(obj2); \ + io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + (void)L; checkliveness(L,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) +#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s) +#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h) +#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t) +#define setptvalue2s(L,o,p) setptvalue(L,s2v(o),p) +#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl) +/* from table to same table */ +#define setobjt2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue +/* to table */ +#define setobj2t setobj + + + + +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + + +typedef union StackValue { + TValue val; +} StackValue; + + +typedef StackValue *StkId; /* index to stack elements */ + +/* convert a 'StackValue' to a 'TValue' */ +#define s2v(o) (&(o)->val) + + + +/* +** 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(char *, (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)) + + +/* +** Header for userdata; memory area follows the end of this structure +** (aligned according to 'UUdata'; see next). +*/ +typedef struct Udata { + CommonHeader; + lu_byte ttuv_; /* user value's tag */ + struct Table *metatable; + size_t len; /* number of bytes */ + union Value user_; /* user value */ +} Udata; + + +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UUdata { + LUAI_MAXALIGN; /* ensures maximum alignment for 'local' udata */ + Udata uv; +} UUdata; + + +/* +** Get the address of memory block inside 'Udata'. +** (Access to 'ttuv_' ensures that value is really a 'Udata'.) +*/ +#define getudatamem(u) \ + check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata))) + +#define setuservalue(L,u,o) \ + { const TValue *io=(o); Udata *iu = (u); \ + iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ + checkliveness(L,io); } + + +#define getuservalue(L,u,o) \ + { TValue *io=(o); const Udata *iu = (u); \ + io->value_ = iu->user_; settt_(io, iu->ttuv_); \ + checkliveness(L,io); } + + +/* +** 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 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; + + + +/* +** 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; + + + +/* +** Closures +*/ + +#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 isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) + + +/* +** Tables +*/ + + +/* +** 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 +** only 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)) + + +/* +** (address of) a fixed nil value +*/ +#define luaO_nilobject (&luaO_nilobject_) + + +LUAI_DDEC const TValue luaO_nilobject_; + +/* 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 + diff --git a/3rd/lua/lopcodes.c b/3rd/lua/lopcodes.c new file mode 100644 index 000000000..a5867d235 --- /dev/null +++ b/3rd/lua/lopcodes.c @@ -0,0 +1,176 @@ +/* +** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#define lopcodes_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lopcodes.h" + + +/* ORDER OP */ + +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADI", + "LOADF", + "LOADK", + "LOADKX", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "SETUPVAL", + "GETTABUP", + "GETTABLE", + "GETI", + "GETFIELD", + "SETTABUP", + "SETTABLE", + "SETI", + "SETFIELD", + "NEWTABLE", + "SELF", + "ADDI", + "SUBI", + "MULI", + "MODI", + "POWI", + "DIVI", + "IDIVI", + "BANDK", + "BORK", + "BXORK", + "SHRI", + "SHLI", + "ADD", + "SUB", + "MUL", + "MOD", + "POW", + "DIV", + "IDIV", + "BAND", + "BOR", + "BXOR", + "SHL", + "SHR", + "UNM", + "BNOT", + "NOT", + "LEN", + "CONCAT", + "CLOSE", + "JMP", + "EQ", + "LT", + "LE", + "EQK", + "EQI", + "LTI", + "LEI", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "RETURN0", + "RETURN1", + "FORLOOP1", + "FORPREP1", + "FORLOOP", + "FORPREP", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "EXTRAARG", + NULL +}; + + +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* OT IT T A mode opcode */ + opmode(0, 0, 0, 1, iABC) /* OP_MOVE */ + ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADI */ + ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADF */ + ,opmode(0, 0, 0, 1, iABx) /* OP_LOADK */ + ,opmode(0, 0, 0, 1, iABx) /* OP_LOADKX */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LOADBOOL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LOADNIL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETUPVAL */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABUP */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETFIELD */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABLE */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETI */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETFIELD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_NEWTABLE */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SELF */ + ,opmode(0, 0, 0, 1, iABC) /* OP_ADDI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SUBI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MULI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MODI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_POWI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_DIVI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHRI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHLI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_ADD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SUB */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MUL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MOD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_POW */ + ,opmode(0, 0, 0, 1, iABC) /* OP_DIV */ + ,opmode(0, 0, 0, 1, iABC) /* OP_IDIV */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BAND */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BOR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BXOR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_UNM */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BNOT */ + ,opmode(0, 0, 0, 1, iABC) /* OP_NOT */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LEN */ + ,opmode(0, 0, 0, 1, iABC) /* OP_CONCAT */ + ,opmode(0, 0, 0, 0, iABC) /* OP_CLOSE */ + ,opmode(0, 0, 0, 0, isJ) /* OP_JMP */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQ */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LT */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LE */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQK */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LTI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LEI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ + ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ + ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ + ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ + ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ + ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */ + ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP */ + ,opmode(0, 0, 0, 0, iABC) /* OP_TFORCALL */ + ,opmode(0, 0, 0, 1, iABx) /* OP_TFORLOOP */ + ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ + ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ + ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ + ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ +}; + diff --git a/3rd/lua/lopcodes.h b/3rd/lua/lopcodes.h new file mode 100644 index 000000000..eae0dfaf5 --- /dev/null +++ b/3rd/lua/lopcodes.h @@ -0,0 +1,361 @@ +/* +** $Id: lopcodes.h,v 1.180 2017/12/18 17:49:31 roberto Exp roberto $ +** 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 |k| C(8) | | B(8) | | A(8) | | Op(7) | +iABx | Bx(17) | | A(8) | | Op(7) | +iAsBx | sBx (signed)(17) | | A(8) | | Op(7) | +iAx | Ax(25) | | Op(7) | +iksJ |k| sJ(24) | | 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_Cx (SIZE_C + 1) +#define SIZE_B 8 +#define SIZE_Bx (SIZE_Cx + SIZE_B) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_Cx + SIZE_B + SIZE_A) +#define SIZE_sJ (SIZE_C + SIZE_B + SIZE_A) + + +#define SIZE_OP 7 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_B (POS_A + SIZE_A) +#define POS_C (POS_B + SIZE_B) +#define POS_k (POS_C + SIZE_C) +#define POS_Bx POS_B +#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 LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ + + +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<> 1) + + +#define MAXARG_A ((1<> 1) +#define MAXARG_Cx ((1<<(SIZE_C + 1))-1) + + +/* 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)<> C */ +OP_SHLI,/* A B C R(A) := C << 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_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) := length of R(B) */ + +OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ + +OP_CLOSE,/* A close all upvalues >= R(A) */ +OP_JMP,/* k sJ pc += sJ (k is used in code generation) */ +OP_EQ,/* A B if ((R(A) == R(B)) ~= k) then pc++ */ +OP_LT,/* A B if ((R(A) < R(B)) ~= k) then pc++ */ +OP_LE,/* A B if ((R(A) <= R(B)) ~= k) then pc++ */ + +OP_EQK,/* A B if ((R(A) == K(B)) ~= k) then pc++ */ +OP_EQI,/* A sB if ((R(A) == sB) ~= k) then pc++ */ +OP_LTI,/* A sB if ((R(A) < sB) ~= k) then pc++ */ +OP_LEI,/* A sB if ((R(A) <= sB) ~= k) then pc++ */ + +OP_TEST,/* A if (not R(A) == k) then pc++ */ +OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ + +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ +OP_RETURN0,/* return */ +OP_RETURN1,/* A return R(A) */ + +OP_FORLOOP1,/* A Bx R(A)++; + if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ +OP_FORPREP1,/* A Bx R(A)--; pc+=Bx */ + +OP_FORLOOP,/* A Bx R(A)+=R(A+2); + if R(A) (!(B<=A)) or (A<=B) => (!(Btop' for next instruction (when C == 0) +** bit 6: instruction uses 'L->top' set by previous instruction (when B == 0) +*/ + +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 testOTMode(m) (luaP_opmodes[m] & (1 << 5)) +#define testITMode(m) (luaP_opmodes[m] & (1 << 6)) + +/* "out top" (set top for next instruction) */ +#define isOT(i) (testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) + +/* "in top" (uses top from previous instruction) */ +#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) + +#define opmode(ot,it,t,a,m) (((ot)<<5) | ((it)<<6) | ((t)<<4) | ((a)<<3) | (m)) + + +LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/3rd/lua/loslib.c b/3rd/lua/loslib.c new file mode 100644 index 000000000..62988d270 --- /dev/null +++ b/3rd/lua/loslib.c @@ -0,0 +1,409 @@ +/* +** $Id: loslib.c,v 1.65 2016/07/18 17:58:58 roberto Exp roberto $ +** 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 +** =================================================================== +*/ + +#if !defined(l_time_t) /* { */ +/* +** type to represent time_t in Lua +*/ +#define l_timet lua_Integer +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) + +static time_t l_checktime (lua_State *L, int arg) { + lua_Integer t = luaL_checkinteger(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} + +#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 = 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 (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=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + 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, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon + 1); + setfield(L, "year", stm->tm_year + 1900); + setfield(L, "wday", stm->tm_wday + 1); + setfield(L, "yday", stm->tm_yday + 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; +} + + +/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ +#if !defined(L_MAXDATEFIELD) +#define L_MAXDATEFIELD (INT_MAX / 2) +#endif + +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 (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (d < 0) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); + res = d; + } + else { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + 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 */ +} + + +/* 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, + "time 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_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); + 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/3rd/lua/lparser.c b/3rd/lua/lparser.c new file mode 100644 index 000000000..e99b33ffb --- /dev/null +++ b/3rd/lua/lparser.c @@ -0,0 +1,1733 @@ +/* +** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#define lparser_c +#define LUA_CORE + +#include "lprefix.h" + + +#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 */ + int brks; /* list of break jumps in this block */ + lu_byte brkcls; /* true if some 'break' needs to close upvalues */ + 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 */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void statement (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove "near " from final message */ + luaX_syntaxerror(ls, msg); +} + + +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); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "%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 (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname (LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} + + +static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; + } +} + + +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +} + + +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 int newupvalue (FuncState *fs, TString *name, expdesc *v) { + 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; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + if (eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + 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; +} + + +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ +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); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* 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 == VVOID) /* not found? */ + return; /* it is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ + } + } +} + + +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(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ +} + + +#define enterlevel(ls) luaE_incCcalls((ls)->L) + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local '%s'", + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchgoto(fs, gt->pc, label->pc, 1); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int solvelabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +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].pc = pc; + l->n = n + 1; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void solvegotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); /* will remove 'i' from the list */ + else + i++; + } +} + + +/* +** export pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. Also export +** break list. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { /* for each pending goto */ + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { /* leaving a variable scope? */ + if (bl->upval) /* variable may be an upvalue? */ + luaK_patchclose(fs, gt->pc); /* jump will need a close */ + gt->nactvar = bl->nactvar; /* update goto level */ + } + if (!solvelabel(fs->ls, i)) + i++; /* move to next one */ + /* else, 'solvelabel' removed current goto from the list + and 'i' now points to next one */ + } + /* handles break list */ + if (bl->upval) /* exiting the scope of an upvalue? */ + luaK_patchclose(fs, bl->brks); /* breaks will need OP_CLOSE */ + /* move breaks to outer block */ + luaK_concat(fs, &bl->previous->brks, bl->brks); + bl->previous->brkcls |= bl->brkcls; +} + + +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->brks = NO_JUMP; + bl->brkcls = 0; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +/* +** Fix all breaks in block 'bl' to jump to the end of the block. +*/ +static void fixbreaks (FuncState *fs, BlockCnt *bl) { + int target = fs->pc; + if (bl->brkcls) /* does the block need to close upvalues? */ + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_patchgoto(fs, bl->brks, target, bl->brkcls); + bl->brks = NO_JUMP; /* no more breaks to fix */ + bl->brkcls = 0; /* no more need to close upvalues */ + lua_assert(!bl->upval); /* loop body cannot have local variables */ +} + + +/* +** generates an error for an undefined 'goto'. +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = "no visible label '%s' for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->upval && bl->brks != NO_JUMP) /* breaks in upvalue scopes? */ + bl->brkcls = 1; /* these breaks must close the upvalues */ + if (bl->isloop) + fixbreaks(fs, bl); /* fix pending breaks */ + if (bl->previous && bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* 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 { + lua_assert(bl->brks == NO_JUMP); /* no pending breaks */ + 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 must use 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->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f->source = ls->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, 0, 0); /* final return */ + leaveblock(fs); + 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->nlocvars, LocVar); + luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + lua_assert(fs->bl == NULL); + 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 */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of 'record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | '['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"); + checkname(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, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.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); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void field (LexState *ls, struct 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); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOC, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ + 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); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { ',' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + if (ls->t.token != ')') { /* is 'parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: { /* param -> '...' */ + luaX_next(ls); + if (testnext(ls, '=')) + new_localvar(ls, str_checkname(ls)); + else + new_localvarliteral(ls, "_ARG"); + f->is_vararg = 1; /* declared vararg */ + nparams++; + break; + } + default: luaX_syntaxerror(ls, " or '...' expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar) - f->is_vararg; + luaK_reserveregs(fs, fs->nactvar); /* reserve register 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); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use 'seminfo' before 'next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + } + } + 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); + checkname(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(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + int lastparam = fs->f->numparams; + check_condition(ls, fs->f->is_vararg, + "cannot use '...' outside a vararg function"); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, lastparam, 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; + } +} + + +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) { + int line = ls->linenumber; + luaX_next(ls); + 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); + 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.info) { + 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.info) { + 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') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (!vkisindexed(nv.v.k)) + check_conflict(ls, lh, &nv.v); + luaE_incCcalls(ls->L); /* control recursion depth */ + assignment(ls, &nv, nvars+1); + ls->L->nCcalls--; + } + else { /* assignment -> '=' 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, int pc) { + int line = ls->linenumber; + int g; + luaX_next(ls); /* skip 'goto' */ + g = newlabelentry(ls, &ls->dyd->gt, str_checkname(ls), line, pc); + solvelabel(ls, g); /* close it if label already defined */ +} + + +static void breakstat (LexState *ls, int pc) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + luaX_next(ls); /* skip break */ + while (bl && !bl->isloop) { bl = bl->previous; } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + luaK_concat(fs, &fs->bl->brks, pc); +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label '%s' already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +/* skip no-op statements */ +static void skipnoopstat (LexState *ls) { + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ + FuncState *fs = ls->fs; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); + luaK_codeABC(fs, OP_CLOSE, fs->nactvar, 0, 0); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + solvegotos(ls, &ll->arr[l]); +} + + +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) */ + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit); + 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, 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. Return true if expression is a constant integer and, +** if 'i' is not-zero, its value is equal to 'i'. +** +*/ +static int exp1 (LexState *ls, int i) { + expdesc e; + int res; + expr(ls, &e); + res = luaK_isKint(&e) && (i == 0 || i == e.u.ival); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); + return res; +} + + +/* +** 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 (offset > MAXARG_Bx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_Bx(*jmp, offset); +} + + +/* +** Generate code for a 'for' loop. 'kind' can be zero (a common for +** loop), one (a basic for loop, with integer values and increment of +** 1), or two (a generic for loop). +*/ +static void forbody (LexState *ls, int base, int line, int nvars, int kind) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0) + : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0) + : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + if (kind == 2) { /* generic for? */ + luaK_patchtohere(fs, prep); + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); + } + else { + fixforjump(fs, prep, luaK_getlabel(fs), 0); + endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0) + : luaK_codeABx(fs, OP_FORLOOP1, 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; + int basicfor = 1; /* true if it is a "basic" 'for' (integer + 1) */ + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + if (!exp1(ls, 0)) /* initial value not an integer? */ + basicfor = 0; /* not a basic 'for' */ + checknext(ls, ','); + exp1(ls, 0); /* limit */ + if (testnext(ls, ',')) { + if (!exp1(ls, 1)) /* optional step not 1? */ + basicfor = 0; /* not a basic 'for' */ + } + else { /* default step = 1 */ + luaK_int(fs, fs->freereg, 1); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, basicfor); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* 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, 3, explist(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 2); +} + + +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_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + if (ls->t.token == TK_GOTO) + gotostat(ls, v.t); /* handle goto */ + else + breakstat(ls, v.t); /* handle break */ + while (testnext(ls, ';')) {} /* skip semicolons */ + if (block_follow(ls, 0)) { /* 'goto'/'break' 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 goto/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; + 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! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls)); + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {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); + 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; + assignment(ls, &v, 1); + } + else { /* stat -> func */ + Instruction *inst = &getinstruction(fs, &v.v); + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(*inst, 1); /* call statement uses no results */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + if (block_follow(ls, 1) || ls->t.token == ';') + first = 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) { /* tail call? */ + SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the stack */ + first = fs->nactvar; /* return all active values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); + 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, luaK_jump(ls->fs)); + break; + } + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; + } + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); +} + +/* }====================================================================== */ + + +/* +** 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; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always declared vararg */ + fs->f->numparams = 0; + new_localvarliteral(ls, "_ARG"); + adjustlocalvars(ls, 1); + luaK_reserveregs(fs, 1); /* reserve register for vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + 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); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ + 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/3rd/lua/lparser.h b/3rd/lua/lparser.h new file mode 100644 index 000000000..6007d618b --- /dev/null +++ b/3rd/lua/lparser.h @@ -0,0 +1,143 @@ +/* +** $Id: lparser.h,v 1.79 2017/11/30 13:29:18 roberto Exp roberto $ +** 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 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; nval = numerical integer value */ + VNONRELOC, /* expression has its value in a fixed register; + info = result register */ + VLOCAL, /* local variable; info = local register */ + VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ + 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) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + +typedef struct expdesc { + expkind k; + union { + lua_Integer ival; /* for VKINT */ + lua_Number nval; /* for VKFLT */ + int info; /* for generic use */ + struct { /* for indexed variables */ + short idx; /* index (R or "long" K) */ + lu_byte t; /* table (register or upvalue) */ + } ind; + } u; + int t; /* patch list of 'exit when true' */ + int f; /* patch list of 'exit when false' */ +} expdesc; + + +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} 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; /* local level where it appears in current block */ +} 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 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) */ + short nlocvars; /* 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 */ +} FuncState; + + +LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); + + +#endif diff --git a/3rd/lua/lprefix.h b/3rd/lua/lprefix.h new file mode 100644 index 000000000..6b72f0eba --- /dev/null +++ b/3rd/lua/lprefix.h @@ -0,0 +1,45 @@ +/* +** $Id: lprefix.h,v 1.1 2014/11/03 15:12:44 roberto Exp roberto $ +** 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/3rd/lua/lstate.c b/3rd/lua/lstate.c new file mode 100644 index 000000000..81e10851a --- /dev/null +++ b/3rd/lua/lstate.c @@ -0,0 +1,370 @@ +/* +** $Id: lstate.c,v 2.148 2017/11/23 16:35:54 roberto Exp roberto $ +** 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" + + + +/* +** a macro to help the creation of a unique random seed when a state is +** created; the seed is used to randomize hashes. +*/ +#if !defined(luai_makeseed) +#include +#define luai_makeseed() cast(unsigned int, time(NULL)) +#endif + + + +/* +** 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))) + + +/* +** Compute an initial seed as random as possible. Rely on Address Space +** Layout Randomization (if present) to increase randomness.. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast(size_t, e); \ + memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int makeseed (lua_State *L) { + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + + +/* +** 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; +} + + +/* +** Increment count of "C calls" and check for overflows. In case of +** a stack overflow, check appropriate error ("regular" overflow or +** overflow while handling stack overflow). If 'nCalls' is larger than +** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but +** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to +** allow overflow handling to work) +*/ +void luaE_incCcalls (lua_State *L) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci; + luaE_incCcalls(L); + 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; + L->nCcalls -= L->nci; /* to subtract removed elements from 'nCcalls' */ + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } + L->nCcalls += L->nci; /* to subtract removed elements from 'nCcalls' */ +} + + +/* +** free half of the CallInfo structures not in use by a thread +*/ +void luaE_shrinkCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next2; /* next's next */ + L->nCcalls -= L->nci; /* to subtract removed elements from 'nCcalls' */ + /* while there are two nexts */ + while (ci->next != NULL && (next2 = ci->next->next) != NULL) { + luaM_free(L, ci->next); /* free next */ + L->nci--; + ci->next = next2; /* remove 'next' from the list */ + next2->previous = ci; + ci = next2; /* keep next's next */ + } + L->nCcalls += L->nci; /* to subtract removed elements from 'nCcalls' */ +} + + +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, StackValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(s2v(L1->stack + i)); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = CIST_C; + ci->func = L1->top; + 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, L->stacksize); /* free stack array */ +} + + +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue temp; + /* 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, &temp, L); /* temp = L */ + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); +} + + +/* +** open parts of the state that may cause memory-allocation errors. +** ('g->version' != NULL flags that the state was completely build) +*/ +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->gcrunning = 1; /* allow gc */ + g->gcemergency = 0; + g->version = lua_version(NULL); + 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->stacksize = 0; + L->twups = L; /* thread has no upvalues */ + L->errorJmp = NULL; + L->nCcalls = 0; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->nny = 1; + L->status = LUA_OK; + L->errfunc = 0; +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeallobjects(L); /* collect all objects */ + if (g->version) /* closing a fully built state? */ + 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 = G(L); + lua_State *L1; + lua_lock(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_TTHREAD; + /* 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_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); +} + + +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_TTHREAD; + 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; + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->seed = makeseed(L); + g->gcrunning = 0; /* no GC while building state */ + g->strt.size = g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + g->panic = NULL; + g->version = NULL; + g->gcstate = GCSpause; + g->gckind = KGC_INC; + g->finobj = g->tobefnz = g->fixedgc = NULL; + g->survival = g->old = g->reallyold = NULL; + g->finobjsur = g->finobjold = g->finobjrold = NULL; + g->sweepgc = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = g->protogray = NULL; + g->twups = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + 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) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + close_state(L); +} + + diff --git a/3rd/lua/lstate.h b/3rd/lua/lstate.h new file mode 100644 index 000000000..bc4df4e56 --- /dev/null +++ b/3rd/lua/lstate.h @@ -0,0 +1,265 @@ +/* +** $Id: lstate.h,v 2.152 2017/11/23 16:35:54 roberto Exp roberto $ +** 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). +** +** 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: +** +** '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. +** There is also a list 'protogray' for prototypes that need to have +** their caches cleared. + +*/ + + +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 */ +#define EXTRA_STACK 5 + + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + +/* 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. +*/ +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; + l_signalT trap; + } 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 */ + } u2; + short nresults; /* expected number of results from this function */ + lu_byte 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_HOOKED (1<<2) /* call is running a debug hook */ +#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */ +#define CIST_TAIL (1<<4) /* call was tail called */ +#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */ +#define CIST_LEQ (1<<6) /* using __lt for __le */ +#define CIST_FIN (1<<7) /* call is running a finalizer */ + +/* 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 */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + 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 genminormul; /* control for minor generational collections */ + lu_byte genmajormul; /* control for major generational collections */ + lu_byte gcrunning; /* true if 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 *protogray; /* list of prototypes with "new" caches */ + 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 *old; /* start of old objects */ + GCObject *reallyold; /* old objects with more than one cycle */ + GCObject *finobjsur; /* list of survival objects with finalizers */ + GCObject *finobjold; /* list of old 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; + const lua_Number *version; /* pointer to version number */ + TString *nfield; /* string "n" (key in vararg tables) */ + 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 */ +} global_State; + + +/* +** 'per thread' state +*/ +struct lua_State { + CommonHeader; + unsigned short nci; /* number of items in 'ci' list */ + lu_byte status; + StkId top; /* first free slot in the stack */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *oldpc; /* last pc traced */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + UpVal *openupval; /* list of open upvalues in this stack */ + 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) */ + int stacksize; + int basehookcount; + int hookcount; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + l_signalT hookmask; + lu_byte allowhook; +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects (only for conversions) +*/ +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; +}; + + +#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_TUSERDATA, &((cast_u(o))->u)) +#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) +#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((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_TTABLE, &((cast_u(o))->h)) +#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) +#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) +#define gco2upv(o) check_exp((o)->tt == LUA_TUPVAL, &((cast_u(o))->upv)) + + +/* macro to convert a Lua object into a GCObject */ +#define obj2gco(v) (&(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_incCcalls (lua_State *L); + + +#endif + diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c new file mode 100644 index 000000000..60d4702de --- /dev/null +++ b/3rd/lua/lstring.c @@ -0,0 +1,283 @@ +/* +** $Id: lstring.c,v 2.61 2017/12/12 11:52:35 roberto Exp roberto $ +** 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" + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT 5 +#endif + + + +/* +** 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_TLNGSTR && b->tt == LUA_TLNGSTR); + 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(unsigned int, l); + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (; l >= step; l -= step) + h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); + return h; +} + + +unsigned int luaS_hashlongstr (TString *ts) { + lua_assert(ts->tt == LUA_TLNGSTR); + if (ts->extra == 0) { /* no hash? */ + ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, 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 (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->nfield; /* 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; + TString *memerrmsg; + 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 */ + memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(memerrmsg)); /* it should never be collected */ + g->nfield = luaS_newliteral(L, "n"); /* pre-create "n" field name */ + luaC_fix(L, obj2gco(g->nfield)); /* it also 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->nfield; +} + + + +/* +** 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_TLNGSTR, 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 (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_TSHRSTR, 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 >= (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) { + Udata *u; + GCObject *o; + if (s > MAX_SIZE - sizeof(Udata)) + luaM_toobig(L); + o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); + u = gco2u(o); + u->len = s; + u->metatable = NULL; + setuservalue(L, u, luaO_nilobject); + return u; +} + diff --git a/3rd/lua/lstring.h b/3rd/lua/lstring.h new file mode 100644 index 000000000..a994fe1e5 --- /dev/null +++ b/3rd/lua/lstring.h @@ -0,0 +1,56 @@ +/* +** $Id: lstring.h,v 1.62 2017/07/27 13:50:16 roberto Exp roberto $ +** 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" + + +#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) + +#define sizeludata(l) (sizeof(union UUdata) + (l)) +#define sizeudata(u) sizeludata((u)->len) + +#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_TSHRSTR && (s)->extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (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); +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/3rd/lua/lstrlib.c b/3rd/lua/lstrlib.c new file mode 100644 index 000000000..84b6e4eb2 --- /dev/null +++ b/3rd/lua/lstrlib.c @@ -0,0 +1,1744 @@ +/* +** $Id: lstrlib.c,v 1.259 2017/11/16 13:19:06 roberto Exp roberto $ +** 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 string position: negative means back from end */ +static lua_Integer 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; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); + lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (lua_Integer)l) end = l; + if (start <= end) + lua_pushlstring(L, s + start - 1, (size_t)(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) /* may overflow? */ + 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 posi = posrelat(luaL_optinteger(L, 2, 1), l); + lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi < 1) posi = 1; + if (pose > (lua_Integer)l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= 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; i= 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 (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with '%%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a ']' */ + if (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 (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 (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 (*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 */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index %%%d", i + 1); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +/* 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); + lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ + lua_pushnil(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 - 1, ls - (size_t)init + 1, 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 - 1; + 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); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +/* 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); + GMatchState *gm; + lua_settop(L, 2); /* keep them on closure to avoid being collected */ + gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s; 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, i; + lua_State *L = ms->L; + const char *news = lua_tolstring(L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC) + luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); + luaL_addchar(b, news[i]); + } + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ + lua_remove(L, -2); /* remove original value */ + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void 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: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl, 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 */ + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + 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++; + add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ + 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; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + 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_mathlim(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 (fmt[SIZELENMOD] != 'a') + return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; +} + +#endif /* } */ + + +/* +** Maximum size of each formatted item. This maximum 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 then rounded to 120 for "extra +** expenses", such as locale-dependent stuff) +*/ +#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) + + +/* valid flags in a format specification */ +#define FLAGS "-+ #0" + +/* +** maximum size of each format specification (such as "%-099.99d") +*/ +#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 *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; + *form = '\0'; + return p; +} + + +/* +** 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; + 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 ('%...') */ + char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); + break; + } + case 'd': case 'i': + case 'o': case 'u': case 'x': case 'X': { + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); + break; + } + case 'a': case 'A': + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, MAX_ITEM, form, + luaL_checknumber(L, arg)); + break; + case 'e': case 'E': case 'f': + case 'g': case 'G': { + lua_Number n = luaL_checknumber(L, arg); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); + break; + } + case 'q': { + 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"); + if (!strchr(form, '.') && 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, MAX_ITEM, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } + } + break; + } + default: { /* also treat cases 'pnLlh' */ + return luaL_error(L, "invalid option '%%%c' to 'format'", + *(strfrmt - 1)); + } + } + lua_assert(nb < MAX_ITEM); + 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}; + + +/* dummy structure to get native alignment requirements */ +struct cD { + char c; + union { double d; void *p; lua_Integer i; lua_Number n; } u; +}; + +#define MAXALIGN (offsetof(struct cD, u)) + + +/* +** Union for serializing floats +*/ +typedef union Ftypes { + float f; + double d; + lua_Number n; + char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ +} Ftypes; + + +/* +** 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, /* 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 (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) { + 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 'd': *size = sizeof(double); return Kfloat; + case 'n': *size = sizeof(lua_Number); return Kfloat; + 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 (*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 '!': 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 ((align & (align - 1)) != 0) /* is 'align' 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 (volatile char *dest, volatile const char *src, + int size, int islittle) { + if (islittle == nativeendian.little) { + while (size-- != 0) + *(dest++) = *(src++); + } + 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: { /* floating-point options */ + volatile Ftypes u; + char *buff = luaL_prepbuffsize(&b, size); + lua_Number n = luaL_checknumber(L, arg); /* get argument */ + if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ + else if (size == sizeof(u.d)) u.d = (double)n; + else u.n = n; + /* move 'u' to final result, correcting endianness if needed */ + copywithendian(buff, u.buff, size, 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); + size += ntoalign; /* total space used by option */ + luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, + "format result too large"); + totalsize += size; + switch (opt) { + case Kstring: /* strings with length count */ + case Kzstr: /* zero-terminated string */ + luaL_argerror(L, 1, "variable-length format"); + /* call never return, but to avoid warnings: *//* FALLTHROUGH */ + default: break; + } + } + 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 ((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 = (size_t)posrelat(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); + if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) + luaL_argerror(L, 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: { + volatile Ftypes u; + lua_Number num; + copywithendian(u.buff, data + pos, size, h.islittle); + if (size == sizeof(u.f)) num = (lua_Number)u.f; + else if (size == sizeof(u.d)) num = (lua_Number)u.d; + else num = u.n; + lua_pushnumber(L, num); + 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, pos + len + size <= ld, 2, "data string too short"); + lua_pushlstring(L, data + pos + size, len); + pos += len; /* skip string */ + break; + } + case Kzstr: { + size_t len = (int)strlen(data + pos); + 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/3rd/lua/ltable.c b/3rd/lua/ltable.c new file mode 100644 index 000000000..419f9f6c5 --- /dev/null +++ b/3rd/lua/ltable.c @@ -0,0 +1,785 @@ +/* +** $Id: ltable.c,v 2.129 2017/12/08 17:28:25 roberto Exp roberto $ +** 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 such that, measured in bytes, +** it 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) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->hash) +#define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, point2uint(p)) + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_TNIL, /* value's value and type */ + LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ +}; + + +/* +** 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(unsigned int, i) + cast(unsigned int, ni); + return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); + } +} +#endif + + +/* +** returns the 'main' position of an element in a table (that is, +** the index of its hash value). The key comes broken (tag in 'ktt' +** and value in 'vkl') so that we can call it on keys inserted into +** nodes. +*/ +static Node *mainposition (const Table *t, int ktt, const Value *kvl) { + switch (ttyperaw(ktt)) { + case LUA_TNUMINT: + return hashint(t, ivalueraw(*kvl)); + case LUA_TNUMFLT: + return hashmod(t, l_hashfloat(fltvalueraw(*kvl))); + case LUA_TSHRSTR: + return hashstr(t, tsvalueraw(*kvl)); + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalueraw(*kvl))); + case LUA_TBOOLEAN: + return hashboolean(t, bvalueraw(*kvl)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalueraw(*kvl)); + case LUA_TLCF: + return hashpointer(t, fvalueraw(*kvl)); + default: + return hashpointer(t, gcvalueraw(*kvl)); + } +} + + +static Node *mainpositionTV (const Table *t, const TValue *key) { + return mainposition(t, rttype(key), valraw(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. +*/ +static int equalkey (const TValue *k1, const Node *n2) { + if (rttype(k1) != keytt(n2)) /* not the same variants? */ + return 0; /* cannot be same key */ + switch (ttype(k1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMINT: + return (ivalue(k1) == keyival(n2)); + case LUA_TNUMFLT: + return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); + case LUA_TBOOLEAN: + return bvalue(k1) == bvalueraw(keyval(n2)); + case LUA_TLIGHTUSERDATA: + return pvalue(k1) == pvalueraw(keyval(n2)); + case LUA_TLCF: + return fvalue(k1) == fvalueraw(keyval(n2)); + case LUA_TLNGSTR: + return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); + default: + return gcvalue(k1) == gcvalueraw(keyval(n2)); + } +} + + +/* +** "Generic" get version. (Not that generic: not valid for integers, +** which may be in array part, nor for floats with integral values.) +*/ +static const TValue *getgeneric (Table *t, const TValue *key) { + Node *n = mainpositionTV(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (equalkey(key, n)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* 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 (0 < k && l_castS2U(k) <= MAXASIZE) + return cast(unsigned int, 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 i; + if (ttisnil(key)) return 0; /* first iteration */ + i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; + if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ + return i; /* yes; that's the index */ + else { + const TValue *n = getgeneric(t, key); + if (n == luaO_nilobject) + 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) + t->sizearray; + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + unsigned int i = findindex(L, t, s2v(key)); /* find original element */ + for (; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setivalue(s2v(key), i + 1); + setobj2s(L, key + 1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + 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(size_t, 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 */ + /* traverse each slice */ + for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { + unsigned int lc = 0; /* counter */ + unsigned int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg - 1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, 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 (!ttisnil(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); + setnilvalue(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 (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + TValue k; + getnodekey(L, &k, old); + setobjt2t(L, 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 = t->sizearray; + TValue *newarray; + /* create new hash part with appropriate size into 'newt' */ + setnodevector(L, &newt, nhsize); + if (newasize < oldasize) { /* will array shrink? */ + t->sizearray = 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 (!ttisnil(&t->array[i])) + luaH_setint(L, t, i + 1, &t->array[i]); + } + t->sizearray = 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 (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->sizearray = newasize; + for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ + setnilvalue(&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 */ + 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_TTABLE, sizeof(Table)); + Table *t = gco2t(o); + t->metatable = NULL; + t->flags = cast_byte(~0); + t->array = NULL; + t->sizearray = 0; + setnodevector(L, t, 0); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + freehash(L, t); + luaM_freearray(L, t->array, t->sizearray); + 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. +*/ +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + TValue aux; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Integer k; + if (luaV_flttointeger(key, &k, 0)) { /* does index fit in an integer? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + else if (luai_numisnan(fltvalue(key))) + luaG_runerror(L, "table index is NaN"); + } + mp = mainpositionTV(t, key); + if (!ttisnil(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 */ + return luaH_set(L, t, key); /* insert key into grown table */ + } + lua_assert(!isdummy(t)); + othern = mainposition(t, keytt(mp), &keyval(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 */ + } + setnilvalue(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, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getint (Table *t, lua_Integer key) { + /* (1 <= key && key <= t->sizearray) */ + if (l_castS2U(key) - 1u < t->sizearray) + 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 luaO_nilobject; + } +} + + +/* +** search function for short strings +*/ +const TValue *luaH_getshortstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + lua_assert(key->tt == LUA_TSHRSTR); + 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 luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_TSHRSTR) + 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); + } +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); + case LUA_TNIL: return luaO_nilobject; + case LUA_TNUMFLT: { + lua_Integer k; + if (luaV_flttointeger(key, &k, 0)) /* index is an integral? */ + return luaH_getint(t, k); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return getgeneric(t, key); + } +} + + +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else return luaH_newkey(L, t, key); +} + + +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; + if (p != luaO_nilobject) + cell = cast(TValue *, p); + else { + TValue k; + setivalue(&k, key); + cell = luaH_newkey(L, t, &k); + } + setobj2t(L, cell, 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 (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */ + break; /* 'j' now is an absent index */ + else /* weird case */ + return j; /* well, max integer is a boundary... */ + } + } while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */ + /* i < j && t[i] !≃ nil && t[j] == nil */ + while (j - i > 1u) { /* do a binary search between them */ + lua_Unsigned m = (i + j) / 2; + if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table 't'. (A 'boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil +** and 'maxinteger' if t[maxinteger] is not nil.) +** First, try the array part: if there is an array part and its last +** element is nil, there must be a boundary there; a binary search +** finds that boundary. Otherwise, if the hash part is empty or does not +** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' +** to find a boundary in the hash part. +*/ +lua_Unsigned luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + unsigned int i = 0; + while (j - i > 1u) { /* binary search */ + unsigned int m = (i + j) / 2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + else { /* 'j' is zero or present in table */ + if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1)))) + return j; /* 'j + 1' is absent... */ + else /* 'j + 1' is also present */ + return hash_search(t, j); + } +} + + + +#if defined(LUA_DEBUG) + +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/3rd/lua/ltable.h b/3rd/lua/ltable.h new file mode 100644 index 000000000..88f906361 --- /dev/null +++ b/3rd/lua/ltable.h @@ -0,0 +1,56 @@ +/* +** $Id: ltable.h,v 2.24 2017/05/19 12:48:15 roberto Exp roberto $ +** 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) + + +#define invalidateTMcache(t) ((t)->flags = 0) + + +/* 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 TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L); +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); + + +#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/3rd/lua/ltablib.c b/3rd/lua/ltablib.c new file mode 100644 index 000000000..588bf40d2 --- /dev/null +++ b/3rd/lua/ltablib.c @@ -0,0 +1,450 @@ +/* +** $Id: ltablib.c,v 1.92 2016/02/08 12:55:19 roberto Exp roberto $ +** 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 */ + } +} + + +#if defined(LUA_COMPAT_MAXN) +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} +#endif + + +static int tinsert (lua_State *L) { + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ + lua_Integer pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + lua_Integer i; + pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ + luaL_argcheck(L, 1 <= pos && pos <= 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 */ + luaL_argcheck(L, 1 <= pos && pos <= size + 1, 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); /* t[pos] = nil */ + 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 (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", + luaL_typename(L, -1), 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 pack (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 unpack (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 (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 (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (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 (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (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}, +#if defined(LUA_COMPAT_MAXN) + {"maxn", maxn}, +#endif + {"insert", tinsert}, + {"pack", pack}, + {"unpack", unpack}, + {"remove", tremove}, + {"move", tmove}, + {"sort", sort}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_table (lua_State *L) { + luaL_newlib(L, tab_funcs); +#if defined(LUA_COMPAT_UNPACK) + /* _G.unpack = table.unpack */ + lua_getfield(L, -1, "unpack"); + lua_setglobal(L, "unpack"); +#endif + return 1; +} + diff --git a/3rd/lua/ltests.c b/3rd/lua/ltests.c new file mode 100644 index 000000000..513c846b4 --- /dev/null +++ b/3rd/lua/ltests.c @@ -0,0 +1,1735 @@ +/* +** $Id: ltests.c,v 2.237 2017/12/15 18:53:48 roberto Exp roberto $ +** Internal Module for Debugging of the Lua Implementation +** See Copyright Notice in lua.h +*/ + +#define ltests_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "lauxlib.h" +#include "lcode.h" +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lualib.h" + + + +/* +** The whole module only makes sense with LUA_DEBUG on +*/ +#if defined(LUA_DEBUG) + + +void *l_Trick = 0; + + +#define obj_at(L,k) s2v(L->ci->func + (k)) + + +static int runC (lua_State *L, lua_State *L1, const char *pc); + + +static void setnameval (lua_State *L, const char *name, int val) { + lua_pushstring(L, name); + lua_pushinteger(L, val); + lua_settable(L, -3); +} + + +static void pushobject (lua_State *L, const TValue *o) { + setobj2s(L, L->top, o); + api_incr_top(L); +} + + +static int tpanic (lua_State *L) { + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return (exit(EXIT_FAILURE), 0); /* do not return to Lua */ +} + + +/* +** {====================================================================== +** Controlled version for realloc. +** ======================================================================= +*/ + +#define MARK 0x55 /* 01010101 (a nice pattern) */ + +typedef union Header { + LUAI_MAXALIGN; + struct { + size_t size; + int type; + } d; +} Header; + + +#if !defined(EXTERNMEMCHECK) + +/* full memory check */ +#define MARKSIZE 16 /* size of marks after each block */ +#define fillmem(mem,size) memset(mem, -MARK, size) + +#else + +/* external memory check: don't do it twice */ +#define MARKSIZE 0 +#define fillmem(mem,size) /* empty */ + +#endif + + +Memcontrol l_memcontrol = + {0L, 0L, 0L, 0L, (~0L), {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}}; + + +static void freeblock (Memcontrol *mc, Header *block) { + if (block) { + size_t size = block->d.size; + int i; + for (i = 0; i < MARKSIZE; i++) /* check marks after block */ + lua_assert(*(cast(char *, block + 1) + size + i) == MARK); + mc->objcount[block->d.type]--; + fillmem(block, sizeof(Header) + size + MARKSIZE); /* erase block */ + free(block); /* actually free block */ + mc->numblocks--; /* update counts */ + mc->total -= size; + } +} + + +void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) { + Memcontrol *mc = cast(Memcontrol *, ud); + Header *block = cast(Header *, b); + int type; + if (mc->memlimit == 0) { /* first time? */ + char *limit = getenv("MEMLIMIT"); /* initialize memory limit */ + mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX; + } + if (block == NULL) { + type = (oldsize < LUA_NUMTAGS) ? oldsize : 0; + oldsize = 0; + } + else { + block--; /* go to real header */ + type = block->d.type; + lua_assert(oldsize == block->d.size); + } + if (size == 0) { + freeblock(mc, block); + return NULL; + } + if (mc->countlimit != ~0UL && size > 0) { /* count limit in use? */ + if (mc->countlimit == 0) + return NULL; /* fake a memory allocation error */ + mc->countlimit--; + } + if (size > oldsize && mc->total+size-oldsize > mc->memlimit) + return NULL; /* fake a memory allocation error */ + else { + Header *newblock; + int i; + size_t commonsize = (oldsize < size) ? oldsize : size; + size_t realsize = sizeof(Header) + size + MARKSIZE; + if (realsize < size) return NULL; /* arithmetic overflow! */ + newblock = cast(Header *, malloc(realsize)); /* alloc a new block */ + if (newblock == NULL) return NULL; /* really out of memory? */ + if (block) { + memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */ + freeblock(mc, block); /* erase (and check) old copy */ + } + /* initialize new part of the block with something weird */ + fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize); + /* initialize marks after block */ + for (i = 0; i < MARKSIZE; i++) + *(cast(char *, newblock + 1) + size + i) = MARK; + newblock->d.size = size; + newblock->d.type = type; + mc->total += size; + if (mc->total > mc->maxmem) + mc->maxmem = mc->total; + mc->numblocks++; + mc->objcount[type]++; + return newblock + 1; + } +} + + +/* }====================================================================== */ + + + +/* +** {====================================================== +** Functions to check memory consistency +** ======================================================= +*/ + + +/* +** Check GC invariants. For incremental mode, a black object cannot +** point to a white one. For generational mode, really old objects +** cannot point to young objects. Both old1 and touched2 objects +** cannot point to new objects (but can point to survivals). +** (Threads and open upvalues, despite being marked "really old", +** continue to be visited in all collections, and therefore can point to +** new objects. They, and only they, are old but gray.) +*/ +static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { + if (isdead(g,t)) return 0; + if (issweepphase(g)) + return 1; /* no invariants */ + else if (g->gckind == KGC_INC) + return !(isblack(f) && iswhite(t)); /* basic incremental invariant */ + else { /* generational mode */ + if ((getage(f) == G_OLD && isblack(f)) && !isold(t)) + return 0; + if (((getage(f) == G_OLD1 || getage(f) == G_TOUCHED2) && isblack(f)) && + getage(t) == G_NEW) + return 0; + return 1; + } +} + + +static void printobj (global_State *g, GCObject *o) { + printf("||%s(%p)-%c%c(%02X)||", + ttypename(novariant(o->tt)), (void *)o, + isdead(g,o) ? 'd' : isblack(o) ? 'b' : iswhite(o) ? 'w' : 'g', + "ns01oTt"[getage(o)], o->marked); + if (o->tt == LUA_TSHRSTR || o->tt == LUA_TLNGSTR) + printf(" '%s'", getstr(gco2ts(o))); +} + + +static int testobjref (global_State *g, GCObject *f, GCObject *t) { + int r1 = testobjref1(g, f, t); + if (!r1) { + printf("%d(%02X) - ", g->gcstate, g->currentwhite); + printobj(g, f); + printf(" -> "); + printobj(g, t); + printf("\n"); + } + return r1; +} + +#define checkobjref(g,f,t) \ + { if (t) lua_longassert(testobjref(g,f,obj2gco(t))); } + + +static void checkvalref (global_State *g, GCObject *f, const TValue *t) { + lua_assert(!iscollectable(t) || + (righttt(t) && testobjref(g, f, gcvalue(t)))); +} + + +static void checktable (global_State *g, Table *h) { + unsigned int i; + Node *n, *limit = gnode(h, sizenode(h)); + GCObject *hgc = obj2gco(h); + checkobjref(g, hgc, h->metatable); + for (i = 0; i < h->sizearray; i++) + checkvalref(g, hgc, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n))) { + TValue k; + getnodekey(g->mainthread, &k, n); + lua_assert(!keyisnil(n)); + checkvalref(g, hgc, &k); + checkvalref(g, hgc, gval(n)); + } + } +} + + +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ +static void checkproto (global_State *g, Proto *f) { + int i; + GCObject *fgc = obj2gco(f); + checkobjref(g, fgc, f->cache); + checkobjref(g, fgc, f->source); + for (i=0; isizek; i++) { + if (ttisstring(f->k + i)) + checkobjref(g, fgc, tsvalue(f->k + i)); + } + for (i=0; isizeupvalues; i++) + checkobjref(g, fgc, f->upvalues[i].name); + for (i=0; isizep; i++) + checkobjref(g, fgc, f->p[i]); + for (i=0; isizelocvars; i++) + checkobjref(g, fgc, f->locvars[i].varname); +} + + + +static void checkCclosure (global_State *g, CClosure *cl) { + GCObject *clgc = obj2gco(cl); + int i; + for (i = 0; i < cl->nupvalues; i++) + checkvalref(g, clgc, &cl->upvalue[i]); +} + + +static void checkLclosure (global_State *g, LClosure *cl) { + GCObject *clgc = obj2gco(cl); + int i; + checkobjref(g, clgc, cl->p); + for (i=0; inupvalues; i++) { + UpVal *uv = cl->upvals[i]; + if (uv) { + checkobjref(g, clgc, uv); + if (!upisopen(uv)) + checkvalref(g, obj2gco(uv), uv->v); + } + } +} + + +static int lua_checkpc (CallInfo *ci) { + if (!isLua(ci)) return 1; + else { + StkId f = ci->func; + Proto *p = clLvalue(s2v(f))->p; + return p->code <= ci->u.l.savedpc && + ci->u.l.savedpc <= p->code + p->sizecode; + } +} + + +static void checkstack (global_State *g, lua_State *L1) { + StkId o; + CallInfo *ci; + UpVal *uv; + lua_assert(!isdead(g, L1)); + for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) + lua_assert(upisopen(uv)); /* must be open */ + for (ci = L1->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L1->stack_last); + lua_assert(lua_checkpc(ci)); + } + if (L1->stack) { /* complete thread? */ + for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) + checkliveness(L1, s2v(o)); /* entire stack must have valid values */ + } + else lua_assert(L1->stacksize == 0); +} + + +static void checkrefs (global_State *g, GCObject *o) { + switch (o->tt) { + case LUA_TUSERDATA: { + TValue uservalue; + Table *mt = gco2u(o)->metatable; + checkobjref(g, o, mt); + getuservalue(g->mainthread, gco2u(o), &uservalue); + checkvalref(g, o, &uservalue); + break; + } + case LUA_TUPVAL: { + checkvalref(g, o, gco2upv(o)->v); + break; + } + case LUA_TTABLE: { + checktable(g, gco2t(o)); + break; + } + case LUA_TTHREAD: { + checkstack(g, gco2th(o)); + break; + } + case LUA_TLCL: { + checkLclosure(g, gco2lcl(o)); + break; + } + case LUA_TCCL: { + checkCclosure(g, gco2ccl(o)); + break; + } + case LUA_TPROTO: { + checkproto(g, gco2p(o)); + break; + } + case LUA_TSHRSTR: + case LUA_TLNGSTR: { + lua_assert(!isgray(o)); /* strings are never gray */ + break; + } + default: lua_assert(0); + } +} + + +/* +** Check consistency of an object: +** - Dead objects can only happen in the 'allgc' list during a sweep +** phase (controled by the caller through 'maybedead'). +** - During pause, all objects must be white. +** - In generational mode: +** * objects must be old enough for their lists ('listage'). +** * old objects cannot be white. +** * old objects must be black, except for 'touched1', 'old0', +** threads, and open upvalues. +*/ +static void checkobject (global_State *g, GCObject *o, int maybedead, + int listage) { + if (isdead(g, o)) + lua_assert(maybedead); + else { + lua_assert(g->gcstate != GCSpause || iswhite(o)); + if (g->gckind == KGC_GEN) { /* generational mode? */ + lua_assert(getage(o) >= listage); + lua_assert(!iswhite(o) || !isold(o)); + if (isold(o)) { + lua_assert(isblack(o) || + getage(o) == G_TOUCHED1 || + getage(o) == G_OLD0 || + o->tt == LUA_TTHREAD || + (o->tt == LUA_TPROTO && + (gco2p(o)->cache != NULL || gco2p(o)->cachemiss >= MAXMISS)) || + (o->tt == LUA_TUPVAL && upisopen(gco2upv(o)))); + } + } + checkrefs(g, o); + } +} + + +static void checkgraylist (global_State *g, GCObject *o) { + ((void)g); /* better to keep it available if we need to print an object */ + while (o) { + lua_assert(isgray(o) || getage(o) == G_TOUCHED2); + lua_assert(!testbit(o->marked, TESTGRAYBIT)); + l_setbit(o->marked, TESTGRAYBIT); + switch (o->tt) { + case LUA_TTABLE: o = gco2t(o)->gclist; break; + case LUA_TLCL: o = gco2lcl(o)->gclist; break; + case LUA_TCCL: o = gco2ccl(o)->gclist; break; + case LUA_TTHREAD: o = gco2th(o)->gclist; break; + case LUA_TPROTO: o = gco2p(o)->gclist; break; + default: lua_assert(0); /* other objects cannot be in a gray list */ + } + } +} + + +/* +** mark all objects in gray lists with the TESTGRAYBIT, so that +** 'checkmemory' can check that all gray objects are in a gray list +*/ +static void markgrays (global_State *g) { + if (!keepinvariant(g)) return; + checkgraylist(g, g->gray); + checkgraylist(g, g->grayagain); + checkgraylist(g, g->weak); + checkgraylist(g, g->ephemeron); + checkgraylist(g, g->protogray); +} + + +static void checkgray (global_State *g, GCObject *o) { + for (; o != NULL; o = o->next) { + if ((isgray(o) && o->tt != LUA_TUPVAL) || getage(o) == G_TOUCHED2) { + lua_assert(!keepinvariant(g) || testbit(o->marked, TESTGRAYBIT)); + resetbit(o->marked, TESTGRAYBIT); + } + lua_assert(!testbit(o->marked, TESTGRAYBIT)); + } +} + + +static void checklist (global_State *g, int maybedead, int tof, + GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { + GCObject *o; + for (o = newl; o != survival; o = o->next) { + checkobject(g, o, maybedead, G_NEW); + lua_assert(!tof == !tofinalize(o)); + } + for (o = survival; o != old; o = o->next) { + checkobject(g, o, 0, G_SURVIVAL); + lua_assert(!tof == !tofinalize(o)); + } + for (o = old; o != reallyold; o = o->next) { + checkobject(g, o, 0, G_OLD1); + lua_assert(!tof == !tofinalize(o)); + } + for (o = reallyold; o != NULL; o = o->next) { + checkobject(g, o, 0, G_OLD); + lua_assert(!tof == !tofinalize(o)); + } +} + + +int lua_checkmemory (lua_State *L) { + global_State *g = G(L); + GCObject *o; + int maybedead; + if (keepinvariant(g)) { + lua_assert(!iswhite(g->mainthread)); + lua_assert(!iswhite(gcvalue(&g->l_registry))); + } + lua_assert(!isdead(g, gcvalue(&g->l_registry))); + lua_assert(g->sweepgc == NULL || issweepphase(g)); + markgrays(g); + + /* check 'fixedgc' list */ + for (o = g->fixedgc; o != NULL; o = o->next) { + lua_assert(o->tt == LUA_TSHRSTR && isgray(o) && getage(o) == G_OLD); + } + + /* check 'allgc' list */ + checkgray(g, g->allgc); + maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); + checklist(g, maybedead, 0, g->allgc, g->survival, g->old, g->reallyold); + + /* check 'finobj' list */ + checkgray(g, g->finobj); + checklist(g, 0, 1, g->finobj, g->finobjsur, g->finobjold, g->finobjrold); + + /* check 'tobefnz' list */ + checkgray(g, g->tobefnz); + for (o = g->tobefnz; o != NULL; o = o->next) { + checkobject(g, o, 0, G_NEW); + lua_assert(tofinalize(o)); + lua_assert(o->tt == LUA_TUSERDATA || o->tt == LUA_TTABLE); + } + return 0; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Disassembler +** ======================================================= +*/ + + +static char *buildop (Proto *p, int pc, char *buff) { + Instruction i = p->code[pc]; + OpCode o = GET_OPCODE(i); + const char *name = luaP_opnames[o]; + int line = luaG_getfuncline(p, pc); + sprintf(buff, "(%4d) %4d - ", line, pc); + switch (getOpMode(o)) { + case iABC: + sprintf(buff+strlen(buff), "%-12s%4d %4d %4d%s", name, + GETARG_A(i), GETARG_B(i), GETARG_C(i), + GETARG_k(i) ? " (k)" : ""); + break; + case iABx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), + GETARG_Bx(i)); + break; + case iAsBx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), + GETARG_sBx(i)); + break; + case iAx: + sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i)); + break; + case isJ: + sprintf(buff+strlen(buff), "%-12s%4d (%1d)", name, GETARG_sJ(i), + !!GETARG_k(i)); + break; + } + return buff; +} + + +#if 0 +void luaI_printcode (Proto *pt, int size) { + int pc; + for (pc=0; pcmaxstacksize); + setnameval(L, "numparams", p->numparams); + for (pc=0; pcsizecode; pc++) { + char buff[100]; + lua_pushinteger(L, pc+1); + lua_pushstring(L, buildop(p, pc, buff)); + lua_settable(L, -3); + } + return 1; +} + + +static int printcode (lua_State *L) { + int pc; + Proto *p; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = getproto(obj_at(L, 1)); + printf("maxstack: %d\n", p->maxstacksize); + printf("numparams: %d\n", p->numparams); + for (pc=0; pcsizecode; pc++) { + char buff[100]; + printf("%d\t%s\n", pc + 1, buildop(p, pc, buff)); + } + return 0; +} + + +static int listk (lua_State *L) { + Proto *p; + int i; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = getproto(obj_at(L, 1)); + lua_createtable(L, p->sizek, 0); + for (i=0; isizek; i++) { + pushobject(L, p->k+i); + lua_rawseti(L, -2, i+1); + } + return 1; +} + + +static int listlocals (lua_State *L) { + Proto *p; + int pc = cast_int(luaL_checkinteger(L, 2)) - 1; + int i = 0; + const char *name; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = getproto(obj_at(L, 1)); + while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) + lua_pushstring(L, name); + return i-1; +} + +/* }====================================================== */ + + + +static void printstack (lua_State *L) { + int i; + int n = lua_gettop(L); + for (i = 1; i <= n; i++) { + printf("%3d: %s\n", i, luaL_tolstring(L, i, NULL)); + lua_pop(L, 1); + } + printf("\n"); +} + + +static int get_limits (lua_State *L) { + lua_createtable(L, 0, 5); + setnameval(L, "BITS_INT", LUAI_BITSINT); + setnameval(L, "MAXARG_Ax", MAXARG_Ax); + setnameval(L, "MAXARG_Bx", MAXARG_Bx); + setnameval(L, "OFFSET_sBx", OFFSET_sBx); + setnameval(L, "BITS_INT", LUAI_BITSINT); + setnameval(L, "LFPF", LFIELDS_PER_FLUSH); + setnameval(L, "NUM_OPCODES", NUM_OPCODES); + return 1; +} + + +static int mem_query (lua_State *L) { + if (lua_isnone(L, 1)) { + lua_pushinteger(L, l_memcontrol.total); + lua_pushinteger(L, l_memcontrol.numblocks); + lua_pushinteger(L, l_memcontrol.maxmem); + return 3; + } + else if (lua_isnumber(L, 1)) { + unsigned long limit = cast(unsigned long, luaL_checkinteger(L, 1)); + if (limit == 0) limit = ULONG_MAX; + l_memcontrol.memlimit = limit; + return 0; + } + else { + const char *t = luaL_checkstring(L, 1); + int i; + for (i = LUA_NUMTAGS - 1; i >= 0; i--) { + if (strcmp(t, ttypename(i)) == 0) { + lua_pushinteger(L, l_memcontrol.objcount[i]); + return 1; + } + } + return luaL_error(L, "unkown type '%s'", t); + } +} + + +static int alloc_count (lua_State *L) { + if (lua_isnone(L, 1)) + l_memcontrol.countlimit = ~0L; + else + l_memcontrol.countlimit = luaL_checkinteger(L, 1); + return 0; +} + + +static int settrick (lua_State *L) { + if (ttisnil(obj_at(L, 1))) + l_Trick = NULL; + else + l_Trick = gcvalue(obj_at(L, 1)); + return 0; +} + + +static int gc_color (lua_State *L) { + TValue *o; + luaL_checkany(L, 1); + o = obj_at(L, 1); + if (!iscollectable(o)) + lua_pushstring(L, "no collectable"); + else { + GCObject *obj = gcvalue(o); + lua_pushstring(L, isdead(G(L), obj) ? "dead" : + iswhite(obj) ? "white" : + isblack(obj) ? "black" : "grey"); + } + return 1; +} + + +static int gc_age (lua_State *L) { + TValue *o; + luaL_checkany(L, 1); + o = obj_at(L, 1); + if (!iscollectable(o)) + lua_pushstring(L, "no collectable"); + else { + static const char *gennames[] = {"new", "survival", "old0", "old1", + "old", "touched1", "touched2"}; + GCObject *obj = gcvalue(o); + lua_pushstring(L, gennames[getage(obj)]); + } + return 1; +} + + +static int gc_printobj (lua_State *L) { + TValue *o; + luaL_checkany(L, 1); + o = obj_at(L, 1); + if (!iscollectable(o)) + printf("no collectable\n"); + else { + GCObject *obj = gcvalue(o); + printobj(G(L), obj); + printf("\n"); + } + return 0; +} + + +static int gc_state (lua_State *L) { + static const char *statenames[] = { + "propagate", "atomic", "enteratomic", "sweepallgc", "sweepfinobj", + "sweeptobefnz", "sweepend", "callfin", "pause", ""}; + static const int states[] = { + GCSpropagate, GCSenteratomic, GCSatomic, GCSswpallgc, GCSswpfinobj, + GCSswptobefnz, GCSswpend, GCScallfin, GCSpause, -1}; + int option = states[luaL_checkoption(L, 1, "", statenames)]; + if (option == -1) { + lua_pushstring(L, statenames[G(L)->gcstate]); + return 1; + } + else { + global_State *g = G(L); + if (G(L)->gckind == KGC_GEN) + luaL_error(L, "cannot change states in generational mode"); + lua_lock(L); + if (option < g->gcstate) { /* must cross 'pause'? */ + luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */ + } + luaC_runtilstate(L, bitmask(option)); + lua_assert(G(L)->gcstate == option); + lua_unlock(L); + return 0; + } +} + + +static int hash_query (lua_State *L) { + if (lua_isnone(L, 2)) { + luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); + lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash); + } + else { + TValue *o = obj_at(L, 1); + Table *t; + luaL_checktype(L, 2, LUA_TTABLE); + t = hvalue(obj_at(L, 2)); + lua_pushinteger(L, luaH_mainposition(t, o) - t->node); + } + return 1; +} + + +static int stacklevel (lua_State *L) { + unsigned long a = 0; + lua_pushinteger(L, (L->top - L->stack)); + lua_pushinteger(L, (L->stack_last - L->stack)); + lua_pushinteger(L, L->nCcalls); + lua_pushinteger(L, L->nci); + lua_pushinteger(L, (unsigned long)&a); + return 5; +} + + +static int table_query (lua_State *L) { + const Table *t; + int i = cast_int(luaL_optinteger(L, 2, -1)); + luaL_checktype(L, 1, LUA_TTABLE); + t = hvalue(obj_at(L, 1)); + if (i == -1) { + lua_pushinteger(L, t->sizearray); + lua_pushinteger(L, allocsizenode(t)); + lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node); + } + else if ((unsigned int)i < t->sizearray) { + lua_pushinteger(L, i); + pushobject(L, &t->array[i]); + lua_pushnil(L); + } + else if ((i -= t->sizearray) < sizenode(t)) { + TValue k; + getnodekey(L, &k, gnode(t, i)); + if (!ttisnil(gval(gnode(t, i))) || + ttisnil(&k) || + ttisnumber(&k)) { + pushobject(L, &k); + } + else + lua_pushliteral(L, ""); + pushobject(L, gval(gnode(t, i))); + if (gnext(&t->node[i]) != 0) + lua_pushinteger(L, gnext(&t->node[i])); + else + lua_pushnil(L); + } + return 3; +} + + +static int string_query (lua_State *L) { + stringtable *tb = &G(L)->strt; + int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; + if (s == -1) { + lua_pushinteger(L ,tb->size); + lua_pushinteger(L ,tb->nuse); + return 2; + } + else if (s < tb->size) { + TString *ts; + int n = 0; + for (ts = tb->hash[s]; ts != NULL; ts = ts->u.hnext) { + setsvalue2s(L, L->top, ts); + api_incr_top(L); + n++; + } + return n; + } + else return 0; +} + + +static int tref (lua_State *L) { + int level = lua_gettop(L); + luaL_checkany(L, 1); + lua_pushvalue(L, 1); + lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); + lua_assert(lua_gettop(L) == level+1); /* +1 for result */ + return 1; +} + +static int getref (lua_State *L) { + int level = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_checkinteger(L, 1)); + lua_assert(lua_gettop(L) == level+1); + return 1; +} + +static int unref (lua_State *L) { + int level = lua_gettop(L); + luaL_unref(L, LUA_REGISTRYINDEX, cast_int(luaL_checkinteger(L, 1))); + lua_assert(lua_gettop(L) == level); + return 0; +} + + +static int upvalue (lua_State *L) { + int n = cast_int(luaL_checkinteger(L, 2)); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_isnone(L, 3)) { + const char *name = lua_getupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + return 2; + } + else { + const char *name = lua_setupvalue(L, 1, n); + lua_pushstring(L, name); + return 1; + } +} + + +static int newuserdata (lua_State *L) { + size_t size = cast(size_t, luaL_checkinteger(L, 1)); + char *p = cast(char *, lua_newuserdata(L, size)); + while (size--) *p++ = '\0'; + return 1; +} + + +static int pushuserdata (lua_State *L) { + lua_Integer u = luaL_checkinteger(L, 1); + lua_pushlightuserdata(L, cast(void *, cast(size_t, u))); + return 1; +} + + +static int udataval (lua_State *L) { + lua_pushinteger(L, cast(long, lua_touserdata(L, 1))); + return 1; +} + + +static int doonnewstack (lua_State *L) { + lua_State *L1 = lua_newthread(L); + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + int status = luaL_loadbuffer(L1, s, l, s); + if (status == LUA_OK) + status = lua_pcall(L1, 0, 0, 0); + lua_pushinteger(L, status); + return 1; +} + + +static int s2d (lua_State *L) { + lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1))); + return 1; +} + + +static int d2s (lua_State *L) { + double d = luaL_checknumber(L, 1); + lua_pushlstring(L, cast(char *, &d), sizeof(d)); + return 1; +} + + +static int num2int (lua_State *L) { + lua_pushinteger(L, lua_tointeger(L, 1)); + return 1; +} + + +static int newstate (lua_State *L) { + void *ud; + lua_Alloc f = lua_getallocf(L, &ud); + lua_State *L1 = lua_newstate(f, ud); + if (L1) { + lua_atpanic(L1, tpanic); + lua_pushlightuserdata(L, L1); + } + else + lua_pushnil(L); + return 1; +} + + +static lua_State *getstate (lua_State *L) { + lua_State *L1 = cast(lua_State *, lua_touserdata(L, 1)); + luaL_argcheck(L, L1 != NULL, 1, "state expected"); + return L1; +} + + +static int loadlib (lua_State *L) { + static const luaL_Reg libs[] = { + {LUA_GNAME, luaopen_base}, + {"coroutine", luaopen_coroutine}, + {"debug", luaopen_debug}, + {"io", luaopen_io}, + {"os", luaopen_os}, + {"math", luaopen_math}, + {"string", luaopen_string}, + {"table", luaopen_table}, + {"T", luaB_opentests}, + {NULL, NULL} + }; + lua_State *L1 = getstate(L); + int i; + luaL_requiref(L1, "package", luaopen_package, 0); + lua_assert(lua_type(L1, -1) == LUA_TTABLE); + /* 'requiref' should not reload module already loaded... */ + luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ + /* ...but should return the same module */ + lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); + luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + for (i = 0; libs[i].name; i++) { + lua_pushcfunction(L1, libs[i].func); + lua_setfield(L1, -2, libs[i].name); + } + return 0; +} + +static int closestate (lua_State *L) { + lua_State *L1 = getstate(L); + lua_close(L1); + return 0; +} + +static int doremote (lua_State *L) { + lua_State *L1 = getstate(L); + size_t lcode; + const char *code = luaL_checklstring(L, 2, &lcode); + int status; + lua_settop(L1, 0); + status = luaL_loadbuffer(L1, code, lcode, code); + if (status == LUA_OK) + status = lua_pcall(L1, 0, LUA_MULTRET, 0); + if (status != LUA_OK) { + lua_pushnil(L); + lua_pushstring(L, lua_tostring(L1, -1)); + lua_pushinteger(L, status); + return 3; + } + else { + int i = 0; + while (!lua_isnone(L1, ++i)) + lua_pushstring(L, lua_tostring(L1, i)); + lua_pop(L1, i-1); + return i-1; + } +} + + +static int int2fb_aux (lua_State *L) { + int b = luaO_int2fb((unsigned int)luaL_checkinteger(L, 1)); + lua_pushinteger(L, b); + lua_pushinteger(L, (unsigned int)luaO_fb2int(b)); + return 2; +} + + +static int log2_aux (lua_State *L) { + unsigned int x = (unsigned int)luaL_checkinteger(L, 1); + lua_pushinteger(L, luaO_ceillog2(x)); + return 1; +} + + +struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; }; + +/* +** does a long-jump back to "main program". +*/ +static int panicback (lua_State *L) { + struct Aux *b; + lua_checkstack(L, 1); /* open space for 'Aux' struct */ + lua_getfield(L, LUA_REGISTRYINDEX, "_jmpbuf"); /* get 'Aux' struct */ + b = (struct Aux *)lua_touserdata(L, -1); + lua_pop(L, 1); /* remove 'Aux' struct */ + runC(b->L, L, b->paniccode); /* run optional panic code */ + longjmp(b->jb, 1); + return 1; /* to avoid warnings */ +} + +static int checkpanic (lua_State *L) { + struct Aux b; + void *ud; + lua_State *L1; + const char *code = luaL_checkstring(L, 1); + lua_Alloc f = lua_getallocf(L, &ud); + b.paniccode = luaL_optstring(L, 2, ""); + b.L = L; + L1 = lua_newstate(f, ud); /* create new state */ + if (L1 == NULL) { /* error? */ + lua_pushnil(L); + return 1; + } + lua_atpanic(L1, panicback); /* set its panic function */ + lua_pushlightuserdata(L1, &b); + lua_setfield(L1, LUA_REGISTRYINDEX, "_jmpbuf"); /* store 'Aux' struct */ + if (setjmp(b.jb) == 0) { /* set jump buffer */ + runC(L, L1, code); /* run code unprotected */ + lua_pushliteral(L, "no errors"); + } + else { /* error handling */ + /* move error message to original state */ + lua_pushstring(L, lua_tostring(L1, -1)); + } + lua_close(L1); + return 1; +} + + + +/* +** {==================================================================== +** function to test the API with C. It interprets a kind of assembler +** language with calls to the API, so the test can be driven by Lua code +** ===================================================================== +*/ + + +static void sethookaux (lua_State *L, int mask, int count, const char *code); + +static const char *const delimits = " \t\n,;"; + +static void skip (const char **pc) { + for (;;) { + if (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; + else if (**pc == '#') { + while (**pc != '\n' && **pc != '\0') (*pc)++; + } + else break; + } +} + +static int getnum_aux (lua_State *L, lua_State *L1, const char **pc) { + int res = 0; + int sig = 1; + skip(pc); + if (**pc == '.') { + res = cast_int(lua_tointeger(L1, -1)); + lua_pop(L1, 1); + (*pc)++; + return res; + } + else if (**pc == '*') { + res = lua_gettop(L1); + (*pc)++; + return res; + } + else if (**pc == '-') { + sig = -1; + (*pc)++; + } + if (!lisdigit(cast_uchar(**pc))) + luaL_error(L, "number expected (%s)", *pc); + while (lisdigit(cast_uchar(**pc))) res = res*10 + (*(*pc)++) - '0'; + return sig*res; +} + +static const char *getstring_aux (lua_State *L, char *buff, const char **pc) { + int i = 0; + skip(pc); + if (**pc == '"' || **pc == '\'') { /* quoted string? */ + int quote = *(*pc)++; + while (**pc != quote) { + if (**pc == '\0') luaL_error(L, "unfinished string in C script"); + buff[i++] = *(*pc)++; + } + (*pc)++; + } + else { + while (**pc != '\0' && !strchr(delimits, **pc)) + buff[i++] = *(*pc)++; + } + buff[i] = '\0'; + return buff; +} + + +static int getindex_aux (lua_State *L, lua_State *L1, const char **pc) { + skip(pc); + switch (*(*pc)++) { + case 'R': return LUA_REGISTRYINDEX; + case 'G': return luaL_error(L, "deprecated index 'G'"); + case 'U': return lua_upvalueindex(getnum_aux(L, L1, pc)); + default: (*pc)--; return getnum_aux(L, L1, pc); + } +} + + +static void pushcode (lua_State *L, int code) { + static const char *const codes[] = {"OK", "YIELD", "ERRRUN", + "ERRSYNTAX", "ERRMEM", "ERRGCMM", "ERRERR"}; + lua_pushstring(L, codes[code]); +} + + +#define EQ(s1) (strcmp(s1, inst) == 0) + +#define getnum (getnum_aux(L, L1, &pc)) +#define getstring (getstring_aux(L, buff, &pc)) +#define getindex (getindex_aux(L, L1, &pc)) + + +static int testC (lua_State *L); +static int Cfunck (lua_State *L, int status, lua_KContext ctx); + +/* +** arithmetic operation encoding for 'arith' instruction +** LUA_OPIDIV -> \ +** LUA_OPSHL -> < +** LUA_OPSHR -> > +** LUA_OPUNM -> _ +** LUA_OPBNOT -> ! +*/ +static const char ops[] = "+-*%^/\\&|~<>_!"; + +static int runC (lua_State *L, lua_State *L1, const char *pc) { + char buff[300]; + int status = 0; + if (pc == NULL) return luaL_error(L, "attempt to runC null script"); + for (;;) { + const char *inst = getstring; + if EQ("") return 0; + else if EQ("absindex") { + lua_pushnumber(L1, lua_absindex(L1, getindex)); + } + else if EQ("append") { + int t = getindex; + int i = lua_rawlen(L1, t); + lua_rawseti(L1, t, i + 1); + } + else if EQ("arith") { + int op; + skip(&pc); + op = strchr(ops, *pc++) - ops; + lua_arith(L1, op); + } + else if EQ("call") { + int narg = getnum; + int nres = getnum; + lua_call(L1, narg, nres); + } + else if EQ("callk") { + int narg = getnum; + int nres = getnum; + int i = getindex; + lua_callk(L1, narg, nres, i, Cfunck); + } + else if EQ("checkstack") { + int sz = getnum; + const char *msg = getstring; + if (*msg == '\0') + msg = NULL; /* to test 'luaL_checkstack' with no message */ + luaL_checkstack(L1, sz, msg); + } + else if EQ("rawcheckstack") { + int sz = getnum; + lua_pushboolean(L1, lua_checkstack(L1, sz)); + } + else if EQ("compare") { + const char *opt = getstring; /* EQ, LT, or LE */ + int op = (opt[0] == 'E') ? LUA_OPEQ + : (opt[1] == 'T') ? LUA_OPLT : LUA_OPLE; + int a = getindex; + int b = getindex; + lua_pushboolean(L1, lua_compare(L1, a, b, op)); + } + else if EQ("concat") { + lua_concat(L1, getnum); + } + else if EQ("copy") { + int f = getindex; + lua_copy(L1, f, getindex); + } + else if EQ("func2num") { + lua_CFunction func = lua_tocfunction(L1, getindex); + lua_pushnumber(L1, cast(size_t, func)); + } + else if EQ("getfield") { + int t = getindex; + lua_getfield(L1, t, getstring); + } + else if EQ("getglobal") { + lua_getglobal(L1, getstring); + } + else if EQ("getmetatable") { + if (lua_getmetatable(L1, getindex) == 0) + lua_pushnil(L1); + } + else if EQ("gettable") { + lua_gettable(L1, getindex); + } + else if EQ("gettop") { + lua_pushinteger(L1, lua_gettop(L1)); + } + else if EQ("gsub") { + int a = getnum; int b = getnum; int c = getnum; + luaL_gsub(L1, lua_tostring(L1, a), + lua_tostring(L1, b), + lua_tostring(L1, c)); + } + else if EQ("insert") { + lua_insert(L1, getnum); + } + else if EQ("iscfunction") { + lua_pushboolean(L1, lua_iscfunction(L1, getindex)); + } + else if EQ("isfunction") { + lua_pushboolean(L1, lua_isfunction(L1, getindex)); + } + else if EQ("isnil") { + lua_pushboolean(L1, lua_isnil(L1, getindex)); + } + else if EQ("isnull") { + lua_pushboolean(L1, lua_isnone(L1, getindex)); + } + else if EQ("isnumber") { + lua_pushboolean(L1, lua_isnumber(L1, getindex)); + } + else if EQ("isstring") { + lua_pushboolean(L1, lua_isstring(L1, getindex)); + } + else if EQ("istable") { + lua_pushboolean(L1, lua_istable(L1, getindex)); + } + else if EQ("isudataval") { + lua_pushboolean(L1, lua_islightuserdata(L1, getindex)); + } + else if EQ("isuserdata") { + lua_pushboolean(L1, lua_isuserdata(L1, getindex)); + } + else if EQ("len") { + lua_len(L1, getindex); + } + else if EQ("Llen") { + lua_pushinteger(L1, luaL_len(L1, getindex)); + } + else if EQ("loadfile") { + luaL_loadfile(L1, luaL_checkstring(L1, getnum)); + } + else if EQ("loadstring") { + const char *s = luaL_checkstring(L1, getnum); + luaL_loadstring(L1, s); + } + else if EQ("newmetatable") { + lua_pushboolean(L1, luaL_newmetatable(L1, getstring)); + } + else if EQ("newtable") { + lua_newtable(L1); + } + else if EQ("newthread") { + lua_newthread(L1); + } + else if EQ("newuserdata") { + lua_newuserdata(L1, getnum); + } + else if EQ("next") { + lua_next(L1, -2); + } + else if EQ("objsize") { + lua_pushinteger(L1, lua_rawlen(L1, getindex)); + } + else if EQ("pcall") { + int narg = getnum; + int nres = getnum; + status = lua_pcall(L1, narg, nres, getnum); + } + else if EQ("pcallk") { + int narg = getnum; + int nres = getnum; + int i = getindex; + status = lua_pcallk(L1, narg, nres, 0, i, Cfunck); + } + else if EQ("pop") { + lua_pop(L1, getnum); + } + else if EQ("printstack") { + int n = getnum; + if (n != 0) { + printf("%s\n", luaL_tolstring(L1, n, NULL)); + lua_pop(L1, 1); + } + else printstack(L1); + } + else if EQ("print") { + const char *msg = getstring; + printf("%s\n", msg); + } + else if EQ("pushbool") { + lua_pushboolean(L1, getnum); + } + else if EQ("pushcclosure") { + lua_pushcclosure(L1, testC, getnum); + } + else if EQ("pushint") { + lua_pushinteger(L1, getnum); + } + else if EQ("pushnil") { + lua_pushnil(L1); + } + else if EQ("pushnum") { + lua_pushnumber(L1, (lua_Number)getnum); + } + else if EQ("pushstatus") { + pushcode(L1, status); + } + else if EQ("pushstring") { + lua_pushstring(L1, getstring); + } + else if EQ("pushupvalueindex") { + lua_pushinteger(L1, lua_upvalueindex(getnum)); + } + else if EQ("pushvalue") { + lua_pushvalue(L1, getindex); + } + else if EQ("rawgeti") { + int t = getindex; + lua_rawgeti(L1, t, getnum); + } + else if EQ("rawgetp") { + int t = getindex; + lua_rawgetp(L1, t, cast(void *, cast(size_t, getnum))); + } + else if EQ("rawsetp") { + int t = getindex; + lua_rawsetp(L1, t, cast(void *, cast(size_t, getnum))); + } + else if EQ("remove") { + lua_remove(L1, getnum); + } + else if EQ("replace") { + lua_replace(L1, getindex); + } + else if EQ("resume") { + int i = getindex; + int nres; + status = lua_resume(lua_tothread(L1, i), L, getnum, &nres); + } + else if EQ("return") { + int n = getnum; + if (L1 != L) { + int i; + for (i = 0; i < n; i++) { + int idx = -(n - i); + switch (lua_type(L1, idx)) { + case LUA_TBOOLEAN: + lua_pushboolean(L, lua_toboolean(L1, idx)); + break; + default: + lua_pushstring(L, lua_tostring(L1, idx)); + break; + } + } + } + return n; + } + else if EQ("rotate") { + int i = getindex; + lua_rotate(L1, i, getnum); + } + else if EQ("setfield") { + int t = getindex; + lua_setfield(L1, t, getstring); + } + else if EQ("setglobal") { + lua_setglobal(L1, getstring); + } + else if EQ("sethook") { + int mask = getnum; + int count = getnum; + sethookaux(L1, mask, count, getstring); + } + else if EQ("setmetatable") { + lua_setmetatable(L1, getindex); + } + else if EQ("settable") { + lua_settable(L1, getindex); + } + else if EQ("settop") { + lua_settop(L1, getnum); + } + else if EQ("testudata") { + int i = getindex; + lua_pushboolean(L1, luaL_testudata(L1, i, getstring) != NULL); + } + else if EQ("error") { + lua_error(L1); + } + else if EQ("throw") { +#if defined(__cplusplus) +static struct X { int x; } x; + throw x; +#else + luaL_error(L1, "C++"); +#endif + break; + } + else if EQ("tobool") { + lua_pushboolean(L1, lua_toboolean(L1, getindex)); + } + else if EQ("tocfunction") { + lua_pushcfunction(L1, lua_tocfunction(L1, getindex)); + } + else if EQ("tointeger") { + lua_pushinteger(L1, lua_tointeger(L1, getindex)); + } + else if EQ("tonumber") { + lua_pushnumber(L1, lua_tonumber(L1, getindex)); + } + else if EQ("topointer") { + lua_pushnumber(L1, cast(size_t, lua_topointer(L1, getindex))); + } + else if EQ("tostring") { + const char *s = lua_tostring(L1, getindex); + const char *s1 = lua_pushstring(L1, s); + lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0); + } + else if EQ("type") { + lua_pushstring(L1, luaL_typename(L1, getnum)); + } + else if EQ("xmove") { + int f = getindex; + int t = getindex; + lua_State *fs = (f == 0) ? L1 : lua_tothread(L1, f); + lua_State *ts = (t == 0) ? L1 : lua_tothread(L1, t); + int n = getnum; + if (n == 0) n = lua_gettop(fs); + lua_xmove(fs, ts, n); + } + else if EQ("yield") { + return lua_yield(L1, getnum); + } + else if EQ("yieldk") { + int nres = getnum; + int i = getindex; + return lua_yieldk(L1, nres, i, Cfunck); + } + else luaL_error(L, "unknown instruction %s", buff); + } + return 0; +} + + +static int testC (lua_State *L) { + lua_State *L1; + const char *pc; + if (lua_isuserdata(L, 1)) { + L1 = getstate(L); + pc = luaL_checkstring(L, 2); + } + else if (lua_isthread(L, 1)) { + L1 = lua_tothread(L, 1); + pc = luaL_checkstring(L, 2); + } + else { + L1 = L; + pc = luaL_checkstring(L, 1); + } + return runC(L, L1, pc); +} + + +static int Cfunc (lua_State *L) { + return runC(L, L, lua_tostring(L, lua_upvalueindex(1))); +} + + +static int Cfunck (lua_State *L, int status, lua_KContext ctx) { + pushcode(L, status); + lua_setglobal(L, "status"); + lua_pushinteger(L, ctx); + lua_setglobal(L, "ctx"); + return runC(L, L, lua_tostring(L, ctx)); +} + + +static int makeCfunc (lua_State *L) { + luaL_checkstring(L, 1); + lua_pushcclosure(L, Cfunc, lua_gettop(L)); + return 1; +} + + +/* }====================================================== */ + + +/* +** {====================================================== +** tests for C hooks +** ======================================================= +*/ + +/* +** C hook that runs the C script stored in registry.C_HOOK[L] +*/ +static void Chook (lua_State *L, lua_Debug *ar) { + const char *scpt; + const char *const events [] = {"call", "ret", "line", "count", "tailcall"}; + lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK"); + lua_pushlightuserdata(L, L); + lua_gettable(L, -2); /* get C_HOOK[L] (script saved by sethookaux) */ + scpt = lua_tostring(L, -1); /* not very religious (string will be popped) */ + lua_pop(L, 2); /* remove C_HOOK and script */ + lua_pushstring(L, events[ar->event]); /* may be used by script */ + lua_pushinteger(L, ar->currentline); /* may be used by script */ + runC(L, L, scpt); /* run script from C_HOOK[L] */ +} + + +/* +** sets 'registry.C_HOOK[L] = scpt' and sets 'Chook' as a hook +*/ +static void sethookaux (lua_State *L, int mask, int count, const char *scpt) { + if (*scpt == '\0') { /* no script? */ + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + return; + } + lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* get C_HOOK table */ + if (!lua_istable(L, -1)) { /* no hook table? */ + lua_pop(L, 1); /* remove previous value */ + lua_newtable(L); /* create new C_HOOK table */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* register it */ + } + lua_pushlightuserdata(L, L); + lua_pushstring(L, scpt); + lua_settable(L, -3); /* C_HOOK[L] = script */ + lua_sethook(L, Chook, mask, count); +} + + +static int sethook (lua_State *L) { + if (lua_isnoneornil(L, 1)) + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + else { + const char *scpt = luaL_checkstring(L, 1); + const char *smask = luaL_checkstring(L, 2); + int count = cast_int(luaL_optinteger(L, 3, 0)); + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + sethookaux(L, mask, count, scpt); + } + return 0; +} + + +static int coresume (lua_State *L) { + int status, nres; + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + status = lua_resume(co, L, 0, &nres); + if (status != LUA_OK && status != LUA_YIELD) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + return 1; + } +} + +/* }====================================================== */ + + + +static const struct luaL_Reg tests_funcs[] = { + {"checkmemory", lua_checkmemory}, + {"closestate", closestate}, + {"d2s", d2s}, + {"doonnewstack", doonnewstack}, + {"doremote", doremote}, + {"gccolor", gc_color}, + {"gcage", gc_age}, + {"gcstate", gc_state}, + {"pobj", gc_printobj}, + {"getref", getref}, + {"hash", hash_query}, + {"int2fb", int2fb_aux}, + {"log2", log2_aux}, + {"limits", get_limits}, + {"listcode", listcode}, + {"printcode", printcode}, + {"listk", listk}, + {"listlocals", listlocals}, + {"loadlib", loadlib}, + {"checkpanic", checkpanic}, + {"newstate", newstate}, + {"newuserdata", newuserdata}, + {"num2int", num2int}, + {"pushuserdata", pushuserdata}, + {"querystr", string_query}, + {"querytab", table_query}, + {"ref", tref}, + {"resume", coresume}, + {"s2d", s2d}, + {"sethook", sethook}, + {"stacklevel", stacklevel}, + {"testC", testC}, + {"makeCfunc", makeCfunc}, + {"totalmem", mem_query}, + {"alloccount", alloc_count}, + {"trick", settrick}, + {"udataval", udataval}, + {"unref", unref}, + {"upvalue", upvalue}, + {NULL, NULL} +}; + + +static void checkfinalmem (void) { + lua_assert(l_memcontrol.numblocks == 0); + lua_assert(l_memcontrol.total == 0); +} + + +int luaB_opentests (lua_State *L) { + void *ud; + lua_atpanic(L, &tpanic); + atexit(checkfinalmem); + lua_assert(lua_getallocf(L, &ud) == debug_realloc); + lua_assert(ud == cast(void *, &l_memcontrol)); + lua_setallocf(L, lua_getallocf(L, NULL), ud); + luaL_newlib(L, tests_funcs); + return 1; +} + +#endif + diff --git a/3rd/lua/ltests.h b/3rd/lua/ltests.h new file mode 100644 index 000000000..9de63a66b --- /dev/null +++ b/3rd/lua/ltests.h @@ -0,0 +1,136 @@ +/* +** $Id: ltests.h,v 2.54 2017/12/07 18:51:39 roberto Exp roberto $ +** Internal Header for Debugging of the Lua Implementation +** See Copyright Notice in lua.h +*/ + +#ifndef ltests_h +#define ltests_h + + +#include +#include + +/* test Lua with compatibility code */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_IPAIRS +#define LUA_COMPAT_BITLIB +#define LUA_COMPAT_APIINTCASTS +#define LUA_COMPAT_FLOATSTRING +#define LUA_COMPAT_UNPACK +#define LUA_COMPAT_LOADERS +#define LUA_COMPAT_LOG10 +#define LUA_COMPAT_LOADSTRING +#define LUA_COMPAT_MAXN +#define LUA_COMPAT_MODULE + + +#define LUA_DEBUG + + +/* turn on assertions */ +#undef NDEBUG +#include +#define lua_assert(c) assert(c) + + +/* compiled with -O0, Lua uses a lot of C stack space... */ +#undef LUAI_MAXCCALLS +#define LUAI_MAXCCALLS 200 + +/* to avoid warnings, and to make sure value is really unused */ +#define UNUSED(x) (x=0, (void)(x)) + + +/* test for sizes in 'l_sprintf' (make sure whole buffer is available) */ +#undef l_sprintf +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), snprintf(s,sz,f,i)) +#else +#define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), sprintf(s,f,i)) +#endif + + +/* memory-allocator control variables */ +typedef struct Memcontrol { + unsigned long numblocks; + unsigned long total; + unsigned long maxmem; + unsigned long memlimit; + unsigned long countlimit; + unsigned long objcount[LUA_NUMTAGS]; +} Memcontrol; + +LUA_API Memcontrol l_memcontrol; + + +/* +** generic variable for debug tricks +*/ +extern void *l_Trick; + + + +/* +** Function to traverse and check all memory used by Lua +*/ +int lua_checkmemory (lua_State *L); + + +/* test for lock/unlock */ + +struct L_EXTRA { int lock; int *plock; }; +#undef LUA_EXTRASPACE +#define LUA_EXTRASPACE sizeof(struct L_EXTRA) +#define getlock(l) cast(struct L_EXTRA*, lua_getextraspace(l)) +#define luai_userstateopen(l) \ + (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock)) +#define luai_userstateclose(l) \ + lua_assert(getlock(l)->lock == 1 && getlock(l)->plock == &(getlock(l)->lock)) +#define luai_userstatethread(l,l1) \ + lua_assert(getlock(l1)->plock == getlock(l)->plock) +#define luai_userstatefree(l,l1) \ + lua_assert(getlock(l)->plock == getlock(l1)->plock) +#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0) +#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0) + + + +LUA_API int luaB_opentests (lua_State *L); + +LUA_API void *debug_realloc (void *ud, void *block, + size_t osize, size_t nsize); + +#if defined(lua_c) +#define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) +#define luaL_openlibs(L) \ + { (luaL_openlibs)(L); \ + luaL_requiref(L, "T", luaB_opentests, 1); \ + lua_pop(L, 1); } +#endif + + + +/* change some sizes to give some bugs a chance */ + +#undef LUAL_BUFFERSIZE +#define LUAL_BUFFERSIZE 23 +#define MINSTRTABSIZE 2 +#define MAXINDEXRK 1 +#define MAXIWTHABS 3 + + +/* make stack-overflow tests run faster */ +//#undef LUAI_MAXSTACK +//#define LUAI_MAXSTACK 50000 + + +#undef LUAI_USER_ALIGNMENT_T +#define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; } + + +#define STRCACHE_N 23 +#define STRCACHE_M 5 + +#endif + diff --git a/3rd/lua/ltm.c b/3rd/lua/ltm.c new file mode 100644 index 000000000..4b14f197d --- /dev/null +++ b/3rd/lua/ltm.c @@ -0,0 +1,254 @@ +/* +** $Id: ltm.c,v 2.55 2017/12/20 14:58:05 roberto Exp roberto $ +** 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 "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_TOTALTAGS] = { + "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" + }; + 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 (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttnov(o)]; + } + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + + +/* +** 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(ttnov(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 (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(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 (!callbinTM(L, p1, p2, res, event)) { + switch (event) { + case TM_CONCAT: + luaG_concaterror(L, p1, p2); + /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ + 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_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, int inv, TMS event) { + if (inv) + luaT_trybinTM(L, p2, p1, res, event); + else + luaT_trybinTM(L, p1, p2, res, event); +} + + +void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2, + int inv, StkId res, TMS event) { + TValue aux; + setivalue(&aux, i2); + luaT_trybinassocTM(L, p1, &aux, res, inv, event); +} + + +int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ + return !l_isfalse(s2v(L->top)); + 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 */ + } + 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 inv, TMS event) { + TValue aux; const TValue *p2; + setivalue(&aux, v2); + if (inv) { /* arguments were exchanged? */ + p2 = p1; p1 = &aux; /* correct them */ + event = (event == TM_LE) ? TM_LT : TM_LE; + } + else + p2 = &aux; + return (luaT_callorderTM(L, p1, p2, event) != inv); +} + + +void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) { + int i; + Table *vtab; + TValue nname; + int nfixparams = p->numparams; /* number of fixed parameters */ + actual -= nfixparams; /* number of extra arguments */ + vtab = luaH_new(L); /* create vararg table */ + sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ + L->top++; /* space ensured by caller */ + luaH_resize(L, vtab, actual, 1); + for (i = 0; i < actual; i++) /* put extra arguments into vararg table */ + setobj2n(L, &vtab->array[i], s2v(L->top - actual + i - 1)); + setsvalue(L, &nname, G(L)->nfield); /* get field 'n' */ + setivalue(luaH_set(L, vtab, &nname), actual); /* store counter there */ + L->top -= actual; /* remove extra elements from the stack */ + sethvalue2s(L, L->top - 1, vtab); /* move table to new top */ +} + + +void luaT_getvarargs (lua_State *L, TValue *t, StkId where, int wanted) { + if (!ttistable(t)) + luaG_runerror(L, "'vararg' parameter is not a table"); + else { + int i; + Table *h = hvalue(t); + if (wanted < 0) { /* get all? */ + const TValue *ns = luaH_getstr(h, G(L)->nfield); + int n = (ttisinteger(ns)) ? cast_int(ivalue(ns)) : 0; + wanted = n; + checkstackp(L, n, where); + L->top = where + n; + } + for (i = 0; i < wanted; i++) /* get what is available */ + setobj2s(L, where + i, luaH_getint(h, i + 1)); + return; + } +} diff --git a/3rd/lua/ltm.h b/3rd/lua/ltm.h new file mode 100644 index 000000000..34dbc82cc --- /dev/null +++ b/3rd/lua/ltm.h @@ -0,0 +1,85 @@ +/* +** $Id: ltm.h,v 2.27 2017/11/27 17:44:31 roberto Exp roberto $ +** 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_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +#define ttypename(x) luaT_typenames_[(x) + 1] + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; + + +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_trybinassocTM (lua_State *L, const TValue *p1, + const TValue *p2, StkId res, int inv, TMS event); +LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, int 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, TMS event); + +LUAI_FUNC void luaT_adjustvarargs (lua_State *L, Proto *p, int actual); +LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, + int wanted); + + +#endif diff --git a/3rd/lua/lua b/3rd/lua/lua new file mode 100755 index 0000000000000000000000000000000000000000..d9882eb0106a8208434948e8b797ee50e94308e4 GIT binary patch literal 627136 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

D0n3ecnijMRr2)Hr-t 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

jUiZu!c9aU%&birEOTf_S~@I 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 +#include +#include + +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT_VAR) +#define LUA_INIT_VAR "LUA_INIT" +#endif + +#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#if !defined(lua_stdin_is_tty) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include +#define lua_stdin_is_tty() isatty(0) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#include +#include + +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) + +#else /* }{ */ + +/* ISO C definition */ +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ + +#endif /* } */ + +#endif /* } */ + + +/* +** lua_readline defines how to show a prompt and then read a line from +** the standard input. +** lua_saveline defines how to "save" a read line in a "history". +** lua_freeline defines how to free a line read by lua_readline. +*/ +#if !defined(lua_readline) /* { */ + +#if defined(LUA_USE_READLINE) /* { */ + +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,line) ((void)L, add_history(line)) +#define lua_freeline(L,b) ((void)L, free(b)) + +#else /* }{ */ + +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,line) { (void)L; (void)line; } +#define lua_freeline(L,b) { (void)L; (void)b; } + +#endif /* } */ + +#endif /* } */ + + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + +/* +** Hook set by signal function to stop the interpreter. +*/ +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); /* reset hook */ + luaL_error(L, "interrupted!"); +} + + +/* +** Function to be called at a C signal. Because a C signal cannot +** just change a Lua state (as there is no proper synchronization), +** this function only sets a hook that, when called, will stop the +** interpreter. +*/ +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (const char *badoption) { + lua_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + lua_writestringerror("'%s' needs argument\n", badoption); + else + lua_writestringerror("unrecognized option '%s'\n", badoption); + lua_writestringerror( + "usage: %s [options] [script [args]]\n" + "Available options are:\n" + " -e stat execute string 'stat'\n" + " -i enter interactive mode after executing 'script'\n" + " -l name require library 'name' into global 'name'\n" + " -v show version information\n" + " -E ignore environment variables\n" + " -- stop handling options\n" + " - stop handling options and execute stdin\n" + , + progname); +} + + +/* +** Prints an error message, adding the program name in front of it +** (if present) +*/ +static void l_message (const char *pname, const char *msg) { + if (pname) lua_writestringerror("%s: ", pname); + lua_writestringerror("%s\n", msg); +} + + +/* +** Check whether 'status' is not OK and, if so, prints the error +** message on the top of the stack. It assumes that the error object +** is a string, as it was either generated by Lua or by 'msghandler'. +*/ +static int report (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = lua_tostring(L, -1); + l_message(progname, msg); + lua_pop(L, 1); /* remove message */ + } + return status; +} + + +/* +** Message handler used to run all chunks +*/ +static int msghandler (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg == NULL) { /* is error object not a string? */ + if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ + lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ + return 1; /* that is the message */ + else + msg = lua_pushfstring(L, "(error object is a %s value)", + luaL_typename(L, 1)); + } + luaL_traceback(L, L, msg, 1); /* append a standard traceback */ + return 1; /* return the traceback */ +} + + +/* +** Interface to 'lua_pcall', which sets appropriate message function +** and C-signal handler. Used to run all chunks. +*/ +static int docall (lua_State *L, int narg, int nres) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, msghandler); /* push message handler */ + lua_insert(L, base); /* put it under function and args */ + globalL = L; /* to be available to 'laction' */ + signal(SIGINT, laction); /* set C-signal handler */ + status = lua_pcall(L, narg, nres, base); + signal(SIGINT, SIG_DFL); /* reset C-signal handler */ + lua_remove(L, base); /* remove message handler from the stack */ + return status; +} + + +static void print_version (void) { + lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + lua_writeline(); +} + + +/* +** Create the 'arg' table, which stores all arguments from the +** command line ('argv'). It should be aligned so that, at index 0, +** it has 'argv[script]', which is the script name. The arguments +** to the script (everything after 'script') go to positive indices; +** other arguments (before the script name) go to negative indices. +** If there is no script name, assume interpreter's name as base. +*/ +static void createargtable (lua_State *L, char **argv, int argc, int script) { + int i, narg; + if (script == argc) script = 0; /* no script name? */ + narg = argc - (script + 1); /* number of positive indices */ + lua_createtable(L, narg, script + 1); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - script); + } + lua_setglobal(L, "arg"); +} + + +static int dochunk (lua_State *L, int status) { + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dofile (lua_State *L, const char *name) { + return dochunk(L, luaL_loadfile(L, name)); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); +} + + +/* +** Calls 'require(name)' and stores the result in a global variable +** with the given name. +*/ +static int dolibrary (lua_State *L, const char *name) { + int status; + lua_getglobal(L, "require"); + lua_pushstring(L, name); + status = docall(L, 1, 1); /* call 'require(name)' */ + if (status == LUA_OK) + lua_setglobal(L, name); /* global[name] = require return */ + return report(L, status); +} + + +/* +** Returns the string to be used as a prompt by the interpreter. +*/ +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + return p; +} + +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + + +/* +** Check whether 'status' signals a syntax error and the error +** message at the top of the stack ends with the above mark for +** incomplete statements. +*/ +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +/* +** Prompt the user, read a line, and push it into the Lua stack. +*/ +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + int readstatus = lua_readline(L, b, prmt); + if (readstatus == 0) + return 0; /* no input (prompt will be popped by caller) */ + lua_pop(L, 1); /* remove prompt */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[--l] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ + lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ + else + lua_pushlstring(L, b, l); + lua_freeline(L, b); + return 1; +} + + +/* +** Try to compile line on the stack as 'return ;'; on return, stack +** has either compiled chunk or original line (if compilation failed). +*/ +static int addreturn (lua_State *L) { + const char *line = lua_tostring(L, -1); /* original line */ + const char *retline = lua_pushfstring(L, "return %s;", line); + int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); + if (status == LUA_OK) { + lua_remove(L, -2); /* remove modified line */ + if (line[0] != '\0') /* non empty? */ + lua_saveline(L, line); /* keep history */ + } + else + lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ + return status; +} + + +/* +** Read multiple lines until a complete Lua statement +*/ +static int multiline (lua_State *L) { + for (;;) { /* repeat until gets a complete statement */ + size_t len; + const char *line = lua_tolstring(L, 1, &len); /* get what it has */ + int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ + if (!incomplete(L, status) || !pushline(L, 0)) { + lua_saveline(L, line); /* keep history */ + return status; /* cannot or should not try to add continuation line */ + } + lua_pushliteral(L, "\n"); /* add newline... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } +} + + +/* +** Read a line and try to load (compile) it first as an expression (by +** adding "return " in front of it) and second as a statement. Return +** the final status of load/call with the resulting function (if any) +** in the top of the stack. +*/ +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ + status = multiline(L); /* try as command, maybe with continuation lines */ + lua_remove(L, 1); /* remove line from the stack */ + lua_assert(lua_gettop(L) == 1); + return status; +} + + +/* +** Prints (calling the Lua 'print' function) any values on the stack +*/ +static void l_print (lua_State *L) { + int n = lua_gettop(L); + if (n > 0) { /* any result to be printed? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, n, 0, 0) != LUA_OK) + l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", + lua_tostring(L, -1))); + } +} + + +/* +** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and +** print any results. +*/ +static void doREPL (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; /* no 'progname' on errors in interactive mode */ + while ((status = loadline(L)) != -1) { + if (status == LUA_OK) + status = docall(L, 0, LUA_MULTRET); + if (status == LUA_OK) l_print(L); + else report(L, status); + } + lua_settop(L, 0); /* clear stack */ + lua_writeline(); + progname = oldprogname; +} + + +/* +** Push on the stack the contents of table 'arg' from 1 to #arg +*/ +static int pushargs (lua_State *L) { + int i, n; + if (lua_getglobal(L, "arg") != LUA_TTABLE) + luaL_error(L, "'arg' is not a table"); + n = (int)luaL_len(L, -1); + luaL_checkstack(L, n + 3, "too many arguments to script"); + for (i = 1; i <= n; i++) + lua_rawgeti(L, -i, i); + lua_remove(L, -i); /* remove table from the stack */ + return n; +} + + +static int handle_script (lua_State *L, char **argv) { + int status; + const char *fname = argv[0]; + if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + if (status == LUA_OK) { + int n = pushargs(L); /* push arguments to script */ + status = docall(L, n, LUA_MULTRET); + } + return report(L, status); +} + + + +/* bits of various argument indicators in 'args' */ +#define has_error 1 /* bad option */ +#define has_i 2 /* -i */ +#define has_v 4 /* -v */ +#define has_e 8 /* -e */ +#define has_E 16 /* -E */ + +/* +** Traverses all arguments from 'argv', returning a mask with those +** needed before running any Lua code (or an error code if it finds +** any invalid argument). 'first' returns the first not-handled argument +** (either the script name or a bad argument in case of error). +*/ +static int collectargs (char **argv, int *first) { + int args = 0; + int i; + for (i = 1; argv[i] != NULL; i++) { + *first = i; + if (argv[i][0] != '-') /* not an option? */ + return args; /* stop handling options */ + switch (argv[i][1]) { /* else check option */ + case '-': /* '--' */ + if (argv[i][2] != '\0') /* extra characters after '--'? */ + return has_error; /* invalid option */ + *first = i + 1; + return args; + case '\0': /* '-' */ + return args; /* script "name" is '-' */ + case 'E': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_E; + break; + case 'i': + args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ + case 'v': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_v; + break; + case 'e': + args |= has_e; /* FALLTHROUGH */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return has_error; /* no next argument or it is another option */ + } + break; + default: /* invalid option */ + return has_error; + } + } + *first = i; /* no script name */ + return args; +} + + +/* +** Processes options 'e' and 'l', which involve running Lua code. +** Returns 0 if some code raises an error. +*/ +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + int option = argv[i][1]; + lua_assert(argv[i][0] == '-'); /* already checked */ + if (option == 'e' || option == 'l') { + int status; + const char *extra = argv[i] + 2; /* both options need an argument */ + if (*extra == '\0') extra = argv[++i]; + lua_assert(extra != NULL); + status = (option == 'e') + ? dostring(L, extra, "=(command line)") + : dolibrary(L, extra); + if (status != LUA_OK) return 0; + } + } + return 1; +} + + + +static int handle_luainit (lua_State *L) { + const char *name = "=" LUA_INITVARVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT_VAR; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, name); +} + + +/* +** Main body of stand-alone interpreter (to be called in protected mode). +** Reads the options and handles them all. +*/ +static int pmain (lua_State *L) { + int argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); + int script; + int args = collectargs(argv, &script); + luaL_checkversion(L); /* check that interpreter has correct version */ + if (argv[0] && argv[0][0]) progname = argv[0]; + if (args == has_error) { /* bad arg? */ + print_usage(argv[script]); /* 'script' has index of bad arg. */ + return 0; + } + if (args & has_v) /* option '-v'? */ + print_version(); + if (args & has_E) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + luaL_openlibs(L); /* open standard libraries */ + createargtable(L, argv, argc, script); /* create table 'arg' */ + if (!(args & has_E)) { /* no option '-E'? */ + if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ + return 0; /* error running LUA_INIT */ + } + if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + return 0; /* something failed */ + if (script < argc && /* execute main script (if there is one) */ + handle_script(L, argv + script) != LUA_OK) + return 0; + if (args & has_i) /* -i option? */ + doREPL(L); /* do read-eval-print loop */ + else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + if (lua_stdin_is_tty()) { /* running in interactive mode? */ + print_version(); + doREPL(L); /* do read-eval-print loop */ + } + else dofile(L, NULL); /* executes stdin as a file */ + } + lua_pushboolean(L, 1); /* signal no errors */ + return 1; +} + + +int main (int argc, char **argv) { + int status, result; + lua_State *L = luaL_newstate(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); /* do the call */ + result = lua_toboolean(L, -1); /* get result */ + report(L, status); + lua_close(L); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/3rd/lua/lua.h b/3rd/lua/lua.h new file mode 100644 index 000000000..2d8ff8382 --- /dev/null +++ b/3rd/lua/lua.h @@ -0,0 +1,489 @@ +/* +** $Id: lua.h,v 1.337 2017/11/02 11:28:56 roberto Exp $ +** 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_NUM 504 +#define LUA_VERSION_RELEASE "0" + +#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-2017 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_ERRGCMM 5 +#define LUA_ERRERR 6 + + +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_NUMTAGS 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); + + + +/* +** 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 lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const 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_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); + + +/* +** 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 void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** '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) + + +/* +** 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); + + + +/* +** {============================================================== +** 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 for unsigned conversions +** =============================================================== +*/ +#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 +/* }============================================================== */ + +/* +** {====================================================================== +** 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); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int 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) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2017 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/3rd/lua/luaconf.h b/3rd/lua/luaconf.h new file mode 100644 index 000000000..888e402b3 --- /dev/null +++ b/3rd/lua/luaconf.h @@ -0,0 +1,797 @@ +/* +** $Id: luaconf.h,v 1.262 2017/12/07 18:53:33 roberto Exp roberto $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ 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 */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ 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 +#endif + + + +/* +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. +*/ +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 +#endif + + +/* +@@ 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 (if 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 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* 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 defined(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 + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#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 "\\" +#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" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** 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 LUALIB_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 +** that are not 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("hidden"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_2) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. +*/ +#define LUA_COMPAT_BITLIB + +/* +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +*/ +#define LUA_COMPAT_APIINTCASTS + +#endif /* } */ + + +#if defined(LUA_COMPAT_5_1) /* { */ + +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ 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. +*/ +#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) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name '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 numeric string 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 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_mathlim(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_mathlim(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_mathlim(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_INTEGER is the integer type used by Lua. +** +@@ 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_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 + +#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 + +#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 + +#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 + +#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 numeric string 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 numeric string. +** 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 header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#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). You probably do not want/need to change them. +** ===================================================================== +*/ + +/* +@@ 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_BITSINT >= 32 +#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. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) +*/ +#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif + +/* +@@ 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 + +/* }================================================================== */ + + +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/3rd/lua/lualib.h b/3rd/lua/lualib.h new file mode 100644 index 000000000..c01eb9c8c --- /dev/null +++ b/3rd/lua/lualib.h @@ -0,0 +1,61 @@ +/* +** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp roberto $ +** 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_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (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); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/3rd/lua/lundump.c b/3rd/lua/lundump.c new file mode 100644 index 000000000..25ab102da --- /dev/null +++ b/3rd/lua/lundump.c @@ -0,0 +1,293 @@ +/* +** $Id: lundump.c,v 2.48 2017/11/28 11:19:07 roberto Exp roberto $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define lundump_c +#define LUA_CORE + +#include "lprefix.h" + + +#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,b,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: %s precompiled chunk", 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"); +} + + +#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"); + return cast_byte(b); +} + + +static size_t LoadSize (LoadState *S) { + size_t x = 0; + int b; + do { + b = LoadByte(S); + x = (x << 7) | (b & 0x7f); + } while ((b & 0x80) == 0); + return x; +} + + +static int LoadInt (LoadState *S) { + return cast_int(LoadSize(S)); +} + + +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; +} + + +static TString *LoadString (LoadState *S) { + size_t size = LoadSize(S); + if (size == 0) + return NULL; + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + LoadVector(S, buff, size); + return luaS_newlstr(S->L, buff, size); + } + else { /* long string */ + TString *ts = luaS_createlngstrobj(S->L, size); + LoadVector(S, getstr(ts), size); /* load directly in final place */ + return ts; + } +} + + +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_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o, LoadByte(S)); + break; + case LUA_TNUMFLT: + setfltvalue(o, LoadNumber(S)); + break; + case LUA_TNUMINT: + setivalue(o, LoadInteger(S)); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + setsvalue2n(S->L, o, LoadString(S)); + 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); + LoadFunction(S, f->p[i], f->source); + } +} + + +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++) + f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) { + f->upvalues[i].instack = LoadByte(S); + f->upvalues[i].idx = 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 = LoadString(S); + 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 = LoadString(S); +} + + +static void LoadFunction (LoadState *S, Proto *f, TString *psource) { + f->source = LoadString(S); + 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 in", tname)); +} + + +#define checksize(S,t) fchecksize(S,sizeof(t),#t) + +static void checkHeader (LoadState *S) { + checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ + if (LoadByte(S) != LUAC_VERSION) + error(S, "version mismatch in"); + if (LoadByte(S) != LUAC_FORMAT) + error(S, "format mismatch in"); + checkliteral(S, LUAC_DATA, "corrupted"); + checksize(S, int); + checksize(S, size_t); + checksize(S, Instruction); + checksize(S, lua_Integer); + checksize(S, lua_Number); + if (LoadInteger(S) != LUAC_INT) + error(S, "endianness mismatch in"); + if (LoadNumber(S) != LUAC_NUM) + error(S, "float format mismatch in"); +} + + +/* +** 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); + LoadFunction(&S, cl->p, NULL); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luai_verifycode(L, buff, cl->p); + return cl; +} + diff --git a/3rd/lua/lundump.h b/3rd/lua/lundump.h new file mode 100644 index 000000000..bc9f99a29 --- /dev/null +++ b/3rd/lua/lundump.h @@ -0,0 +1,32 @@ +/* +** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp roberto $ +** 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) + +#define MYINT(s) (s[0]-'0') +#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/3rd/lua/lutf8lib.c b/3rd/lua/lutf8lib.c new file mode 100644 index 000000000..57bd59e01 --- /dev/null +++ b/3rd/lua/lutf8lib.c @@ -0,0 +1,256 @@ +/* +** $Id: lutf8lib.c,v 1.16 2016/12/22 13:08:50 roberto Exp roberto $ +** 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 0x10FFFF + +#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. +*/ +static const char *utf8_decode (const char *o, int *val) { + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char *s = (const unsigned char *)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) { /* still have continuation bytes? */ + int cc = 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 */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char *)s + 1; /* +1 to include first byte */ +} + + +/* +** utf8len(s [, i [, j]]) --> 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) { + int n = 0; + size_t len; + 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); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of string"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of string"); + while (posi <= posj) { + const char *s1 = utf8_decode(s + posi, NULL); + if (s1 == NULL) { /* conversion error? */ + lua_pushnil(L); /* return nil ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; +} + + +/* +** codepoint(s, [i, [j]]) -> 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 n; + const char *se; + luaL_argcheck(L, posi >= 1, 2, "out of range"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); + 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; + luaL_checkstack(L, n, "string slice too long"); + n = 0; + se = s + pose; + for (s += posi - 1; s < se;) { + int code; + s = utf8_decode(s, &code); + 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_Integer code = luaL_checkinteger(L, arg); + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, 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 range"); + 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 */ + lua_pushnil(L); + return 1; +} + + +static int iter_aux (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else { + int code; + const char *next = utf8_decode(s + n, &code); + if (next == NULL || iscont(next)) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } +} + + +static int iter_codes (lua_State *L) { + luaL_checkstring(L, 1); + lua_pushcfunction(L, iter_aux); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + + +/* pattern to match a single UTF-8 character */ +#define UTF8PATT "[\0-\x7F\xC2-\xF4][\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/3rd/lua/lvm.c b/3rd/lua/lvm.c new file mode 100644 index 000000000..2b0359325 --- /dev/null +++ b/3rd/lua/lvm.c @@ -0,0 +1,1717 @@ +/* +** $Id: lvm.c,v 2.330 2017/12/28 15:42:57 roberto Exp roberto $ +** 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" + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 2000 + + +/* +** 'l_intfitsf' checks whether a given integer can be converted to a +** float without rounding. Used in comparisons. Left undefined if +** all integers fit in a float precisely. +*/ +#if !defined(l_intfitsf) + +/* number of bits in the mantissa of a float */ +#define NBM (l_mathlim(MANT_DIG)) + +/* +** Check whether some integers may not fit in a float, that is, 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(integer) == 32.) +*/ +#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ + >> (NBM - (3 * (NBM / 4)))) > 0 + +#define l_intfitsf(i) \ + (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) + +#endif + +#endif + + + +/* +** 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 (cvt2num(obj) && /* string coercible to number? */ + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { + *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': +** mode == 0: accepts only integral values +** mode == 1: takes the floor of the number +** mode == 2: takes the ceil of the number +*/ +int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode) { + if (!ttisfloat(obj)) + return 0; + else { + lua_Number n = fltvalue(obj); + lua_Number f = l_floor(n); + if (n != f) { /* not an integral value? */ + if (mode == 0) return 0; /* fails if mode demands integral value */ + else if (mode > 1) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numbertointeger(f, p); + } +} + + +/* +** try to convert a value to an integer. ("Fast track" is handled +** by macro 'tointeger'.) +*/ +int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { + TValue v; + if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) + obj = &v; /* change string to its corresponding number */ + if (ttisinteger(obj)) { + *p = ivalue(obj); + return 1; + } + else + return luaV_flttointeger(obj, p, mode); +} + + +/* +** Try to convert a 'for' limit to an integer, preserving the semantics +** of the loop. (The following explanation assumes a non-negative 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 it. +** Otherwise, check whether the limit can be converted to a float. If +** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, +** which means no limit. If the number is too negative, the loop +** should not run, because any initial integer value is larger than the +** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects +** the extreme case when the initial value is LUA_MININTEGER, in which +** case the LUA_MININTEGER limit would still run the loop once. +*/ +static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, + int *stopnow) { + *stopnow = 0; /* usually, let loops run */ + if (ttisinteger(obj)) + *p = ivalue(obj); + else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { + /* not coercible to in integer */ + lua_Number n; /* try to convert to float */ + if (!tonumber(obj, &n)) /* cannot convert to float? */ + return 0; /* not a number */ + if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ + *p = LUA_MAXINTEGER; + if (step < 0) *stopnow = 1; + } + else { /* float is smaller than min integer */ + *p = LUA_MININTEGER; + if (step >= 0) *stopnow = 1; + } + } + return 1; +} + + +/* +** 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 nil). +*/ +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 (ttisnil(tm)) + luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else { /* 't' is a table */ + lua_assert(ttisnil(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 'luaO_nilobject' if there is no such +** entry. (The value at 'slot' must be nil, 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(ttisnil(slot)); /* old value must be nil */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) { /* no metamethod? */ + if (slot == luaO_nilobject) /* no previous entry? */ + slot = luaH_newkey(L, h, key); /* create one */ + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, cast(TValue *, slot), val); /* set its new value */ + invalidateTMcache(h); + luaC_barrierback(L, h, val); + return; + } + /* else will try the metamethod */ + } + else { /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + 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 smaller-equal- +** -larger than zero if 'ls' is smaller-equal-larger 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 smaller 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, if 'f' is outside the range for integers, result +** is trivial. Otherwise, compare them as integers. (When 'i' has no +** float representation, either 'f' is "far away" from 'i' or 'f' has +** no precision left for a fractional part; either way, how 'f' is +** truncated is irrelevant.) When 'f' is NaN, comparisons must result +** in false. +*/ +static int LTintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ + return (i < cast(lua_Integer, f)); /* compare them as integers */ + else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ + return 0; + } +#endif + return luai_numlt(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Check whether integer 'i' is less than or equal to float 'f'. +** See comments on previous function. +*/ +static int LEintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ + return (i <= cast(lua_Integer, f)); /* compare them as integers */ + else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ + return 0; + } +#endif + return luai_numle(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Return 'l < r', for numbers. +*/ +static 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 if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN < i is always false */ + else /* without NaN, (l < r) <--> not(r <= l) */ + return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ + } +} + + +/* +** Return 'l <= r', for numbers. +*/ +static 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 if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN <= i is always false */ + else /* without NaN, (l <= r) <--> not(r < l) */ + return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ + } +} + + +/* +** 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. +** If it needs a metamethod and 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 rmetatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + 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 */ + 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) { + lua_assert(total >= 2); + 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_trybinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT); + 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 >= (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 (ttype(rb)) { + case LUA_TTABLE: { + 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_TSHRSTR: { + setivalue(s2v(ra), tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: { + setivalue(s2v(ra), tsvalue(rb)->u.lnglen); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(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_div (lua_State *L, lua_Integer m, lua_Integer n) { + if (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_div.) +*/ +lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { + if (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 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ + r += n; /* correct result for different rounding */ + 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'.) +*/ +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); + } +} + + +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { + LClosure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? s2v(base + uv[i].idx) : encup[uv[i].idx]->v; + if (c->upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + p->cachemiss = 0; /* got a hit */ + } + return c; /* return cached closure (or NULL if no cached closure) */ +} + + +/* +** 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]; + /* new closure is white, so we do not need a barrier here */ + } + if (p->cachemiss >= MAXMISS) /* too many missings? */ + p->cache = NULL; /* give up cache */ + else { + p->cache = ncl; /* save it on cache for reuse */ + luaC_protobarrier(L, p, ncl); + p->cachemiss++; + } +} + + +/* +** 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_ADDI: case OP_SUBI: + case OP_MULI: case OP_DIVI: case OP_IDIVI: + case OP_MODI: case OP_POWI: + case OP_ADD: case OP_SUB: + case OP_MUL: case OP_DIV: case OP_IDIV: + case OP_BANDK: case OP_BORK: case OP_BXORK: + case OP_BAND: case OP_BOR: case OP_BXOR: + case OP_SHRI: case OP_SHL: case OP_SHR: + case OP_MOD: case OP_POW: + 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_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ + int res = !l_isfalse(s2v(L->top - 1)); + L->top--; + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + lua_assert(op == OP_LE || + (op == OP_LTI && GETARG_C(inst)) || + (op == OP_LEI && !GETARG_C(inst))); + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (GETARG_C(inst)) res = !res; + 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_trybinTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobjs2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobjs2s(L, ci->func + 1 + GETARG_A(inst), L->top - 1); + break; + } + case OP_TFORCALL: case OP_CALL: case OP_TAILCALL: + case OP_SETTABUP: case OP_SETTABLE: + case OP_SETI: case OP_SETFIELD: + break; + default: lua_assert(0); + } +} + + + + +/* +** {================================================================== +** 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) + + +/* +** 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) { i = *pc; dojump(ci, i, 1); } + +/* +** 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 will finish the loop (returns). +*/ +#define halfProtect(exp) (savepc(L), (exp)) + + +#define checkGC(L,c) \ + { luaC_condGC(L, L->top = (c), /* limit of live values */ \ + updatetrap(ci)); \ + luai_threadyield(L); } + + +/* fetch an instruction and prepare its execution */ +#define vmfetch() { \ + i = *(pc++); \ + if (trap) { \ + if (!(L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))) \ + trap = ci->u.l.trap = 0; /* no need to stop again */ \ + else { savepc(L); luaG_traceexec(L); } \ + updatebase(ci); /* the trap may be just for that */ \ + } \ + ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ + vra = s2v(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 = ci->u.l.trap; + tailcall: + cl = clLvalue(s2v(ci->func)); + k = cl->p->k; + base = ci->func + 1; + pc = ci->u.l.savedpc; + /* main loop of interpreter */ + for (;;) { + int cond; /* flag for conditional jumps */ + Instruction i; /* instruction being executed */ + StkId ra; /* instruction's A register */ + TValue *vra; /* corresponding value */ + vmfetch(); + lua_assert(base == ci->func + 1); + lua_assert(base <= L->top && L->top < L->stack + L->stacksize); + lua_assert(ci->top < L->stack + L->stacksize); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE) { + setobjs2s(L, ra, RB(i)); + vmbreak; + } + vmcase(OP_LOADK) { + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADI) { + lua_Integer b = GETARG_sBx(i); + setivalue(vra, b); + vmbreak; + } + vmcase(OP_LOADF) { + int b = GETARG_sBx(i); + setfltvalue(vra, cast_num(b)); + vmbreak; + } + vmcase(OP_LOADKX) { + TValue *rb; + rb = k + GETARG_Ax(*pc); pc++; + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADBOOL) { + setbvalue(vra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + 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, vra); + luaC_barrier(L, uv, vra); + 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? */ + ? (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? */ + ? (n = ivalue(rb), luaV_fastgeti(L, vra, n, slot)) + : luaV_fastget(L, vra, rb, slot, luaH_get)) { + luaV_finishfastset(L, vra, slot, rc); + } + else + Protect(luaV_finishset(L, vra, rb, rc, slot)); + vmbreak; + } + vmcase(OP_SETI) { + const TValue *slot; + int c = GETARG_B(i); + TValue *rc = RKC(i); + if (luaV_fastgeti(L, vra, c, slot)) { + luaV_finishfastset(L, vra, slot, rc); + } + else { + TValue key; + setivalue(&key, c); + Protect(luaV_finishset(L, vra, &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, vra, key, slot, luaH_getshortstr)) { + luaV_finishfastset(L, vra, slot, rc); + } + else + Protect(luaV_finishset(L, vra, rb, rc, slot)); + vmbreak; + } + vmcase(OP_NEWTABLE) { + int b = GETARG_B(i); + int c = GETARG_C(i); + Table *t; + L->top = ci->top; /* correct top in case of GC */ + t = luaH_new(L); /* memory allocation */ + sethvalue2s(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); /* 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) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (ttisinteger(rb)) { + setivalue(vra, intop(+, ivalue(rb), ic)); + } + else if (tonumberns(rb, nb)) { + setfltvalue(vra, luai_numadd(L, nb, cast_num(ic))); + } + else + Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_ADD)); + vmbreak; + } + vmcase(OP_SUBI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (ttisinteger(rb)) { + setivalue(vra, intop(-, ivalue(rb), ic)); + } + else if (tonumberns(rb, nb)) { + setfltvalue(vra, luai_numsub(L, nb, cast_num(ic))); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_SUB)); + vmbreak; + } + vmcase(OP_MULI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (ttisinteger(rb)) { + setivalue(vra, intop(*, ivalue(rb), ic)); + } + else if (tonumberns(rb, nb)) { + setfltvalue(vra, luai_nummul(L, nb, cast_num(ic))); + } + else + Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_MUL)); + vmbreak; + } + vmcase(OP_MODI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (ttisinteger(rb)) { + setivalue(vra, luaV_mod(L, ivalue(rb), ic)); + } + else if (tonumberns(rb, nb)) { + lua_Number m; + lua_Number nc = cast_num(ic); + luai_nummod(L, nb, nc, m); + setfltvalue(vra, m); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_MOD)); + vmbreak; + } + vmcase(OP_POWI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (tonumberns(rb, nb)) { + lua_Number nc = cast_num(ic); + setfltvalue(vra, luai_numpow(L, nb, nc)); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_POW)); + vmbreak; + } + vmcase(OP_DIVI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (tonumberns(rb, nb)) { + lua_Number nc = cast_num(ic); + setfltvalue(vra, luai_numdiv(L, nb, nc)); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_DIV)); + vmbreak; + } + vmcase(OP_IDIVI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Number nb; + if (ttisinteger(rb)) { + setivalue(vra, luaV_div(L, ivalue(rb), ic)); + } + else if (tonumberns(rb, nb)) { + lua_Number nc = cast_num(ic); + setfltvalue(vra, luai_numdiv(L, nb, nc)); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_IDIV)); + vmbreak; + } + vmcase(OP_ADD) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(vra, intop(+, ib, ic)); + } + else if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_numadd(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); + vmbreak; + } + vmcase(OP_SUB) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(vra, intop(-, ib, ic)); + } + else if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_numsub(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); + vmbreak; + } + vmcase(OP_MUL) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(vra, intop(*, ib, ic)); + } + else if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_nummul(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); + vmbreak; + } + vmcase(OP_DIV) { /* float division (always with floats) */ + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_numdiv(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); + vmbreak; + } + vmcase(OP_BANDK) { + TValue *p1 = vRB(i); + TValue *p2 = KC(i); + lua_Integer i1; + if (tointegerns(p1, &i1)) { + setivalue(vra, intop(&, i1, ivalue(p2))); + } + else + Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BAND)); + vmbreak; + } + vmcase(OP_BORK) { + TValue *p1 = vRB(i); + TValue *p2 = KC(i); + lua_Integer i1; + if (tointegerns(p1, &i1)) { + setivalue(vra, intop(|, i1, ivalue(p2))); + } + else + Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BOR)); + vmbreak; + } + vmcase(OP_BXORK) { + TValue *p1 = vRB(i); + TValue *p2 = KC(i); + lua_Integer i1; + if (tointegerns(p1, &i1)) { + setivalue(vra, intop(^, i1, ivalue(p2))); + } + else + Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BXOR)); + vmbreak; + } + vmcase(OP_BAND) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Integer ib; lua_Integer ic; + if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { + setivalue(vra, intop(&, ib, ic)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); + vmbreak; + } + vmcase(OP_BOR) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Integer ib; lua_Integer ic; + if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { + setivalue(vra, intop(|, ib, ic)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); + vmbreak; + } + vmcase(OP_BXOR) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Integer ib; lua_Integer ic; + if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { + setivalue(vra, intop(^, ib, ic)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); + vmbreak; + } + vmcase(OP_SHRI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + setivalue(vra, luaV_shiftl(ib, -ic)); + } + else { + TMS ev = TM_SHR; + if (TESTARG_k(i)) { + ic = -ic; ev = TM_SHL; + } + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, ev)); + } + vmbreak; + } + vmcase(OP_SHLI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + setivalue(vra, luaV_shiftl(ic, ib)); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL)); + vmbreak; + } + vmcase(OP_SHL) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Integer ib; lua_Integer ic; + if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { + setivalue(vra, luaV_shiftl(ib, ic)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); + vmbreak; + } + vmcase(OP_SHR) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Integer ib; lua_Integer ic; + if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { + setivalue(vra, luaV_shiftl(ib, -ic)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); + vmbreak; + } + vmcase(OP_MOD) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(vra, luaV_mod(L, ib, ic)); + } + else if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + lua_Number m; + luai_nummod(L, nb, nc, m); + setfltvalue(vra, m); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); + vmbreak; + } + vmcase(OP_IDIV) { /* floor division */ + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(vra, luaV_div(L, ib, ic)); + } + else if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_numidiv(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); + vmbreak; + } + vmcase(OP_POW) { + TValue *rb = vRB(i); + TValue *rc = vRC(i); + lua_Number nb; lua_Number nc; + if (tonumberns(rb, nb) && tonumberns(rc, nc)) { + setfltvalue(vra, luai_numpow(L, nb, nc)); + } + else + Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); + vmbreak; + } + vmcase(OP_UNM) { + TValue *rb = vRB(i); + lua_Number nb; + if (ttisinteger(rb)) { + lua_Integer ib = ivalue(rb); + setivalue(vra, intop(-, 0, ib)); + } + else if (tonumberns(rb, nb)) { + setfltvalue(vra, 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(vra, intop(^, ~l_castS2U(0), ib)); + } + else + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); + vmbreak; + } + vmcase(OP_NOT) { + TValue *rb = vRB(i); + int nrb = l_isfalse(rb); /* next assignment may change this value */ + setbvalue(vra, nrb); + vmbreak; + } + vmcase(OP_LEN) { + Protect(luaV_objlen(L, ra, vRB(i))); + vmbreak; + } + vmcase(OP_CONCAT) { + int b = GETARG_B(i); + int c = GETARG_C(i); + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + ProtectNT(luaV_concat(L, c - b + 1)); + if (trap) { /* 'luaV_concat' may move the stack */ + updatebase(ci); + ra = RA(i); + } + rb = base + b; + setobjs2s(L, ra, rb); + checkGC(L, (ra >= rb ? ra + 1 : rb)); + vmbreak; + } + vmcase(OP_CLOSE) { + luaF_close(L, ra); + vmbreak; + } + vmcase(OP_JMP) { + dojump(ci, i, 0); + vmbreak; + } + vmcase(OP_EQ) { + TValue *rb = vRB(i); + Protect(cond = luaV_equalobj(L, vra, rb)); + condjump: + if (cond != GETARG_k(i)) + pc++; /* skip next jump */ + else + donextjump(ci); + vmbreak; + } + vmcase(OP_LT) { + TValue *rb = vRB(i); + if (ttisinteger(vra) && ttisinteger(rb)) + cond = (ivalue(vra) < ivalue(rb)); + else if (ttisnumber(vra) && ttisnumber(rb)) + cond = LTnum(vra, rb); + else + Protect(cond = lessthanothers(L, vra, rb)); + goto condjump; + } + vmcase(OP_LE) { + TValue *rb = vRB(i); + if (ttisinteger(vra) && ttisinteger(rb)) + cond = (ivalue(vra) <= ivalue(rb)); + else if (ttisnumber(vra) && ttisnumber(rb)) + cond = LEnum(vra, rb); + else + Protect(cond = lessequalothers(L, vra, rb)); + goto condjump; + } + vmcase(OP_EQK) { + TValue *rb = KB(i); + /* basic types do not use '__eq'; we can use raw equality */ + cond = luaV_equalobj(NULL, vra, rb); + goto condjump; + } + vmcase(OP_EQI) { + int im = GETARG_sB(i); + if (ttisinteger(vra)) + cond = (ivalue(vra) == im); + else if (ttisfloat(vra)) + cond = luai_numeq(fltvalue(vra), cast_num(im)); + else + cond = 0; /* other types cannot be equal to a number */ + goto condjump; + } + vmcase(OP_LTI) { + int im = GETARG_sB(i); + if (ttisinteger(vra)) + cond = (ivalue(vra) < im); + else if (ttisfloat(vra)) { + lua_Number f = fltvalue(vra); + cond = (!luai_numisnan(f)) ? luai_numlt(f, cast_num(im)) + : GETARG_C(i); /* NaN */ + } + else + Protect(cond = luaT_callorderiTM(L, vra, im, GETARG_C(i), TM_LT)); + goto condjump; + } + vmcase(OP_LEI) { + int im = GETARG_sB(i); + if (ttisinteger(vra)) + cond = (ivalue(vra) <= im); + else if (ttisfloat(vra)) { + lua_Number f = fltvalue(vra); + cond = (!luai_numisnan(f)) ? luai_numle(f, cast_num(im)) + : GETARG_C(i); /* NaN? */ + } + else + Protect(cond = luaT_callorderiTM(L, vra, im, GETARG_C(i), TM_LE)); + goto condjump; + } + vmcase(OP_TEST) { + cond = !l_isfalse(vra); + goto condjump; + } + 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) { + 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 */ + ProtectNT(luaD_call(L, ra, nresults)); + vmbreak; + } + vmcase(OP_TAILCALL) { + int b = GETARG_B(i); /* number of arguments + 1 (function) */ + if (b != 0) + L->top = ra + b; + else /* previous instruction set top */ + b = L->top - ra; + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + if (!ttisfunction(vra)) { /* not a function? */ + /* try to get '__call' metamethod */ + ProtectNT(ra = luaD_tryfuncTM(L, ra)); + vra = s2v(ra); + b++; /* there is now one extra argument */ + } + if (!ttisLclosure(vra)) { /* C function? */ + ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ + /* next instruction will do the return */ + } + else { /* tail call */ + if (TESTARG_k(i)) /* close upvalues from previous call */ + luaF_close(L, ci->func + 1); + luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ + goto tailcall; + } + vmbreak; + } + vmcase(OP_RETURN) { + int b = GETARG_B(i); + if (TESTARG_k(i)) + luaF_close(L, base); + halfProtect( + luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) + ); + return; + } + vmcase(OP_RETURN0) { + if (TESTARG_k(i)) + luaF_close(L, base); + if (L->hookmask) + halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ + else { + int nres = ci->nresults; + L->ci = ci->previous; /* back to caller */ + L->top = base - 1; + while (nres-- > 0) + setnilvalue(s2v(L->top++)); /* all results are nil */ + } + return; + } + vmcase(OP_RETURN1) { + if (TESTARG_k(i)) + luaF_close(L, base); + if (L->hookmask) + halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ + else { + 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; + while (--nres > 0) /* complete missing results */ + setnilvalue(s2v(L->top++)); + } + } + return; + } + vmcase(OP_FORLOOP1) { + lua_Integer idx = intop(+, ivalue(vra), 1); /* increment index */ + lua_Integer limit = ivalue(s2v(ra + 1)); + if (idx <= limit) { + pc -= GETARG_Bx(i); /* jump back */ + chgivalue(vra, idx); /* update internal index... */ + setivalue(s2v(ra + 3), idx); /* ...and external index */ + } + updatetrap(ci); + vmbreak; + } + vmcase(OP_FORPREP1) { + TValue *init = vra; + TValue *plimit = s2v(ra + 1); + lua_Integer ilimit, initv; + int stopnow; + if (!forlimit(plimit, &ilimit, 1, &stopnow)) { + savestate(L, ci); /* for the error message */ + luaG_runerror(L, "'for' limit must be a number"); + } + initv = (stopnow ? 0 : ivalue(init)); + setivalue(plimit, ilimit); + setivalue(init, intop(-, initv, 1)); + pc += GETARG_Bx(i); + vmbreak; + } + vmcase(OP_FORLOOP) { + if (ttisinteger(vra)) { /* integer loop? */ + lua_Integer step = ivalue(s2v(ra + 2)); + lua_Integer idx = intop(+, ivalue(vra), step); /* increment index */ + lua_Integer limit = ivalue(s2v(ra + 1)); + if ((0 < step) ? (idx <= limit) : (limit <= idx)) { + pc -= GETARG_Bx(i); /* jump back */ + chgivalue(vra, idx); /* update internal index... */ + setivalue(s2v(ra + 3), idx); /* ...and external index */ + } + } + else { /* floating loop */ + lua_Number step = fltvalue(s2v(ra + 2)); + lua_Number limit = fltvalue(s2v(ra + 1)); + lua_Number idx = fltvalue(vra); + idx = luai_numadd(L, idx, step); /* inc. index */ + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + pc -= GETARG_Bx(i); /* jump back */ + chgfltvalue(vra, idx); /* update internal index... */ + setfltvalue(s2v(ra + 3), idx); /* ...and external index */ + } + } + updatetrap(ci); + vmbreak; + } + vmcase(OP_FORPREP) { + TValue *init = vra; + TValue *plimit = s2v(ra + 1); + TValue *pstep = s2v(ra + 2); + lua_Integer ilimit; + int stopnow; + if (ttisinteger(init) && ttisinteger(pstep) && + forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { + /* all values are integer */ + lua_Integer initv = (stopnow ? 0 : ivalue(init)); + setivalue(plimit, ilimit); + setivalue(init, intop(-, initv, ivalue(pstep))); + } + else { /* try making all values floats */ + lua_Number ninit; lua_Number nlimit; lua_Number nstep; + savestate(L, ci); /* in case of errors */ + if (!tonumber(plimit, &nlimit)) + luaG_runerror(L, "'for' limit must be a number"); + setfltvalue(plimit, nlimit); + if (!tonumber(pstep, &nstep)) + luaG_runerror(L, "'for' step must be a number"); + setfltvalue(pstep, nstep); + if (!tonumber(init, &ninit)) + luaG_runerror(L, "'for' initial value must be a number"); + setfltvalue(init, luai_numsub(L, ninit, nstep)); + } + pc += GETARG_Bx(i); + vmbreak; + } + vmcase(OP_TFORCALL) { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + if (trap) /* keep 'base' correct for next instruction */ + updatebase(ci); + i = *(pc++); /* go to next instruction */ + ra = RA(i); /* get its 'ra' */ + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + } + vmcase(OP_TFORLOOP) { + l_tforloop: + if (!ttisnil(s2v(ra + 1))) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + pc -= GETARG_Bx(i); /* jump back */ + } + vmbreak; + } + vmcase(OP_SETLIST) { + int n = GETARG_B(i); + int c = GETARG_C(i); + unsigned int last; + Table *h; + if (n == 0) + n = cast_int(L->top - ra) - 1; + else + L->top = ci->top; /* correct top in case of GC */ + if (c == 0) { + c = GETARG_Ax(*pc); pc++; + } + h = hvalue(vra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* 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, h, val); + } + vmbreak; + } + vmcase(OP_CLOSURE) { + Proto *p = cl->p->p[GETARG_Bx(i)]; + LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) { /* no match? */ + savestate(L, ci); /* in case of allocation errors */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + } + else + setclLvalue2s(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_VARARG) { + int n = GETARG_C(i) - 1; /* required results */ + TValue *vtab = vRB(i); /* vararg table */ + Protect(luaT_getvarargs(L, vtab, ra, n)); + vmbreak; + } + vmcase(OP_EXTRAARG) { + lua_assert(0); + vmbreak; + } + } + } +} + +/* }================================================================== */ + diff --git a/3rd/lua/lvm.h b/3rd/lua/lvm.h new file mode 100644 index 000000000..0d2eed14f --- /dev/null +++ b/3rd/lua/lvm.h @@ -0,0 +1,122 @@ +/* +** $Id: lvm.h,v 2.47 2017/11/08 14:50:23 roberto Exp roberto $ +** 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 0 +#endif + + +/* 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) \ + (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) \ + (ttisinteger(o) ? (*(i) = ivalue(o), 1) \ + : luaV_flttointeger(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 not nil, +** 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 a nil '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 */ \ + !ttisnil(slot))) /* result not nil? */ + + +/* +** 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)->sizearray) \ + ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ + !ttisnil(slot))) /* result not nil? */ + + +/* +** 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, hvalue(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, int mode); +LUAI_FUNC int luaV_flttointeger (const TValue *obj, lua_Integer *p, int 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_div (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_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/3rd/lua/lzio.c b/3rd/lua/lzio.c new file mode 100644 index 000000000..eb6151a0b --- /dev/null +++ b/3rd/lua/lzio.c @@ -0,0 +1,68 @@ +/* +** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp roberto $ +** 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/3rd/lua/lzio.h b/3rd/lua/lzio.h new file mode 100644 index 000000000..fb310b99c --- /dev/null +++ b/3rd/lua/lzio.h @@ -0,0 +1,66 @@ +/* +** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp roberto $ +** 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/3rd/lua/makefile b/3rd/lua/makefile new file mode 100644 index 000000000..078f4f8d2 --- /dev/null +++ b/3rd/lua/makefile @@ -0,0 +1,198 @@ +# makefile for building Lua +# see INSTALL for installation instructions +# see ../Makefile and luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Warnings valid for both C and C++ +CWARNSCPP= \ + -pedantic \ + -Wextra \ + -Wshadow \ + -Wsign-compare \ + -Wundef \ + -Wwrite-strings \ + -Wredundant-decls \ + -Wdisabled-optimization \ + -Waggregate-return \ + -Wdouble-promotion \ + #-Wno-aggressive-loop-optimizations # not accepted by clang \ + #-Wlogical-op # not accepted by clang \ + # the next warnings generate too much noise, so they are disabled + # -Wconversion -Wno-sign-conversion \ + # -Wsign-conversion \ + # -Wconversion \ + # -Wstrict-overflow=2 \ + # -Wformat=2 \ + # -Wcast-qual \ + +# The next warnings are neither valid nor needed for C++ +CWARNSC= -Wdeclaration-after-statement \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wstrict-prototypes \ + -Wc++-compat \ + -Wold-style-definition \ + + +CWARNS= $(CWARNSCPP) $(CWARNSC) + + +# -DEXTERNMEMCHECK -DHARDSTACKTESTS -DHARDMEMTESTS -DTRACEMEM='"tempmem"' +# -g -DLUA_USER_H='"ltests.h"' +# -pg -malign-double +# -DLUA_USE_CTYPE -DLUA_USE_APICHECK +# (in clang, '-ftrapv' for runtime checks of integer overflows) +# -fsanitize=undefined -ftrapv +TESTS= -DLUA_USER_H='"ltests.h"' + +# -mtune=native -fomit-frame-pointer +# -fno-stack-protector +LOCAL = $(TESTS) $(CWARNS) -g + + + +# enable Linux goodies +MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_COMPAT_5_2 +#MYLDFLAGS= $(LOCAL) -Wl,-E +MYLIBS= -ldl -lreadline + + +CC= clang +CFLAGS= -Wall -g $(MYCFLAGS) +AR= ar rcu +RANLIB= ranlib +RM= rm -f + + + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + + +LIBS = -lm + +CORE_T= liblua.a +CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ + lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ + ltm.o lundump.o lvm.o lzio.o ltests.o +AUX_O= lauxlib.o +LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \ + lutf8lib.o lbitlib.o loadlib.o lcorolib.o linit.o + +LUA_T= lua +LUA_O= lua.o + +# LUAC_T= luac +# LUAC_O= luac.o print.o + +ALL_T= $(CORE_T) $(LUA_T) $(LUAC_T) +ALL_O= $(CORE_O) $(LUA_O) $(LUAC_O) $(AUX_O) $(LIB_O) +ALL_A= $(CORE_T) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(CORE_T): $(CORE_O) $(AUX_O) $(LIB_O) + $(AR) $@ $? + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(CORE_T) + $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(CORE_T) $(LIBS) $(MYLIBS) $(DL) + +$(LUAC_T): $(LUAC_O) $(CORE_T) + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(CORE_T) $(LIBS) $(MYLIBS) + +clean: + rcsclean -u + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM *.c + +echo: + @echo "CC = $(CC)" + @echo "CFLAGS = $(CFLAGS)" + @echo "AR = $(AR)" + @echo "RANLIB = $(RANLIB)" + @echo "RM = $(RM)" + @echo "MYCFLAGS = $(MYCFLAGS)" + @echo "MYLDFLAGS = $(MYLDFLAGS)" + @echo "MYLIBS = $(MYLIBS)" + @echo "DL = $(DL)" + +$(ALL_O): makefile + +# DO NOT EDIT +# automatically made with 'gcc -MM l*.c' + +lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ + ltable.h lundump.h lvm.h +lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lgc.h lstring.h ltable.h lvm.h +lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h +ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ + ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ + lparser.h lstring.h ltable.h lundump.h lvm.h +ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \ + lgc.h lstate.h ltm.h lzio.h lmem.h +lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \ + lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \ + lstring.h ltable.h +lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h +loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \ + ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ + lvm.h +lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lfunc.h lstring.h lgc.h ltable.h +lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ + lstring.h ltable.h +lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h +lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h +ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ltests.o: ltests.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h lauxlib.h lcode.h llex.h lopcodes.h \ + lparser.h lctype.h ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h \ + lualib.h +ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h +lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ + lundump.h +lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ + ltable.h lvm.h +lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ + lobject.h ltm.h lzio.h + +# (end of Makefile) diff --git a/3rd/lua/tags b/3rd/lua/tags new file mode 100644 index 000000000..bd5778f83 --- /dev/null +++ b/3rd/lua/tags @@ -0,0 +1,2911 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.8 // +ABSLINEINFO ldebug.h /^#define ABSLINEINFO /;" d +AGEBITS lgc.h /^#define AGEBITS /;" d +ALLONES lbitlib.c /^#define ALLONES /;" d file: +ALL_A makefile /^ALL_A= $(CORE_T)$/;" m +ALL_O makefile /^ALL_O= $(CORE_O) $(LUA_O) $(LUAC_O) $(AUX_O) $(LIB_O)$/;" m +ALL_T makefile /^ALL_T= $(CORE_T) $(LUA_T) $(LUAC_T)$/;" m +ALPHABIT lctype.h /^#define ALPHABIT /;" d +AR makefile /^AR= ar rcu$/;" m +AUXMARK loadlib.c /^#define AUXMARK /;" d file: +AUX_O makefile /^AUX_O= lauxlib.o$/;" m +AbsLineInfo lobject.h /^typedef struct AbsLineInfo {$/;" s +AbsLineInfo lobject.h /^} AbsLineInfo;$/;" t typeref:struct:AbsLineInfo +Aux ltests.c /^struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; };$/;" s file: +BASIC_STACK_SIZE lstate.h /^#define BASIC_STACK_SIZE /;" d +BIT_ISCOLLECTABLE lobject.h /^#define BIT_ISCOLLECTABLE /;" d +BLACKBIT lgc.h /^#define BLACKBIT /;" d +BinOpr lcode.h /^typedef enum BinOpr {$/;" g +BinOpr lcode.h /^} BinOpr;$/;" t typeref:enum:BinOpr +BlockCnt lparser.c /^typedef struct BlockCnt {$/;" s file: +BlockCnt lparser.c /^} BlockCnt;$/;" t typeref:struct:BlockCnt file: +CAP_POSITION lstrlib.c /^#define CAP_POSITION /;" d file: +CAP_UNFINISHED lstrlib.c /^#define CAP_UNFINISHED /;" d file: +CC makefile /^CC= clang-3.8$/;" m +CClosure lobject.h /^typedef struct CClosure {$/;" s +CClosure lobject.h /^} CClosure;$/;" t typeref:struct:CClosure +CFLAGS makefile /^CFLAGS= -Wall -O2 $(MYCFLAGS)$/;" m +CIST_C lstate.h /^#define CIST_C /;" d +CIST_FIN lstate.h /^#define CIST_FIN /;" d +CIST_HOOKED lstate.h /^#define CIST_HOOKED /;" d +CIST_HOOKYIELD lstate.h /^#define CIST_HOOKYIELD /;" d +CIST_LEQ lstate.h /^#define CIST_LEQ /;" d +CIST_OAH lstate.h /^#define CIST_OAH /;" d +CIST_TAIL lstate.h /^#define CIST_TAIL /;" d +CIST_YPCALL lstate.h /^#define CIST_YPCALL /;" d +CLIBS loadlib.c /^static const int CLIBS = 0;$/;" v file: +CORE_O makefile /^CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \\$/;" m +CORE_T makefile /^CORE_T= liblua.a$/;" m +CREATE_ABCk lopcodes.h /^#define CREATE_ABCk(/;" d +CREATE_ABx lopcodes.h /^#define CREATE_ABx(/;" d +CREATE_Ax lopcodes.h /^#define CREATE_Ax(/;" d +CREATE_sJ lopcodes.h /^#define CREATE_sJ(/;" d +CWARNS makefile /^CWARNS= $(CWARNSCPP) $(CWARNSC)$/;" m +CWARNSC makefile /^CWARNSC= -Wdeclaration-after-statement \\$/;" m +CWARNSCPP makefile /^CWARNSCPP= \\$/;" m +CallInfo lstate.h /^typedef struct CallInfo {$/;" s +CallInfo lstate.h /^} CallInfo;$/;" t typeref:struct:CallInfo +CallS lapi.c /^struct CallS { \/* data to 'f_call' *\/$/;" s file: +Cfunc ltests.c /^static int Cfunc (lua_State *L) {$/;" f file: +Cfunck ltests.c /^static int Cfunck (lua_State *L, int status, lua_KContext ctx) {$/;" f file: +Chook ltests.c /^static void Chook (lua_State *L, lua_Debug *ar) {$/;" f file: +Closure lobject.h /^typedef union Closure {$/;" u +Closure lobject.h /^} Closure;$/;" t typeref:union:Closure +ClosureHeader lobject.h /^ ClosureHeader;$/;" m struct:CClosure +ClosureHeader lobject.h /^ ClosureHeader;$/;" m struct:LClosure +ClosureHeader lobject.h /^#define ClosureHeader /;" d +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:GCObject +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:Proto +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:TString +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:Table +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:Udata +CommonHeader lobject.h /^ CommonHeader;$/;" m struct:UpVal +CommonHeader lobject.h /^#define CommonHeader /;" d +CommonHeader lstate.h /^ CommonHeader;$/;" m struct:lua_State +ConsControl lparser.c /^struct ConsControl {$/;" s file: +DIBS ldump.c /^#define DIBS /;" d file: +DIGITBIT lctype.h /^#define DIGITBIT /;" d +DLMSG loadlib.c /^#define DLMSG /;" d file: +DumpBlock ldump.c /^static void DumpBlock (const void *b, size_t size, DumpState *D) {$/;" f file: +DumpByte ldump.c /^static void DumpByte (int y, DumpState *D) {$/;" f file: +DumpCode ldump.c /^static void DumpCode (const Proto *f, DumpState *D) {$/;" f file: +DumpConstants ldump.c /^static void DumpConstants (const Proto *f, DumpState *D) {$/;" f file: +DumpDebug ldump.c /^static void DumpDebug (const Proto *f, DumpState *D) {$/;" f file: +DumpFunction ldump.c /^static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {$/;" f file: +DumpHeader ldump.c /^static void DumpHeader (DumpState *D) {$/;" f file: +DumpInt ldump.c /^static void DumpInt (int x, DumpState *D) {$/;" f file: +DumpInteger ldump.c /^static void DumpInteger (lua_Integer x, DumpState *D) {$/;" f file: +DumpLiteral ldump.c /^#define DumpLiteral(/;" d file: +DumpNumber ldump.c /^static void DumpNumber (lua_Number x, DumpState *D) {$/;" f file: +DumpProtos ldump.c /^static void DumpProtos (const Proto *f, DumpState *D) {$/;" f file: +DumpSize ldump.c /^static void DumpSize (size_t x, DumpState *D) {$/;" f file: +DumpState ldump.c /^} DumpState;$/;" t typeref:struct:__anon2 file: +DumpString ldump.c /^static void DumpString (const TString *s, DumpState *D) {$/;" f file: +DumpUpvalues ldump.c /^static void DumpUpvalues (const Proto *f, DumpState *D) {$/;" f file: +DumpVar ldump.c /^#define DumpVar(/;" d file: +DumpVector ldump.c /^#define DumpVector(/;" d file: +Dyndata lparser.h /^typedef struct Dyndata {$/;" s +Dyndata lparser.h /^} Dyndata;$/;" t typeref:struct:Dyndata +EOFMARK lua.c /^#define EOFMARK /;" d file: +EOZ lzio.h /^#define EOZ /;" d +EQ ltests.c /^#define EQ(/;" d file: +ERRFUNC loadlib.c /^#define ERRFUNC /;" d file: +ERRLIB loadlib.c /^#define ERRLIB /;" d file: +ERRORSTACKSIZE ldo.c /^#define ERRORSTACKSIZE /;" d file: +EXTRA_STACK lstate.h /^#define EXTRA_STACK /;" d +FINALIZEDBIT lgc.h /^#define FINALIZEDBIT /;" d +FIRST_RESERVED llex.h /^#define FIRST_RESERVED /;" d +FLAGS lstrlib.c /^#define FLAGS /;" d file: +Ftypes lstrlib.c /^typedef union Ftypes {$/;" u file: +Ftypes lstrlib.c /^} Ftypes;$/;" t typeref:union:Ftypes file: +FuncState lparser.h /^typedef struct FuncState {$/;" s +FuncState lparser.h /^} FuncState;$/;" t typeref:struct:FuncState +G lstate.h /^#define G(/;" d +GCFINALIZECOST lgc.c /^#define GCFINALIZECOST /;" d file: +GCFINMAX lgc.c /^#define GCFINMAX /;" d file: +GCObject lobject.h /^struct GCObject {$/;" s +GCObject lobject.h /^typedef struct GCObject GCObject;$/;" t typeref:struct:GCObject +GCSWEEPMAX lgc.c /^#define GCSWEEPMAX /;" d file: +GCSatomic lgc.h /^#define GCSatomic /;" d +GCScallfin lgc.h /^#define GCScallfin /;" d +GCSenteratomic lgc.h /^#define GCSenteratomic /;" d +GCSpause lgc.h /^#define GCSpause /;" d +GCSpropagate lgc.h /^#define GCSpropagate /;" d +GCSswpallgc lgc.h /^#define GCSswpallgc /;" d +GCSswpend lgc.h /^#define GCSswpend /;" d +GCSswpfinobj lgc.h /^#define GCSswpfinobj /;" d +GCSswptobefnz lgc.h /^#define GCSswptobefnz /;" d +GCTM lgc.c /^static void GCTM (lua_State *L, int propagateerrors) {$/;" f file: +GCUnion lstate.h /^union GCUnion {$/;" u +GCdebt lstate.h /^ l_mem GCdebt; \/* bytes allocated not yet compensated by the collector *\/$/;" m struct:global_State +GCestimate lstate.h /^ lu_mem GCestimate; \/* an estimate of the non-garbage memory in use *\/$/;" m struct:global_State +GETARG_A lopcodes.h /^#define GETARG_A(/;" d +GETARG_Ax lopcodes.h /^#define GETARG_Ax(/;" d +GETARG_B lopcodes.h /^#define GETARG_B(/;" d +GETARG_Bx lopcodes.h /^#define GETARG_Bx(/;" d +GETARG_C lopcodes.h /^#define GETARG_C(/;" d +GETARG_k lopcodes.h /^#define GETARG_k(/;" d +GETARG_sB lopcodes.h /^#define GETARG_sB(/;" d +GETARG_sBx lopcodes.h /^#define GETARG_sBx(/;" d +GETARG_sC lopcodes.h /^#define GETARG_sC(/;" d +GETARG_sJ lopcodes.h /^#define GETARG_sJ(/;" d +GET_OPCODE lopcodes.h /^#define GET_OPCODE(/;" d +GMatchState lstrlib.c /^typedef struct GMatchState {$/;" s file: +GMatchState lstrlib.c /^} GMatchState;$/;" t typeref:struct:GMatchState file: +G_NEW lgc.h /^#define G_NEW /;" d +G_OLD lgc.h /^#define G_OLD /;" d +G_OLD0 lgc.h /^#define G_OLD0 /;" d +G_OLD1 lgc.h /^#define G_OLD1 /;" d +G_SURVIVAL lgc.h /^#define G_SURVIVAL /;" d +G_TOUCHED1 lgc.h /^#define G_TOUCHED1 /;" d +G_TOUCHED2 lgc.h /^#define G_TOUCHED2 /;" d +HOOKKEY ldblib.c /^static const int HOOKKEY = 0;$/;" v file: +Header lstrlib.c /^typedef struct Header {$/;" s file: +Header lstrlib.c /^} Header;$/;" t typeref:struct:Header file: +Header ltests.c /^typedef union Header {$/;" u file: +Header ltests.c /^} Header;$/;" t typeref:union:Header file: +IOPREF_LEN liolib.c /^#define IOPREF_LEN /;" d file: +IO_INPUT liolib.c /^#define IO_INPUT /;" d file: +IO_OUTPUT liolib.c /^#define IO_OUTPUT /;" d file: +IO_PREFIX liolib.c /^#define IO_PREFIX /;" d file: +IdxT ltablib.c /^typedef unsigned int IdxT;$/;" t file: +Instruction llimits.h /^typedef unsigned int Instruction;$/;" t +Instruction llimits.h /^typedef unsigned long Instruction;$/;" t +KB lvm.c /^#define KB(/;" d file: +KC lvm.c /^#define KC(/;" d file: +KGC_GEN lstate.h /^#define KGC_GEN /;" d +KGC_INC lstate.h /^#define KGC_INC /;" d +KOption lstrlib.c /^typedef enum KOption {$/;" g file: +KOption lstrlib.c /^} KOption;$/;" t typeref:enum:KOption file: +Kchar lstrlib.c /^ Kchar, \/* fixed-length strings *\/$/;" e enum:KOption file: +Kfloat lstrlib.c /^ Kfloat, \/* floating-point numbers *\/$/;" e enum:KOption file: +Kint lstrlib.c /^ Kint, \/* signed integers *\/$/;" e enum:KOption file: +Knop lstrlib.c /^ Knop \/* no-op (configuration or spaces) *\/$/;" e enum:KOption file: +Kpaddalign lstrlib.c /^ Kpaddalign, \/* padding for alignment *\/$/;" e enum:KOption file: +Kpadding lstrlib.c /^ Kpadding, \/* padding *\/$/;" e enum:KOption file: +Kstring lstrlib.c /^ Kstring, \/* strings with prefixed length *\/$/;" e enum:KOption file: +Kuint lstrlib.c /^ Kuint, \/* unsigned integers *\/$/;" e enum:KOption file: +Kzstr lstrlib.c /^ Kzstr, \/* zero-terminated strings *\/$/;" e enum:KOption file: +L lauxlib.h /^ lua_State *L;$/;" m struct:luaL_Buffer +L ldump.c /^ lua_State *L;$/;" m struct:__anon2 file: +L llex.h /^ struct lua_State *L;$/;" m struct:LexState typeref:struct:LexState::lua_State +L lstrlib.c /^ lua_State *L;$/;" m struct:Header file: +L lstrlib.c /^ lua_State *L;$/;" m struct:MatchState file: +L ltests.c /^struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; };$/;" m struct:Aux file: +L lundump.c /^ lua_State *L;$/;" m struct:__anon23 file: +L lzio.h /^ lua_State *L; \/* Lua state (for reader) *\/$/;" m struct:Zio +LClosure lobject.h /^typedef struct LClosure {$/;" s +LClosure lobject.h /^} LClosure;$/;" t typeref:struct:LClosure +LEVELS1 lauxlib.c /^#define LEVELS1 /;" d file: +LEVELS2 lauxlib.c /^#define LEVELS2 /;" d file: +LEintfloat lvm.c /^static int LEintfloat (lua_Integer i, lua_Number f) {$/;" f file: +LEnum lvm.c /^static int LEnum (const TValue *l, const TValue *r) {$/;" f file: +LFIELDS_PER_FLUSH lopcodes.h /^#define LFIELDS_PER_FLUSH /;" d +LG lstate.c /^typedef struct LG {$/;" s file: +LG lstate.c /^} LG;$/;" t typeref:struct:LG file: +LHS_assign lparser.c /^struct LHS_assign {$/;" s file: +LIBS makefile /^LIBS = -lm$/;" m +LIB_FAIL loadlib.c /^#define LIB_FAIL /;" d file: +LIB_FAIL loadlib.c /^#undef LIB_FAIL$/;" d file: +LIB_O makefile /^LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \\$/;" m +LL lobject.c /^#define LL(/;" d file: +LOCAL makefile /^LOCAL = $(TESTS) $(CWARNS) -g$/;" m +LStream liolib.c /^typedef luaL_Stream LStream;$/;" t file: +LTintfloat lvm.c /^static int LTintfloat (lua_Integer i, lua_Number f) {$/;" f file: +LTnum lvm.c /^static int LTnum (const TValue *l, const TValue *r) {$/;" f file: +LUAC_DATA lundump.h /^#define LUAC_DATA /;" d +LUAC_FORMAT lundump.h /^#define LUAC_FORMAT /;" d +LUAC_INT lundump.h /^#define LUAC_INT /;" d +LUAC_NUM lundump.h /^#define LUAC_NUM /;" d +LUAC_VERSION lundump.h /^#define LUAC_VERSION /;" d +LUAI_BITSINT luaconf.h /^#define LUAI_BITSINT /;" d +LUAI_DDEC luaconf.h /^#define LUAI_DDEC /;" d +LUAI_DDEF luaconf.h /^#define LUAI_DDEF /;" d +LUAI_FUNC luaconf.h /^#define LUAI_FUNC /;" d +LUAI_GCMUL lgc.h /^#define LUAI_GCMUL /;" d +LUAI_GCPAUSE lgc.h /^#define LUAI_GCPAUSE /;" d +LUAI_GCSTEPSIZE lgc.h /^#define LUAI_GCSTEPSIZE /;" d +LUAI_GENMAJORMUL lgc.h /^#define LUAI_GENMAJORMUL /;" d +LUAI_GENMINORMUL lgc.h /^#define LUAI_GENMINORMUL /;" d +LUAI_HASHLIMIT lstring.c /^#define LUAI_HASHLIMIT /;" d file: +LUAI_MAXALIGN lauxlib.h /^ LUAI_MAXALIGN; \/* ensure maximum alignment for buffer *\/$/;" m union:luaL_Buffer::__anon1 +LUAI_MAXALIGN lobject.h /^ LUAI_MAXALIGN; \/* ensures maximum alignment for 'local' udata *\/$/;" m union:UUdata +LUAI_MAXALIGN lobject.h /^ LUAI_MAXALIGN; \/* ensures maximum alignment for strings *\/$/;" m union:UTString +LUAI_MAXALIGN ltests.c /^ LUAI_MAXALIGN;$/;" m union:Header file: +LUAI_MAXALIGN luaconf.h /^#define LUAI_MAXALIGN /;" d +LUAI_MAXCCALLS llimits.h /^#define LUAI_MAXCCALLS /;" d +LUAI_MAXCCALLS ltests.h /^#define LUAI_MAXCCALLS /;" d +LUAI_MAXCCALLS ltests.h /^#undef LUAI_MAXCCALLS$/;" d +LUAI_MAXSHORTLEN llimits.h /^#define LUAI_MAXSHORTLEN /;" d +LUAI_MAXSTACK ltests.h /^#define LUAI_MAXSTACK /;" d +LUAI_MAXSTACK ltests.h /^#undef LUAI_MAXSTACK$/;" d +LUAI_MAXSTACK luaconf.h /^#define LUAI_MAXSTACK /;" d +LUAI_THROW ldo.c /^#define LUAI_THROW(/;" d file: +LUAI_TRY ldo.c /^#define LUAI_TRY(/;" d file: +LUAI_UACINT luaconf.h /^#define LUAI_UACINT /;" d +LUAI_UACNUMBER luaconf.h /^#define LUAI_UACNUMBER /;" d +LUAI_USER_ALIGNMENT_T ltests.h /^#define LUAI_USER_ALIGNMENT_T /;" d +LUAI_USER_ALIGNMENT_T ltests.h /^#undef LUAI_USER_ALIGNMENT_T$/;" d +LUALIB_API luaconf.h /^#define LUALIB_API /;" d +LUAL_BUFFERSIZE ltests.h /^#define LUAL_BUFFERSIZE /;" d +LUAL_BUFFERSIZE ltests.h /^#undef LUAL_BUFFERSIZE$/;" d +LUAL_BUFFERSIZE luaconf.h /^#define LUAL_BUFFERSIZE /;" d +LUAL_BUFFERSIZE luaconf.h /^#define LUAL_BUFFERSIZE /;" d +LUAL_NUMSIZES lauxlib.h /^#define LUAL_NUMSIZES /;" d +LUAL_PACKPADBYTE lstrlib.c /^#define LUAL_PACKPADBYTE /;" d file: +LUAMOD_API luaconf.h /^#define LUAMOD_API /;" d +LUA_API luaconf.h /^#define LUA_API /;" d +LUA_API luaconf.h /^#define LUA_API /;" d +LUA_AUTHORS lua.h /^#define LUA_AUTHORS /;" d +LUA_BITLIBNAME lualib.h /^#define LUA_BITLIBNAME /;" d +LUA_C89_NUMBERS luaconf.h /^#define LUA_C89_NUMBERS$/;" d +LUA_CDIR luaconf.h /^#define LUA_CDIR /;" d +LUA_COLIBNAME lualib.h /^#define LUA_COLIBNAME /;" d +LUA_COMPAT_APIINTCASTS ltests.h /^#define LUA_COMPAT_APIINTCASTS$/;" d +LUA_COMPAT_APIINTCASTS luaconf.h /^#define LUA_COMPAT_APIINTCASTS$/;" d +LUA_COMPAT_BITLIB ltests.h /^#define LUA_COMPAT_BITLIB$/;" d +LUA_COMPAT_BITLIB luaconf.h /^#define LUA_COMPAT_BITLIB$/;" d +LUA_COMPAT_FLOATSTRING ltests.h /^#define LUA_COMPAT_FLOATSTRING$/;" d +LUA_COMPAT_IPAIRS ltests.h /^#define LUA_COMPAT_IPAIRS$/;" d +LUA_COMPAT_IPAIRS luaconf.h /^#define LUA_COMPAT_IPAIRS$/;" d +LUA_COMPAT_LOADERS ltests.h /^#define LUA_COMPAT_LOADERS$/;" d +LUA_COMPAT_LOADERS luaconf.h /^#define LUA_COMPAT_LOADERS$/;" d +LUA_COMPAT_LOADSTRING ltests.h /^#define LUA_COMPAT_LOADSTRING$/;" d +LUA_COMPAT_LOADSTRING luaconf.h /^#define LUA_COMPAT_LOADSTRING$/;" d +LUA_COMPAT_LOG10 ltests.h /^#define LUA_COMPAT_LOG10$/;" d +LUA_COMPAT_LOG10 luaconf.h /^#define LUA_COMPAT_LOG10$/;" d +LUA_COMPAT_MATHLIB ltests.h /^#define LUA_COMPAT_MATHLIB$/;" d +LUA_COMPAT_MATHLIB luaconf.h /^#define LUA_COMPAT_MATHLIB$/;" d +LUA_COMPAT_MAXN ltests.h /^#define LUA_COMPAT_MAXN$/;" d +LUA_COMPAT_MAXN luaconf.h /^#define LUA_COMPAT_MAXN$/;" d +LUA_COMPAT_MODULE ltests.h /^#define LUA_COMPAT_MODULE$/;" d +LUA_COMPAT_MODULE luaconf.h /^#define LUA_COMPAT_MODULE$/;" d +LUA_COMPAT_UNPACK ltests.h /^#define LUA_COMPAT_UNPACK$/;" d +LUA_COMPAT_UNPACK luaconf.h /^#define LUA_COMPAT_UNPACK$/;" d +LUA_COPYRIGHT lua.h /^#define LUA_COPYRIGHT /;" d +LUA_CORE lapi.c /^#define LUA_CORE$/;" d file: +LUA_CORE lcode.c /^#define LUA_CORE$/;" d file: +LUA_CORE lctype.c /^#define LUA_CORE$/;" d file: +LUA_CORE ldebug.c /^#define LUA_CORE$/;" d file: +LUA_CORE ldo.c /^#define LUA_CORE$/;" d file: +LUA_CORE ldump.c /^#define LUA_CORE$/;" d file: +LUA_CORE lfunc.c /^#define LUA_CORE$/;" d file: +LUA_CORE lgc.c /^#define LUA_CORE$/;" d file: +LUA_CORE llex.c /^#define LUA_CORE$/;" d file: +LUA_CORE lmem.c /^#define LUA_CORE$/;" d file: +LUA_CORE lobject.c /^#define LUA_CORE$/;" d file: +LUA_CORE lopcodes.c /^#define LUA_CORE$/;" d file: +LUA_CORE lparser.c /^#define LUA_CORE$/;" d file: +LUA_CORE lstate.c /^#define LUA_CORE$/;" d file: +LUA_CORE lstring.c /^#define LUA_CORE$/;" d file: +LUA_CORE ltable.c /^#define LUA_CORE$/;" d file: +LUA_CORE ltests.c /^#define LUA_CORE$/;" d file: +LUA_CORE ltm.c /^#define LUA_CORE$/;" d file: +LUA_CORE lundump.c /^#define LUA_CORE$/;" d file: +LUA_CORE lvm.c /^#define LUA_CORE$/;" d file: +LUA_CORE lzio.c /^#define LUA_CORE$/;" d file: +LUA_CPATH_DEFAULT luaconf.h /^#define LUA_CPATH_DEFAULT /;" d +LUA_CPATH_VAR loadlib.c /^#define LUA_CPATH_VAR /;" d file: +LUA_CSUBSEP loadlib.c /^#define LUA_CSUBSEP /;" d file: +LUA_DBLIBNAME lualib.h /^#define LUA_DBLIBNAME /;" d +LUA_DEBUG ltests.h /^#define LUA_DEBUG$/;" d +LUA_DIRSEP luaconf.h /^#define LUA_DIRSEP /;" d +LUA_DL_DLL luaconf.h /^#define LUA_DL_DLL /;" d +LUA_ENV llex.h /^#define LUA_ENV /;" d +LUA_ERRERR lua.h /^#define LUA_ERRERR /;" d +LUA_ERRFILE lauxlib.h /^#define LUA_ERRFILE /;" d +LUA_ERRGCMM lua.h /^#define LUA_ERRGCMM /;" d +LUA_ERRMEM lua.h /^#define LUA_ERRMEM /;" d +LUA_ERRRUN lua.h /^#define LUA_ERRRUN /;" d +LUA_ERRSYNTAX lua.h /^#define LUA_ERRSYNTAX /;" d +LUA_EXEC_DIR luaconf.h /^#define LUA_EXEC_DIR /;" d +LUA_EXTRASPACE ltests.h /^#define LUA_EXTRASPACE /;" d +LUA_EXTRASPACE ltests.h /^#undef LUA_EXTRASPACE$/;" d +LUA_EXTRASPACE luaconf.h /^#define LUA_EXTRASPACE /;" d +LUA_FILEHANDLE lauxlib.h /^#define LUA_FILEHANDLE /;" d +LUA_FLOAT_DOUBLE luaconf.h /^#define LUA_FLOAT_DOUBLE /;" d +LUA_FLOAT_FLOAT luaconf.h /^#define LUA_FLOAT_FLOAT /;" d +LUA_FLOAT_LONGDOUBLE luaconf.h /^#define LUA_FLOAT_LONGDOUBLE /;" d +LUA_FLOAT_TYPE luaconf.h /^#define LUA_FLOAT_TYPE /;" d +LUA_FLOORN2I lvm.h /^#define LUA_FLOORN2I /;" d +LUA_GCCOLLECT lua.h /^#define LUA_GCCOLLECT /;" d +LUA_GCCOUNT lua.h /^#define LUA_GCCOUNT /;" d +LUA_GCCOUNTB lua.h /^#define LUA_GCCOUNTB /;" d +LUA_GCGEN lua.h /^#define LUA_GCGEN /;" d +LUA_GCINC lua.h /^#define LUA_GCINC /;" d +LUA_GCISRUNNING lua.h /^#define LUA_GCISRUNNING /;" d +LUA_GCRESTART lua.h /^#define LUA_GCRESTART /;" d +LUA_GCSETPAUSE lua.h /^#define LUA_GCSETPAUSE /;" d +LUA_GCSETSTEPMUL lua.h /^#define LUA_GCSETSTEPMUL /;" d +LUA_GCSTEP lua.h /^#define LUA_GCSTEP /;" d +LUA_GCSTOP lua.h /^#define LUA_GCSTOP /;" d +LUA_GNAME lauxlib.h /^#define LUA_GNAME /;" d +LUA_HOOKCALL lua.h /^#define LUA_HOOKCALL /;" d +LUA_HOOKCOUNT lua.h /^#define LUA_HOOKCOUNT /;" d +LUA_HOOKLINE lua.h /^#define LUA_HOOKLINE /;" d +LUA_HOOKRET lua.h /^#define LUA_HOOKRET /;" d +LUA_HOOKTAILCALL lua.h /^#define LUA_HOOKTAILCALL /;" d +LUA_IDSIZE luaconf.h /^#define LUA_IDSIZE /;" d +LUA_IGMARK loadlib.c /^#define LUA_IGMARK /;" d file: +LUA_INITVARVERSION lua.c /^#define LUA_INITVARVERSION /;" d file: +LUA_INIT_VAR lua.c /^#define LUA_INIT_VAR /;" d file: +LUA_INTEGER luaconf.h /^#define LUA_INTEGER /;" d +LUA_INTEGER_FMT luaconf.h /^#define LUA_INTEGER_FMT /;" d +LUA_INTEGER_FRMLEN luaconf.h /^#define LUA_INTEGER_FRMLEN /;" d +LUA_INT_INT luaconf.h /^#define LUA_INT_INT /;" d +LUA_INT_LONG luaconf.h /^#define LUA_INT_LONG /;" d +LUA_INT_LONGLONG luaconf.h /^#define LUA_INT_LONGLONG /;" d +LUA_INT_TYPE luaconf.h /^#define LUA_INT_TYPE /;" d +LUA_IOLIBNAME lualib.h /^#define LUA_IOLIBNAME /;" d +LUA_KCONTEXT luaconf.h /^#define LUA_KCONTEXT /;" d +LUA_KCONTEXT luaconf.h /^#undef LUA_KCONTEXT$/;" d +LUA_LDIR luaconf.h /^#define LUA_LDIR /;" d +LUA_LIB lauxlib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lbaselib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lbitlib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lcorolib.c /^#define LUA_LIB$/;" d file: +LUA_LIB ldblib.c /^#define LUA_LIB$/;" d file: +LUA_LIB linit.c /^#define LUA_LIB$/;" d file: +LUA_LIB liolib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lmathlib.c /^#define LUA_LIB$/;" d file: +LUA_LIB loadlib.c /^#define LUA_LIB$/;" d file: +LUA_LIB loslib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lstrlib.c /^#define LUA_LIB$/;" d file: +LUA_LIB ltablib.c /^#define LUA_LIB$/;" d file: +LUA_LIB lutf8lib.c /^#define LUA_LIB$/;" d file: +LUA_LLE_FLAGS loadlib.c /^#define LUA_LLE_FLAGS /;" d file: +LUA_LOADED_TABLE lauxlib.h /^#define LUA_LOADED_TABLE /;" d +LUA_LOADLIBNAME lualib.h /^#define LUA_LOADLIBNAME /;" d +LUA_LSUBSEP loadlib.c /^#define LUA_LSUBSEP /;" d file: +LUA_MASKCALL lua.h /^#define LUA_MASKCALL /;" d +LUA_MASKCOUNT lua.h /^#define LUA_MASKCOUNT /;" d +LUA_MASKLINE lua.h /^#define LUA_MASKLINE /;" d +LUA_MASKRET lua.h /^#define LUA_MASKRET /;" d +LUA_MATHLIBNAME lualib.h /^#define LUA_MATHLIBNAME /;" d +LUA_MAXCAPTURES lstrlib.c /^#define LUA_MAXCAPTURES /;" d file: +LUA_MAXINPUT lua.c /^#define LUA_MAXINPUT /;" d file: +LUA_MAXINTEGER luaconf.h /^#define LUA_MAXINTEGER /;" d +LUA_MINBUFFER llimits.h /^#define LUA_MINBUFFER /;" d +LUA_MININTEGER luaconf.h /^#define LUA_MININTEGER /;" d +LUA_MINSTACK lua.h /^#define LUA_MINSTACK /;" d +LUA_MULTRET lua.h /^#define LUA_MULTRET /;" d +LUA_NBITS lbitlib.c /^#define LUA_NBITS /;" d file: +LUA_NOREF lauxlib.h /^#define LUA_NOREF /;" d +LUA_NUMBER luaconf.h /^#define LUA_NUMBER /;" d +LUA_NUMBER_FMT luaconf.h /^#define LUA_NUMBER_FMT /;" d +LUA_NUMBER_FRMLEN luaconf.h /^#define LUA_NUMBER_FRMLEN /;" d +LUA_NUMTAGS lua.h /^#define LUA_NUMTAGS /;" d +LUA_O makefile /^LUA_O= lua.o$/;" m +LUA_OFSEP loadlib.c /^#define LUA_OFSEP /;" d file: +LUA_OK lua.h /^#define LUA_OK /;" d +LUA_OPADD lua.h /^#define LUA_OPADD /;" d +LUA_OPBAND lua.h /^#define LUA_OPBAND /;" d +LUA_OPBNOT lua.h /^#define LUA_OPBNOT /;" d +LUA_OPBOR lua.h /^#define LUA_OPBOR /;" d +LUA_OPBXOR lua.h /^#define LUA_OPBXOR /;" d +LUA_OPDIV lua.h /^#define LUA_OPDIV /;" d +LUA_OPEQ lua.h /^#define LUA_OPEQ /;" d +LUA_OPIDIV lua.h /^#define LUA_OPIDIV /;" d +LUA_OPLE lua.h /^#define LUA_OPLE /;" d +LUA_OPLT lua.h /^#define LUA_OPLT /;" d +LUA_OPMOD lua.h /^#define LUA_OPMOD /;" d +LUA_OPMUL lua.h /^#define LUA_OPMUL /;" d +LUA_OPPOW lua.h /^#define LUA_OPPOW /;" d +LUA_OPSHL lua.h /^#define LUA_OPSHL /;" d +LUA_OPSHR lua.h /^#define LUA_OPSHR /;" d +LUA_OPSUB lua.h /^#define LUA_OPSUB /;" d +LUA_OPUNM lua.h /^#define LUA_OPUNM /;" d +LUA_OSLIBNAME lualib.h /^#define LUA_OSLIBNAME /;" d +LUA_PATH_DEFAULT luaconf.h /^#define LUA_PATH_DEFAULT /;" d +LUA_PATH_MARK luaconf.h /^#define LUA_PATH_MARK /;" d +LUA_PATH_SEP luaconf.h /^#define LUA_PATH_SEP /;" d +LUA_PATH_VAR loadlib.c /^#define LUA_PATH_VAR /;" d file: +LUA_POF loadlib.c /^#define LUA_POF /;" d file: +LUA_PRELOAD_TABLE lauxlib.h /^#define LUA_PRELOAD_TABLE /;" d +LUA_PROGNAME lua.c /^#define LUA_PROGNAME /;" d file: +LUA_PROMPT lua.c /^#define LUA_PROMPT /;" d file: +LUA_PROMPT2 lua.c /^#define LUA_PROMPT2 /;" d file: +LUA_QL luaconf.h /^#define LUA_QL(/;" d +LUA_QS luaconf.h /^#define LUA_QS /;" d +LUA_REFNIL lauxlib.h /^#define LUA_REFNIL /;" d +LUA_REGISTRYINDEX lua.h /^#define LUA_REGISTRYINDEX /;" d +LUA_RELEASE lua.h /^#define LUA_RELEASE /;" d +LUA_RIDX_GLOBALS lua.h /^#define LUA_RIDX_GLOBALS /;" d +LUA_RIDX_LAST lua.h /^#define LUA_RIDX_LAST /;" d +LUA_RIDX_MAINTHREAD lua.h /^#define LUA_RIDX_MAINTHREAD /;" d +LUA_ROOT luaconf.h /^#define LUA_ROOT /;" d +LUA_SHRDIR luaconf.h /^#define LUA_SHRDIR /;" d +LUA_SIGNATURE lua.h /^#define LUA_SIGNATURE /;" d +LUA_STRFTIMEOPTIONS loslib.c /^#define LUA_STRFTIMEOPTIONS /;" d file: +LUA_STRLIBNAME lualib.h /^#define LUA_STRLIBNAME /;" d +LUA_T makefile /^LUA_T= lua$/;" m +LUA_TABLIBNAME lualib.h /^#define LUA_TABLIBNAME /;" d +LUA_TBOOLEAN lua.h /^#define LUA_TBOOLEAN /;" d +LUA_TCCL lobject.h /^#define LUA_TCCL /;" d +LUA_TFUNCTION lua.h /^#define LUA_TFUNCTION /;" d +LUA_TLCF lobject.h /^#define LUA_TLCF /;" d +LUA_TLCL lobject.h /^#define LUA_TLCL /;" d +LUA_TLIGHTUSERDATA lua.h /^#define LUA_TLIGHTUSERDATA /;" d +LUA_TLNGSTR lobject.h /^#define LUA_TLNGSTR /;" d +LUA_TMPNAMBUFSIZE loslib.c /^#define LUA_TMPNAMBUFSIZE /;" d file: +LUA_TMPNAMTEMPLATE loslib.c /^#define LUA_TMPNAMTEMPLATE /;" d file: +LUA_TNIL lua.h /^#define LUA_TNIL /;" d +LUA_TNONE lua.h /^#define LUA_TNONE /;" d +LUA_TNUMBER lua.h /^#define LUA_TNUMBER /;" d +LUA_TNUMFLT lobject.h /^#define LUA_TNUMFLT /;" d +LUA_TNUMINT lobject.h /^#define LUA_TNUMINT /;" d +LUA_TOTALTAGS lobject.h /^#define LUA_TOTALTAGS /;" d +LUA_TPROTO lobject.h /^#define LUA_TPROTO /;" d +LUA_TSHRSTR lobject.h /^#define LUA_TSHRSTR /;" d +LUA_TSTRING lua.h /^#define LUA_TSTRING /;" d +LUA_TTABLE lua.h /^#define LUA_TTABLE /;" d +LUA_TTHREAD lua.h /^#define LUA_TTHREAD /;" d +LUA_TUPVAL lobject.h /^#define LUA_TUPVAL /;" d +LUA_TUSERDATA lua.h /^#define LUA_TUSERDATA /;" d +LUA_UNSIGNED luaconf.h /^#define LUA_UNSIGNED /;" d +LUA_USE_C89 luaconf.h /^#define LUA_USE_C89 /;" d +LUA_USE_CTYPE lctype.h /^#define LUA_USE_CTYPE /;" d +LUA_USE_DLOPEN luaconf.h /^#define LUA_USE_DLOPEN /;" d +LUA_USE_POSIX luaconf.h /^#define LUA_USE_POSIX$/;" d +LUA_USE_READLINE luaconf.h /^#define LUA_USE_READLINE /;" d +LUA_USE_WINDOWS luaconf.h /^#define LUA_USE_WINDOWS /;" d +LUA_UTF8LIBNAME lualib.h /^#define LUA_UTF8LIBNAME /;" d +LUA_VDIR luaconf.h /^#define LUA_VDIR /;" d +LUA_VERSION lua.h /^#define LUA_VERSION /;" d +LUA_VERSION_MAJOR lua.h /^#define LUA_VERSION_MAJOR /;" d +LUA_VERSION_MINOR lua.h /^#define LUA_VERSION_MINOR /;" d +LUA_VERSION_NUM lua.h /^#define LUA_VERSION_NUM /;" d +LUA_VERSION_RELEASE lua.h /^#define LUA_VERSION_RELEASE /;" d +LUA_VERSUFFIX lualib.h /^#define LUA_VERSUFFIX /;" d +LUA_YIELD lua.h /^#define LUA_YIELD /;" d +LX lstate.c /^typedef struct LX {$/;" s file: +LX lstate.c /^} LX;$/;" t typeref:struct:LX file: +L_ESC lstrlib.c /^#define L_ESC /;" d file: +L_EXTRA ltests.h /^struct L_EXTRA { int lock; int *plock; };$/;" s +L_MAXDATEFIELD loslib.c /^#define L_MAXDATEFIELD /;" d file: +L_MAXLENNUM liolib.c /^#define L_MAXLENNUM /;" d file: +L_MAXLENNUM lobject.c /^#define L_MAXLENNUM /;" d file: +L_MODEEXT liolib.c /^#define L_MODEEXT /;" d file: +L_NBFD lstrlib.c /^#define L_NBFD /;" d file: +L_RANDMAX lmathlib.c /^#define L_RANDMAX /;" d file: +L_STRFTIMEC89 loslib.c /^#define L_STRFTIMEC89 /;" d file: +L_STRFTIMEC99 loslib.c /^#define L_STRFTIMEC99 /;" d file: +L_STRFTIMEWIN loslib.c /^#define L_STRFTIMEWIN /;" d file: +Labeldesc lparser.h /^typedef struct Labeldesc {$/;" s +Labeldesc lparser.h /^} Labeldesc;$/;" t typeref:struct:Labeldesc +Labellist lparser.h /^typedef struct Labellist {$/;" s +Labellist lparser.h /^} Labellist;$/;" t typeref:struct:Labellist +LexState llex.h /^typedef struct LexState {$/;" s +LexState llex.h /^} LexState;$/;" t typeref:struct:LexState +LoadBlock lundump.c /^static void LoadBlock (LoadState *S, void *b, size_t size) {$/;" f file: +LoadByte lundump.c /^static lu_byte LoadByte (LoadState *S) {$/;" f file: +LoadCode lundump.c /^static void LoadCode (LoadState *S, Proto *f) {$/;" f file: +LoadConstants lundump.c /^static void LoadConstants (LoadState *S, Proto *f) {$/;" f file: +LoadDebug lundump.c /^static void LoadDebug (LoadState *S, Proto *f) {$/;" f file: +LoadF lauxlib.c /^typedef struct LoadF {$/;" s file: +LoadF lauxlib.c /^} LoadF;$/;" t typeref:struct:LoadF file: +LoadFunction lundump.c /^static void LoadFunction (LoadState *S, Proto *f, TString *psource) {$/;" f file: +LoadInt lundump.c /^static int LoadInt (LoadState *S) {$/;" f file: +LoadInteger lundump.c /^static lua_Integer LoadInteger (LoadState *S) {$/;" f file: +LoadNumber lundump.c /^static lua_Number LoadNumber (LoadState *S) {$/;" f file: +LoadProtos lundump.c /^static void LoadProtos (LoadState *S, Proto *f) {$/;" f file: +LoadS lauxlib.c /^typedef struct LoadS {$/;" s file: +LoadS lauxlib.c /^} LoadS;$/;" t typeref:struct:LoadS file: +LoadSize lundump.c /^static size_t LoadSize (LoadState *S) {$/;" f file: +LoadState lundump.c /^} LoadState;$/;" t typeref:struct:__anon23 file: +LoadString lundump.c /^static TString *LoadString (LoadState *S) {$/;" f file: +LoadUpvalues lundump.c /^static void LoadUpvalues (LoadState *S, Proto *f) {$/;" f file: +LoadVar lundump.c /^#define LoadVar(/;" d file: +LoadVector lundump.c /^#define LoadVector(/;" d file: +LocVar lobject.h /^typedef struct LocVar {$/;" s +LocVar lobject.h /^} LocVar;$/;" t typeref:struct:LocVar +MARK ltests.c /^#define MARK /;" d file: +MARKSIZE ltests.c /^#define MARKSIZE /;" d file: +MASK lctype.h /^#define MASK(/;" d +MASK0 lopcodes.h /^#define MASK0(/;" d +MASK1 lopcodes.h /^#define MASK1(/;" d +MAXABITS ltable.c /^#define MAXABITS /;" d file: +MAXALIGN lstrlib.c /^#define MAXALIGN /;" d file: +MAXARGLINE liolib.c /^#define MAXARGLINE /;" d file: +MAXARG_A lopcodes.h /^#define MAXARG_A /;" d +MAXARG_Ax lopcodes.h /^#define MAXARG_Ax /;" d +MAXARG_B lopcodes.h /^#define MAXARG_B /;" d +MAXARG_Bx lopcodes.h /^#define MAXARG_Bx /;" d +MAXARG_C lopcodes.h /^#define MAXARG_C /;" d +MAXARG_Cx lopcodes.h /^#define MAXARG_Cx /;" d +MAXARG_sJ lopcodes.h /^#define MAXARG_sJ /;" d +MAXASIZE ltable.c /^#define MAXASIZE /;" d file: +MAXBY10 lobject.c /^#define MAXBY10 /;" d file: +MAXCCALLS lstrlib.c /^#define MAXCCALLS /;" d file: +MAXHBITS ltable.c /^#define MAXHBITS /;" d file: +MAXHSIZE ltable.c /^#define MAXHSIZE /;" d file: +MAXINDEXRK lopcodes.h /^#define MAXINDEXRK /;" d +MAXINDEXRK ltests.h /^#define MAXINDEXRK /;" d +MAXINTSIZE lstrlib.c /^#define MAXINTSIZE /;" d file: +MAXIWTHABS lcode.c /^#define MAXIWTHABS /;" d file: +MAXIWTHABS ltests.h /^#define MAXIWTHABS /;" d +MAXLASTD lobject.c /^#define MAXLASTD /;" d file: +MAXMISS lfunc.h /^#define MAXMISS /;" d +MAXNUMBER2STR lobject.c /^#define MAXNUMBER2STR /;" d file: +MAXREGS lcode.c /^#define MAXREGS /;" d file: +MAXSIGDIG lobject.c /^#define MAXSIGDIG /;" d file: +MAXSIZE lstrlib.c /^#define MAXSIZE /;" d file: +MAXSTRTB lstring.c /^#define MAXSTRTB /;" d file: +MAXTAGLOOP lvm.c /^#define MAXTAGLOOP /;" d file: +MAXUNICODE lutf8lib.c /^#define MAXUNICODE /;" d file: +MAXUPVAL lfunc.h /^#define MAXUPVAL /;" d +MAXVARS lparser.c /^#define MAXVARS /;" d file: +MAX_FORMAT lstrlib.c /^#define MAX_FORMAT /;" d file: +MAX_INT llimits.h /^#define MAX_INT /;" d +MAX_ITEM lstrlib.c /^#define MAX_ITEM /;" d file: +MAX_LMEM llimits.h /^#define MAX_LMEM /;" d +MAX_LUMEM llimits.h /^#define MAX_LUMEM /;" d +MAX_SIZE llimits.h /^#define MAX_SIZE /;" d +MAX_SIZET llimits.h /^#define MAX_SIZET /;" d +MAX_SIZET lstrlib.c /^#define MAX_SIZET /;" d file: +MC lstrlib.c /^#define MC /;" d file: +MEMERRMSG lstring.h /^#define MEMERRMSG /;" d +MINSIZEARRAY lmem.c /^#define MINSIZEARRAY /;" d file: +MINSTRTABSIZE llimits.h /^#define MINSTRTABSIZE /;" d +MINSTRTABSIZE ltests.h /^#define MINSTRTABSIZE /;" d +MYCFLAGS makefile /^MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_COMPAT_5_2$/;" m +MYINT lundump.h /^#define MYINT(/;" d +MYLDFLAGS makefile /^MYLDFLAGS= $(LOCAL) -Wl,-E$/;" m +MYLIBS makefile /^MYLIBS= -ldl -lreadline$/;" m +MatchState lstrlib.c /^typedef struct MatchState {$/;" s file: +MatchState lstrlib.c /^} MatchState;$/;" t typeref:struct:MatchState file: +Mbuffer lzio.h /^typedef struct Mbuffer {$/;" s +Mbuffer lzio.h /^} Mbuffer;$/;" t typeref:struct:Mbuffer +Memcontrol ltests.h /^typedef struct Memcontrol {$/;" s +Memcontrol ltests.h /^} Memcontrol;$/;" t typeref:struct:Memcontrol +NB lstrlib.c /^#define NB /;" d file: +NBITS lvm.c /^#define NBITS /;" d file: +NBM lvm.c /^#define NBM /;" d file: +NDEBUG ltests.h /^#undef NDEBUG$/;" d +NILCONSTANT lobject.h /^#define NILCONSTANT /;" d +NONVALIDVALUE lapi.c /^#define NONVALIDVALUE /;" d file: +NO_JUMP lcode.h /^#define NO_JUMP /;" d +NO_REG lopcodes.h /^#define NO_REG /;" d +NUM_OPCODES lopcodes.h /^#define NUM_OPCODES /;" d +NUM_RESERVED llex.h /^#define NUM_RESERVED /;" d +Node lobject.h /^typedef union Node {$/;" u +Node lobject.h /^} Node;$/;" t typeref:union:Node +NodeKey lobject.h /^ struct NodeKey {$/;" s union:Node +OFFSET_sBx lopcodes.h /^#define OFFSET_sBx /;" d +OFFSET_sC lopcodes.h /^#define OFFSET_sC /;" d +OFFSET_sJ lopcodes.h /^#define OFFSET_sJ /;" d +OPR_ADD lcode.h /^ OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,$/;" e enum:BinOpr +OPR_AND lcode.h /^ OPR_AND, OPR_OR,$/;" e enum:BinOpr +OPR_BAND lcode.h /^ OPR_BAND, OPR_BOR, OPR_BXOR,$/;" e enum:BinOpr +OPR_BNOT lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" e enum:UnOpr +OPR_BOR lcode.h /^ OPR_BAND, OPR_BOR, OPR_BXOR,$/;" e enum:BinOpr +OPR_BXOR lcode.h /^ OPR_BAND, OPR_BOR, OPR_BXOR,$/;" e enum:BinOpr +OPR_CONCAT lcode.h /^ OPR_CONCAT,$/;" e enum:BinOpr +OPR_DIV lcode.h /^ OPR_DIV,$/;" e enum:BinOpr +OPR_EQ lcode.h /^ OPR_EQ, OPR_LT, OPR_LE,$/;" e enum:BinOpr +OPR_GE lcode.h /^ OPR_NE, OPR_GT, OPR_GE,$/;" e enum:BinOpr +OPR_GT lcode.h /^ OPR_NE, OPR_GT, OPR_GE,$/;" e enum:BinOpr +OPR_IDIV lcode.h /^ OPR_IDIV,$/;" e enum:BinOpr +OPR_LE lcode.h /^ OPR_EQ, OPR_LT, OPR_LE,$/;" e enum:BinOpr +OPR_LEN lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" e enum:UnOpr +OPR_LT lcode.h /^ OPR_EQ, OPR_LT, OPR_LE,$/;" e enum:BinOpr +OPR_MINUS lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" e enum:UnOpr +OPR_MOD lcode.h /^ OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,$/;" e enum:BinOpr +OPR_MUL lcode.h /^ OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,$/;" e enum:BinOpr +OPR_NE lcode.h /^ OPR_NE, OPR_GT, OPR_GE,$/;" e enum:BinOpr +OPR_NOBINOPR lcode.h /^ OPR_NOBINOPR$/;" e enum:BinOpr +OPR_NOT lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" e enum:UnOpr +OPR_NOUNOPR lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" e enum:UnOpr +OPR_OR lcode.h /^ OPR_AND, OPR_OR,$/;" e enum:BinOpr +OPR_POW lcode.h /^ OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,$/;" e enum:BinOpr +OPR_SHL lcode.h /^ OPR_SHL, OPR_SHR,$/;" e enum:BinOpr +OPR_SHR lcode.h /^ OPR_SHL, OPR_SHR,$/;" e enum:BinOpr +OPR_SUB lcode.h /^ OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,$/;" e enum:BinOpr +OP_ADD lopcodes.h /^OP_ADD,\/* A B C R(A) := R(B) + R(C) *\/$/;" e enum:__anon8 +OP_ADDI lopcodes.h /^OP_ADDI,\/* A B sC R(A) := R(B) + C *\/$/;" e enum:__anon8 +OP_BAND lopcodes.h /^OP_BAND,\/* A B C R(A) := R(B) & R(C) *\/$/;" e enum:__anon8 +OP_BANDK lopcodes.h /^OP_BANDK,\/* A B C R(A) := R(B) & K(C):integer *\/$/;" e enum:__anon8 +OP_BNOT lopcodes.h /^OP_BNOT,\/* A B R(A) := ~R(B) *\/$/;" e enum:__anon8 +OP_BOR lopcodes.h /^OP_BOR,\/* A B C R(A) := R(B) | R(C) *\/$/;" e enum:__anon8 +OP_BORK lopcodes.h /^OP_BORK,\/* A B C R(A) := R(B) | K(C):integer *\/$/;" e enum:__anon8 +OP_BXOR lopcodes.h /^OP_BXOR,\/* A B C R(A) := R(B) ~ R(C) *\/$/;" e enum:__anon8 +OP_BXORK lopcodes.h /^OP_BXORK,\/* A B C R(A) := R(B) ~ K(C):integer *\/$/;" e enum:__anon8 +OP_CALL lopcodes.h /^OP_CALL,\/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) *\/$/;" e enum:__anon8 +OP_CLOSE lopcodes.h /^OP_CLOSE,\/* A close all upvalues >= R(A) *\/$/;" e enum:__anon8 +OP_CLOSURE lopcodes.h /^OP_CLOSURE,\/* A Bx R(A) := closure(KPROTO[Bx]) *\/$/;" e enum:__anon8 +OP_CONCAT lopcodes.h /^OP_CONCAT,\/* A B C R(A) := R(B).. ... ..R(C) *\/$/;" e enum:__anon8 +OP_DIV lopcodes.h /^OP_DIV,\/* A B C R(A) := R(B) \/ R(C) *\/$/;" e enum:__anon8 +OP_DIVI lopcodes.h /^OP_DIVI,\/* A B sC R(A) := R(B) \/ C *\/$/;" e enum:__anon8 +OP_EQ lopcodes.h /^OP_EQ,\/* A B if ((R(A) == R(B)) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_EQI lopcodes.h /^OP_EQI,\/* A sB if ((R(A) == sB) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_EQK lopcodes.h /^OP_EQK,\/* A B if ((R(A) == K(B)) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_EXTRAARG lopcodes.h /^OP_EXTRAARG\/* Ax extra (larger) argument for previous opcode *\/$/;" e enum:__anon8 +OP_FORLOOP lopcodes.h /^OP_FORLOOP,\/* A Bx R(A)+=R(A+2);$/;" e enum:__anon8 +OP_FORLOOP1 lopcodes.h /^OP_FORLOOP1,\/* A Bx R(A)++;$/;" e enum:__anon8 +OP_FORPREP lopcodes.h /^OP_FORPREP,\/* A Bx R(A)-=R(A+2); pc+=Bx *\/$/;" e enum:__anon8 +OP_FORPREP1 lopcodes.h /^OP_FORPREP1,\/* A Bx R(A)--; pc+=Bx *\/$/;" e enum:__anon8 +OP_GETFIELD lopcodes.h /^OP_GETFIELD,\/* A B C R(A) := R(B)[K(C):string] *\/$/;" e enum:__anon8 +OP_GETI lopcodes.h /^OP_GETI,\/* A B C R(A) := R(B)[C] *\/$/;" e enum:__anon8 +OP_GETTABLE lopcodes.h /^OP_GETTABLE,\/* A B C R(A) := R(B)[R(C)] *\/$/;" e enum:__anon8 +OP_GETTABUP lopcodes.h /^OP_GETTABUP,\/* A B C R(A) := UpValue[B][K(C):string] *\/$/;" e enum:__anon8 +OP_GETUPVAL lopcodes.h /^OP_GETUPVAL,\/* A B R(A) := UpValue[B] *\/$/;" e enum:__anon8 +OP_IDIV lopcodes.h /^OP_IDIV,\/* A B C R(A) := R(B) \/\/ R(C) *\/$/;" e enum:__anon8 +OP_IDIVI lopcodes.h /^OP_IDIVI,\/* A B sC R(A) := R(B) \/\/ C *\/$/;" e enum:__anon8 +OP_JMP lopcodes.h /^OP_JMP,\/* k sJ pc += sJ (k is used in code generation) *\/$/;" e enum:__anon8 +OP_LE lopcodes.h /^OP_LE,\/* A B if ((R(A) <= R(B)) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_LEI lopcodes.h /^OP_LEI,\/* A sB if ((R(A) <= sB) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_LEN lopcodes.h /^OP_LEN,\/* A B R(A) := length of R(B) *\/$/;" e enum:__anon8 +OP_LOADBOOL lopcodes.h /^OP_LOADBOOL,\/* A B C R(A) := (Bool)B; if (C) pc++ *\/$/;" e enum:__anon8 +OP_LOADF lopcodes.h /^OP_LOADF,\/* A sBx R(A) := (lua_Number)sBx *\/$/;" e enum:__anon8 +OP_LOADI lopcodes.h /^OP_LOADI,\/* A sBx R(A) := sBx *\/$/;" e enum:__anon8 +OP_LOADK lopcodes.h /^OP_LOADK,\/* A Bx R(A) := K(Bx) *\/$/;" e enum:__anon8 +OP_LOADKX lopcodes.h /^OP_LOADKX,\/* A R(A) := K(extra arg) *\/$/;" e enum:__anon8 +OP_LOADNIL lopcodes.h /^OP_LOADNIL,\/* A B R(A), R(A+1), ..., R(A+B) := nil *\/$/;" e enum:__anon8 +OP_LT lopcodes.h /^OP_LT,\/* A B if ((R(A) < R(B)) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_LTI lopcodes.h /^OP_LTI,\/* A sB if ((R(A) < sB) ~= k) then pc++ *\/$/;" e enum:__anon8 +OP_MOD lopcodes.h /^OP_MOD,\/* A B C R(A) := R(B) % R(C) *\/$/;" e enum:__anon8 +OP_MODI lopcodes.h /^OP_MODI,\/* A B sC R(A) := R(B) % C *\/$/;" e enum:__anon8 +OP_MOVE lopcodes.h /^OP_MOVE,\/* A B R(A) := R(B) *\/$/;" e enum:__anon8 +OP_MUL lopcodes.h /^OP_MUL,\/* A B C R(A) := R(B) * R(C) *\/$/;" e enum:__anon8 +OP_MULI lopcodes.h /^OP_MULI,\/* A B sC R(A) := R(B) * C *\/$/;" e enum:__anon8 +OP_NEWTABLE lopcodes.h /^OP_NEWTABLE,\/* A B C R(A) := {} (size = B,C) *\/$/;" e enum:__anon8 +OP_NOT lopcodes.h /^OP_NOT,\/* A B R(A) := not R(B) *\/$/;" e enum:__anon8 +OP_POW lopcodes.h /^OP_POW,\/* A B C R(A) := R(B) ^ R(C) *\/$/;" e enum:__anon8 +OP_POWI lopcodes.h /^OP_POWI,\/* A B sC R(A) := R(B) ^ C *\/$/;" e enum:__anon8 +OP_RETURN lopcodes.h /^OP_RETURN,\/* A B return R(A), ... ,R(A+B-2) (see note) *\/$/;" e enum:__anon8 +OP_RETURN0 lopcodes.h /^OP_RETURN0,\/* return *\/$/;" e enum:__anon8 +OP_RETURN1 lopcodes.h /^OP_RETURN1,\/* A return R(A) *\/$/;" e enum:__anon8 +OP_SELF lopcodes.h /^OP_SELF,\/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] *\/$/;" e enum:__anon8 +OP_SETFIELD lopcodes.h /^OP_SETFIELD,\/* A B C R(A)[K(B):string] := RK(C) *\/$/;" e enum:__anon8 +OP_SETI lopcodes.h /^OP_SETI,\/* A B C R(A)[B] := RK(C) *\/$/;" e enum:__anon8 +OP_SETLIST lopcodes.h /^OP_SETLIST,\/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B *\/$/;" e enum:__anon8 +OP_SETTABLE lopcodes.h /^OP_SETTABLE,\/* A B C R(A)[R(B)] := RK(C) *\/$/;" e enum:__anon8 +OP_SETTABUP lopcodes.h /^OP_SETTABUP,\/* A B C UpValue[A][K(B):string] := RK(C) *\/$/;" e enum:__anon8 +OP_SETUPVAL lopcodes.h /^OP_SETUPVAL,\/* A B UpValue[B] := R(A) *\/$/;" e enum:__anon8 +OP_SHL lopcodes.h /^OP_SHL,\/* A B C R(A) := R(B) << R(C) *\/$/;" e enum:__anon8 +OP_SHLI lopcodes.h /^OP_SHLI,\/* A B C R(A) := C << R(B) *\/$/;" e enum:__anon8 +OP_SHR lopcodes.h /^OP_SHR,\/* A B C R(A) := R(B) >> R(C) *\/$/;" e enum:__anon8 +OP_SHRI lopcodes.h /^OP_SHRI,\/* A B C R(A) := R(B) >> C *\/$/;" e enum:__anon8 +OP_SUB lopcodes.h /^OP_SUB,\/* A B C R(A) := R(B) - R(C) *\/$/;" e enum:__anon8 +OP_SUBI lopcodes.h /^OP_SUBI,\/* A B sC R(A) := R(B) - C *\/$/;" e enum:__anon8 +OP_TAILCALL lopcodes.h /^OP_TAILCALL,\/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) *\/$/;" e enum:__anon8 +OP_TEST lopcodes.h /^OP_TEST,\/* A if (not R(A) == k) then pc++ *\/$/;" e enum:__anon8 +OP_TESTSET lopcodes.h /^OP_TESTSET,\/* A B if (not R(B) == k) then R(A) := R(B) else pc++ *\/$/;" e enum:__anon8 +OP_TFORCALL lopcodes.h /^OP_TFORCALL,\/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); *\/$/;" e enum:__anon8 +OP_TFORLOOP lopcodes.h /^OP_TFORLOOP,\/* A Bx if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx } *\/$/;" e enum:__anon8 +OP_UNM lopcodes.h /^OP_UNM,\/* A B R(A) := -R(B) *\/$/;" e enum:__anon8 +OP_VARARG lopcodes.h /^OP_VARARG,\/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) *\/$/;" e enum:__anon8 +OpCode lopcodes.h /^} OpCode;$/;" t typeref:enum:__anon8 +OpMode lopcodes.h /^enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; \/* basic instruction formats *\/$/;" g +PAUSEADJ lgc.c /^#define PAUSEADJ /;" d file: +PI lmathlib.c /^#define PI /;" d file: +PI lmathlib.c /^#undef PI$/;" d file: +POS lobject.c /^#define POS /;" d file: +POS_A lopcodes.h /^#define POS_A /;" d +POS_Ax lopcodes.h /^#define POS_Ax /;" d +POS_B lopcodes.h /^#define POS_B /;" d +POS_Bx lopcodes.h /^#define POS_Bx /;" d +POS_C lopcodes.h /^#define POS_C /;" d +POS_OP lopcodes.h /^#define POS_OP /;" d +POS_k lopcodes.h /^#define POS_k /;" d +POS_sJ lopcodes.h /^#define POS_sJ /;" d +PRE lobject.c /^#define PRE /;" d file: +PRINTBIT lctype.h /^#define PRINTBIT /;" d +Pfunc ldo.h /^typedef void (*Pfunc) (lua_State *L, void *ud);$/;" t +Protect lvm.c /^#define Protect(/;" d file: +ProtectNT lvm.c /^#define ProtectNT(/;" d file: +Proto lobject.h /^typedef struct Proto {$/;" s +Proto lobject.h /^} Proto;$/;" t typeref:struct:Proto +RA lvm.c /^#define RA(/;" d file: +RANLIB makefile /^RANLIB= ranlib$/;" m +RANLIMIT ltablib.c /^#define RANLIMIT /;" d file: +RB lvm.c /^#define RB(/;" d file: +RC lvm.c /^#define RC(/;" d file: +RESERVED llex.h /^enum RESERVED {$/;" g +RESERVEDSLOT lbaselib.c /^#define RESERVEDSLOT /;" d file: +RETS lobject.c /^#define RETS /;" d file: +RKC lvm.c /^#define RKC(/;" d file: +RM makefile /^RM= rm -f$/;" m +RN liolib.c /^} RN;$/;" t typeref:struct:__anon3 file: +SETARG_A lopcodes.h /^#define SETARG_A(/;" d +SETARG_Ax lopcodes.h /^#define SETARG_Ax(/;" d +SETARG_B lopcodes.h /^#define SETARG_B(/;" d +SETARG_Bx lopcodes.h /^#define SETARG_Bx(/;" d +SETARG_C lopcodes.h /^#define SETARG_C(/;" d +SETARG_k lopcodes.h /^#define SETARG_k(/;" d +SETARG_sBx lopcodes.h /^#define SETARG_sBx(/;" d +SETARG_sJ lopcodes.h /^#define SETARG_sJ(/;" d +SET_OPCODE lopcodes.h /^#define SET_OPCODE(/;" d +SIZELENMOD lstrlib.c /^#define SIZELENMOD /;" d file: +SIZETIMEFMT loslib.c /^#define SIZETIMEFMT /;" d file: +SIZE_A lopcodes.h /^#define SIZE_A /;" d +SIZE_Ax lopcodes.h /^#define SIZE_Ax /;" d +SIZE_B lopcodes.h /^#define SIZE_B /;" d +SIZE_Bx lopcodes.h /^#define SIZE_Bx /;" d +SIZE_C lopcodes.h /^#define SIZE_C /;" d +SIZE_Cx lopcodes.h /^#define SIZE_Cx /;" d +SIZE_OP lopcodes.h /^#define SIZE_OP /;" d +SIZE_sJ lopcodes.h /^#define SIZE_sJ /;" d +SPACEBIT lctype.h /^#define SPACEBIT /;" d +SPACECHARS lbaselib.c /^#define SPACECHARS /;" d file: +SPECIALS lstrlib.c /^#define SPECIALS /;" d file: +SParser ldo.c /^struct SParser { \/* data to 'f_parser' *\/$/;" s file: +STRCACHE_M llimits.h /^#define STRCACHE_M /;" d +STRCACHE_M ltests.h /^#define STRCACHE_M /;" d +STRCACHE_N llimits.h /^#define STRCACHE_N /;" d +STRCACHE_N ltests.h /^#define STRCACHE_N /;" d +SZINT lstrlib.c /^#define SZINT /;" d file: +SemInfo llex.h /^} SemInfo; \/* semantics information *\/$/;" t typeref:union:__anon4 +StackValue lobject.h /^typedef union StackValue {$/;" u +StackValue lobject.h /^} StackValue;$/;" t typeref:union:StackValue +StkId lobject.h /^typedef StackValue *StkId; \/* index to stack elements *\/$/;" t +TAB_L ltablib.c /^#define TAB_L /;" d file: +TAB_R ltablib.c /^#define TAB_R /;" d file: +TAB_RW ltablib.c /^#define TAB_RW /;" d file: +TAB_W ltablib.c /^#define TAB_W /;" d file: +TESTARG_k lopcodes.h /^#define TESTARG_k(/;" d +TESTGRAYBIT lgc.h /^#define TESTGRAYBIT /;" d +TESTS makefile /^TESTS= -DLUA_USER_H='"ltests.h"'$/;" m +TK_AND llex.h /^ TK_AND = FIRST_RESERVED, TK_BREAK,$/;" e enum:RESERVED +TK_BREAK llex.h /^ TK_AND = FIRST_RESERVED, TK_BREAK,$/;" e enum:RESERVED +TK_CONCAT llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_DBCOLON llex.h /^ TK_DBCOLON, TK_EOS,$/;" e enum:RESERVED +TK_DO llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_DOTS llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_ELSE llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_ELSEIF llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_END llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_EOS llex.h /^ TK_DBCOLON, TK_EOS,$/;" e enum:RESERVED +TK_EQ llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_FALSE llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_FLT llex.h /^ TK_FLT, TK_INT, TK_NAME, TK_STRING$/;" e enum:RESERVED +TK_FOR llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_FUNCTION llex.h /^ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,$/;" e enum:RESERVED +TK_GE llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_GOTO llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_IDIV llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_IF llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_IN llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_INT llex.h /^ TK_FLT, TK_INT, TK_NAME, TK_STRING$/;" e enum:RESERVED +TK_LE llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_LOCAL llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_NAME llex.h /^ TK_FLT, TK_INT, TK_NAME, TK_STRING$/;" e enum:RESERVED +TK_NE llex.h /^ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,$/;" e enum:RESERVED +TK_NIL llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_NOT llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_OR llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_REPEAT llex.h /^ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,$/;" e enum:RESERVED +TK_RETURN llex.h /^ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,$/;" e enum:RESERVED +TK_SHL llex.h /^ TK_SHL, TK_SHR,$/;" e enum:RESERVED +TK_SHR llex.h /^ TK_SHL, TK_SHR,$/;" e enum:RESERVED +TK_STRING llex.h /^ TK_FLT, TK_INT, TK_NAME, TK_STRING$/;" e enum:RESERVED +TK_THEN llex.h /^ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,$/;" e enum:RESERVED +TK_TRUE llex.h /^ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,$/;" e enum:RESERVED +TK_UNTIL llex.h /^ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,$/;" e enum:RESERVED +TK_WHILE llex.h /^ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,$/;" e enum:RESERVED +TMS ltm.h /^} TMS;$/;" t typeref:enum:__anon22 +TM_ADD ltm.h /^ TM_ADD,$/;" e enum:__anon22 +TM_BAND ltm.h /^ TM_BAND,$/;" e enum:__anon22 +TM_BNOT ltm.h /^ TM_BNOT,$/;" e enum:__anon22 +TM_BOR ltm.h /^ TM_BOR,$/;" e enum:__anon22 +TM_BXOR ltm.h /^ TM_BXOR,$/;" e enum:__anon22 +TM_CALL ltm.h /^ TM_CALL,$/;" e enum:__anon22 +TM_CONCAT ltm.h /^ TM_CONCAT,$/;" e enum:__anon22 +TM_DIV ltm.h /^ TM_DIV,$/;" e enum:__anon22 +TM_EQ ltm.h /^ TM_EQ, \/* last tag method with fast access *\/$/;" e enum:__anon22 +TM_GC ltm.h /^ TM_GC,$/;" e enum:__anon22 +TM_IDIV ltm.h /^ TM_IDIV,$/;" e enum:__anon22 +TM_INDEX ltm.h /^ TM_INDEX,$/;" e enum:__anon22 +TM_LE ltm.h /^ TM_LE,$/;" e enum:__anon22 +TM_LEN ltm.h /^ TM_LEN,$/;" e enum:__anon22 +TM_LT ltm.h /^ TM_LT,$/;" e enum:__anon22 +TM_MOD ltm.h /^ TM_MOD,$/;" e enum:__anon22 +TM_MODE ltm.h /^ TM_MODE,$/;" e enum:__anon22 +TM_MUL ltm.h /^ TM_MUL,$/;" e enum:__anon22 +TM_N ltm.h /^ TM_N \/* number of elements in the enum *\/$/;" e enum:__anon22 +TM_NEWINDEX ltm.h /^ TM_NEWINDEX,$/;" e enum:__anon22 +TM_POW ltm.h /^ TM_POW,$/;" e enum:__anon22 +TM_SHL ltm.h /^ TM_SHL,$/;" e enum:__anon22 +TM_SHR ltm.h /^ TM_SHR,$/;" e enum:__anon22 +TM_SUB ltm.h /^ TM_SUB,$/;" e enum:__anon22 +TM_UNM ltm.h /^ TM_UNM,$/;" e enum:__anon22 +TString lobject.h /^typedef struct TString {$/;" s +TString lobject.h /^} TString;$/;" t typeref:struct:TString +TValue lobject.h /^typedef struct TValue {$/;" s +TValue lobject.h /^} TValue;$/;" t typeref:struct:TValue +TValuefields lobject.h /^ TValuefields; \/* fields for value *\/$/;" m struct:Node::NodeKey +TValuefields lobject.h /^ TValuefields;$/;" m struct:TValue +TValuefields lobject.h /^#define TValuefields /;" d +Table lobject.h /^typedef struct Table {$/;" s +Table lobject.h /^} Table;$/;" t typeref:struct:Table +Token llex.h /^typedef struct Token {$/;" s +Token llex.h /^} Token;$/;" t typeref:struct:Token +UBox lauxlib.c /^typedef struct UBox {$/;" s file: +UBox lauxlib.c /^} UBox;$/;" t typeref:struct:UBox file: +UNARY_PRIORITY lparser.c /^#define UNARY_PRIORITY /;" d file: +UNUSED llimits.h /^#define UNUSED(/;" d +UNUSED ltests.h /^#define UNUSED(/;" d +UTF8BUFFSZ lobject.h /^#define UTF8BUFFSZ /;" d +UTF8PATT lutf8lib.c /^#define UTF8PATT /;" d file: +UTString lobject.h /^typedef union UTString {$/;" u +UTString lobject.h /^} UTString;$/;" t typeref:union:UTString +UUdata lobject.h /^typedef union UUdata {$/;" u +UUdata lobject.h /^} UUdata;$/;" t typeref:union:UUdata +Udata lobject.h /^typedef struct Udata {$/;" s +Udata lobject.h /^} Udata;$/;" t typeref:struct:Udata +UnOpr lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" g +UnOpr lcode.h /^typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;$/;" t typeref:enum:UnOpr +UpVal lobject.h /^typedef struct UpVal {$/;" s +UpVal lobject.h /^} UpVal;$/;" t typeref:struct:UpVal +Upvaldesc lobject.h /^typedef struct Upvaldesc {$/;" s +Upvaldesc lobject.h /^} Upvaldesc;$/;" t typeref:struct:Upvaldesc +VCALL lparser.h /^ VCALL, \/* expression is a function call; info = instruction pc *\/$/;" e enum:__anon10 +VFALSE lparser.h /^ VFALSE, \/* constant false *\/$/;" e enum:__anon10 +VINDEXED lparser.h /^ VINDEXED, \/* indexed variable;$/;" e enum:__anon10 +VINDEXI lparser.h /^ VINDEXI, \/* indexed variable with constant integer;$/;" e enum:__anon10 +VINDEXSTR lparser.h /^ VINDEXSTR, \/* indexed variable with literal string;$/;" e enum:__anon10 +VINDEXUP lparser.h /^ VINDEXUP, \/* indexed upvalue;$/;" e enum:__anon10 +VJMP lparser.h /^ VJMP, \/* expression is a test\/comparison;$/;" e enum:__anon10 +VK lparser.h /^ VK, \/* constant in 'k'; info = index of constant in 'k' *\/$/;" e enum:__anon10 +VKFLT lparser.h /^ VKFLT, \/* floating constant; nval = numerical float value *\/$/;" e enum:__anon10 +VKINT lparser.h /^ VKINT, \/* integer constant; nval = numerical integer value *\/$/;" e enum:__anon10 +VLOCAL lparser.h /^ VLOCAL, \/* local variable; info = local register *\/$/;" e enum:__anon10 +VNIL lparser.h /^ VNIL, \/* constant nil *\/$/;" e enum:__anon10 +VNONRELOC lparser.h /^ VNONRELOC, \/* expression has its value in a fixed register;$/;" e enum:__anon10 +VRELOC lparser.h /^ VRELOC, \/* expression can put result in any register;$/;" e enum:__anon10 +VTRUE lparser.h /^ VTRUE, \/* constant true *\/$/;" e enum:__anon10 +VUPVAL lparser.h /^ VUPVAL, \/* upvalue variable; info = index of upvalue in 'upvalues' *\/$/;" e enum:__anon10 +VVARARG lparser.h /^ VVARARG \/* vararg expression; info = instruction pc *\/$/;" e enum:__anon10 +VVOID lparser.h /^ VVOID, \/* when 'expdesc' describes the last expression a list,$/;" e enum:__anon10 +Value lobject.h /^typedef union Value {$/;" u +Value lobject.h /^} Value;$/;" t typeref:union:Value +Vardesc lparser.h /^typedef struct Vardesc {$/;" s +Vardesc lparser.h /^} Vardesc;$/;" t typeref:struct:Vardesc +WHITE0BIT lgc.h /^#define WHITE0BIT /;" d +WHITE1BIT lgc.h /^#define WHITE1BIT /;" d +WHITEBITS lgc.h /^#define WHITEBITS /;" d +WORK2MEM lgc.c /^#define WORK2MEM /;" d file: +XDIGITBIT lctype.h /^#define XDIGITBIT /;" d +Z lundump.c /^ ZIO *Z;$/;" m struct:__anon23 file: +ZIO lzio.h /^typedef struct Zio ZIO;$/;" t typeref:struct:Zio +Zio lzio.h /^struct Zio {$/;" s +_CRT_SECURE_NO_WARNINGS lprefix.h /^#define _CRT_SECURE_NO_WARNINGS /;" d +_FILE_OFFSET_BITS lprefix.h /^#define _FILE_OFFSET_BITS /;" d +_LARGEFILE_SOURCE lprefix.h /^#define _LARGEFILE_SOURCE /;" d +_XOPEN_SOURCE lprefix.h /^#define _XOPEN_SOURCE /;" d +_XOPEN_SOURCE lprefix.h /^#undef _XOPEN_SOURCE /;" d +abslineinfo lobject.h /^ AbsLineInfo *abslineinfo; \/* idem *\/$/;" m struct:Proto +actvar lparser.h /^ } actvar;$/;" m struct:Dyndata typeref:struct:Dyndata::__anon13 +add_s lstrlib.c /^static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,$/;" f file: +add_value lstrlib.c /^static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,$/;" f file: +addbuff lstate.c /^#define addbuff(/;" d file: +adddigit lstrlib.c /^static lua_Number adddigit (char *buff, int n, lua_Number x) {$/;" f file: +addfield ltablib.c /^static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {$/;" f file: +addk lcode.c /^static int addk (FuncState *fs, TValue *key, TValue *v) {$/;" f file: +addlenmod lstrlib.c /^static void addlenmod (char *form, const char *lenmod) {$/;" f file: +addliteral lstrlib.c /^static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {$/;" f file: +addprototype lparser.c /^static Proto *addprototype (LexState *ls) {$/;" f file: +addquoted lstrlib.c /^static void addquoted (luaL_Buffer *b, const char *s, size_t len) {$/;" f file: +addreturn lua.c /^static int addreturn (lua_State *L) {$/;" f file: +addstr lobject.c /^#define addstr(/;" d file: +addtoclib loadlib.c /^static void addtoclib (lua_State *L, const char *path, void *plib) {$/;" f file: +adjust_assign lparser.c /^static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {$/;" f file: +adjustlocalvars lparser.c /^static void adjustlocalvars (LexState *ls, int nvars) {$/;" f file: +adjustresults lapi.h /^#define adjustresults(/;" d +allgc lstate.h /^ GCObject *allgc; \/* list of all collectable objects *\/$/;" m struct:global_State +alloc_count ltests.c /^static int alloc_count (lua_State *L) {$/;" f file: +allocsizenode ltable.h /^#define allocsizenode(/;" d +allowhook lstate.h /^ lu_byte allowhook;$/;" m struct:lua_State +allweak lstate.h /^ GCObject *allweak; \/* list of all-weak tables *\/$/;" m struct:global_State +andaux lbitlib.c /^static lua_Unsigned andaux (lua_State *L) {$/;" f file: +api_check llimits.h /^#define api_check(/;" d +api_checknelems lapi.h /^#define api_checknelems(/;" d +api_checkstackindex lapi.c /^#define api_checkstackindex(/;" d file: +api_checkvalidindex lapi.c /^#define api_checkvalidindex(/;" d file: +api_incr_top lapi.h /^#define api_incr_top(/;" d +arith lstrlib.c /^static int arith (lua_State *L, int op, const char *mtname) {$/;" f file: +arith_add lstrlib.c /^static int arith_add (lua_State *L) {$/;" f file: +arith_div lstrlib.c /^static int arith_div (lua_State *L) {$/;" f file: +arith_idiv lstrlib.c /^static int arith_idiv (lua_State *L) {$/;" f file: +arith_mod lstrlib.c /^static int arith_mod (lua_State *L) {$/;" f file: +arith_mul lstrlib.c /^static int arith_mul (lua_State *L) {$/;" f file: +arith_pow lstrlib.c /^static int arith_pow (lua_State *L) {$/;" f file: +arith_sub lstrlib.c /^static int arith_sub (lua_State *L) {$/;" f file: +arith_unm lstrlib.c /^static int arith_unm (lua_State *L) {$/;" f file: +arr lparser.h /^ Vardesc *arr;$/;" m struct:Dyndata::__anon13 +arr lparser.h /^ Labeldesc *arr; \/* array *\/$/;" m struct:Labellist +array lobject.h /^ TValue *array; \/* array part *\/$/;" m struct:Table +arrayindex ltable.c /^static unsigned int arrayindex (lua_Integer k) {$/;" f file: +assignment lparser.c /^static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {$/;" f file: +atomic lgc.c /^static lu_mem atomic (lua_State *L) {$/;" f file: +aux_close liolib.c /^static int aux_close (lua_State *L) {$/;" f file: +aux_getn ltablib.c /^#define aux_getn(/;" d file: +aux_lines liolib.c /^static void aux_lines (lua_State *L, int toclose) {$/;" f file: +aux_upvalue lapi.c /^static const char *aux_upvalue (TValue *fi, int n, TValue **val,$/;" f file: +auxgetinfo ldebug.c /^static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,$/;" f file: +auxgetstr lapi.c /^static int auxgetstr (lua_State *L, const TValue *t, const char *k) {$/;" f file: +auxresume lcorolib.c /^static int auxresume (lua_State *L, lua_State *co, int narg) {$/;" f file: +auxsetstr lapi.c /^static void auxsetstr (lua_State *L, const TValue *t, const char *k) {$/;" f file: +auxsort ltablib.c /^static void auxsort (lua_State *L, IdxT lo, IdxT up,$/;" f file: +auxupvalue ldblib.c /^static int auxupvalue (lua_State *L, int get) {$/;" f file: +b lauxlib.h /^ char b[LUAL_BUFFERSIZE]; \/* initial buffer *\/$/;" m union:luaL_Buffer::__anon1 +b lauxlib.h /^ char *b; \/* buffer address *\/$/;" m struct:luaL_Buffer +b ldo.c /^ luai_jmpbuf b;$/;" m struct:lua_longjmp file: +b lobject.h /^ int b; \/* booleans *\/$/;" m union:Value +b_and lbitlib.c /^static int b_and (lua_State *L) {$/;" f file: +b_arshift lbitlib.c /^static int b_arshift (lua_State *L) {$/;" f file: +b_extract lbitlib.c /^static int b_extract (lua_State *L) {$/;" f file: +b_lrot lbitlib.c /^static int b_lrot (lua_State *L) {$/;" f file: +b_lshift lbitlib.c /^static int b_lshift (lua_State *L) {$/;" f file: +b_not lbitlib.c /^static int b_not (lua_State *L) {$/;" f file: +b_or lbitlib.c /^static int b_or (lua_State *L) {$/;" f file: +b_replace lbitlib.c /^static int b_replace (lua_State *L) {$/;" f file: +b_rot lbitlib.c /^static int b_rot (lua_State *L, lua_Integer d) {$/;" f file: +b_rrot lbitlib.c /^static int b_rrot (lua_State *L) {$/;" f file: +b_rshift lbitlib.c /^static int b_rshift (lua_State *L) {$/;" f file: +b_shift lbitlib.c /^static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {$/;" f file: +b_str2int lbaselib.c /^static const char *b_str2int (const char *s, int base, lua_Integer *pn) {$/;" f file: +b_test lbitlib.c /^static int b_test (lua_State *L) {$/;" f file: +b_xor lbitlib.c /^static int b_xor (lua_State *L) {$/;" f file: +base_ci lstate.h /^ CallInfo base_ci; \/* CallInfo for first level (C calling Lua) *\/$/;" m struct:lua_State +base_funcs lbaselib.c /^static const luaL_Reg base_funcs[] = {$/;" v file: +basehookcount lstate.h /^ int basehookcount;$/;" m struct:lua_State +bit2mask lgc.h /^#define bit2mask(/;" d +bitlib lbitlib.c /^static const luaL_Reg bitlib[] = {$/;" v file: +bitmask lgc.h /^#define bitmask(/;" d +bitwise lstrlib.c /^static int bitwise (lua_State *L, int op, const char *mtname) {$/;" f file: +bitwise_band lstrlib.c /^static int bitwise_band (lua_State *L) {$/;" f file: +bitwise_bnot lstrlib.c /^static int bitwise_bnot (lua_State *L) {$/;" f file: +bitwise_bor lstrlib.c /^static int bitwise_bor (lua_State *L) {$/;" f file: +bitwise_bxor lstrlib.c /^static int bitwise_bxor (lua_State *L) {$/;" f file: +bitwise_shl lstrlib.c /^static int bitwise_shl (lua_State *L) {$/;" f file: +bitwise_shr lstrlib.c /^static int bitwise_shr (lua_State *L) {$/;" f file: +bl lparser.h /^ struct BlockCnt *bl; \/* chain of current blocks *\/$/;" m struct:FuncState typeref:struct:FuncState::BlockCnt +black2gray lgc.c /^#define black2gray(/;" d file: +block lparser.c /^static void block (LexState *ls) {$/;" f file: +block_follow lparser.c /^static int block_follow (LexState *ls, int withuntil) {$/;" f file: +body lparser.c /^static void body (LexState *ls, expdesc *e, int ismethod, int line) {$/;" f file: +boolK lcode.c /^static int boolK (FuncState *fs, int b) {$/;" f file: +box lauxlib.c /^ void *box;$/;" m struct:UBox file: +boxgc lauxlib.c /^static int boxgc (lua_State *L) {$/;" f file: +breakstat lparser.c /^static void breakstat (LexState *ls, int pc) {$/;" f file: +brkcls lparser.c /^ lu_byte brkcls; \/* true if some 'break' needs to close upvalues *\/$/;" m struct:BlockCnt file: +brks lparser.c /^ int brks; \/* list of break jumps in this block *\/$/;" m struct:BlockCnt file: +bsize lauxlib.c /^ size_t bsize;$/;" m struct:UBox file: +buff lauxlib.c /^ char buff[BUFSIZ]; \/* area for reading file *\/$/;" m struct:LoadF file: +buff ldo.c /^ Mbuffer buff; \/* dynamic structure used by the scanner *\/$/;" m struct:SParser file: +buff liolib.c /^ char buff[L_MAXLENNUM + 1]; \/* +1 for ending '\\0' *\/$/;" m struct:__anon3 file: +buff llex.h /^ Mbuffer *buff; \/* buffer for tokens *\/$/;" m struct:LexState +buff lstrlib.c /^ char buff[5 * sizeof(lua_Number)]; \/* enough for any float type *\/$/;" m union:Ftypes file: +buffer lzio.h /^ char *buffer;$/;" m struct:Mbuffer +buffonstack lauxlib.c /^#define buffonstack(/;" d file: +buffsize lzio.h /^ size_t buffsize;$/;" m struct:Mbuffer +buildop ltests.c /^static char *buildop (Proto *p, int pc, char *buff) {$/;" f file: +bvalue lobject.h /^#define bvalue(/;" d +bvalueraw lobject.h /^#define bvalueraw(/;" d +byteoffset lutf8lib.c /^static int byteoffset (lua_State *L) {$/;" f file: +c liolib.c /^ int c; \/* current character (look ahead) *\/$/;" m struct:__anon3 file: +c lobject.h /^ CClosure c;$/;" m union:Closure +c lstate.h /^ } c;$/;" m union:CallInfo::__anon14 typeref:struct:CallInfo::__anon14::__anon16 +c lstrlib.c /^ char c;$/;" m struct:cD file: +cD lstrlib.c /^struct cD {$/;" s file: +cache lobject.h /^ struct LClosure *cache; \/* last-created closure with this prototype *\/$/;" m struct:Proto typeref:struct:Proto::LClosure +cachemiss lobject.h /^ lu_byte cachemiss; \/* count for successive misses for 'cache' field *\/$/;" m struct:Proto +callallpendingfinalizers lgc.c /^static void callallpendingfinalizers (lua_State *L) {$/;" f file: +callbinTM ltm.c /^static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,$/;" f file: +callstatus lstate.h /^ lu_byte callstatus;$/;" m struct:CallInfo +capture lstrlib.c /^ } capture[LUA_MAXCAPTURES];$/;" m struct:MatchState typeref:struct:MatchState::__anon18 file: +capture_to_close lstrlib.c /^static int capture_to_close (MatchState *ms) {$/;" f file: +cast llimits.h /^#define cast(/;" d +cast_byte llimits.h /^#define cast_byte(/;" d +cast_func loadlib.c /^#define cast_func(/;" d file: +cast_int llimits.h /^#define cast_int(/;" d +cast_num llimits.h /^#define cast_num(/;" d +cast_u lstate.h /^#define cast_u(/;" d +cast_uchar llimits.h /^#define cast_uchar(/;" d +cast_void llimits.h /^#define cast_void(/;" d +changeage lgc.h /^#define changeage(/;" d +changedline ldebug.c /^static int changedline (Proto *p, int oldpc, int newpc) {$/;" f file: +changewhite lgc.h /^#define changewhite(/;" d +check lparser.c /^static void check (LexState *ls, int c) {$/;" f file: +checkCclosure ltests.c /^static void checkCclosure (global_State *g, CClosure *cl) {$/;" f file: +checkGC lvm.c /^#define checkGC(/;" d file: +checkHeader lundump.c /^static void checkHeader (LoadState *S) {$/;" f file: +checkLclosure ltests.c /^static void checkLclosure (global_State *g, LClosure *cl) {$/;" f file: +checkSizes lgc.c /^static void checkSizes (lua_State *L, global_State *g) {$/;" f file: +check_capture lstrlib.c /^static int check_capture (MatchState *ms, int l) {$/;" f file: +check_condition lparser.c /^#define check_condition(/;" d file: +check_conflict lparser.c /^static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {$/;" f file: +check_exp llimits.h /^#define check_exp(/;" d +check_match lparser.c /^static void check_match (LexState *ls, int what, int who, int where) {$/;" f file: +check_next1 llex.c /^static int check_next1 (LexState *ls, int c) {$/;" f file: +check_next2 llex.c /^static int check_next2 (LexState *ls, const char *set) {$/;" f file: +checkclib loadlib.c /^static void *checkclib (lua_State *L, const char *path) {$/;" f file: +checkconsistency lgc.c /^#define checkconsistency(/;" d file: +checkfield ltablib.c /^static int checkfield (lua_State *L, const char *key, int n) {$/;" f file: +checkfinalmem ltests.c /^static void checkfinalmem (void) {$/;" f file: +checkgray ltests.c /^static void checkgray (global_State *g, GCObject *o) {$/;" f file: +checkgraylist ltests.c /^static void checkgraylist (global_State *g, GCObject *o) {$/;" f file: +checklimit lparser.c /^static void checklimit (FuncState *fs, int v, int l, const char *what) {$/;" f file: +checklist ltests.c /^static void checklist (global_State *g, int maybedead, int tof,$/;" f file: +checkliteral lundump.c /^static void checkliteral (LoadState *S, const char *s, const char *msg) {$/;" f file: +checkliveness lobject.h /^#define checkliveness(/;" d +checkload loadlib.c /^static int checkload (lua_State *L, int stat, const char *filename) {$/;" f file: +checkmode ldo.c /^static void checkmode (lua_State *L, const char *mode, const char *x) {$/;" f file: +checkname lparser.c /^static void checkname (LexState *ls, expdesc *e) {$/;" f file: +checknext lparser.c /^static void checknext (LexState *ls, int c) {$/;" f file: +checkobject ltests.c /^static void checkobject (global_State *g, GCObject *o, int maybedead,$/;" f file: +checkobjref ltests.c /^#define checkobjref(/;" d file: +checkopm lopcodes.h /^#define checkopm(/;" d +checkoption loslib.c /^static const char *checkoption (lua_State *L, const char *conv,$/;" f file: +checkpanic ltests.c /^static int checkpanic (lua_State *L) {$/;" f file: +checkproto ltests.c /^static void checkproto (global_State *g, Proto *f) {$/;" f file: +checkprotocache lgc.c /^static void checkprotocache (global_State *g, Proto *p) {$/;" f file: +checkrefs ltests.c /^static void checkrefs (global_State *g, GCObject *o) {$/;" f file: +checkrepeated lparser.c /^static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {$/;" f file: +checkresults lapi.c /^#define checkresults(/;" d file: +checksize lundump.c /^#define checksize(/;" d file: +checkstack ldblib.c /^static void checkstack (lua_State *L, lua_State *L1, int n) {$/;" f file: +checkstack ltests.c /^static void checkstack (global_State *g, lua_State *L1) {$/;" f file: +checkstackp ldo.h /^#define checkstackp(/;" d +checktab ltablib.c /^static void checktab (lua_State *L, int arg, int what) {$/;" f file: +checktable ltests.c /^static void checktable (global_State *g, Table *h) {$/;" f file: +checktag lobject.h /^#define checktag(/;" d +checktype lobject.h /^#define checktype(/;" d +checkunsigned lbitlib.c /^#define checkunsigned(/;" d file: +checkupval ldblib.c /^static int checkupval (lua_State *L, int argf, int argnup) {$/;" f file: +checkvalref ltests.c /^static void checkvalref (global_State *g, GCObject *f, const TValue *t) {$/;" f file: +chgfltvalue lobject.h /^#define chgfltvalue(/;" d +chgivalue lobject.h /^#define chgivalue(/;" d +choosePivot ltablib.c /^static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {$/;" f file: +ci lstate.h /^ CallInfo *ci; \/* call info for current function *\/$/;" m struct:lua_State +ci_func ldebug.c /^#define ci_func(/;" d file: +cl lstate.h /^ union Closure cl;$/;" m union:GCUnion typeref:union:GCUnion::Closure +clCvalue lobject.h /^#define clCvalue(/;" d +clLvalue lobject.h /^#define clLvalue(/;" d +classend lstrlib.c /^static const char *classend (MatchState *ms, const char *p) {$/;" f file: +clearkeys lgc.c /^static void clearkeys (global_State *g, GCObject *l) {$/;" f file: +clearprotolist lgc.c /^static void clearprotolist (global_State *g) {$/;" f file: +clearvalues lgc.c /^static void clearvalues (global_State *g, GCObject *l, GCObject *f) {$/;" f file: +close_func lparser.c /^static void close_func (LexState *ls) {$/;" f file: +close_state lstate.c /^static void close_state (lua_State *L) {$/;" f file: +closef lauxlib.h /^ lua_CFunction closef; \/* to close stream (NULL for closed streams) *\/$/;" m struct:luaL_Stream +closegoto lparser.c /^static void closegoto (LexState *ls, int g, Labeldesc *label) {$/;" f file: +closelistfield lparser.c /^static void closelistfield (FuncState *fs, struct ConsControl *cc) {$/;" f file: +closestate ltests.c /^static int closestate (lua_State *L) {$/;" f file: +clvalue lobject.h /^#define clvalue(/;" d +co_funcs lcorolib.c /^static const luaL_Reg co_funcs[] = {$/;" v file: +code lobject.h /^ Instruction *code; \/* opcodes *\/$/;" m struct:Proto +codeABRK lcode.c /^static void codeABRK (FuncState *fs, OpCode o, int a, int b,$/;" f file: +codeABsC lcode.c /^#define codeABsC(/;" d file: +code_loadbool lcode.c /^static int code_loadbool (FuncState *fs, int A, int b, int jump) {$/;" f file: +codearith lcode.c /^static void codearith (FuncState *fs, OpCode op,$/;" f file: +codebinexpval lcode.c /^static void codebinexpval (FuncState *fs, OpCode op,$/;" f file: +codebini lcode.c /^static void codebini (FuncState *fs, OpCode op,$/;" f file: +codebitwise lcode.c /^static void codebitwise (FuncState *fs, BinOpr opr,$/;" f file: +codeclosure lparser.c /^static void codeclosure (LexState *ls, expdesc *v) {$/;" f file: +codecommutative lcode.c /^static void codecommutative (FuncState *fs, OpCode op,$/;" f file: +codeeq lcode.c /^static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {$/;" f file: +codeextraarg lcode.c /^static int codeextraarg (FuncState *fs, int a) {$/;" f file: +codenot lcode.c /^static void codenot (FuncState *fs, expdesc *e) {$/;" f file: +codeorder lcode.c /^static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {$/;" f file: +codepoint lutf8lib.c /^static int codepoint (lua_State *L) {$/;" f file: +codesJ lcode.c /^static int codesJ (FuncState *fs, OpCode o, int sj, int k) {$/;" f file: +codeshift lcode.c /^static void codeshift (FuncState *fs, OpCode op,$/;" f file: +codestring lparser.c /^static void codestring (LexState *ls, expdesc *e, TString *s) {$/;" f file: +codeunexpval lcode.c /^static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {$/;" f file: +collectargs lua.c /^static int collectargs (char **argv, int *first) {$/;" f file: +collectvalidlines ldebug.c /^static void collectvalidlines (lua_State *L, Closure *f) {$/;" f file: +computesizes ltable.c /^static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {$/;" f file: +cond lparser.c /^static int cond (LexState *ls) {$/;" f file: +condchangemem llimits.h /^#define condchangemem(/;" d +condjump lcode.c /^static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) {$/;" f file: +condmovestack llimits.h /^#define condmovestack(/;" d +constfolding lcode.c /^static int constfolding (FuncState *fs, int op, expdesc *e1,$/;" f file: +constructor lparser.c /^static void constructor (LexState *ls, expdesc *t) {$/;" f file: +convergeephemerons lgc.c /^static void convergeephemerons (global_State *g) {$/;" f file: +copy2buff lvm.c /^static void copy2buff (StkId top, int n, char *buff) {$/;" f file: +copywithendian lstrlib.c /^static void copywithendian (volatile char *dest, volatile const char *src,$/;" f file: +coresume ltests.c /^static int coresume (lua_State *L) {$/;" f file: +correctgraylist lgc.c /^static GCObject **correctgraylist (GCObject **p) {$/;" f file: +correctgraylists lgc.c /^static void correctgraylists (global_State *g) {$/;" f file: +correctstack ldo.c /^static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {$/;" f file: +countint ltable.c /^static int countint (lua_Integer key, unsigned int *nums) {$/;" f file: +countlimit ltests.h /^ unsigned long countlimit;$/;" m struct:Memcontrol +createargtable lua.c /^static void createargtable (lua_State *L, char **argv, int argc, int script) {$/;" f file: +createclibstable loadlib.c /^static void createclibstable (lua_State *L) {$/;" f file: +createmeta liolib.c /^static void createmeta (lua_State *L) {$/;" f file: +createmetatable lstrlib.c /^static void createmetatable (lua_State *L) {$/;" f file: +createsearcherstable loadlib.c /^static void createsearcherstable (lua_State *L) {$/;" f file: +createstdfile liolib.c /^static void createstdfile (lua_State *L, FILE *f, const char *k,$/;" f file: +createstrobj lstring.c /^static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {$/;" f file: +ctb lobject.h /^#define ctb(/;" d +ctx lstate.h /^ lua_KContext ctx; \/* context info. in case of yields *\/$/;" m struct:CallInfo::__anon14::__anon16 +currIsNewline llex.c /^#define currIsNewline(/;" d file: +current llex.h /^ int current; \/* current character (charint) *\/$/;" m struct:LexState +currentline ldebug.c /^static int currentline (CallInfo *ci) {$/;" f file: +currentline lua.h /^ int currentline; \/* (l) *\/$/;" m struct:lua_Debug +currentpc ldebug.c /^static int currentpc (CallInfo *ci) {$/;" f file: +currentwhite lstate.h /^ lu_byte currentwhite;$/;" m struct:global_State +cvt2num lvm.h /^#define cvt2num(/;" d +cvt2str lvm.h /^#define cvt2str(/;" d +d lstrlib.c /^ double d;$/;" m union:Ftypes file: +d lstrlib.c /^ union { double d; void *p; lua_Integer i; lua_Number n; } u;$/;" m union:cD::__anon20 file: +d ltests.c /^ } d;$/;" m union:Header typeref:struct:Header::__anon21 file: +d2s ltests.c /^static int d2s (lua_State *L) {$/;" f file: +data ldump.c /^ void *data;$/;" m struct:__anon2 file: +data lzio.h /^ void *data; \/* additional data *\/$/;" m struct:Zio +db_debug ldblib.c /^static int db_debug (lua_State *L) {$/;" f file: +db_gethook ldblib.c /^static int db_gethook (lua_State *L) {$/;" f file: +db_getinfo ldblib.c /^static int db_getinfo (lua_State *L) {$/;" f file: +db_getlocal ldblib.c /^static int db_getlocal (lua_State *L) {$/;" f file: +db_getmetatable ldblib.c /^static int db_getmetatable (lua_State *L) {$/;" f file: +db_getregistry ldblib.c /^static int db_getregistry (lua_State *L) {$/;" f file: +db_getupvalue ldblib.c /^static int db_getupvalue (lua_State *L) {$/;" f file: +db_getuservalue ldblib.c /^static int db_getuservalue (lua_State *L) {$/;" f file: +db_sethook ldblib.c /^static int db_sethook (lua_State *L) {$/;" f file: +db_setlocal ldblib.c /^static int db_setlocal (lua_State *L) {$/;" f file: +db_setmetatable ldblib.c /^static int db_setmetatable (lua_State *L) {$/;" f file: +db_setupvalue ldblib.c /^static int db_setupvalue (lua_State *L) {$/;" f file: +db_setuservalue ldblib.c /^static int db_setuservalue (lua_State *L) {$/;" f file: +db_traceback ldblib.c /^static int db_traceback (lua_State *L) {$/;" f file: +db_upvalueid ldblib.c /^static int db_upvalueid (lua_State *L) {$/;" f file: +db_upvaluejoin ldblib.c /^static int db_upvaluejoin (lua_State *L) {$/;" f file: +dblib ldblib.c /^static const luaL_Reg dblib[] = {$/;" v file: +debug_realloc ltests.c /^void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {$/;" f +deletelist lgc.c /^static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {$/;" f file: +delimits ltests.c /^static const char *const delimits = " \\t\\n,;";$/;" v file: +digit lstrlib.c /^static int digit (int c) { return '0' <= c && c <= '9'; }$/;" f file: +discharge2anyreg lcode.c /^static void discharge2anyreg (FuncState *fs, expdesc *e) {$/;" f file: +discharge2reg lcode.c /^static void discharge2reg (FuncState *fs, expdesc *e, int reg) {$/;" f file: +doREPL lua.c /^static void doREPL (lua_State *L) {$/;" f file: +docall lua.c /^static int docall (lua_State *L, int narg, int nres) {$/;" f file: +dochunk lua.c /^static int dochunk (lua_State *L, int status) {$/;" f file: +dofile lua.c /^static int dofile (lua_State *L, const char *name) {$/;" f file: +dofilecont lbaselib.c /^static int dofilecont (lua_State *L, int d1, lua_KContext d2) {$/;" f file: +dojump lvm.c /^#define dojump(/;" d file: +dolibrary lua.c /^static int dolibrary (lua_State *L, const char *name) {$/;" f file: +donextjump lvm.c /^#define donextjump(/;" d file: +doonnewstack ltests.c /^static int doonnewstack (lua_State *L) {$/;" f file: +dooptions loadlib.c /^static void dooptions (lua_State *L, int n) {$/;" f file: +doremote ltests.c /^static int doremote (lua_State *L) {$/;" f file: +dostring lua.c /^static int dostring (lua_State *L, const char *s, const char *name) {$/;" f file: +dothecall lgc.c /^static void dothecall (lua_State *L, void *ud) {$/;" f file: +dummy lstrlib.c /^ int dummy;$/;" m union:__anon19 file: +dummynode ltable.c /^#define dummynode /;" d file: +dummynode_ ltable.c /^static const Node dummynode_ = {$/;" v file: +dyd ldo.c /^ Dyndata dyd; \/* dynamic structures used by the parser *\/$/;" m struct:SParser file: +dyd llex.h /^ struct Dyndata *dyd; \/* dynamic structures used by the parser *\/$/;" m struct:LexState typeref:struct:LexState::Dyndata +end_capture lstrlib.c /^static const char *end_capture (MatchState *ms, const char *s,$/;" f file: +endpc lobject.h /^ int endpc; \/* first point where variable is dead *\/$/;" m struct:LocVar +enterblock lparser.c /^static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {$/;" f file: +entergen lgc.c /^static void entergen (lua_State *L, global_State *g) {$/;" f file: +enterinc lgc.c /^static void enterinc (global_State *g) {$/;" f file: +enterlevel lparser.c /^#define enterlevel(/;" d file: +entersweep lgc.c /^static void entersweep (lua_State *L) {$/;" f file: +envn llex.h /^ TString *envn; \/* environment variable name *\/$/;" m struct:LexState +ephemeron lstate.h /^ GCObject *ephemeron; \/* list of ephemeron tables (weak keys) *\/$/;" m struct:global_State +eqshrstr lstring.h /^#define eqshrstr(/;" d +eqstr lparser.c /^#define eqstr(/;" d file: +equalkey ltable.c /^static int equalkey (const TValue *k1, const Node *n2) {$/;" f file: +errfile lauxlib.c /^static int errfile (lua_State *L, const char *what, int fnameindex) {$/;" f file: +errfunc lstate.h /^ ptrdiff_t errfunc; \/* current error handling function (stack index) *\/$/;" m struct:lua_State +error lundump.c /^static l_noret error(LoadState *S, const char *why) {$/;" f file: +errorJmp lstate.h /^ struct lua_longjmp *errorJmp; \/* current error recover point *\/$/;" m struct:lua_State typeref:struct:lua_State::lua_longjmp +error_expected lparser.c /^static l_noret error_expected (LexState *ls, int token) {$/;" f file: +errorlimit lparser.c /^static l_noret errorlimit (FuncState *fs, int limit, const char *what) {$/;" f file: +errorstatus ldo.c /^#define errorstatus(/;" d file: +esccheck llex.c /^static void esccheck (LexState *ls, int c, const char *msg) {$/;" f file: +event lua.h /^ int event;$/;" m struct:lua_Debug +exchangehashpart ltable.c /^static void exchangehashpart (Table *t1, Table *t2) {$/;" f file: +exp1 lparser.c /^static int exp1 (LexState *ls, int i) {$/;" f file: +exp2reg lcode.c /^static void exp2reg (FuncState *fs, expdesc *e, int reg) {$/;" f file: +expdesc lparser.h /^typedef struct expdesc {$/;" s +expdesc lparser.h /^} expdesc;$/;" t typeref:struct:expdesc +expkind lparser.h /^} expkind;$/;" t typeref:enum:__anon10 +explist lparser.c /^static int explist (LexState *ls, expdesc *v) {$/;" f file: +expr lparser.c /^static void expr (LexState *ls, expdesc *v) {$/;" f file: +exprstat lparser.c /^static void exprstat (LexState *ls) {$/;" f file: +extra lobject.h /^ lu_byte extra; \/* reserved words for short strings; "has hash" for longs *\/$/;" m struct:TString +extra_ lstate.c /^ lu_byte extra_[LUA_EXTRASPACE];$/;" m struct:LX file: +f lauxlib.c /^ FILE *f; \/* file being read *\/$/;" m struct:LoadF file: +f lauxlib.h /^ FILE *f; \/* stream (NULL for incompletely created streams) *\/$/;" m struct:luaL_Stream +f liolib.c /^ FILE *f; \/* file being read *\/$/;" m struct:__anon3 file: +f lobject.h /^ lua_CFunction f; \/* light C functions *\/$/;" m union:Value +f lobject.h /^ lua_CFunction f;$/;" m struct:CClosure +f lparser.h /^ Proto *f; \/* current function header *\/$/;" m struct:FuncState +f lparser.h /^ int f; \/* patch list of 'exit when false' *\/$/;" m struct:expdesc +f lstrlib.c /^ float f;$/;" m union:Ftypes file: +f_call lapi.c /^static void f_call (lua_State *L, void *ud) {$/;" f file: +f_close liolib.c /^static int f_close (lua_State *L) {$/;" f file: +f_flush liolib.c /^static int f_flush (lua_State *L) {$/;" f file: +f_gc liolib.c /^static int f_gc (lua_State *L) {$/;" f file: +f_lines liolib.c /^static int f_lines (lua_State *L) {$/;" f file: +f_luaopen lstate.c /^static void f_luaopen (lua_State *L, void *ud) {$/;" f file: +f_parser ldo.c /^static void f_parser (lua_State *L, void *ud) {$/;" f file: +f_read liolib.c /^static int f_read (lua_State *L) {$/;" f file: +f_seek liolib.c /^static int f_seek (lua_State *L) {$/;" f file: +f_setvbuf liolib.c /^static int f_setvbuf (lua_State *L) {$/;" f file: +f_tostring liolib.c /^static int f_tostring (lua_State *L) {$/;" f file: +f_write liolib.c /^static int f_write (lua_State *L) {$/;" f file: +fasttm ltm.h /^#define fasttm(/;" d +fchecksize lundump.c /^static void fchecksize (LoadState *S, size_t size, const char *tname) {$/;" f file: +field lparser.c /^static void field (LexState *ls, struct ConsControl *cc) {$/;" f file: +fieldargs lbitlib.c /^static int fieldargs (lua_State *L, int farg, int *width) {$/;" f file: +fieldsel lparser.c /^static void fieldsel (LexState *ls, expdesc *v) {$/;" f file: +fillmem ltests.c /^#define fillmem(/;" d file: +filterpc ldebug.c /^static int filterpc (int pc, int jmptarget) {$/;" f file: +finaltarget lcode.c /^static int finaltarget (Instruction *code, int i) {$/;" f file: +findfield lauxlib.c /^static int findfield (lua_State *L, int objidx, int level) {$/;" f file: +findfile loadlib.c /^static const char *findfile (lua_State *L, const char *name,$/;" f file: +findindex ltable.c /^static unsigned int findindex (lua_State *L, Table *t, TValue *key) {$/;" f file: +findlast lgc.c /^static GCObject **findlast (GCObject **p) {$/;" f file: +findloader loadlib.c /^static void findloader (lua_State *L, const char *name) {$/;" f file: +findlocal ldebug.c /^static const char *findlocal (lua_State *L, CallInfo *ci, int n,$/;" f file: +findpcall ldo.c /^static CallInfo *findpcall (lua_State *L) {$/;" f file: +findsetreg ldebug.c /^static int findsetreg (Proto *p, int lastpc, int reg) {$/;" f file: +finishCcall ldo.c /^static void finishCcall (lua_State *L, int status) {$/;" f file: +finishbinexpval lcode.c /^static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,$/;" f file: +finishgencycle lgc.c /^static void finishgencycle (lua_State *L, global_State *g) {$/;" f file: +finishpcall lbaselib.c /^static int finishpcall (lua_State *L, int status, lua_KContext extra) {$/;" f file: +finobj lstate.h /^ GCObject *finobj; \/* list of collectable objects with finalizers *\/$/;" m struct:global_State +finobjold lstate.h /^ GCObject *finobjold; \/* list of old objects with finalizers *\/$/;" m struct:global_State +finobjrold lstate.h /^ GCObject *finobjrold; \/* list of really old objects with finalizers *\/$/;" m struct:global_State +finobjsur lstate.h /^ GCObject *finobjsur; \/* list of survival objects with finalizers *\/$/;" m struct:global_State +firstgoto lparser.c /^ int firstgoto; \/* index of first pending goto in this block *\/$/;" m struct:BlockCnt file: +firstlabel lparser.c /^ int firstlabel; \/* index of first label in this block *\/$/;" m struct:BlockCnt file: +firstlocal lparser.h /^ int firstlocal; \/* index of first local var (in Dyndata array) *\/$/;" m struct:FuncState +fitsBx lcode.c /^static int fitsBx (lua_Integer i) {$/;" f file: +fitsC lcode.c /^static int fitsC (lua_Integer i) {$/;" f file: +fixbreaks lparser.c /^static void fixbreaks (FuncState *fs, BlockCnt *bl) {$/;" f file: +fixedgc lstate.h /^ GCObject *fixedgc; \/* list of objects not to be collected *\/$/;" m struct:global_State +fixforjump lparser.c /^static void fixforjump (FuncState *fs, int pc, int dest, int back) {$/;" f file: +fixjump lcode.c /^static void fixjump (FuncState *fs, int pc, int dest) {$/;" f file: +flags lobject.h /^ lu_byte flags; \/* 1<

locvars' *\/$/;" m struct:FuncState +nny lstate.h /^ unsigned short nny; \/* number of non-yieldable calls in stack *\/$/;" m struct:lua_State +noLuaClosure ldebug.c /^#define noLuaClosure(/;" d file: +node lobject.h /^ Node *node;$/;" m struct:Table +nodefromval ltable.h /^#define nodefromval(/;" d +noenv loadlib.c /^static int noenv (lua_State *L) {$/;" f file: +nospecials lstrlib.c /^static int nospecials (const char *p, size_t l) {$/;" f file: +novariant lobject.h /^#define novariant(/;" d +np lparser.h /^ int np; \/* number of elements in 'p' *\/$/;" m struct:FuncState +nparams lua.h /^ unsigned char nparams;\/* (u) number of parameters *\/$/;" m struct:lua_Debug +nresults lapi.c /^ int nresults;$/;" m struct:CallS file: +nresults lstate.h /^ short nresults; \/* expected number of results from this function *\/$/;" m struct:CallInfo +num2int ltests.c /^static int num2int (lua_State *L) {$/;" f file: +num2straux lstrlib.c /^static int num2straux (char *buff, int sz, lua_Number x) {$/;" f file: +numarith lobject.c /^static lua_Number numarith (lua_State *L, int op, lua_Number v1,$/;" f file: +numblocks ltests.h /^ unsigned long numblocks;$/;" m struct:Memcontrol +numparams lobject.h /^ lu_byte numparams; \/* number of fixed parameters *\/$/;" m struct:Proto +numusearray ltable.c /^static unsigned int numusearray (const Table *t, unsigned int *nums) {$/;" f file: +numusehash ltable.c /^static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {$/;" f file: +nups lparser.h /^ lu_byte nups; \/* number of upvalues *\/$/;" m struct:FuncState +nups lua.h /^ unsigned char nups; \/* (u) number of upvalues *\/$/;" m struct:lua_Debug +nuse lstate.h /^ int nuse; \/* number of elements *\/$/;" m struct:stringtable +nval lparser.h /^ lua_Number nval; \/* for VKFLT *\/$/;" m union:expdesc::__anon11 +nvalue lobject.h /^#define nvalue(/;" d +nyield lstate.h /^ int nyield; \/* number of values yielded *\/$/;" m union:CallInfo::__anon17 +obj2gco lstate.h /^#define obj2gco(/;" d +obj_at ltests.c /^#define obj_at(/;" d file: +objcount ltests.h /^ unsigned long objcount[LUA_NUMTAGS];$/;" m struct:Memcontrol +old lstate.h /^ GCObject *old; \/* start of old objects *\/$/;" m struct:global_State +old_errfunc lstate.h /^ ptrdiff_t old_errfunc;$/;" m struct:CallInfo::__anon14::__anon16 +oldpc lstate.h /^ const Instruction *oldpc; \/* last pc traced *\/$/;" m struct:lua_State +open lobject.h /^ } open;$/;" m union:UpVal::__anon6 typeref:struct:UpVal::__anon6::__anon7 +open_func lparser.c /^static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {$/;" f file: +opencheck liolib.c /^static void opencheck (lua_State *L, const char *fname, const char *mode) {$/;" f file: +openupval lstate.h /^ UpVal *openupval; \/* list of open upvalues in this stack *\/$/;" m struct:lua_State +opmode lopcodes.h /^#define opmode(/;" d +ops ltests.c /^static const char ops[] = "+-*%^\/\\\\&|~<>_!";$/;" v file: +os_clock loslib.c /^static int os_clock (lua_State *L) {$/;" f file: +os_date loslib.c /^static int os_date (lua_State *L) {$/;" f file: +os_difftime loslib.c /^static int os_difftime (lua_State *L) {$/;" f file: +os_execute loslib.c /^static int os_execute (lua_State *L) {$/;" f file: +os_exit loslib.c /^static int os_exit (lua_State *L) {$/;" f file: +os_getenv loslib.c /^static int os_getenv (lua_State *L) {$/;" f file: +os_remove loslib.c /^static int os_remove (lua_State *L) {$/;" f file: +os_rename loslib.c /^static int os_rename (lua_State *L) {$/;" f file: +os_setlocale loslib.c /^static int os_setlocale (lua_State *L) {$/;" f file: +os_time loslib.c /^static int os_time (lua_State *L) {$/;" f file: +os_tmpname loslib.c /^static int os_tmpname (lua_State *L) {$/;" f file: +otherwhite lgc.h /^#define otherwhite(/;" d +p lobject.h /^ struct Proto **p; \/* functions defined inside the function *\/$/;" m struct:Proto typeref:struct:Proto::Proto +p lobject.h /^ struct Proto *p;$/;" m struct:LClosure typeref:struct:LClosure::Proto +p lobject.h /^ void *p; \/* light userdata *\/$/;" m union:Value +p lstate.h /^ struct Proto p;$/;" m union:GCUnion typeref:struct:GCUnion::Proto +p lstrlib.c /^ const char *p; \/* pattern *\/$/;" m struct:GMatchState file: +p lstrlib.c /^ union { double d; void *p; lua_Integer i; lua_Number n; } u;$/;" m union:cD::__anon20 file: +p lzio.h /^ const char *p; \/* current position in buffer *\/$/;" m struct:Zio +p_end lstrlib.c /^ const char *p_end; \/* end ('\\0') of pattern *\/$/;" m struct:MatchState file: +pack ltablib.c /^static int pack (lua_State *L) {$/;" f file: +packint lstrlib.c /^static void packint (luaL_Buffer *b, lua_Unsigned n,$/;" f file: +pairsmeta lbaselib.c /^static int pairsmeta (lua_State *L, const char *method, int iszero,$/;" f file: +panic lauxlib.c /^static int panic (lua_State *L) {$/;" f file: +panic lstate.h /^ lua_CFunction panic; \/* to be called in unprotected errors *\/$/;" m struct:global_State +panicback ltests.c /^static int panicback (lua_State *L) {$/;" f file: +paniccode ltests.c /^struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; };$/;" m struct:Aux file: +parlist lparser.c /^static void parlist (LexState *ls) {$/;" f file: +partition ltablib.c /^static IdxT partition (lua_State *L, IdxT lo, IdxT up) {$/;" f file: +patchlistaux lcode.c /^static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,$/;" f file: +patchtestreg lcode.c /^static int patchtestreg (FuncState *fs, int node, int reg) {$/;" f file: +pc lobject.h /^ int pc;$/;" m struct:AbsLineInfo +pc lparser.h /^ int pc; \/* next position to code (equivalent to 'ncode') *\/$/;" m struct:FuncState +pc lparser.h /^ int pc; \/* position in code *\/$/;" m struct:Labeldesc +pcRel ldebug.h /^#define pcRel(/;" d +pk_funcs loadlib.c /^static const luaL_Reg pk_funcs[] = {$/;" v file: +plock ltests.h /^struct L_EXTRA { int lock; int *plock; };$/;" m struct:L_EXTRA +pmain lua.c /^static int pmain (lua_State *L) {$/;" f file: +point2uint llimits.h /^#define point2uint(/;" d +posrelat lstrlib.c /^static lua_Integer posrelat (lua_Integer pos, size_t len) {$/;" f file: +preinit_thread lstate.c /^static void preinit_thread (lua_State *L, global_State *g) {$/;" f file: +prepstate lstrlib.c /^static void prepstate (MatchState *ms, lua_State *L,$/;" f file: +prev lparser.c /^ struct LHS_assign *prev;$/;" m struct:LHS_assign typeref:struct:LHS_assign::LHS_assign file: +prev lparser.h /^ struct FuncState *prev; \/* enclosing function *\/$/;" m struct:FuncState typeref:struct:FuncState::FuncState +previous ldo.c /^ struct lua_longjmp *previous;$/;" m struct:lua_longjmp typeref:struct:lua_longjmp::lua_longjmp file: +previous lobject.h /^ struct UpVal **previous;$/;" m struct:UpVal::__anon6::__anon7 typeref:struct:UpVal::__anon6::__anon7::UpVal +previous lparser.c /^ struct BlockCnt *previous; \/* chain *\/$/;" m struct:BlockCnt typeref:struct:BlockCnt::BlockCnt file: +previous lstate.h /^ struct CallInfo *previous, *next; \/* dynamic call link *\/$/;" m struct:CallInfo typeref:struct:CallInfo::CallInfo +previousline lparser.h /^ int previousline; \/* last line that was saved in 'lineinfo' *\/$/;" m struct:FuncState +primaryexp lparser.c /^static void primaryexp (LexState *ls, expdesc *v) {$/;" f file: +print_usage lua.c /^static void print_usage (const char *badoption) {$/;" f file: +print_version lua.c /^static void print_version (void) {$/;" f file: +printcode ltests.c /^static int printcode (lua_State *L) {$/;" f file: +printobj ltests.c /^static void printobj (global_State *g, GCObject *o) {$/;" f file: +printstack ltests.c /^static void printstack (lua_State *L) {$/;" f file: +priority lparser.c /^} priority[] = { \/* ORDER OPR *\/$/;" v typeref:struct:__anon9 file: +progname lua.c /^static const char *progname = LUA_PROGNAME;$/;" v file: +propagateall lgc.c /^static lu_mem propagateall (global_State *g) {$/;" f file: +propagatemark lgc.c /^static lu_mem propagatemark (global_State *g) {$/;" f file: +protogray lstate.h /^ GCObject *protogray; \/* list of prototypes with "new" caches *\/$/;" m struct:global_State +push_captures lstrlib.c /^static int push_captures (MatchState *ms, const char *s, const char *e) {$/;" f file: +push_onecapture lstrlib.c /^static void push_onecapture (MatchState *ms, int i, const char *s,$/;" f file: +pushargs lua.c /^static int pushargs (lua_State *L) {$/;" f file: +pushclosure lvm.c /^static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,$/;" f file: +pushcode ltests.c /^static void pushcode (lua_State *L, int code) {$/;" f file: +pusherror loadlib.c /^static void pusherror (lua_State *L) {$/;" f file: +pushfuncname lauxlib.c /^static void pushfuncname (lua_State *L, lua_Debug *ar) {$/;" f file: +pushglobalfuncname lauxlib.c /^static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {$/;" f file: +pushline lua.c /^static int pushline (lua_State *L, int firstline) {$/;" f file: +pushnexttemplate loadlib.c /^static const char *pushnexttemplate (lua_State *L, const char *path) {$/;" f file: +pushnumint lmathlib.c /^static void pushnumint (lua_State *L, lua_Number d) {$/;" f file: +pushobject ltests.c /^static void pushobject (lua_State *L, const TValue *o) {$/;" f file: +pushstr lobject.c /^static void pushstr (lua_State *L, const char *str, size_t l) {$/;" f file: +pushunsigned lbitlib.c /^#define pushunsigned(/;" d file: +pushuserdata ltests.c /^static int pushuserdata (lua_State *L) {$/;" f file: +pushutfchar lutf8lib.c /^static void pushutfchar (lua_State *L, int arg) {$/;" f file: +pvalue lobject.h /^#define pvalue(/;" d +pvalueraw lobject.h /^#define pvalueraw(/;" d +quotefloat lstrlib.c /^static int quotefloat (lua_State *L, char *buff, lua_Number n) {$/;" f file: +r llex.h /^ lua_Number r;$/;" m union:__anon4 +read_all liolib.c /^static void read_all (lua_State *L, FILE *f) {$/;" f file: +read_chars liolib.c /^static int read_chars (lua_State *L, FILE *f, size_t n) {$/;" f file: +read_line liolib.c /^static int read_line (lua_State *L, FILE *f, int chop) {$/;" f file: +read_long_string llex.c /^static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {$/;" f file: +read_number liolib.c /^static int read_number (lua_State *L, FILE *f) {$/;" f file: +read_numeral llex.c /^static int read_numeral (LexState *ls, SemInfo *seminfo) {$/;" f file: +read_string llex.c /^static void read_string (LexState *ls, int del, SemInfo *seminfo) {$/;" f file: +readable loadlib.c /^static int readable (const char *filename) {$/;" f file: +readdecesc llex.c /^static int readdecesc (LexState *ls) {$/;" f file: +readdigits liolib.c /^static int readdigits (RN *rn, int hex) {$/;" f file: +reader lzio.h /^ lua_Reader reader; \/* reader function *\/$/;" m struct:Zio +readhexaesc llex.c /^static int readhexaesc (LexState *ls) {$/;" f file: +readutf8esc llex.c /^static unsigned long readutf8esc (LexState *ls) {$/;" f file: +reallymarkobject lgc.c /^static void reallymarkobject (global_State *g, GCObject *o) {$/;" f file: +reallyold lstate.h /^ GCObject *reallyold; \/* old objects with more than one cycle *\/$/;" m struct:global_State +recfield lparser.c /^static void recfield (LexState *ls, struct ConsControl *cc) {$/;" f file: +recover ldo.c /^static int recover (lua_State *L, int status) {$/;" f file: +registerlocalvar lparser.c /^static int registerlocalvar (LexState *ls, TString *varname) {$/;" f file: +rehash ltable.c /^static void rehash (lua_State *L, Table *t, const TValue *ek) {$/;" f file: +reinsert ltable.c /^static void reinsert (lua_State *L, Table *ot, Table *t) {$/;" f file: +remarkupvals lgc.c /^static int remarkupvals (global_State *g) {$/;" f file: +removeentry lgc.c /^static void removeentry (Node *n) {$/;" f file: +removevalues lcode.c /^static void removevalues (FuncState *fs, int list) {$/;" f file: +removevars lparser.c /^static void removevars (FuncState *fs, int tolevel) {$/;" f file: +repeatstat lparser.c /^static void repeatstat (LexState *ls, int line) {$/;" f file: +report lua.c /^static int report (lua_State *L, int status) {$/;" f file: +reprepstate lstrlib.c /^static void reprepstate (MatchState *ms) {$/;" f file: +resetbit lgc.h /^#define resetbit(/;" d +resetbits lgc.h /^#define resetbits(/;" d +resethookcount ldebug.h /^#define resethookcount(/;" d +resizebox lauxlib.c /^static void *resizebox (lua_State *L, int idx, size_t newsize) {$/;" f file: +restartcollection lgc.c /^static void restartcollection (global_State *g) {$/;" f file: +restorestack ldo.h /^#define restorestack(/;" d +resume ldo.c /^static void resume (lua_State *L, void *ud) {$/;" f file: +resume_error ldo.c /^static int resume_error (lua_State *L, const char *msg, int narg) {$/;" f file: +rethook ldo.c /^static void rethook (lua_State *L, CallInfo *ci) {$/;" f file: +retstat lparser.c /^static void retstat (LexState *ls) {$/;" f file: +reverse lapi.c /^static void reverse (lua_State *L, StkId from, StkId to) {$/;" f file: +right lparser.c /^ lu_byte right; \/* right priority *\/$/;" m struct:__anon9 file: +righttt lobject.h /^#define righttt(/;" d +rkname ldebug.c /^static void rkname (Proto *p, int pc, Instruction i, const char **name) {$/;" f file: +rname ldebug.c /^static void rname (Proto *p, int pc, int c, const char **name) {$/;" f file: +rttype lobject.h /^#define rttype(/;" d +runC ltests.c /^static int runC (lua_State *L, lua_State *L1, const char *pc) {$/;" f file: +runafewfinalizers lgc.c /^static int runafewfinalizers (lua_State *L, int n) {$/;" f file: +runargs lua.c /^static int runargs (lua_State *L, char **argv, int n) {$/;" f file: +s lauxlib.c /^ const char *s;$/;" m struct:LoadS file: +s2d ltests.c /^static int s2d (lua_State *L) {$/;" f file: +s2v lobject.h /^#define s2v(/;" d +save llex.c /^static void save (LexState *ls, int c) {$/;" f file: +save_and_next llex.c /^#define save_and_next(/;" d file: +savedpc lstate.h /^ const Instruction *savedpc;$/;" m struct:CallInfo::__anon14::__anon15 +savelineinfo lcode.c /^static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) {$/;" f file: +savepc lvm.c /^#define savepc(/;" d file: +savestack ldo.h /^#define savestack(/;" d +savestate lvm.c /^#define savestate(/;" d file: +scanformat lstrlib.c /^static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {$/;" f file: +searcher_C loadlib.c /^static int searcher_C (lua_State *L) {$/;" f file: +searcher_Croot loadlib.c /^static int searcher_Croot (lua_State *L) {$/;" f file: +searcher_Lua loadlib.c /^static int searcher_Lua (lua_State *L) {$/;" f file: +searcher_preload loadlib.c /^static int searcher_preload (lua_State *L) {$/;" f file: +searchpath loadlib.c /^static const char *searchpath (lua_State *L, const char *name,$/;" f file: +searchupvalue lparser.c /^static int searchupvalue (FuncState *fs, TString *name) {$/;" f file: +searchvar lparser.c /^static int searchvar (FuncState *fs, TString *n) {$/;" f file: +seed lstate.h /^ unsigned int seed; \/* randomized seed for hashes *\/$/;" m struct:global_State +semerror lparser.c /^static l_noret semerror (LexState *ls, const char *msg) {$/;" f file: +seminfo llex.h /^ SemInfo seminfo;$/;" m struct:Token +separatetobefnz lgc.c /^static void separatetobefnz (global_State *g, int all) {$/;" f file: +set2 ltablib.c /^static void set2 (lua_State *L, IdxT i, IdxT j) {$/;" f file: +set_env loadlib.c /^static void set_env (lua_State *L) {$/;" f file: +setage lgc.h /^#define setage(/;" d +setallfields loslib.c /^static void setallfields (lua_State *L, struct tm *stm) {$/;" f file: +setarg lopcodes.h /^#define setarg(/;" d +setbits lgc.h /^#define setbits(/;" d +setboolfield loslib.c /^static void setboolfield (lua_State *L, const char *key, int value) {$/;" f file: +setbvalue lobject.h /^#define setbvalue(/;" d +setclCvalue lobject.h /^#define setclCvalue(/;" d +setclLvalue lobject.h /^#define setclLvalue(/;" d +setclLvalue2s lobject.h /^#define setclLvalue2s(/;" d +setdeadkey lobject.h /^#define setdeadkey(/;" d +seterrorobj ldo.c /^static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {$/;" f file: +setfield loslib.c /^static void setfield (lua_State *L, const char *key, int value) {$/;" f file: +setfltvalue lobject.h /^#define setfltvalue(/;" d +setfvalue lobject.h /^#define setfvalue(/;" d +setgcovalue lobject.h /^#define setgcovalue(/;" d +setgcparam lgc.h /^#define setgcparam(/;" d +sethook ltests.c /^static int sethook (lua_State *L) {$/;" f file: +sethookaux ltests.c /^static void sethookaux (lua_State *L, int mask, int count, const char *scpt) {$/;" f file: +sethvalue lobject.h /^#define sethvalue(/;" d +sethvalue2s lobject.h /^#define sethvalue2s(/;" d +setivalue lobject.h /^#define setivalue(/;" d +setnameval ltests.c /^static void setnameval (lua_State *L, const char *name, int val) {$/;" f file: +setnilkey lobject.h /^#define setnilkey(/;" d +setnilvalue lobject.h /^#define setnilvalue(/;" d +setnodekey lobject.h /^#define setnodekey(/;" d +setnodevector ltable.c /^static void setnodevector (lua_State *L, Table *t, unsigned int size) {$/;" f file: +setoah lstate.h /^#define setoah(/;" d +setobj lobject.h /^#define setobj(/;" d +setobj2n lobject.h /^#define setobj2n /;" d +setobj2s lobject.h /^#define setobj2s(/;" d +setobj2t lobject.h /^#define setobj2t /;" d +setobjs2s lobject.h /^#define setobjs2s(/;" d +setobjt2t lobject.h /^#define setobjt2t /;" d +setpath loadlib.c /^static void setpath (lua_State *L, const char *fieldname,$/;" f file: +setpause lgc.c /^static void setpause (global_State *g) {$/;" f file: +setprogdir loadlib.c /^#define setprogdir(/;" d file: +setprogdir loadlib.c /^#undef setprogdir$/;" d file: +setprogdir loadlib.c /^static void setprogdir (lua_State *L) {$/;" f file: +setptvalue2s lobject.h /^#define setptvalue2s(/;" d +setpvalue lobject.h /^#define setpvalue(/;" d +setsvalue lobject.h /^#define setsvalue(/;" d +setsvalue2n lobject.h /^#define setsvalue2n /;" d +setsvalue2s lobject.h /^#define setsvalue2s(/;" d +settabsb ldblib.c /^static void settabsb (lua_State *L, const char *k, int v) {$/;" f file: +settabsi ldblib.c /^static void settabsi (lua_State *L, const char *k, int v) {$/;" f file: +settabss ldblib.c /^static void settabss (lua_State *L, const char *k, const char *v) {$/;" f file: +setthvalue lobject.h /^#define setthvalue(/;" d +setthvalue2s lobject.h /^#define setthvalue2s(/;" d +settraps ldebug.c /^static void settraps (CallInfo *ci) {$/;" f file: +settrick ltests.c /^static int settrick (lua_State *L) {$/;" f file: +settt_ lobject.h /^#define settt_(/;" d +setuservalue lobject.h /^#define setuservalue(/;" d +setuvalue lobject.h /^#define setuvalue(/;" d +short_src lua.h /^ char short_src[LUA_IDSIZE]; \/* (S) *\/$/;" m struct:lua_Debug +shrlen lobject.h /^ lu_byte shrlen; \/* length for short strings *\/$/;" m struct:TString +simpleexp lparser.c /^static void simpleexp (LexState *ls, expdesc *v) {$/;" f file: +singlematch lstrlib.c /^static int singlematch (MatchState *ms, const char *s, const char *p,$/;" f file: +singlestep lgc.c /^static lu_mem singlestep (lua_State *L) {$/;" f file: +singlevar lparser.c /^static void singlevar (LexState *ls, expdesc *var) {$/;" f file: +singlevaraux lparser.c /^static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {$/;" f file: +size lauxlib.c /^ size_t size;$/;" m struct:LoadS file: +size lauxlib.h /^ size_t size; \/* buffer size *\/$/;" m struct:luaL_Buffer +size lparser.h /^ int size;$/;" m struct:Dyndata::__anon13 +size lparser.h /^ int size; \/* array size *\/$/;" m struct:Labellist +size lstate.h /^ int size;$/;" m struct:stringtable +size ltests.c /^ size_t size;$/;" m struct:Header::__anon21 file: +sizeCclosure lfunc.h /^#define sizeCclosure(/;" d +sizeLclosure lfunc.h /^#define sizeLclosure(/;" d +sizeabslineinfo lobject.h /^ int sizeabslineinfo; \/* size of 'abslineinfo' *\/$/;" m struct:Proto +sizearray lobject.h /^ unsigned int sizearray; \/* size of 'array' array *\/$/;" m struct:Table +sizecode lobject.h /^ int sizecode;$/;" m struct:Proto +sizek lobject.h /^ int sizek; \/* size of 'k' *\/$/;" m struct:Proto +sizelineinfo lobject.h /^ int sizelineinfo;$/;" m struct:Proto +sizelocvars lobject.h /^ int sizelocvars;$/;" m struct:Proto +sizelstring lstring.h /^#define sizelstring(/;" d +sizeludata lstring.h /^#define sizeludata(/;" d +sizenode lobject.h /^#define sizenode(/;" d +sizep lobject.h /^ int sizep; \/* size of 'p' *\/$/;" m struct:Proto +sizeudata lstring.h /^#define sizeudata(/;" d +sizeupvalues lobject.h /^ int sizeupvalues; \/* size of 'upvalues' *\/$/;" m struct:Proto +skip ltests.c /^static void skip (const char **pc) {$/;" f file: +skipBOM lauxlib.c /^static int skipBOM (LoadF *lf) {$/;" f file: +skip_sep llex.c /^static int skip_sep (LexState *ls) {$/;" f file: +skipcomment lauxlib.c /^static int skipcomment (LoadF *lf, int *cp) {$/;" f file: +skipnoopstat lparser.c /^static void skipnoopstat (LexState *ls) {$/;" f file: +sof ltablib.c /^#define sof(/;" d file: +solvegotos lparser.c /^static void solvegotos (LexState *ls, Labeldesc *lb) {$/;" f file: +solvelabel lparser.c /^static int solvelabel (LexState *ls, int g) {$/;" f file: +sort ltablib.c /^static int sort (lua_State *L) {$/;" f file: +sort_comp ltablib.c /^static int sort_comp (lua_State *L, int a, int b) {$/;" f file: +source llex.h /^ TString *source; \/* current source name *\/$/;" m struct:LexState +source lobject.h /^ TString *source; \/* used for debug information *\/$/;" m struct:Proto +source lua.h /^ const char *source; \/* (S) *\/$/;" m struct:lua_Debug +src lstrlib.c /^ const char *src; \/* current position *\/$/;" m struct:GMatchState file: +src_end lstrlib.c /^ const char *src_end; \/* end ('\\0') of source string *\/$/;" m struct:MatchState file: +src_init lstrlib.c /^ const char *src_init; \/* init of source string *\/$/;" m struct:MatchState file: +stack lstate.h /^ StkId stack; \/* stack base *\/$/;" m struct:lua_State +stack_init lstate.c /^static void stack_init (lua_State *L1, lua_State *L) {$/;" f file: +stack_last lstate.h /^ StkId stack_last; \/* last free slot in the stack *\/$/;" m struct:lua_State +stackinuse ldo.c /^static int stackinuse (lua_State *L) {$/;" f file: +stacklevel ltests.c /^static int stacklevel (lua_State *L) {$/;" f file: +stacksize lstate.h /^ int stacksize;$/;" m struct:lua_State +start_capture lstrlib.c /^static const char *start_capture (MatchState *ms, const char *s,$/;" f file: +startpc lobject.h /^ int startpc; \/* first point where variable is active *\/$/;" m struct:LocVar +statement lparser.c /^static void statement (LexState *ls) {$/;" f file: +statlist lparser.c /^static void statlist (LexState *ls) {$/;" f file: +status ldo.c /^ volatile int status; \/* error code *\/$/;" m struct:lua_longjmp file: +status ldump.c /^ int status;$/;" m struct:__anon2 file: +status lstate.h /^ lu_byte status;$/;" m struct:lua_State +str_byte lstrlib.c /^static int str_byte (lua_State *L) {$/;" f file: +str_char lstrlib.c /^static int str_char (lua_State *L) {$/;" f file: +str_checkname lparser.c /^static TString *str_checkname (LexState *ls) {$/;" f file: +str_dump lstrlib.c /^static int str_dump (lua_State *L) {$/;" f file: +str_find lstrlib.c /^static int str_find (lua_State *L) {$/;" f file: +str_find_aux lstrlib.c /^static int str_find_aux (lua_State *L, int find) {$/;" f file: +str_format lstrlib.c /^static int str_format (lua_State *L) {$/;" f file: +str_gsub lstrlib.c /^static int str_gsub (lua_State *L) {$/;" f file: +str_len lstrlib.c /^static int str_len (lua_State *L) {$/;" f file: +str_lower lstrlib.c /^static int str_lower (lua_State *L) {$/;" f file: +str_match lstrlib.c /^static int str_match (lua_State *L) {$/;" f file: +str_pack lstrlib.c /^static int str_pack (lua_State *L) {$/;" f file: +str_packsize lstrlib.c /^static int str_packsize (lua_State *L) {$/;" f file: +str_rep lstrlib.c /^static int str_rep (lua_State *L) {$/;" f file: +str_reverse lstrlib.c /^static int str_reverse (lua_State *L) {$/;" f file: +str_sub lstrlib.c /^static int str_sub (lua_State *L) {$/;" f file: +str_unpack lstrlib.c /^static int str_unpack (lua_State *L) {$/;" f file: +str_upper lstrlib.c /^static int str_upper (lua_State *L) {$/;" f file: +strcache lstate.h /^ TString *strcache[STRCACHE_N][STRCACHE_M]; \/* cache for strings in API *\/$/;" m struct:global_State +string_query ltests.c /^static int string_query (lua_State *L) {$/;" f file: +stringmetamethods lstrlib.c /^static const luaL_Reg stringmetamethods[] = {$/;" v file: +stringtable lstate.h /^typedef struct stringtable {$/;" s +stringtable lstate.h /^} stringtable;$/;" t typeref:struct:stringtable +strip ldump.c /^ int strip;$/;" m struct:__anon2 file: +strlib lstrlib.c /^static const luaL_Reg strlib[] = {$/;" v file: +strt lstate.h /^ stringtable strt; \/* hash table for strings *\/$/;" m struct:global_State +subexpr lparser.c /^static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {$/;" f file: +suffixedexp lparser.c /^static void suffixedexp (LexState *ls, expdesc *v) {$/;" f file: +survival lstate.h /^ GCObject *survival; \/* start of objects that survived one GC cycle *\/$/;" m struct:global_State +svalue lobject.h /^#define svalue(/;" d +swapexps lcode.c /^static void swapexps (expdesc *e1, expdesc *e2) {$/;" f file: +sweep2old lgc.c /^static void sweep2old (lua_State *L, GCObject **p) {$/;" f file: +sweepgc lstate.h /^ GCObject **sweepgc; \/* current position of sweep in list *\/$/;" m struct:global_State +sweepgen lgc.c /^static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,$/;" f file: +sweeplist lgc.c /^static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,$/;" f file: +sweepstep lgc.c /^static int sweepstep (lua_State *L, global_State *g,$/;" f file: +sweeptolive lgc.c /^static GCObject **sweeptolive (lua_State *L, GCObject **p) {$/;" f file: +syslib loslib.c /^static const luaL_Reg syslib[] = {$/;" v file: +t llex.h /^ Token t; \/* current token *\/$/;" m struct:LexState +t lparser.c /^ expdesc *t; \/* table descriptor *\/$/;" m struct:ConsControl file: +t lparser.h /^ lu_byte t; \/* table (register or upvalue) *\/$/;" m struct:expdesc::__anon11::__anon12 +t lparser.h /^ int t; \/* patch list of 'exit when true' *\/$/;" m struct:expdesc +tab_funcs ltablib.c /^static const luaL_Reg tab_funcs[] = {$/;" v file: +table_query ltests.c /^static int table_query (lua_State *L) {$/;" f file: +tablerehash lstring.c /^static void tablerehash (TString **vect, int osize, int nsize) {$/;" f file: +tag_error lauxlib.c /^static void tag_error (lua_State *L, int arg, int tag) {$/;" f file: +tconcat ltablib.c /^static int tconcat (lua_State *L) {$/;" f file: +test2 liolib.c /^static int test2 (RN *rn, const char *set) {$/;" f file: +testAMode lopcodes.h /^#define testAMode(/;" d +testC ltests.c /^static int testC (lua_State *L) {$/;" f file: +testITMode lopcodes.h /^#define testITMode(/;" d +testOTMode lopcodes.h /^#define testOTMode(/;" d +testTMode lopcodes.h /^#define testTMode(/;" d +test_eof liolib.c /^static int test_eof (lua_State *L, FILE *f) {$/;" f file: +test_then_block lparser.c /^static void test_then_block (LexState *ls, int *escapelist) {$/;" f file: +testbit lgc.h /^#define testbit(/;" d +testbits lgc.h /^#define testbits(/;" d +testnext lparser.c /^static int testnext (LexState *ls, int c) {$/;" f file: +testobjref ltests.c /^static int testobjref (global_State *g, GCObject *f, GCObject *t) {$/;" f file: +testobjref1 ltests.c /^static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {$/;" f file: +testprop lctype.h /^#define testprop(/;" d +tests_funcs ltests.c /^static const struct luaL_Reg tests_funcs[] = {$/;" v typeref:struct:luaL_Reg file: +th lstate.h /^ struct lua_State th; \/* thread *\/$/;" m union:GCUnion typeref:struct:GCUnion::lua_State +thvalue lobject.h /^#define thvalue(/;" d +tinsert ltablib.c /^static int tinsert (lua_State *L) {$/;" f file: +tmname lstate.h /^ TString *tmname[TM_N]; \/* array with tag-method names *\/$/;" m struct:global_State +tmove ltablib.c /^static int tmove (lua_State *L) {$/;" f file: +tobefnz lstate.h /^ GCObject *tobefnz; \/* list of userdata to be GC *\/$/;" m struct:global_State +tofile liolib.c /^static FILE *tofile (lua_State *L) {$/;" f file: +tofinalize lgc.h /^#define tofinalize(/;" d +toint lstrlib.c /^static int toint (lua_State *L, int arg) {$/;" f file: +tointeger lvm.h /^#define tointeger(/;" d +tointegerns lvm.h /^#define tointegerns(/;" d +token llex.h /^ int token;$/;" m struct:Token +tolstream liolib.c /^#define tolstream(/;" d file: +tonum lstrlib.c /^static int tonum (lua_State *L, int arg) {$/;" f file: +tonumber lvm.h /^#define tonumber(/;" d +tonumberns lvm.h /^#define tonumberns(/;" d +tonumeral lcode.c /^static int tonumeral(const expdesc *e, TValue *v) {$/;" f file: +top lstate.h /^ StkId top; \/* top for this function *\/$/;" m struct:CallInfo +top lstate.h /^ StkId top; \/* first free slot in the stack *\/$/;" m struct:lua_State +tostore lparser.c /^ int tostore; \/* number of array elements pending to be stored *\/$/;" m struct:ConsControl file: +tostring lvm.c /^#define tostring(/;" d file: +total ltests.h /^ unsigned long total;$/;" m struct:Memcontrol +totalbytes lstate.h /^ l_mem totalbytes; \/* number of bytes currently allocated - GCdebt *\/$/;" m struct:global_State +tpanic ltests.c /^static int tpanic (lua_State *L) {$/;" f file: +trap lstate.h /^ l_signalT trap;$/;" m struct:CallInfo::__anon14::__anon15 +traverseCclosure lgc.c /^static int traverseCclosure (global_State *g, CClosure *cl) {$/;" f file: +traverseLclosure lgc.c /^static int traverseLclosure (global_State *g, LClosure *cl) {$/;" f file: +traverseephemeron lgc.c /^static int traverseephemeron (global_State *g, Table *h) {$/;" f file: +traverseproto lgc.c /^static int traverseproto (global_State *g, Proto *f) {$/;" f file: +traversestrongtable lgc.c /^static void traversestrongtable (global_State *g, Table *h) {$/;" f file: +traversetable lgc.c /^static lu_mem traversetable (global_State *g, Table *h) {$/;" f file: +traversethread lgc.c /^static int traversethread (global_State *g, lua_State *th) {$/;" f file: +traverseweakvalue lgc.c /^static void traverseweakvalue (global_State *g, Table *h) {$/;" f file: +treatstackoption ldblib.c /^static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {$/;" f file: +tref ltests.c /^static int tref (lua_State *L) {$/;" f file: +tremove ltablib.c /^static int tremove (lua_State *L) {$/;" f file: +trim lbitlib.c /^#define trim(/;" d file: +trymt lstrlib.c /^static void trymt (lua_State *L, const char *mtname) {$/;" f file: +ts llex.h /^ TString *ts;$/;" m union:__anon4 +ts lstate.h /^ struct TString ts;$/;" m union:GCUnion typeref:struct:GCUnion::TString +tsslen lobject.h /^#define tsslen(/;" d +tsv lobject.h /^ TString tsv;$/;" m union:UTString +tsvalue lobject.h /^#define tsvalue(/;" d +tsvalueraw lobject.h /^#define tsvalueraw(/;" d +ttisCclosure lobject.h /^#define ttisCclosure(/;" d +ttisLclosure lobject.h /^#define ttisLclosure(/;" d +ttisboolean lobject.h /^#define ttisboolean(/;" d +ttisclosure lobject.h /^#define ttisclosure(/;" d +ttisfloat lobject.h /^#define ttisfloat(/;" d +ttisfulluserdata lobject.h /^#define ttisfulluserdata(/;" d +ttisfunction lobject.h /^#define ttisfunction(/;" d +ttisinteger lobject.h /^#define ttisinteger(/;" d +ttislcf lobject.h /^#define ttislcf(/;" d +ttislightuserdata lobject.h /^#define ttislightuserdata(/;" d +ttislngstring lobject.h /^#define ttislngstring(/;" d +ttisnil lobject.h /^#define ttisnil(/;" d +ttisnumber lobject.h /^#define ttisnumber(/;" d +ttisshrstring lobject.h /^#define ttisshrstring(/;" d +ttisstring lobject.h /^#define ttisstring(/;" d +ttistable lobject.h /^#define ttistable(/;" d +ttisthread lobject.h /^#define ttisthread(/;" d +ttnov lobject.h /^#define ttnov(/;" d +ttuv_ lobject.h /^ lu_byte ttuv_; \/* user value's tag *\/$/;" m struct:Udata +ttype lobject.h /^#define ttype(/;" d +ttypename ltm.h /^#define ttypename(/;" d +ttyperaw lobject.h /^#define ttyperaw(/;" d +twoto lobject.h /^#define twoto(/;" d +twups lstate.h /^ struct lua_State *twups; \/* list of threads with open upvalues *\/$/;" m struct:global_State typeref:struct:global_State::lua_State +twups lstate.h /^ struct lua_State *twups; \/* list of threads with open upvalues *\/$/;" m struct:lua_State typeref:struct:lua_State::lua_State +txtToken llex.c /^static const char *txtToken (LexState *ls, int token) {$/;" f file: +type ltests.c /^ int type;$/;" m struct:Header::__anon21 file: +typeerror lauxlib.c /^static int typeerror (lua_State *L, int arg, const char *tname) {$/;" f file: +u lobject.h /^ } u;$/;" m struct:TString typeref:union:TString::__anon5 +u lobject.h /^ } u;$/;" m struct:UpVal typeref:union:UpVal::__anon6 +u lobject.h /^ } u;$/;" m union:Node typeref:struct:Node::NodeKey +u lparser.h /^ } u;$/;" m struct:expdesc typeref:union:expdesc::__anon11 +u lstate.h /^ struct Udata u;$/;" m union:GCUnion typeref:struct:GCUnion::Udata +u lstate.h /^ } u;$/;" m struct:CallInfo typeref:union:CallInfo::__anon14 +u lstrlib.c /^ union { double d; void *p; lua_Integer i; lua_Number n; } u;$/;" m struct:cD typeref:union:cD::__anon20 file: +u2 lstate.h /^ } u2;$/;" m struct:CallInfo typeref:union:CallInfo::__anon17 +u_posrelat lutf8lib.c /^static lua_Integer u_posrelat (lua_Integer pos, size_t len) {$/;" f file: +uchar lstrlib.c /^#define uchar(/;" d file: +ud lstate.h /^ void *ud; \/* auxiliary data to 'frealloc' *\/$/;" m struct:global_State +udata2finalize lgc.c /^static GCObject *udata2finalize (global_State *g) {$/;" f file: +udatatypename ltm.c /^static const char udatatypename[] = "userdata";$/;" v file: +udataval ltests.c /^static int udataval (lua_State *L) {$/;" f file: +undefgoto lparser.c /^static l_noret undefgoto (LexState *ls, Labeldesc *gt) {$/;" f file: +unmakemask ldblib.c /^static char *unmakemask (int mask, char *smask) {$/;" f file: +unpack ltablib.c /^static int unpack (lua_State *L) {$/;" f file: +unpackint lstrlib.c /^static lua_Integer unpackint (lua_State *L, const char *str,$/;" f file: +unref ltests.c /^static int unref (lua_State *L) {$/;" f file: +unroll ldo.c /^static void unroll (lua_State *L, void *ud) {$/;" f file: +updatebase lvm.c /^#define updatebase(/;" d file: +updatetrap lvm.c /^#define updatetrap(/;" d file: +upisopen lfunc.h /^#define upisopen(/;" d +uplevel lfunc.h /^#define uplevel(/;" d +upv lstate.h /^ struct UpVal upv;$/;" m union:GCUnion typeref:struct:GCUnion::UpVal +upval lparser.c /^ lu_byte upval; \/* true if some variable in the block is an upvalue *\/$/;" m struct:BlockCnt file: +upvalname ldebug.c /^static const char *upvalname (Proto *p, int uv) {$/;" f file: +upvals lobject.h /^ UpVal *upvals[1]; \/* list of upvalues *\/$/;" m struct:LClosure +upvalue lobject.h /^ TValue upvalue[1]; \/* list of upvalues *\/$/;" m struct:CClosure +upvalue ltests.c /^static int upvalue (lua_State *L) {$/;" f file: +upvalues lobject.h /^ Upvaldesc *upvalues; \/* upvalue information *\/$/;" m struct:Proto +user_ lobject.h /^ union Value user_; \/* user value *\/$/;" m struct:Udata typeref:union:Udata::Value +utf8_decode lutf8lib.c /^static const char *utf8_decode (const char *o, int *val) {$/;" f file: +utf8esc llex.c /^static void utf8esc (LexState *ls) {$/;" f file: +utfchar lutf8lib.c /^static int utfchar (lua_State *L) {$/;" f file: +utflen lutf8lib.c /^static int utflen (lua_State *L) {$/;" f file: +uv lobject.h /^ Udata uv;$/;" m union:UUdata +uvalue lobject.h /^#define uvalue(/;" d +v lobject.h /^ TValue *v; \/* points to stack or to its own value *\/$/;" m struct:UpVal +v lparser.c /^ expdesc v; \/* last list item read *\/$/;" m struct:ConsControl file: +v lparser.c /^ expdesc v; \/* variable (global, local, upvalue, or indexed) *\/$/;" m struct:LHS_assign file: +vRB lvm.c /^#define vRB(/;" d file: +vRC lvm.c /^#define vRC(/;" d file: +val lobject.h /^ TValue val;$/;" m union:StackValue +val_ lobject.h /^#define val_(/;" d +validop lcode.c /^static int validop (int op, TValue *v1, TValue *v2) {$/;" f file: +valiswhite lgc.c /^#define valiswhite(/;" d file: +valraw lobject.h /^#define valraw(/;" d +value lobject.h /^ TValue value; \/* the value (when closed) *\/$/;" m union:UpVal::__anon6 +varinfo ldebug.c /^static const char *varinfo (lua_State *L, const TValue *o) {$/;" f file: +varname lobject.h /^ TString *varname;$/;" m struct:LocVar +version lstate.h /^ const lua_Number *version; \/* pointer to version number *\/$/;" m struct:global_State +vkisindexed lparser.h /^#define vkisindexed(/;" d +vkisinreg lparser.h /^#define vkisinreg(/;" d +vkisvar lparser.h /^#define vkisvar(/;" d +vmbreak lvm.c /^#define vmbreak /;" d file: +vmcase lvm.c /^#define vmcase(/;" d file: +vmdispatch lvm.c /^#define vmdispatch(/;" d file: +vmfetch lvm.c /^#define vmfetch(/;" d file: +vslen lobject.h /^#define vslen(/;" d +weak lstate.h /^ GCObject *weak; \/* list of tables with weak values *\/$/;" m struct:global_State +what lua.h /^ const char *what; \/* (S) 'Lua', 'C', 'main', 'tail' *\/$/;" m struct:lua_Debug +whilestat lparser.c /^static void whilestat (LexState *ls, int line) {$/;" f file: +white2gray lgc.c /^#define white2gray(/;" d file: +whitelist lgc.c /^static void whitelist (global_State *g, GCObject *p) {$/;" f file: +writer ldump.c /^ lua_Writer writer;$/;" m struct:__anon2 file: +writer lstrlib.c /^static int writer (lua_State *L, const void *b, size_t size, void *B) {$/;" f file: +yindex lparser.c /^static void yindex (LexState *ls, expdesc *v) {$/;" f file: +youngcollection lgc.c /^static void youngcollection (lua_State *L, global_State *g) {$/;" f file: +z ldo.c /^ ZIO *z;$/;" m struct:SParser file: +z llex.h /^ ZIO *z; \/* input stream *\/$/;" m struct:LexState +zgetc lzio.h /^#define zgetc(/;" d diff --git a/SConstruct b/SConstruct index 648e28b9d..711d3d787 100644 --- a/SConstruct +++ b/SConstruct @@ -7,7 +7,7 @@ LFTK_TOOLS_ROOT = os.path.join(LFTK_ROOT, 'tools') GTEST_ROOT = os.path.join(LFTK_ROOT, '3rd/gtest/googletest') if os.name == 'posix': - OS_FLAGS='-g -Wall' + OS_FLAGS='-g -Wall -DLUA_USE_POSIX -DLUA_COMPAT_MODULE' OS_LINKFLAGS='' OS_LIBPATH=[] OS_CPPPATH=[] @@ -16,7 +16,7 @@ if os.name == 'posix': OS_SUBSYSTEM_WINDOWS='' elif os.name == 'nt': - OS_FLAGS='-DWIN32 -DWINDOWS /EHsc -D_CONSOLE /DEBUG /INCREMENTA -DUNICODE -D_UNICODE' + OS_FLAGS='-DWIN32 -DWINDOWS /EHsc -D_CONSOLE /DEBUG /INCREMENTA -DUNICODE -D_UNICODE -DLUA_USE_POSIX -DLUA_COMPAT_MODULE' OS_LINKFLAGS='/MACHINE:X64 ' OS_LIBPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/lib/x64'] OS_CPPPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/'] @@ -35,6 +35,7 @@ DefaultEnvironment(CCFLAGS = OS_FLAGS + ' -DLFTK_ROOT=\\\"'+LFTK_ROOT+'\\\"', OS_SUBSYSTEM_CONSOLE=OS_SUBSYSTEM_CONSOLE, OS_SUBSYSTEM_WINDOWS=OS_SUBSYSTEM_WINDOWS, LIBPATH=[os.path.join(LFTK_ROOT, 'src/base'), + os.path.join(LFTK_3RD_ROOT, 'lua'), os.path.join(LFTK_ROOT, 'src/platforms'), os.path.join(LFTK_ROOT, 'src/widgets'), os.path.join(LFTK_ROOT, 'src/lcd'), @@ -64,5 +65,6 @@ SConscript([ 'tools/font_gen/SConscript', 'tools/image_gen/SConscript', 'tests/SConscript', + '3rd/lua/SConscript', 'lua/SConscript' ]) diff --git a/lua/.gitignore b/lua/.gitignore new file mode 100644 index 000000000..891bf0272 --- /dev/null +++ b/lua/.gitignore @@ -0,0 +1 @@ +run_lua diff --git a/lua/button.lua b/lua/button.lua index acfc396eb..5aa12a48a 100644 --- a/lua/button.lua +++ b/lua/button.lua @@ -20,7 +20,7 @@ function application_init() print(ok, getmetatable(ok)); print(e, getmetatable(e)); print("on click:" .. tostring(e.x) .. " " .. tostring(e.y)) - -- ok:off(rid) + ok:off(rid) return Ret.OK; end); diff --git a/lua/custom.c b/lua/custom.c index fb23fa593..b01e000c7 100644 --- a/lua/custom.c +++ b/lua/custom.c @@ -1,12 +1,34 @@ +typedef struct _userdata_info_t { + const char* info; + void* data; +}userdata_info_t; static lua_State* s_current_L = NULL; extern void luaL_openlib (lua_State *L, const char *libname, const luaL_Reg *l, int nup); +static int lftk_newuserdata(lua_State* L, void* data, const char* info, const char* metatable) { + userdata_info_t* udata = NULL; + return_value_if_fail(data != NULL, 0); + + udata = (userdata_info_t*)lua_newuserdata(L, sizeof(userdata_info_t)); + return_value_if_fail(data != NULL, 0); + + udata->data = data; + udata->info = info; + + if(metatable != NULL) { + luaL_getmetatable(L, metatable); + lua_setmetatable(L, -2); + } + + return 1; +} + static const luaL_Reg* find_member(const luaL_Reg* funcs, const char* name) { const luaL_Reg* iter = funcs; while(iter->name) { - if(strcmp(iter->name, name) == 0) { + if(*iter->name == *name && strcmp(iter->name, name) == 0) { return iter; } iter++; @@ -16,8 +38,13 @@ static const luaL_Reg* find_member(const luaL_Reg* funcs, const char* name) { } static void* lftk_checkudata(lua_State* L, int idx, const char* name) { - (void)name; - return lua_touserdata(L, idx); + userdata_info_t* udata = (userdata_info_t*)lua_touserdata(L, idx); + if(udata) { + assert(strstr(udata->info, name) != NULL); + return udata->data; + } else { + return NULL; + } } static ret_t call_on_event(void* ctx, event_t* e) { @@ -26,7 +53,7 @@ static ret_t call_on_event(void* ctx, event_t* e) { lua_settop(L, 0); lua_rawgeti(L, LUA_REGISTRYINDEX, func_id); - lua_pushlightuserdata(L, e); + lftk_newuserdata(L, e, "event_t", NULL); lua_pcall(L,1,1,0); @@ -35,7 +62,7 @@ static ret_t call_on_event(void* ctx, event_t* e) { static int wrap_widget_on(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); event_type_t type = (event_type_t)luaL_checkinteger(L, 2); if(lua_isfunction(L, 3)) { @@ -44,6 +71,7 @@ static int wrap_widget_on(lua_State* L) { func_id = luaL_ref(L, LUA_REGISTRYINDEX); ret = (ret_t)widget_on(widget, type, call_on_event, (char*)NULL + func_id); lua_pushnumber(L,(lua_Number)ret); + return 1; } else { return 0; @@ -52,11 +80,10 @@ static int wrap_widget_on(lua_State* L) { static int wrap_widget_off(lua_State* L) { ret_t ret = 0; - printf("top=%d\n", lua_gettop(L)); - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint32_t id = (uint32_t)luaL_checkinteger(L, 2); emitter_item_t* item = emitter_find(widget->emitter, id); - printf("%s id=%d\n", __func__, id); + if(item) { uint32_t func_id = (char*)(item->ctx) - (char*)NULL; luaL_unref(L, LUA_REGISTRYINDEX, func_id); diff --git a/lua/demo1.lua b/lua/demo1.lua new file mode 100644 index 000000000..8f46b20a9 --- /dev/null +++ b/lua/demo1.lua @@ -0,0 +1,31 @@ +function on_click(ctx, evt) + print('on_click'); +end + +function application_init() + local win = Window.create(nil, 0, 0, 0, 0) + local inc = Button.create(win, 10, 5, 80, 30) + inc:set_text(to_wstr('Inc')); + + local dec = Button.create(win, 100, 5, 80, 30); + dec:set_text(to_wstr('Dec')); + + local progress_bar = ProgressBar.create(win, 10, 80, 168, 30); + progress_bar:set_value(40); + + inc:on(EventType.EVT_CLICK, function(evt) + local e = PointerEvent.cast(evt); + progress_bar:set_value(progress_bar.value + 10); + print('on inc click:(' .. tostring(e.x) .. ' ' .. tostring(e.y) .. ')') + end); + + dec:on(EventType.EVT_CLICK, function(evt) + local e = PointerEvent.cast(evt); + progress_bar:set_value(progress_bar.value - 10); + print('on dec click:(' .. tostring(e.x) .. ' ' .. tostring(e.y) .. ')') + end); +end + +application_init() + + diff --git a/lua/lftk_lua.c b/lua/lftk_lua.c index f54ca9e57..57c4598f8 100644 --- a/lua/lftk_lua.c +++ b/lua/lftk_lua.c @@ -79,23 +79,19 @@ static void globals_init(lua_State* L) { static int wrap_button_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)button_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.button_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/button_t/widget_t", "lftk.button_t"); } static int wrap_button_set_text(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wchar_t* text = (wchar_t*)lua_touserdata(L, 2); ret = (ret_t)button_set_text(widget, text); @@ -111,7 +107,7 @@ static const struct luaL_Reg button_t_member_funcs[] = { }; static int wrap_button_t_set_prop(lua_State* L) { - button_t* obj = (button_t*)lftk_checkudata(L, 1, "lftk.button_t"); + button_t* obj = (button_t*)lftk_checkudata(L, 1, "button_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -121,7 +117,7 @@ static int wrap_button_t_set_prop(lua_State* L) { } static int wrap_button_t_get_prop(lua_State* L) { - button_t* obj = (button_t*)lftk_checkudata(L, 1, "lftk.button_t"); + button_t* obj = (button_t*)lftk_checkudata(L, 1, "button_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(button_t_member_funcs, name); @@ -158,39 +154,31 @@ static void button_t_init(lua_State* L) { } static int wrap_check_button_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)check_button_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.check_button_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/check_button_t/widget_t", "lftk.check_button_t"); } static int wrap_check_button_create_radio(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)check_button_create_radio(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.check_button_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/check_button_t/widget_t", "lftk.check_button_t"); } static int wrap_check_button_set_text(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wchar_t* text = (wchar_t*)lua_touserdata(L, 2); ret = (ret_t)check_button_set_text(widget, text); @@ -201,7 +189,7 @@ static int wrap_check_button_set_text(lua_State* L) { static int wrap_check_button_set_value(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint32_t value = (uint32_t)luaL_checkinteger(L, 2); ret = (ret_t)check_button_set_value(widget, value); @@ -218,7 +206,7 @@ static const struct luaL_Reg check_button_t_member_funcs[] = { }; static int wrap_check_button_t_set_prop(lua_State* L) { - check_button_t* obj = (check_button_t*)lftk_checkudata(L, 1, "lftk.check_button_t"); + check_button_t* obj = (check_button_t*)lftk_checkudata(L, 1, "check_button_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -232,7 +220,7 @@ static int wrap_check_button_t_set_prop(lua_State* L) { } static int wrap_check_button_t_get_prop(lua_State* L) { - check_button_t* obj = (check_button_t*)lftk_checkudata(L, 1, "lftk.check_button_t"); + check_button_t* obj = (check_button_t*)lftk_checkudata(L, 1, "check_button_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(check_button_t_member_funcs, name); @@ -244,7 +232,8 @@ static int wrap_check_button_t_get_prop(lua_State* L) { } if(strcmp(name, "value") == 0) { lua_pushboolean(L,(lua_Integer)(obj->value)); - return 1; + + return 1; } else { return wrap_widget_t_get_prop(L); @@ -274,23 +263,19 @@ static void check_button_t_init(lua_State* L) { } static int wrap_dialog_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)dialog_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.dialog_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/dialog_t/widget_t", "lftk.dialog_t"); } static int wrap_dialog_set_icon(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); ret = (ret_t)dialog_set_icon(widget, name); @@ -301,7 +286,7 @@ static int wrap_dialog_set_icon(lua_State* L) { static int wrap_dialog_set_title(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wchar_t* title = (wchar_t*)lua_touserdata(L, 2); ret = (ret_t)dialog_set_title(widget, title); @@ -312,7 +297,7 @@ static int wrap_dialog_set_title(lua_State* L) { static int wrap_dialog_modal(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (ret_t)dialog_modal(widget); lua_pushnumber(L,(lua_Number)(ret)); @@ -322,7 +307,7 @@ static int wrap_dialog_modal(lua_State* L) { static int wrap_dialog_quit(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint32_t code = (uint32_t)luaL_checkinteger(L, 2); ret = (ret_t)dialog_quit(widget, code); @@ -341,7 +326,7 @@ static const struct luaL_Reg dialog_t_member_funcs[] = { }; static int wrap_dialog_t_set_prop(lua_State* L) { - dialog_t* obj = (dialog_t*)lftk_checkudata(L, 1, "lftk.dialog_t"); + dialog_t* obj = (dialog_t*)lftk_checkudata(L, 1, "dialog_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -351,7 +336,7 @@ static int wrap_dialog_t_set_prop(lua_State* L) { } static int wrap_dialog_t_get_prop(lua_State* L) { - dialog_t* obj = (dialog_t*)lftk_checkudata(L, 1, "lftk.dialog_t"); + dialog_t* obj = (dialog_t*)lftk_checkudata(L, 1, "dialog_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(dialog_t_member_funcs, name); @@ -455,7 +440,7 @@ static const struct luaL_Reg event_t_member_funcs[] = { }; static int wrap_event_t_set_prop(lua_State* L) { - event_t* obj = (event_t*)lftk_checkudata(L, 1, "lftk.event_t"); + event_t* obj = (event_t*)lftk_checkudata(L, 1, "event_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -470,7 +455,7 @@ static int wrap_event_t_set_prop(lua_State* L) { } static int wrap_event_t_get_prop(lua_State* L) { - event_t* obj = (event_t*)lftk_checkudata(L, 1, "lftk.event_t"); + event_t* obj = (event_t*)lftk_checkudata(L, 1, "event_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(event_t_member_funcs, name); @@ -482,7 +467,8 @@ static int wrap_event_t_get_prop(lua_State* L) { } if(strcmp(name, "type") == 0) { lua_pushinteger(L,(lua_Integer)(obj->type)); - return 1; + + return 1; } else { printf("%s: not supported %s\n", __func__, name); @@ -511,14 +497,10 @@ static void event_t_init(lua_State* L) { } static int wrap_pointer_event_cast(lua_State* L) { pointer_event_t* ret = NULL; - event_t* event = (event_t*)lftk_checkudata(L, 1, "lftk.event_t"); + event_t* event = (event_t*)lftk_checkudata(L, 1, "event_t"); ret = (pointer_event_t*)pointer_event_cast(event); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.pointer_event_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/pointer_event_t/event_t", "lftk.pointer_event_t"); } @@ -527,7 +509,7 @@ static const struct luaL_Reg pointer_event_t_member_funcs[] = { }; static int wrap_pointer_event_t_set_prop(lua_State* L) { - pointer_event_t* obj = (pointer_event_t*)lftk_checkudata(L, 1, "lftk.pointer_event_t"); + pointer_event_t* obj = (pointer_event_t*)lftk_checkudata(L, 1, "pointer_event_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -553,7 +535,7 @@ static int wrap_pointer_event_t_set_prop(lua_State* L) { } static int wrap_pointer_event_t_get_prop(lua_State* L) { - pointer_event_t* obj = (pointer_event_t*)lftk_checkudata(L, 1, "lftk.pointer_event_t"); + pointer_event_t* obj = (pointer_event_t*)lftk_checkudata(L, 1, "pointer_event_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(pointer_event_t_member_funcs, name); @@ -565,19 +547,23 @@ static int wrap_pointer_event_t_get_prop(lua_State* L) { } if(strcmp(name, "x") == 0) { lua_pushnumber(L,(lua_Number)(obj->x)); - return 1; + + return 1; } else if(strcmp(name, "y") == 0) { lua_pushnumber(L,(lua_Number)(obj->y)); - return 1; + + return 1; } else if(strcmp(name, "button") == 0) { lua_pushinteger(L,(lua_Integer)(obj->button)); - return 1; + + return 1; } else if(strcmp(name, "pressed") == 0) { lua_pushboolean(L,(lua_Integer)(obj->pressed)); - return 1; + + return 1; } else { return wrap_event_t_get_prop(L); @@ -606,14 +592,10 @@ static void pointer_event_t_init(lua_State* L) { } static int wrap_key_event_cast(lua_State* L) { key_event_t* ret = NULL; - event_t* event = (event_t*)lftk_checkudata(L, 1, "lftk.event_t"); + event_t* event = (event_t*)lftk_checkudata(L, 1, "event_t"); ret = (key_event_t*)key_event_cast(event); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.key_event_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/key_event_t/event_t", "lftk.key_event_t"); } @@ -622,7 +604,7 @@ static const struct luaL_Reg key_event_t_member_funcs[] = { }; static int wrap_key_event_t_set_prop(lua_State* L) { - key_event_t* obj = (key_event_t*)lftk_checkudata(L, 1, "lftk.key_event_t"); + key_event_t* obj = (key_event_t*)lftk_checkudata(L, 1, "key_event_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -648,7 +630,7 @@ static int wrap_key_event_t_set_prop(lua_State* L) { } static int wrap_key_event_t_get_prop(lua_State* L) { - key_event_t* obj = (key_event_t*)lftk_checkudata(L, 1, "lftk.key_event_t"); + key_event_t* obj = (key_event_t*)lftk_checkudata(L, 1, "key_event_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(key_event_t_member_funcs, name); @@ -660,19 +642,23 @@ static int wrap_key_event_t_get_prop(lua_State* L) { } if(strcmp(name, "key") == 0) { lua_pushinteger(L,(lua_Integer)(obj->key)); - return 1; + + return 1; } else if(strcmp(name, "alt") == 0) { lua_pushboolean(L,(lua_Integer)(obj->alt)); - return 1; + + return 1; } else if(strcmp(name, "ctrl") == 0) { lua_pushboolean(L,(lua_Integer)(obj->ctrl)); - return 1; + + return 1; } else if(strcmp(name, "shift") == 0) { lua_pushboolean(L,(lua_Integer)(obj->shift)); - return 1; + + return 1; } else { return wrap_event_t_get_prop(L); @@ -701,18 +687,14 @@ static void key_event_t_init(lua_State* L) { } static int wrap_group_box_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)group_box_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.group_box_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/group_box_t/widget_t", "lftk.group_box_t"); } @@ -721,7 +703,7 @@ static const struct luaL_Reg group_box_t_member_funcs[] = { }; static int wrap_group_box_t_set_prop(lua_State* L) { - group_box_t* obj = (group_box_t*)lftk_checkudata(L, 1, "lftk.group_box_t"); + group_box_t* obj = (group_box_t*)lftk_checkudata(L, 1, "group_box_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -731,7 +713,7 @@ static int wrap_group_box_t_set_prop(lua_State* L) { } static int wrap_group_box_t_get_prop(lua_State* L) { - group_box_t* obj = (group_box_t*)lftk_checkudata(L, 1, "lftk.group_box_t"); + group_box_t* obj = (group_box_t*)lftk_checkudata(L, 1, "group_box_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(group_box_t_member_funcs, name); @@ -768,23 +750,19 @@ static void group_box_t_init(lua_State* L) { } static int wrap_image_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)image_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.image_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/image_t/widget_t", "lftk.image_t"); } static int wrap_image_set_image_name(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); ret = (ret_t)image_set_image_name(widget, name); @@ -800,7 +778,7 @@ static const struct luaL_Reg image_t_member_funcs[] = { }; static int wrap_image_t_set_prop(lua_State* L) { - image_t* obj = (image_t*)lftk_checkudata(L, 1, "lftk.image_t"); + image_t* obj = (image_t*)lftk_checkudata(L, 1, "image_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -810,7 +788,7 @@ static int wrap_image_t_set_prop(lua_State* L) { } static int wrap_image_t_get_prop(lua_State* L) { - image_t* obj = (image_t*)lftk_checkudata(L, 1, "lftk.image_t"); + image_t* obj = (image_t*)lftk_checkudata(L, 1, "image_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(image_t_member_funcs, name); @@ -847,23 +825,19 @@ static void image_t_init(lua_State* L) { } static int wrap_label_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)label_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.label_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/label_t/widget_t", "lftk.label_t"); } static int wrap_label_set_border(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint8_t border = (uint8_t)luaL_checkinteger(L, 2); ret = (ret_t)label_set_border(widget, border); @@ -874,7 +848,7 @@ static int wrap_label_set_border(lua_State* L) { static int wrap_label_set_text_align_h(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint8_t text_align_h = (uint8_t)luaL_checkinteger(L, 2); ret = (ret_t)label_set_text_align_h(widget, text_align_h); @@ -885,7 +859,7 @@ static int wrap_label_set_text_align_h(lua_State* L) { static int wrap_label_set_text_align_v(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint8_t text_align_v = (uint8_t)luaL_checkinteger(L, 2); ret = (ret_t)label_set_text_align_v(widget, text_align_v); @@ -896,7 +870,7 @@ static int wrap_label_set_text_align_v(lua_State* L) { static int wrap_label_set_text(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wchar_t* text = (wchar_t*)lua_touserdata(L, 2); ret = (ret_t)label_set_text(widget, text); @@ -915,7 +889,7 @@ static const struct luaL_Reg label_t_member_funcs[] = { }; static int wrap_label_t_set_prop(lua_State* L) { - label_t* obj = (label_t*)lftk_checkudata(L, 1, "lftk.label_t"); + label_t* obj = (label_t*)lftk_checkudata(L, 1, "label_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -937,7 +911,7 @@ static int wrap_label_t_set_prop(lua_State* L) { } static int wrap_label_t_get_prop(lua_State* L) { - label_t* obj = (label_t*)lftk_checkudata(L, 1, "lftk.label_t"); + label_t* obj = (label_t*)lftk_checkudata(L, 1, "label_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(label_t_member_funcs, name); @@ -949,15 +923,18 @@ static int wrap_label_t_get_prop(lua_State* L) { } if(strcmp(name, "border") == 0) { lua_pushinteger(L,(lua_Integer)(obj->border)); - return 1; + + return 1; } else if(strcmp(name, "text_align_v") == 0) { lua_pushinteger(L,(lua_Integer)(obj->text_align_v)); - return 1; + + return 1; } else if(strcmp(name, "text_align_h") == 0) { lua_pushinteger(L,(lua_Integer)(obj->text_align_h)); - return 1; + + return 1; } else { return wrap_widget_t_get_prop(L); @@ -986,23 +963,19 @@ static void label_t_init(lua_State* L) { } static int wrap_progress_bar_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)progress_bar_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.progress_bar_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/progress_bar_t/widget_t", "lftk.progress_bar_t"); } static int wrap_progress_bar_set_value(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint8_t value = (uint8_t)luaL_checkinteger(L, 2); ret = (ret_t)progress_bar_set_value(widget, value); @@ -1013,7 +986,7 @@ static int wrap_progress_bar_set_value(lua_State* L) { static int wrap_progress_bar_set_vertical(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); bool_t vertical = (bool_t)lua_toboolean(L, 2); ret = (ret_t)progress_bar_set_vertical(widget, vertical); @@ -1024,7 +997,7 @@ static int wrap_progress_bar_set_vertical(lua_State* L) { static int wrap_progress_bar_set_show_text(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); bool_t show_text = (bool_t)lua_toboolean(L, 2); ret = (ret_t)progress_bar_set_show_text(widget, show_text); @@ -1042,7 +1015,7 @@ static const struct luaL_Reg progress_bar_t_member_funcs[] = { }; static int wrap_progress_bar_t_set_prop(lua_State* L) { - progress_bar_t* obj = (progress_bar_t*)lftk_checkudata(L, 1, "lftk.progress_bar_t"); + progress_bar_t* obj = (progress_bar_t*)lftk_checkudata(L, 1, "progress_bar_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1064,7 +1037,7 @@ static int wrap_progress_bar_t_set_prop(lua_State* L) { } static int wrap_progress_bar_t_get_prop(lua_State* L) { - progress_bar_t* obj = (progress_bar_t*)lftk_checkudata(L, 1, "lftk.progress_bar_t"); + progress_bar_t* obj = (progress_bar_t*)lftk_checkudata(L, 1, "progress_bar_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(progress_bar_t_member_funcs, name); @@ -1076,15 +1049,18 @@ static int wrap_progress_bar_t_get_prop(lua_State* L) { } if(strcmp(name, "value") == 0) { lua_pushinteger(L,(lua_Integer)(obj->value)); - return 1; + + return 1; } else if(strcmp(name, "vertical") == 0) { lua_pushboolean(L,(lua_Integer)(obj->vertical)); - return 1; + + return 1; } else if(strcmp(name, "show_text") == 0) { lua_pushboolean(L,(lua_Integer)(obj->show_text)); - return 1; + + return 1; } else { return wrap_widget_t_get_prop(L); @@ -1117,7 +1093,7 @@ static const struct luaL_Reg point_t_member_funcs[] = { }; static int wrap_point_t_set_prop(lua_State* L) { - point_t* obj = (point_t*)lftk_checkudata(L, 1, "lftk.point_t"); + point_t* obj = (point_t*)lftk_checkudata(L, 1, "point_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1136,7 +1112,7 @@ static int wrap_point_t_set_prop(lua_State* L) { } static int wrap_point_t_get_prop(lua_State* L) { - point_t* obj = (point_t*)lftk_checkudata(L, 1, "lftk.point_t"); + point_t* obj = (point_t*)lftk_checkudata(L, 1, "point_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(point_t_member_funcs, name); @@ -1148,11 +1124,13 @@ static int wrap_point_t_get_prop(lua_State* L) { } if(strcmp(name, "x") == 0) { lua_pushnumber(L,(lua_Number)(obj->x)); - return 1; + + return 1; } else if(strcmp(name, "y") == 0) { lua_pushnumber(L,(lua_Number)(obj->y)); - return 1; + + return 1; } else { printf("%s: not supported %s\n", __func__, name); @@ -1185,7 +1163,7 @@ static const struct luaL_Reg rect_t_member_funcs[] = { }; static int wrap_rect_t_set_prop(lua_State* L) { - rect_t* obj = (rect_t*)lftk_checkudata(L, 1, "lftk.rect_t"); + rect_t* obj = (rect_t*)lftk_checkudata(L, 1, "rect_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1212,7 +1190,7 @@ static int wrap_rect_t_set_prop(lua_State* L) { } static int wrap_rect_t_get_prop(lua_State* L) { - rect_t* obj = (rect_t*)lftk_checkudata(L, 1, "lftk.rect_t"); + rect_t* obj = (rect_t*)lftk_checkudata(L, 1, "rect_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(rect_t_member_funcs, name); @@ -1224,19 +1202,23 @@ static int wrap_rect_t_get_prop(lua_State* L) { } if(strcmp(name, "x") == 0) { lua_pushnumber(L,(lua_Number)(obj->x)); - return 1; + + return 1; } else if(strcmp(name, "y") == 0) { lua_pushnumber(L,(lua_Number)(obj->y)); - return 1; + + return 1; } else if(strcmp(name, "w") == 0) { lua_pushnumber(L,(lua_Number)(obj->w)); - return 1; + + return 1; } else if(strcmp(name, "h") == 0) { lua_pushnumber(L,(lua_Number)(obj->h)); - return 1; + + return 1; } else { printf("%s: not supported %s\n", __func__, name); @@ -1269,7 +1251,7 @@ static const struct luaL_Reg style_t_member_funcs[] = { }; static int wrap_style_t_set_prop(lua_State* L) { - style_t* obj = (style_t*)lftk_checkudata(L, 1, "lftk.style_t"); + style_t* obj = (style_t*)lftk_checkudata(L, 1, "style_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1278,7 +1260,7 @@ static int wrap_style_t_set_prop(lua_State* L) { } static int wrap_style_t_get_prop(lua_State* L) { - style_t* obj = (style_t*)lftk_checkudata(L, 1, "lftk.style_t"); + style_t* obj = (style_t*)lftk_checkudata(L, 1, "style_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(style_t_member_funcs, name); @@ -1319,7 +1301,7 @@ static const struct luaL_Reg theme_t_member_funcs[] = { }; static int wrap_theme_t_set_prop(lua_State* L) { - theme_t* obj = (theme_t*)lftk_checkudata(L, 1, "lftk.theme_t"); + theme_t* obj = (theme_t*)lftk_checkudata(L, 1, "theme_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1328,7 +1310,7 @@ static int wrap_theme_t_set_prop(lua_State* L) { } static int wrap_theme_t_get_prop(lua_State* L) { - theme_t* obj = (theme_t*)lftk_checkudata(L, 1, "lftk.theme_t"); + theme_t* obj = (theme_t*)lftk_checkudata(L, 1, "theme_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(theme_t_member_funcs, name); @@ -1568,18 +1550,16 @@ static void value_type_t_init(lua_State* L) { static int wrap_value_set_bool(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); bool_t value = (bool_t)lua_toboolean(L, 2); ret = (value_t*)value_set_bool(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_bool(lua_State* L) { bool_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (bool_t)value_bool(v); lua_pushboolean(L,(lua_Integer)(ret)); @@ -1589,18 +1569,16 @@ static int wrap_value_bool(lua_State* L) { static int wrap_value_set_int8(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); int8_t value = (int8_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_int8(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_int8(lua_State* L) { int8_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int8_t)value_int8(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1610,18 +1588,16 @@ static int wrap_value_int8(lua_State* L) { static int wrap_value_set_uint8(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); uint8_t value = (uint8_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_uint8(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_uint8(lua_State* L) { int8_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int8_t)value_uint8(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1631,18 +1607,16 @@ static int wrap_value_uint8(lua_State* L) { static int wrap_value_set_int16(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); int16_t value = (int16_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_int16(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_int16(lua_State* L) { int16_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int16_t)value_int16(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1652,18 +1626,16 @@ static int wrap_value_int16(lua_State* L) { static int wrap_value_set_uint16(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); uint16_t value = (uint16_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_uint16(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_uint16(lua_State* L) { uint16_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (uint16_t)value_uint16(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1673,18 +1645,16 @@ static int wrap_value_uint16(lua_State* L) { static int wrap_value_set_int32(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); int32_t value = (int32_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_int32(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_int32(lua_State* L) { int32_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int32_t)value_int32(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1694,18 +1664,16 @@ static int wrap_value_int32(lua_State* L) { static int wrap_value_set_uint32(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); uint32_t value = (uint32_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_uint32(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_uint32(lua_State* L) { uint32_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (uint32_t)value_uint32(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1715,18 +1683,16 @@ static int wrap_value_uint32(lua_State* L) { static int wrap_value_set_int64(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); int64_t value = (int64_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_int64(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_int64(lua_State* L) { int64_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int64_t)value_int64(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1736,18 +1702,16 @@ static int wrap_value_int64(lua_State* L) { static int wrap_value_set_uint64(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); uint64_t value = (uint64_t)luaL_checkinteger(L, 2); ret = (value_t*)value_set_uint64(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_uint64(lua_State* L) { uint64_t ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (uint64_t)value_uint64(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1757,18 +1721,16 @@ static int wrap_value_uint64(lua_State* L) { static int wrap_value_set_float(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); float value = (float)luaL_checknumber(L, 2); ret = (value_t*)value_set_float(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_float(lua_State* L) { float ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (float)value_float(v); lua_pushnumber(L,(lua_Number)(ret)); @@ -1778,18 +1740,16 @@ static int wrap_value_float(lua_State* L) { static int wrap_value_set_double(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); double value = (double)luaL_checknumber(L, 2); ret = (value_t*)value_set_double(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_double(lua_State* L) { double ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (double)value_double(v); lua_pushnumber(L,(lua_Number)(ret)); @@ -1799,18 +1759,16 @@ static int wrap_value_double(lua_State* L) { static int wrap_value_set_str(lua_State* L) { value_t* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); char* value = (char*)luaL_checkstring(L, 2); ret = (value_t*)value_set_str(v, value); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_str(lua_State* L) { const char* ret = NULL; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (const char*)value_str(v); lua_pushstring(L,(char*)(ret)); @@ -1820,7 +1778,7 @@ static int wrap_value_str(lua_State* L) { static int wrap_value_is_null(lua_State* L) { bool_t ret = 0; - value_t* value = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* value = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (bool_t)value_is_null(value); lua_pushboolean(L,(lua_Integer)(ret)); @@ -1830,7 +1788,7 @@ static int wrap_value_is_null(lua_State* L) { static int wrap_value_int(lua_State* L) { int ret = 0; - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); ret = (int)value_int(v); lua_pushinteger(L,(lua_Integer)(ret)); @@ -1839,8 +1797,8 @@ static int wrap_value_int(lua_State* L) { } static int wrap_value_copy(lua_State* L) { - value_t* dst = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); - value_t* src = (value_t*)lftk_checkudata(L, 2, "lftk.value_t"); + value_t* dst = (value_t*)lftk_checkudata(L, 1, "value_t"); + value_t* src = (value_t*)lftk_checkudata(L, 2, "value_t"); (void)value_copy(dst, src); return 0; @@ -1850,15 +1808,11 @@ static int wrap_value_create(lua_State* L) { value_t* ret = NULL; ret = (value_t*)value_create(); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.value_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/value_t", "lftk.value_t"); } static int wrap_value_destroy(lua_State* L) { - value_t* v = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 1, "value_t"); (void)value_destroy(v); return 0; @@ -1898,7 +1852,7 @@ static const struct luaL_Reg value_t_member_funcs[] = { }; static int wrap_value_t_set_prop(lua_State* L) { - value_t* obj = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* obj = (value_t*)lftk_checkudata(L, 1, "value_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -1913,7 +1867,7 @@ static int wrap_value_t_set_prop(lua_State* L) { } static int wrap_value_t_get_prop(lua_State* L) { - value_t* obj = (value_t*)lftk_checkudata(L, 1, "lftk.value_t"); + value_t* obj = (value_t*)lftk_checkudata(L, 1, "value_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(value_t_member_funcs, name); @@ -1925,7 +1879,8 @@ static int wrap_value_t_get_prop(lua_State* L) { } if(strcmp(name, "type") == 0) { lua_pushinteger(L,(lua_Integer)(obj->type)); - return 1; + + return 1; } else { printf("%s: not supported %s\n", __func__, name); @@ -2057,7 +2012,7 @@ static void widget_type_t_init(lua_State* L) { static int wrap_widget_count_children(lua_State* L) { uint32_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (uint32_t)widget_count_children(widget); lua_pushinteger(L,(lua_Integer)(ret)); @@ -2067,18 +2022,16 @@ static int wrap_widget_count_children(lua_State* L) { static int wrap_widget_get_child(lua_State* L) { widget_t* ret = NULL; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint32_t index = (uint32_t)luaL_checkinteger(L, 2); ret = (widget_t*)widget_get_child(widget, index); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/widget_t", "lftk.widget_t"); } static int wrap_widget_move(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); ret = (ret_t)widget_move(widget, x, y); @@ -2090,7 +2043,7 @@ static int wrap_widget_move(lua_State* L) { static int wrap_widget_resize(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wh_t w = (wh_t)luaL_checkinteger(L, 2); wh_t h = (wh_t)luaL_checkinteger(L, 3); ret = (ret_t)widget_resize(widget, w, h); @@ -2102,7 +2055,7 @@ static int wrap_widget_resize(lua_State* L) { static int wrap_widget_move_resize(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); @@ -2116,7 +2069,7 @@ static int wrap_widget_move_resize(lua_State* L) { static int wrap_widget_set_value(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); uint32_t value = (uint32_t)luaL_checkinteger(L, 2); ret = (ret_t)widget_set_value(widget, value); @@ -2127,7 +2080,7 @@ static int wrap_widget_set_value(lua_State* L) { static int wrap_widget_set_text(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); wchar_t* text = (wchar_t*)lua_touserdata(L, 2); ret = (ret_t)widget_set_text(widget, text); @@ -2138,7 +2091,7 @@ static int wrap_widget_set_text(lua_State* L) { static int wrap_widget_get_value(lua_State* L) { uint32_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (uint32_t)widget_get_value(widget); lua_pushinteger(L,(lua_Integer)(ret)); @@ -2148,7 +2101,7 @@ static int wrap_widget_get_value(lua_State* L) { static int wrap_widget_get_text(lua_State* L) { wchar_t* ret = NULL; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (wchar_t*)widget_get_text(widget); lua_pushlightuserdata(L,(void*)(ret)); @@ -2158,8 +2111,8 @@ static int wrap_widget_get_text(lua_State* L) { static int wrap_widget_to_local(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - point_t* p = (point_t*)lftk_checkudata(L, 2, "lftk.point_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + point_t* p = (point_t*)lftk_checkudata(L, 2, "point_t"); ret = (ret_t)widget_to_local(widget, p); lua_pushnumber(L,(lua_Number)(ret)); @@ -2169,8 +2122,8 @@ static int wrap_widget_to_local(lua_State* L) { static int wrap_widget_to_global(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - point_t* p = (point_t*)lftk_checkudata(L, 2, "lftk.point_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + point_t* p = (point_t*)lftk_checkudata(L, 2, "point_t"); ret = (ret_t)widget_to_global(widget, p); lua_pushnumber(L,(lua_Number)(ret)); @@ -2180,7 +2133,7 @@ static int wrap_widget_to_global(lua_State* L) { static int wrap_widget_set_name(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); ret = (ret_t)widget_set_name(widget, name); @@ -2191,7 +2144,7 @@ static int wrap_widget_set_name(lua_State* L) { static int wrap_widget_set_enable(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); bool_t enable = (bool_t)lua_toboolean(L, 2); ret = (ret_t)widget_set_enable(widget, enable); @@ -2202,7 +2155,7 @@ static int wrap_widget_set_enable(lua_State* L) { static int wrap_widget_set_focused(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); bool_t focused = (bool_t)lua_toboolean(L, 2); ret = (ret_t)widget_set_focused(widget, focused); @@ -2213,7 +2166,7 @@ static int wrap_widget_set_focused(lua_State* L) { static int wrap_widget_set_state(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); widget_state_t state = (widget_state_t)luaL_checkinteger(L, 2); ret = (ret_t)widget_set_state(widget, state); @@ -2224,7 +2177,7 @@ static int wrap_widget_set_state(lua_State* L) { static int wrap_widget_destroy_children(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (ret_t)widget_destroy_children(widget); lua_pushnumber(L,(lua_Number)(ret)); @@ -2234,8 +2187,8 @@ static int wrap_widget_destroy_children(lua_State* L) { static int wrap_widget_add_child(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - widget_t* child = (widget_t*)lftk_checkudata(L, 2, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + widget_t* child = (widget_t*)lftk_checkudata(L, 2, "widget_t"); ret = (ret_t)widget_add_child(widget, child); lua_pushnumber(L,(lua_Number)(ret)); @@ -2245,8 +2198,8 @@ static int wrap_widget_add_child(lua_State* L) { static int wrap_widget_remove_child(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - widget_t* child = (widget_t*)lftk_checkudata(L, 2, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + widget_t* child = (widget_t*)lftk_checkudata(L, 2, "widget_t"); ret = (ret_t)widget_remove_child(widget, child); lua_pushnumber(L,(lua_Number)(ret)); @@ -2256,19 +2209,17 @@ static int wrap_widget_remove_child(lua_State* L) { static int wrap_widget_lookup(lua_State* L) { widget_t* ret = NULL; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); bool_t recursive = (bool_t)lua_toboolean(L, 3); ret = (widget_t*)widget_lookup(widget, name, recursive); - lua_pushlightuserdata(L,(void*)(ret)); - - return 1; + return lftk_newuserdata(L, ret, "/widget_t", "lftk.widget_t"); } static int wrap_widget_set_visible(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); bool_t visible = (bool_t)lua_toboolean(L, 2); bool_t recursive = (bool_t)lua_toboolean(L, 3); ret = (ret_t)widget_set_visible(widget, visible, recursive); @@ -2280,8 +2231,8 @@ static int wrap_widget_set_visible(lua_State* L) { static int wrap_widget_invalidate(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - rect_t* r = (rect_t*)lftk_checkudata(L, 2, "lftk.rect_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + rect_t* r = (rect_t*)lftk_checkudata(L, 2, "rect_t"); ret = (ret_t)widget_invalidate(widget, r); lua_pushnumber(L,(lua_Number)(ret)); @@ -2291,9 +2242,9 @@ static int wrap_widget_invalidate(lua_State* L) { static int wrap_widget_get_prop(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); - value_t* v = (value_t*)lftk_checkudata(L, 3, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 3, "value_t"); ret = (ret_t)widget_get_prop(widget, name, v); lua_pushnumber(L,(lua_Number)(ret)); @@ -2303,9 +2254,9 @@ static int wrap_widget_get_prop(lua_State* L) { static int wrap_widget_set_prop(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); char* name = (char*)luaL_checkstring(L, 2); - value_t* v = (value_t*)lftk_checkudata(L, 3, "lftk.value_t"); + value_t* v = (value_t*)lftk_checkudata(L, 3, "value_t"); ret = (ret_t)widget_set_prop(widget, name, v); lua_pushnumber(L,(lua_Number)(ret)); @@ -2315,8 +2266,8 @@ static int wrap_widget_set_prop(lua_State* L) { static int wrap_widget_grab(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - widget_t* child = (widget_t*)lftk_checkudata(L, 2, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + widget_t* child = (widget_t*)lftk_checkudata(L, 2, "widget_t"); ret = (ret_t)widget_grab(widget, child); lua_pushnumber(L,(lua_Number)(ret)); @@ -2326,8 +2277,8 @@ static int wrap_widget_grab(lua_State* L) { static int wrap_widget_ungrab(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); - widget_t* child = (widget_t*)lftk_checkudata(L, 2, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); + widget_t* child = (widget_t*)lftk_checkudata(L, 2, "widget_t"); ret = (ret_t)widget_ungrab(widget, child); lua_pushnumber(L,(lua_Number)(ret)); @@ -2337,7 +2288,7 @@ static int wrap_widget_ungrab(lua_State* L) { static int wrap_widget_destroy(lua_State* L) { ret_t ret = 0; - widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* widget = (widget_t*)lftk_checkudata(L, 1, "widget_t"); ret = (ret_t)widget_destroy(widget); lua_pushnumber(L,(lua_Number)(ret)); @@ -2379,7 +2330,7 @@ static const struct luaL_Reg widget_t_member_funcs[] = { }; static int wrap_widget_t_set_prop(lua_State* L) { - widget_t* obj = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* obj = (widget_t*)lftk_checkudata(L, 1, "widget_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -2438,7 +2389,7 @@ static int wrap_widget_t_set_prop(lua_State* L) { } static int wrap_widget_t_get_prop(lua_State* L) { - widget_t* obj = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* obj = (widget_t*)lftk_checkudata(L, 1, "widget_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(widget_t_member_funcs, name); @@ -2450,51 +2401,61 @@ static int wrap_widget_t_get_prop(lua_State* L) { } if(strcmp(name, "x") == 0) { lua_pushnumber(L,(lua_Number)(obj->x)); - return 1; + + return 1; } else if(strcmp(name, "y") == 0) { lua_pushnumber(L,(lua_Number)(obj->y)); - return 1; + + return 1; } else if(strcmp(name, "w") == 0) { lua_pushnumber(L,(lua_Number)(obj->w)); - return 1; + + return 1; } else if(strcmp(name, "h") == 0) { lua_pushnumber(L,(lua_Number)(obj->h)); - return 1; + + return 1; } else if(strcmp(name, "type") == 0) { lua_pushinteger(L,(lua_Integer)(obj->type)); - return 1; + + return 1; } else if(strcmp(name, "subtype") == 0) { lua_pushinteger(L,(lua_Integer)(obj->subtype)); - return 1; + + return 1; } else if(strcmp(name, "state") == 0) { lua_pushinteger(L,(lua_Integer)(obj->state)); - return 1; + + return 1; } else if(strcmp(name, "enable") == 0) { lua_pushboolean(L,(lua_Integer)(obj->enable)); - return 1; + + return 1; } else if(strcmp(name, "visible") == 0) { lua_pushboolean(L,(lua_Integer)(obj->visible)); - return 1; + + return 1; } else if(strcmp(name, "focused") == 0) { lua_pushboolean(L,(lua_Integer)(obj->focused)); - return 1; + + return 1; } else if(strcmp(name, "name") == 0) { lua_pushstring(L,(char*)(obj->name)); - return 1; + + return 1; } else if(strcmp(name, "parent") == 0) { - lua_pushlightuserdata(L,(void*)(obj->parent)); - return 1; + return lftk_newuserdata(L, obj->parent, "/widget_t", "lftk.widget_t"); } else { printf("%s: not supported %s\n", __func__, name); @@ -2527,7 +2488,7 @@ static const struct luaL_Reg window_manager_t_member_funcs[] = { }; static int wrap_window_manager_t_set_prop(lua_State* L) { - window_manager_t* obj = (window_manager_t*)lftk_checkudata(L, 1, "lftk.window_manager_t"); + window_manager_t* obj = (window_manager_t*)lftk_checkudata(L, 1, "window_manager_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -2537,7 +2498,7 @@ static int wrap_window_manager_t_set_prop(lua_State* L) { } static int wrap_window_manager_t_get_prop(lua_State* L) { - window_manager_t* obj = (window_manager_t*)lftk_checkudata(L, 1, "lftk.window_manager_t"); + window_manager_t* obj = (window_manager_t*)lftk_checkudata(L, 1, "window_manager_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(window_manager_t_member_funcs, name); @@ -2573,18 +2534,14 @@ static void window_manager_t_init(lua_State* L) { } static int wrap_window_create(lua_State* L) { widget_t* ret = NULL; - widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "lftk.widget_t"); + widget_t* parent = (widget_t*)lftk_checkudata(L, 1, "widget_t"); xy_t x = (xy_t)luaL_checkinteger(L, 2); xy_t y = (xy_t)luaL_checkinteger(L, 3); wh_t w = (wh_t)luaL_checkinteger(L, 4); wh_t h = (wh_t)luaL_checkinteger(L, 5); ret = (widget_t*)window_create(parent, x, y, w, h); - lua_pushlightuserdata(L,(void*)(ret)); - luaL_getmetatable(L, "lftk.window_t"); - lua_setmetatable(L, -2); - - return 1; + return lftk_newuserdata(L, ret, "/window_t/widget_t", "lftk.window_t"); } @@ -2593,7 +2550,7 @@ static const struct luaL_Reg window_t_member_funcs[] = { }; static int wrap_window_t_set_prop(lua_State* L) { - window_t* obj = (window_t*)lftk_checkudata(L, 1, "lftk.window_t"); + window_t* obj = (window_t*)lftk_checkudata(L, 1, "window_t"); const char* name = (const char*)luaL_checkstring(L, 2); (void)obj; (void)name; @@ -2603,7 +2560,7 @@ static int wrap_window_t_set_prop(lua_State* L) { } static int wrap_window_t_get_prop(lua_State* L) { - window_t* obj = (window_t*)lftk_checkudata(L, 1, "lftk.window_t"); + window_t* obj = (window_t*)lftk_checkudata(L, 1, "window_t"); const char* name = (const char*)luaL_checkstring(L, 2); const luaL_Reg* ret = find_member(window_t_member_funcs, name); diff --git a/lua/window.lua b/lua/window.lua deleted file mode 100644 index fed1c5a05..000000000 --- a/lua/window.lua +++ /dev/null @@ -1,20 +0,0 @@ -function on_click(ctx, evt) - print('on_click'); -end - -function application_init() - local win = Window.create(NULL, 0, 0, 0, 0); - local ok = Button.create(win, 10, 5, 80, 30); - ok:set_text(to_wstr("ok")); - - rid = ok:on(EventType.EVT_CLICK, function(evt) - print("on click:" .. tostring(rid)) - ok:off(rid) - end); - - print(tostring(rid)) -end - -application_init() - - diff --git a/src/base/events.h b/src/base/events.h index b276d57da..12d41aa12 100755 --- a/src/base/events.h +++ b/src/base/events.h @@ -36,7 +36,7 @@ typedef enum _event_type_t { * @const EVT_NONE * 无效事件名称。 */ - EVT_NONE, + EVT_NONE = 0, /** * @const EVT_POINTER_DOWN * 指针按下事件名。 diff --git a/tools/idl_gen/gen_lua.js b/tools/idl_gen/gen_lua.js index 282f2bb7d..13c868038 100644 --- a/tools/idl_gen/gen_lua.js +++ b/tools/idl_gen/gen_lua.js @@ -9,418 +9,447 @@ const fs = require('fs'); const builtin = `#include "custom.c"\n\n`; -function toLuaClassName(name) { - name = name.replace(/_t$/, ''); - name = name.replace(/(^|_)[a-z]/g, r => { - if(r.length > 1) { - r = r.substr(1); - } - - return r.toUpperCase(); - }); - - return name; -} - -function genDecl(index, type, name) { - let str = ''; - str += ` ${type} ${name} = `; - if (index < 0) { - if (type.indexOf('*') >= 0) { - str += 'NULL;\n'; - } else { - str += '0;\n'; - } - } else { - if (type.indexOf('char*') >= 0) { - str += `(${type})luaL_checkstring(L, ${index+1});\n`; - } else if (type.indexOf('wchar_t*') >= 0) { - str += `(${type})lua_touserdata(L, ${index+1});\n`; - } else if (type.indexOf('void*') >= 0) { - if(name !== 'ctx') { - str += `(${type})lua_touserdata(L, ${index+1});\n`; - } else { - str += ' NULL;\n'; - } - } else if (type.indexOf('*') >= 0) { - const type_name = type.replace(/\*/g, ''); - str += `(${type})lftk_checkudata(L, ${index+1}, "lftk.${type_name}");\n`; - } else if (type.indexOf('float') >= 0 || type.indexOf('double') >= 0) { - str += `(${type})luaL_checknumber(L, ${index+1});\n`; - } else if (type.indexOf('bool_t') >= 0) { - str += `(${type})lua_toboolean(L, ${index+1});\n`; - } else if (type.indexOf('func_t') >= 0) { - str += `(${type})lua_tocfunction(L, ${index+1});\n`; - } else { - str += `(${type})luaL_checkinteger(L, ${index+1});\n`; - } - } - - return str; -} - -function genParamsDecl(m) { - let str = ''; - if (m.return != 'void') { - str = genDecl(-1, m.return, 'ret'); - } - - m.params.forEach((iter, index) => { - str += genDecl(index, iter.type, iter.name); - }) - - return str; -} - -function genReturnData(type, name) { - let str = ''; - if (type.indexOf('char*') >= 0) { - str = ` lua_pushstring(L,(char*)(${name}));\n`; - } else if (type.indexOf('wchar_t*') >= 0) { - str = ` lua_pushlightuserdata(L,(void*)(${name}));\n`; - } else if (type.indexOf('*') >= 0) { - str = ` lua_pushlightuserdata(L,(void*)(${name}));\n`; - } else if (type.indexOf('int') >= 0) { - str = ` lua_pushinteger(L,(lua_Integer)(${name}));\n`; - } else if (type.indexOf('bool_t') >= 0) { - str = ` lua_pushboolean(L,(lua_Integer)(${name}));\n`; - } else { - str = ` lua_pushnumber(L,(lua_Number)(${name}));\n`; - } - - return str; -} - -function genCallMethod(cls, m) { - const ret_type = m.return; - let str = ret_type == 'void' ? ' ' : ' ret = ' - str += `(${ret_type})${m.name}(`; - m.params.forEach((iter, index) => { - if (index > 0) { - str += ', ' + iter.name; - } else { - str += iter.name; - } - }) - - str += ');\n'; - - str += '\n'; - if (ret_type == 'void') { - str += ' return 0;\n'; - } else { - str += genReturnData(ret_type, 'ret'); - if (m.isConstructor) { - str += ` luaL_getmetatable(L, "lftk.${cls.name}");\n`; - str += ` lua_setmetatable(L, -2);\n`; - } - str += '\n'; - str += ' return 1;\n'; - } - - return str; -} - -function genMethod(cls, m) { - const args_nr = m.params.length; - let str = `static int wrap_${m.name}(lua_State* L) {\n`; - str += genParamsDecl(m); - str += genCallMethod(cls, m); - str += '}\n\n'; - - return str; -} - -function genSetProperty(index, cls, p) { - let str = ''; - if (index === 0) { - str += ` if(strcmp(name, "${p.name}") == 0) {\n`; - } else { - str += ` else if(strcmp(name, "${p.name}") == 0) {\n`; - } - str += ' '; - if (p.readonly) { - str += ` printf("${p.name} is readonly\\n");\n`; - str += ` return 0;\n`; - } else { - str += genDecl(2, p.type, p.name); - str += ` obj->${p.name} = ${p.name};\n`; - } - str += ' }\n'; - - return str; -} - -function genGetProperty(index, cls, p) { - let str = ''; - if (index === 0) { - str += ` if(strcmp(name, "${p.name}") == 0) {\n`; - } else { - str += ` else if(strcmp(name, "${p.name}") == 0) {\n`; - } - str += ' '; - str += genReturnData(p.type, `obj->${p.name}`); - str += ' return 1;\n'; - str += ' }\n'; - - return str; -} - -function methodToShortName(clsName, methodName) { - return methodName.replace(clsName.replace(/_t$/, '') + "_", '') -} - -function genSetProp(cls) { - let str = ''; - const clsName = cls.name; - - str += `static int wrap_${clsName}_set_prop(lua_State* L) {\n`; - str += genDecl(0, cls.name + '*', "obj"); - str += genDecl(1, "const char*", "name"); - str += '(void)obj;\n'; - str += '(void)name;\n'; - - let hasSetProps = false; - cls.properties.forEach((m, index) => { - str += genSetProperty(index, cls, m); - hasSetProps = true; - }); - - if (hasSetProps) { - str += ` else {\n `; - } - if (cls.parent) { - str += ` return wrap_${cls.parent}_set_prop(L);\n`; - } else if (hasSetProps) { - str += ` printf("%s: not supported %s\\n", __func__, name);\n`; - str += ` return 0;\n`; - } - if (hasSetProps) { - str += ` }\n`; - } else { - str += ` printf("%s: not supported %s\\n", __func__, name);\n`; - str += ` return 0;\n`; - } - - str += `}\n\n`; - - return str; -} - -function genGetProp(cls) { - let str = ''; - const clsName = cls.name; - - str += `static int wrap_${clsName}_get_prop(lua_State* L) {\n`; - str += genDecl(0, cls.name + '*', "obj"); - str += genDecl(1, "const char*", "name"); - str += ` const luaL_Reg* ret = find_member(${cls.name}_member_funcs, name);\n\n`; - - str += ' (void)obj;\n'; - str += ' (void)name;\n'; - str += ' if(ret) {\n'; - str += ' lua_pushcfunction(L, ret->func);\n'; - str += ' return 1;\n'; - str += ' }\n'; - - cls.properties.forEach((m, index) => { - str += genGetProperty(index, cls, m); - }); - - str += ` else {\n`; - if (cls.parent) { - str += ` return wrap_${cls.parent}_get_prop(L);\n`; - } else { - str += ` printf("%s: not supported %s\\n", __func__, name);\n`; - str += ` return 1;\n`; - } - str += ` }\n`; - - str += `}\n\n`; - - return str; -} - -function genClassInit(cls) { - let str = ''; - const clsName = cls.name; - - str += `static void ${cls.name}_init(lua_State* L) {\n`; - str += ' static const struct luaL_Reg static_funcs[] = {\n' - cls.methods.forEach(m => { - const name = methodToShortName(cls.name, m.name); - if (m.isConstructor) { - str += ` {"${name}", wrap_${m.name}},\n`; - } - }); - - str += ` {NULL, NULL}\n`; - str += ' };\n\n' - - str += ' static const struct luaL_Reg index_funcs[] = {\n' - str += ` {"__index", wrap_${clsName}_get_prop},\n`; - str += ` {"__newindex", wrap_${clsName}_set_prop},\n`; - str += ` {NULL, NULL}\n`; - str += ' };\n\n' - - str += ` luaL_newmetatable(L, "lftk.${cls.name}");\n`; - str += ` lua_pushstring(L, "__index");\n`; - str += ' lua_pushvalue(L, -2);\n'; - str += ' lua_settable(L, -3);\n'; - str += ` luaL_openlib(L, NULL, index_funcs, 0);\n`; - str += ` luaL_openlib(L, "${toLuaClassName(cls.name)}", static_funcs, 0);\n`; - - str += ' lua_settop(L, 0);\n'; - str += '}\n'; - - return str; -} - -function genMethods(cls) { - let str = ''; - const clsName = cls.name; - - cls.methods.forEach(m => { - if(!m.isPrivate && !m.isCustom) { - str += genMethod(cls, m); - } - }); - - str += `\nstatic const struct luaL_Reg ${cls.name}_member_funcs[] = {\n` - cls.methods.forEach(m => { - const name = methodToShortName(cls.name, m.name); - if (!m.isConstructor) { - str += ` {"${name}", wrap_${m.name}},\n`; - } - }); - str += ` {NULL, NULL}\n`; - str += '};\n\n' - - return str; -} - -function genClass(cls) { - let str = ''; - - str += genMethods(cls); - str += genSetProp(cls); - str += genGetProp(cls); - str += genClassInit(cls); - - return str; -} - -function genEnum(cls) { - let str = `static void ${cls.name}_init(lua_State* L) {\n`; - - str += ' lua_newtable(L);\n'; - str += ` lua_setglobal(L, "${toLuaClassName(cls.name)}");\n`; - str += ` lua_getglobal(L, "${toLuaClassName(cls.name)}");\n\n`; - - const clsNamePrefix = cls.name.toUpperCase().replace(/_T$/, "_"); - cls.consts.forEach(iter => { - const name = iter.name.replace(clsNamePrefix, ""); - - str += ` lua_pushstring(L, "${name}");\n` - str += ` lua_pushinteger(L, ${iter.name});\n`; - str += ` lua_settable(L, -3); \n\n`; - }); - - str += '}\n\n'; - - return str; -} - -function genOne(cls) { - if (cls.type == 'class') { - return genClass(cls); - } else if (cls.type == 'enum') { - return genEnum(cls); - } else { - return ''; - } -} - -function genIncludes(json) { - let result = '/*XXX: generated by lua_gen. dont edit it.*/\n'; - - result += '#include "lua.h"\n'; - result += '#include "lualib.h"\n'; - result += '#include "lauxlib.h"\n'; - result += '#include "base/utf8.h"\n'; - json.forEach(iter => { - if (result.indexOf(iter.header) <= 0) { - result += `#include "${iter.header}"\n`; - } - }); - result += "\n"; - - return result; -} - -function genFuncDecls(json) { - let result = ''; - - json.forEach(iter => { - if (iter.type == 'class') { - const clsName = iter.name; - result += `static int wrap_${clsName}_get_prop(lua_State* L);\n`; - result += `static int wrap_${clsName}_set_prop(lua_State* L);\n`; - } - }); - result += '\n'; - - return result; -} - -function genInit(json) { - let result = ''; - - result += `\nvoid luaL_openlftk(lua_State* L) {\n`; - result += ` globals_init(L);\n`; - json.forEach(iter => { - if(iter.type === 'class' || iter.type === 'enum') { - result += ` ${iter.name}_init(L);\n`; - } - }); - result += ' s_current_L = L;\n'; - result += '}\n'; - - return result; -} - -function genGlobals(json) { - let str = ''; - - json.forEach(iter => { - if (iter.type == 'method') { - str += genMethod({}, iter); - } - }); - - str += 'static void globals_init(lua_State* L) {\n'; - - json.forEach(iter => { - if (iter.type == 'method') { - str += ` lua_pushcfunction(L, wrap_${iter.name});\n`; - str += ` lua_setglobal(L, "${iter.name}");\n`; - } else if (iter.type == 'const') { - str += ` lua_pushinteger(L, ${iter.name});\n`; - str += ` lua_setglobal(L, "${iter.name}");\n`; - } - }); - - str += ' lua_pushcfunction(L, to_str);\n'; - str += ' lua_setglobal(L, "to_str");\n'; - str += ' lua_pushcfunction(L, to_wstr);\n'; - str += ' lua_setglobal(L, "to_wstr");\n'; - - str += '}\n\n'; - - return str; -} - function genAll(json) { + function toLuaClassName(name) { + name = name.replace(/_t$/, ''); + name = name.replace(/(^|_)[a-z]/g, r => { + if (r.length > 1) { + r = r.substr(1); + } + + return r.toUpperCase(); + }); + + return name; + } + + function getClassInfo(name) { + for (let i = 0; i < json.length; i++) { + let iter = json[i]; + if (iter.type === 'class' && iter.name === name) { + return iter; + } + } + + return null; + } + + function genClassChain(name) { + let str = ''; + let info = getClassInfo(name); + + while (info) { + str += '/' + info.name; + if (!info.parent) { + break; + } + info = getClassInfo(info.parent); + } + + return str; + } + + function genDecl(index, type, name) { + let str = ''; + str += ` ${type} ${name} = `; + if (index < 0) { + if (type.indexOf('*') >= 0) { + str += 'NULL;\n'; + } else { + str += '0;\n'; + } + } else { + if (type.indexOf('char*') >= 0) { + str += `(${type})luaL_checkstring(L, ${index+1});\n`; + } else if (type.indexOf('wchar_t*') >= 0) { + str += `(${type})lua_touserdata(L, ${index+1});\n`; + } else if (type.indexOf('void*') >= 0) { + if (name !== 'ctx') { + str += `(${type})lua_touserdata(L, ${index+1});\n`; + } else { + str += ' NULL;\n'; + } + } else if (type.indexOf('*') >= 0) { + const type_name = type.replace(/\*/g, ''); + str += `(${type})lftk_checkudata(L, ${index+1}, "${type_name}");\n`; + } else if (type.indexOf('float') >= 0 || type.indexOf('double') >= 0) { + str += `(${type})luaL_checknumber(L, ${index+1});\n`; + } else if (type.indexOf('bool_t') >= 0) { + str += `(${type})lua_toboolean(L, ${index+1});\n`; + } else if (type.indexOf('func_t') >= 0) { + str += `(${type})lua_tocfunction(L, ${index+1});\n`; + } else { + str += `(${type})luaL_checkinteger(L, ${index+1});\n`; + } + } + + return str; + } + + function genParamsDecl(m) { + let str = ''; + if (m.return != 'void') { + str = genDecl(-1, m.return, 'ret'); + } + + m.params.forEach((iter, index) => { + str += genDecl(index, iter.type, iter.name); + }) + + return str; + } + + function genReturnData(type, name) { + let str = ''; + if (type.indexOf('char*') >= 0) { + str = ` lua_pushstring(L,(char*)(${name}));\n\n`; + str += ' return 1;\n'; + } else if (type.indexOf('wchar_t*') >= 0) { + str = ` lua_pushlightuserdata(L,(void*)(${name}));\n\n`; + str += ' return 1;\n'; + } else if (type.indexOf('*') >= 0) { + const typeName = type.replace(/\*/g, ""); + str += ` return lftk_newuserdata(L, ${name}, "${genClassChain(typeName)}", "lftk.${typeName}");\n`; + } else if (type.indexOf('int') >= 0) { + str = ` lua_pushinteger(L,(lua_Integer)(${name}));\n\n`; + str += ' return 1;\n'; + } else if (type.indexOf('bool_t') >= 0) { + str = ` lua_pushboolean(L,(lua_Integer)(${name}));\n\n`; + str += ' return 1;\n'; + } else { + str = ` lua_pushnumber(L,(lua_Number)(${name}));\n\n`; + str += ' return 1;\n'; + } + + return str; + } + + function genCallMethod(cls, m) { + const ret_type = m.return; + let str = ret_type == 'void' ? ' ' : ' ret = ' + str += `(${ret_type})${m.name}(`; + m.params.forEach((iter, index) => { + if (index > 0) { + str += ', ' + iter.name; + } else { + str += iter.name; + } + }) + + str += ');\n'; + + str += '\n'; + if (ret_type == 'void') { + str += ' return 0;\n'; + } else { + if (m.isConstructor) { + str += genReturnData(`${cls.name}*`, 'ret'); + } else { + str += genReturnData(ret_type, 'ret'); + } + } + + return str; + } + + function genMethod(cls, m) { + const args_nr = m.params.length; + let str = `static int wrap_${m.name}(lua_State* L) {\n`; + str += genParamsDecl(m); + str += genCallMethod(cls, m); + str += '}\n\n'; + + return str; + } + + function genSetProperty(index, cls, p) { + let str = ''; + if (index === 0) { + str += ` if(strcmp(name, "${p.name}") == 0) {\n`; + } else { + str += ` else if(strcmp(name, "${p.name}") == 0) {\n`; + } + str += ' '; + if (p.readonly) { + str += ` printf("${p.name} is readonly\\n");\n`; + str += ` return 0;\n`; + } else { + str += genDecl(2, p.type, p.name); + str += ` obj->${p.name} = ${p.name};\n`; + } + str += ' }\n'; + + return str; + } + + function genGetProperty(index, cls, p) { + let str = ''; + if (index === 0) { + str += ` if(strcmp(name, "${p.name}") == 0) {\n`; + } else { + str += ` else if(strcmp(name, "${p.name}") == 0) {\n`; + } + str += ' '; + str += genReturnData(p.type, `obj->${p.name}`); + str += ' }\n'; + + return str; + } + + function methodToShortName(clsName, methodName) { + return methodName.replace(clsName.replace(/_t$/, '') + "_", '') + } + + function genSetProp(cls) { + let str = ''; + const clsName = cls.name; + + str += `static int wrap_${clsName}_set_prop(lua_State* L) {\n`; + str += genDecl(0, cls.name + '*', "obj"); + str += genDecl(1, "const char*", "name"); + str += '(void)obj;\n'; + str += '(void)name;\n'; + + let hasSetProps = false; + cls.properties.forEach((m, index) => { + str += genSetProperty(index, cls, m); + hasSetProps = true; + }); + + if (hasSetProps) { + str += ` else {\n `; + } + if (cls.parent) { + str += ` return wrap_${cls.parent}_set_prop(L);\n`; + } else if (hasSetProps) { + str += ` printf("%s: not supported %s\\n", __func__, name);\n`; + str += ` return 0;\n`; + } + if (hasSetProps) { + str += ` }\n`; + } else { + str += ` printf("%s: not supported %s\\n", __func__, name);\n`; + str += ` return 0;\n`; + } + + str += `}\n\n`; + + return str; + } + + function genGetProp(cls) { + let str = ''; + const clsName = cls.name; + + str += `static int wrap_${clsName}_get_prop(lua_State* L) {\n`; + str += genDecl(0, cls.name + '*', "obj"); + str += genDecl(1, "const char*", "name"); + str += ` const luaL_Reg* ret = find_member(${cls.name}_member_funcs, name);\n\n`; + + str += ' (void)obj;\n'; + str += ' (void)name;\n'; + str += ' if(ret) {\n'; + str += ' lua_pushcfunction(L, ret->func);\n'; + str += ' return 1;\n'; + str += ' }\n'; + + cls.properties.forEach((m, index) => { + str += genGetProperty(index, cls, m); + }); + + str += ` else {\n`; + if (cls.parent) { + str += ` return wrap_${cls.parent}_get_prop(L);\n`; + } else { + str += ` printf("%s: not supported %s\\n", __func__, name);\n`; + str += ` return 1;\n`; + } + str += ` }\n`; + + str += `}\n\n`; + + return str; + } + + function genClassInit(cls) { + let str = ''; + const clsName = cls.name; + + str += `static void ${cls.name}_init(lua_State* L) {\n`; + str += ' static const struct luaL_Reg static_funcs[] = {\n' + cls.methods.forEach(m => { + const name = methodToShortName(cls.name, m.name); + if (m.isConstructor) { + str += ` {"${name}", wrap_${m.name}},\n`; + } + }); + + str += ` {NULL, NULL}\n`; + str += ' };\n\n' + + str += ' static const struct luaL_Reg index_funcs[] = {\n' + str += ` {"__index", wrap_${clsName}_get_prop},\n`; + str += ` {"__newindex", wrap_${clsName}_set_prop},\n`; + str += ` {NULL, NULL}\n`; + str += ' };\n\n' + + str += ` luaL_newmetatable(L, "lftk.${cls.name}");\n`; + str += ` lua_pushstring(L, "__index");\n`; + str += ' lua_pushvalue(L, -2);\n'; + str += ' lua_settable(L, -3);\n'; + str += ` luaL_openlib(L, NULL, index_funcs, 0);\n`; + str += ` luaL_openlib(L, "${toLuaClassName(cls.name)}", static_funcs, 0);\n`; + + str += ' lua_settop(L, 0);\n'; + str += '}\n'; + + return str; + } + + function genMethods(cls) { + let str = ''; + const clsName = cls.name; + + cls.methods.forEach(m => { + if (!m.isPrivate && !m.isCustom) { + str += genMethod(cls, m); + } + }); + + str += `\nstatic const struct luaL_Reg ${cls.name}_member_funcs[] = {\n` + cls.methods.forEach(m => { + const name = methodToShortName(cls.name, m.name); + if (!m.isConstructor) { + str += ` {"${name}", wrap_${m.name}},\n`; + } + }); + str += ` {NULL, NULL}\n`; + str += '};\n\n' + + return str; + } + + function genClass(cls) { + let str = ''; + + str += genMethods(cls); + str += genSetProp(cls); + str += genGetProp(cls); + str += genClassInit(cls); + + return str; + } + + function genEnum(cls) { + let str = `static void ${cls.name}_init(lua_State* L) {\n`; + + str += ' lua_newtable(L);\n'; + str += ` lua_setglobal(L, "${toLuaClassName(cls.name)}");\n`; + str += ` lua_getglobal(L, "${toLuaClassName(cls.name)}");\n\n`; + + const clsNamePrefix = cls.name.toUpperCase().replace(/_T$/, "_"); + cls.consts.forEach(iter => { + const name = iter.name.replace(clsNamePrefix, ""); + + str += ` lua_pushstring(L, "${name}");\n` + str += ` lua_pushinteger(L, ${iter.name});\n`; + str += ` lua_settable(L, -3); \n\n`; + }); + + str += '}\n\n'; + + return str; + } + + function genOne(cls) { + if (cls.type == 'class') { + return genClass(cls); + } else if (cls.type == 'enum') { + return genEnum(cls); + } else { + return ''; + } + } + + function genIncludes(json) { + let result = '/*XXX: generated by lua_gen. dont edit it.*/\n'; + + result += '#include "lua.h"\n'; + result += '#include "lualib.h"\n'; + result += '#include "lauxlib.h"\n'; + result += '#include "base/utf8.h"\n'; + json.forEach(iter => { + if (result.indexOf(iter.header) <= 0) { + result += `#include "${iter.header}"\n`; + } + }); + result += "\n"; + + return result; + } + + function genFuncDecls(json) { + let result = ''; + + json.forEach(iter => { + if (iter.type == 'class') { + const clsName = iter.name; + result += `static int wrap_${clsName}_get_prop(lua_State* L);\n`; + result += `static int wrap_${clsName}_set_prop(lua_State* L);\n`; + } + }); + result += '\n'; + + return result; + } + + function genInit(json) { + let result = ''; + + result += `\nvoid luaL_openlftk(lua_State* L) {\n`; + result += ` globals_init(L);\n`; + json.forEach(iter => { + if (iter.type === 'class' || iter.type === 'enum') { + result += ` ${iter.name}_init(L);\n`; + } + }); + result += ' s_current_L = L;\n'; + result += '}\n'; + + return result; + } + + function genGlobals(json) { + let str = ''; + + json.forEach(iter => { + if (iter.type == 'method') { + str += genMethod({}, iter); + } + }); + + str += 'static void globals_init(lua_State* L) {\n'; + + json.forEach(iter => { + if (iter.type == 'method') { + str += ` lua_pushcfunction(L, wrap_${iter.name});\n`; + str += ` lua_setglobal(L, "${iter.name}");\n`; + } else if (iter.type == 'const') { + str += ` lua_pushinteger(L, ${iter.name});\n`; + str += ` lua_setglobal(L, "${iter.name}");\n`; + } + }); + + str += ' lua_pushcfunction(L, to_str);\n'; + str += ' lua_setglobal(L, "to_str");\n'; + str += ' lua_pushcfunction(L, to_wstr);\n'; + str += ' lua_setglobal(L, "to_wstr");\n'; + + str += '}\n\n'; + + return str; + } + let result = genIncludes(json); result += builtin; @@ -439,4 +468,4 @@ function run() { fs.writeFileSync('../../lua/lftk_lua.c', genAll(JSON.parse(fs.readFileSync('idl.json').toString()))); } -run(); +run(); \ No newline at end of file