diff options
Diffstat (limited to 'source/luametatex/source/lua/lmtluaclib.c')
-rw-r--r-- | source/luametatex/source/lua/lmtluaclib.c | 660 |
1 files changed, 660 insertions, 0 deletions
diff --git a/source/luametatex/source/lua/lmtluaclib.c b/source/luametatex/source/lua/lmtluaclib.c new file mode 100644 index 000000000..797585aba --- /dev/null +++ b/source/luametatex/source/lua/lmtluaclib.c @@ -0,0 +1,660 @@ +/* + See license.txt in the root of this project. Most code here is from the luac program by the + official Lua project developers. +*/ + +# include "luametatex.h" + +/* + + This is a slightly adapted version of luac which is not in the library but a separate program. + We keep a copy around in order to check changes. The version below doesn't load files nor saves + one. It is derived from: + + $Id: luac.c $ + Lua compiler (saves bytecodes to files; also lists bytecodes) + See Copyright Notice in lua.h + + I added this helper because I wanted to look to what extend constants were resolved beforehand + but in the end that was seldom the case because we get them from tables and that bit of code is + not resolved at bytecode compile time (so in the end macros made more sense, although the gain + is very little). + + I considered replacing the print with writing to a buffer so that we can deal with it later but + it is not worth the effort. + +*/ + +# include "ldebug.h" +# include "lopcodes.h" +# include "lopnames.h" + +static TString **tmname = NULL; + +# define toproto(L,i) getproto(s2v(L->top+(i))) +# define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +# define LUACVOID(p) ((const void*)(p)) +# define eventname(i) (getstr(tmname[i])) + +static void luaclib_aux_print_string(const TString* ts) +{ + const char* s = getstr(ts); + size_t n = tsslen(ts); + printf("\""); + for (size_t i = 0; i < n; i++) { + int c = (int) (unsigned char) s[i]; + switch (c) { + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + case '\a': + printf("\\a"); + break; + case '\b': + printf("\\b"); + break; + case '\f': + printf("\\f"); + break; + case '\n': + printf("\\n"); + break; + case '\r': + printf("\\r"); + break; + case '\t': + printf("\\t"); + break; + case '\v': + printf("\\v"); + break; + default: + printf(isprint(c) ? "%c" : "\\%03d", c); + break; + } + } + printf("\""); +} + +static void PrintType(const Proto* f, int i) +{ + const TValue* o = &f->k[i]; + switch (ttypetag(o)) { + case LUA_VNIL: + printf("N"); + break; + case LUA_VFALSE: + case LUA_VTRUE: + printf("B"); + break; + case LUA_VNUMFLT: + printf("F"); + break; + case LUA_VNUMINT: + printf("I"); + break; + case LUA_VSHRSTR: + case LUA_VLNGSTR: + printf("S"); + break; + default: + /* cannot happen */ + printf("?%d", ttypetag(o)); + break; + } + printf("\t"); +} + +static void PrintConstant(const Proto* f, int i) +{ + const TValue* o = &f->k[i]; + switch (ttypetag(o)) { + case LUA_VNIL: + printf("nil"); + break; + case LUA_VFALSE: + printf("false"); + break; + case LUA_VTRUE: + printf("true"); + break; + case LUA_VNUMFLT: + { + char buff[100]; + sprintf(buff,"%.14g", fltvalue(o)); /* LUA_NUMBER_FMT */ + printf("%s", buff); + if (buff[strspn(buff, "-0123456789")] == '\0') { + printf(".0"); + } + break; + } + case LUA_VNUMINT: +# if defined(__MINGW64__) || defined(__MINGW32__) + printf("%I64i", ivalue(o)); /* LUA_INTEGER_FMT */ +# else + printf("%lli", ivalue(o)); /* LUA_INTEGER_FMT */ +# endif + break; + case LUA_VSHRSTR: + case LUA_VLNGSTR: + luaclib_aux_print_string(tsvalue(o)); + break; + default: + /* cannot happen */ + printf("?%d", ttypetag(o)); + break; + } +} + +#define COMMENT "\t; " +#define EXTRAARG GETARG_Ax(code[pc+1]) +#define EXTRAARGC (EXTRAARG*(MAXARG_C+1)) +#define ISK (isk ? "k" : "") + +static void luaclib_aux_print_code(const Proto* f) +{ + const Instruction* code = f->code; + int n = f->sizecode; + for (int pc = 0; pc < n; pc++) { + Instruction i = code[pc]; + OpCode o = GET_OPCODE(i); + int a = GETARG_A(i); + int b = GETARG_B(i); + int c = GETARG_C(i); + int ax = GETARG_Ax(i); + int bx = GETARG_Bx(i); + int sb = GETARG_sB(i); + int sc = GETARG_sC(i); + int sbx = GETARG_sBx(i); + int isk = GETARG_k(i); + int line = luaG_getfuncline(f, pc); + printf("\t%d\t", pc + 1); + if (line > 0) { + printf("[%d]\t", line); + } else { + printf("[-]\t"); + } + printf("%-9s\t", opnames[o]); + switch (o) { + case OP_MOVE: + printf("%d %d", a, b); + break; + case OP_LOADI: + printf("%d %d", a, sbx); + break; + case OP_LOADF: + printf("%d %d", a, sbx); + break; + case OP_LOADK: + printf("%d %d", a, bx); + printf(COMMENT); + PrintConstant(f, bx); + break; + case OP_LOADKX: + printf("%d", a); + printf(COMMENT); + PrintConstant(f, EXTRAARG); + break; + case OP_LOADFALSE: + printf("%d", a); + break; + case OP_LFALSESKIP: + printf("%d", a); + break; + case OP_LOADTRUE: + printf("%d", a); + break; + case OP_LOADNIL: + printf("%d %d", a, b); + printf(COMMENT "%d out", b + 1); + break; + case OP_GETUPVAL: + printf("%d %d", a, b); + printf(COMMENT "%s", UPVALNAME(b)); + break; + case OP_SETUPVAL: + printf("%d %d", a, b); + printf(COMMENT "%s", UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("%d %d %d", a, b, c); + printf(COMMENT "%s", UPVALNAME(b)); + printf(" "); + PrintConstant(f, c); + break; + case OP_GETTABLE: + printf("%d %d %d", a, b, c); + break; + case OP_GETI: + printf("%d %d %d", a, b, c); + break; + case OP_GETFIELD: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_SETTABUP: + printf("%d %d %d%s", a, b, c, ISK); + printf(COMMENT "%s", UPVALNAME(a)); + printf(" "); + PrintConstant(f, b); + if (isk) { + printf(" "); + PrintConstant(f, c); + } + break; + case OP_SETTABLE: + printf("%d %d %d%s", a, b, c, ISK); + if (isk) { + printf(COMMENT); + PrintConstant(f, c); + } + break; + case OP_SETI: + printf("%d %d %d%s", a, b, c, ISK); + if (isk) { + printf(COMMENT); + PrintConstant(f, c); + } + break; + case OP_SETFIELD: + printf("%d %d %d%s", a, b, c, ISK); + printf(COMMENT); + PrintConstant(f, b); + if (isk) { + printf(" "); + PrintConstant(f, c); + } + break; + case OP_NEWTABLE: + printf("%d %d %d", a, b, c); + printf(COMMENT "%d", c + EXTRAARGC); + break; + case OP_SELF: + printf("%d %d %d%s", a, b, c, ISK); + if (isk) { + printf(COMMENT); + PrintConstant(f, c); + } + break; + case OP_ADDI: + printf("%d %d %d", a, b, sc); + break; + case OP_ADDK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_SUBK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_MULK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_MODK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_POWK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_DIVK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_IDIVK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_BANDK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_BORK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_BXORK: + printf("%d %d %d", a, b, c); + printf(COMMENT); + PrintConstant(f, c); + break; + case OP_SHRI: + printf("%d %d %d", a, b, sc); + break; + case OP_SHLI: + printf("%d %d %d", a, b, sc); + break; + case OP_ADD: + printf("%d %d %d", a, b, c); + break; + case OP_SUB: + printf("%d %d %d", a, b, c); + break; + case OP_MUL: + printf("%d %d %d", a, b, c); + break; + case OP_MOD: + printf("%d %d %d", a, b, c); + break; + case OP_POW: + printf("%d %d %d", a, b, c); + break; + case OP_DIV: + printf("%d %d %d", a, b, c); + break; + case OP_IDIV: + printf("%d %d %d", a, b, c); + break; + case OP_BAND: + printf("%d %d %d", a, b, c); + break; + case OP_BOR: + printf("%d %d %d", a, b, c); + break; + case OP_BXOR: + printf("%d %d %d", a, b, c); + break; + case OP_SHL: + printf("%d %d %d", a, b, c); + break; + case OP_SHR: + printf("%d %d %d", a, b, c); + break; + case OP_MMBIN: + printf("%d %d %d", a, b, c); + printf(COMMENT "%s", eventname(c)); + break; + case OP_MMBINI: + printf("%d %d %d %d", a, sb, c, isk); + printf(COMMENT "%s", eventname(c)); + if (isk) { + printf(" flip"); + } + break; + case OP_MMBINK: + printf("%d %d %d %d", a, b, c, isk); + printf(COMMENT "%s ", eventname(c)); + PrintConstant(f, b); + if (isk) { + printf(" flip"); + } + break; + case OP_UNM: + printf("%d %d", a, b); + break; + case OP_BNOT: + printf("%d %d", a, b); + break; + case OP_NOT: + printf("%d %d", a, b); + break; + case OP_LEN: + printf("%d %d", a, b); + break; + case OP_CONCAT: + printf("%d %d", a, b); + break; + case OP_CLOSE: + printf("%d", a); + break; + case OP_TBC: + printf("%d", a); + break; + case OP_JMP: + printf("%d", GETARG_sJ(i)); + printf(COMMENT "to %d", GETARG_sJ(i) + pc + 2); + break; + case OP_EQ: + printf("%d %d %d", a, b, isk); + break; + case OP_LT: + printf("%d %d %d", a, b, isk); + break; + case OP_LE: + printf("%d %d %d", a, b, isk); + break; + case OP_EQK: + printf("%d %d %d", a, b, isk); + printf(COMMENT); + PrintConstant(f, b); + break; + case OP_EQI: + printf("%d %d %d", a, sb, isk); + break; + case OP_LTI: + printf("%d %d %d", a, sb, isk); + break; + case OP_LEI: + printf("%d %d %d", a, sb, isk); + break; + case OP_GTI: + printf("%d %d %d", a, sb, isk); + break; + case OP_GEI: + printf("%d %d %d", a, sb, isk); + break; + case OP_TEST: + printf("%d %d", a, isk); + break; + case OP_TESTSET: + printf("%d %d %d", a, b, isk); + break; + case OP_CALL: + printf("%d %d %d", a, b, c); + printf(COMMENT); + if (b==0) { + printf("all in "); + } else { + printf("%d in ", b - 1); + } + if (c==0) { + printf("all out"); + } else { + printf("%d out", c- 1 ); + } + break; + case OP_TAILCALL: + printf("%d %d %d", a, b, c); + printf(COMMENT "%d in", b - 1); + break; + case OP_RETURN: + printf("%d %d %d", a, b, c); + printf(COMMENT); + if (b == 0) { + printf("all out"); + } else { + printf("%d out", b - 1); + } + break; + case OP_RETURN0: + break; + case OP_RETURN1: + printf("%d", a); + break; + case OP_FORLOOP: + printf("%d %d", a, bx); + printf(COMMENT "to %d", pc - bx + 2); + break; + case OP_FORPREP: + printf("%d %d", a, bx); + printf(COMMENT "to %d", pc + bx + 2); + break; + case OP_TFORPREP: + printf("%d %d", a, bx); + printf(COMMENT "to %d", pc + bx + 2); + break; + case OP_TFORCALL: + printf("%d %d", a, c); + break; + case OP_TFORLOOP: + printf("%d %d", a, bx); + printf(COMMENT "to %d", pc - bx + 2); + break; + case OP_SETLIST: + printf("%d %d %d", a, b, c); + if (isk) { + printf(COMMENT "%d", c + EXTRAARGC); + } + break; + case OP_CLOSURE: + printf("%d %d",a,bx); + printf(COMMENT "%p", LUACVOID(f->p[bx])); + break; + case OP_VARARG: + printf("%d %d", a, c); + printf(COMMENT); + if (c == 0) { + printf("all out"); + } else { + printf("%d out", c-1); + } + break; + case OP_VARARGPREP: + printf("%d",a); + break; + case OP_EXTRAARG: + printf("%d", ax); + break; + default: + printf("%d %d %d", a, b, c); + printf(COMMENT "not handled"); + break; + } + printf("\n"); + } +} + +# define SS(x) ((x == 1) ? "" : "s") +# define S(x) (int)(x),SS(x) + +static void luaclib_aux_print_header(const Proto* f) +{ + const char* s = f->source ? getstr(f->source) : "=?"; + if (*s == '@' || *s == '=') { + s++; + } else if (*s == LUA_SIGNATURE[0]) { + s = "(bstring)"; + } else { + s = "(string)"; + } + printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", + (f->linedefined == 0) ? "main" : "function", + s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),LUACVOID(f) + ); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams), + f->is_vararg?"+":"", + SS(f->numparams), + S(f->maxstacksize), + S(f->sizeupvalues) + ); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars), + S(f->sizek), + S(f->sizep) + ); +} + +static void luaclib_aux_print_debug(const Proto* f) +{ + { + int n = f->sizek; + printf("constants (%d) for %p:\n", n, LUACVOID(f)); + for (int i = 0; i < n; i++) { + printf("\t%d\t", i); + PrintType(f, i); + PrintConstant(f, i); + printf("\n"); + } + } + { + int n = f->sizelocvars; + printf("locals (%d) for %p:\n", n, LUACVOID(f)); + for (int i = 0; i < n; i++) { + printf("\t%d\t%s\t%d\t%d\n", + i, + getstr(f->locvars[i].varname), + f->locvars[i].startpc+1, + f->locvars[i].endpc+1 + ); + } + } + { + int n = f->sizeupvalues; + printf("upvalues (%d) for %p:\n", n, LUACVOID(f)); + for (int i = 0; i < n; i++) { + printf("\t%d\t%s\t%d\t%d\n", + i, + UPVALNAME(i), + f->upvalues[i].instack, + f->upvalues[i].idx + ); + } + } +} + +/* We only have one (needs checking). */ + +static void luaclib_aux_print_function(const Proto* f, int full) +{ + int n = f->sizep; + luaclib_aux_print_header(f); + luaclib_aux_print_code(f); + if (full) { + luaclib_aux_print_debug(f); + } + for (int i = 0; i < n; i++) { + luaclib_aux_print_function(f->p[i], full); + } +} + +static int luaclib_print(lua_State *L) +{ + int full = lua_toboolean(L, 2); + size_t len = 0; + const char *str = lua_tolstring(L, 1, &len); + if (len > 0 && luaL_loadbuffer(L, str, len, str) == LUA_OK) { + const Proto *f = toproto(L, -1); + if (f) { + tmname = G(L)->tmname; + luaclib_aux_print_function(f, full); + } + } + return 0; +} + +/* So far for the adapted rip-off. */ + +void lmt_luaclib_initialize(void) +{ + /* not used yet */ +} + +static const struct luaL_Reg luaclib_function_list[] = { + { "print", luaclib_print }, + { NULL, NULL }, +}; + +int luaopen_luac(lua_State *L) +{ + lua_newtable(L); + luaL_setfuncs(L, luaclib_function_list, 0); + return 1; +} |