/* ** Load and dump code. ** Copyright (C) 2005-2022 Mike Pall. See Copyright Notice in luajit.h */ #include #include #define lj_load_c #define LUA_CORE #include "lua.h" #include "lauxlib.h" #include "lj_obj.h" #include "lj_gc.h" #include "lj_err.h" #include "lj_buf.h" #include "lj_func.h" #include "lj_frame.h" #include "lj_vm.h" #include "lj_lex.h" #include "lj_bcdump.h" #include "lj_parse.h" /* -- Load Lua source code and bytecode ----------------------------------- */ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) { LexState *ls = (LexState *)ud; GCproto *pt; GCfunc *fn; int bc; UNUSED(dummy); cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ bc = lj_lex_setup(L, ls); if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); lj_err_throw(L, LUA_ERRSYNTAX); } pt = bc ? lj_bcread(ls) : lj_parse(ls); fn = lj_func_newL_empty(L, pt, tabref(L->env)); /* Don't combine above/below into one statement. */ setfuncV(L, L->top++, fn); return NULL; } LUA_API int lua_loadx(lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode) { LexState ls; int status; ls.rfunc = reader; ls.rdata = data; ls.chunkarg = chunkname ? chunkname : "?"; ls.mode = mode; lj_buf_init(L, &ls.sb); status = lj_vm_cpcall(L, NULL, &ls, cpparser); lj_lex_cleanup(L, &ls); lj_gc_check(L); return status; } LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char *chunkname) { return lua_loadx(L, reader, data, chunkname, NULL); } typedef struct FileReaderCtx { FILE *fp; char buf[LUAL_BUFFERSIZE]; } FileReaderCtx; static const char *reader_file(lua_State *L, void *ud, size_t *size) { FileReaderCtx *ctx = (FileReaderCtx *)ud; UNUSED(L); if (feof(ctx->fp)) return NULL; *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp); return *size > 0 ? ctx->buf : NULL; } LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode) { FileReaderCtx ctx; int status; const char *chunkname; if (filename) { ctx.fp = fopen(filename, "rb"); if (ctx.fp == NULL) { lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno)); return LUA_ERRFILE; } chunkname = lua_pushfstring(L, "@%s", filename); } else { ctx.fp = stdin; chunkname = "=stdin"; } status = lua_loadx(L, reader_file, &ctx, chunkname, mode); if (ferror(ctx.fp)) { L->top -= filename ? 2 : 1; lua_pushfstring(L, "cannot read %s: %s", chunkname+1, strerror(errno)); if (filename) fclose(ctx.fp); return LUA_ERRFILE; } if (filename) { L->top--; copyTV(L, L->top-1, L->top); fclose(ctx.fp); } return status; } LUALIB_API int luaL_loadfile(lua_State *L, const char *filename) { return luaL_loadfilex(L, filename, NULL); } typedef struct StringReaderCtx { const char *str; size_t size; } StringReaderCtx; static const char *reader_string(lua_State *L, void *ud, size_t *size) { StringReaderCtx *ctx = (StringReaderCtx *)ud; UNUSED(L); if (ctx->size == 0) return NULL; *size = ctx->size; ctx->size = 0; return ctx->str; } LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buf, size_t size, const char *name, const char *mode) { StringReaderCtx ctx; ctx.str = buf; ctx.size = size; return lua_loadx(L, reader_string, &ctx, name, mode); } LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size, const char *name) { return luaL_loadbufferx(L, buf, size, name, NULL); } LUALIB_API int luaL_loadstring(lua_State *L, const char *s) { return luaL_loadbuffer(L, s, strlen(s), s); } /* -- Dump bytecode ------------------------------------------------------- */ LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data) { cTValue *o = L->top-1; lj_checkapi(L->top > L->base, "top slot empty"); if (tvisfunc(o) && isluafunc(funcV(o))) return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0); else return 1; }