diff --git a/src/Makefile b/src/Makefile index bfb03e9a..8b7218e7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -447,7 +447,7 @@ LJLIB_C= $(LJLIB_O:.o=.c) LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ - lj_api.o lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o \ + lj_api.o lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ diff --git a/src/Makefile.dep b/src/Makefile.dep index af5d33b1..99acc044 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -41,8 +41,7 @@ lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ - lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h \ - lj_strscan.h + lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ @@ -125,6 +124,9 @@ lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lib.h +lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ + lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_func.h lj_frame.h \ + lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h lj_dispatch.h lj_bc.h \ lj_traceerr.h lj_vm.h @@ -193,18 +195,19 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h \ lj_debug.c lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c lj_ccallback.h \ luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c lj_api.c \ - lj_bcdump.h lj_parse.h lj_lex.c lualib.h lj_parse.c lj_bcread.c \ - lj_bcwrite.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c \ - lj_ccall.h lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h \ - lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h \ - lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h lj_opt_mem.c \ - lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c \ - lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c \ - lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \ - lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h lj_asm_*.h lj_trace.c \ - lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \ - lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \ - lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c + lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h \ + lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c \ + lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h lj_target_*.h \ + lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c \ + lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h \ + lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ + lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ + lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ + lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ + lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ + lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ + lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ + lib_init.c luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ diff --git a/src/lauxlib.h b/src/lauxlib.h index 505a9f52..80585f64 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -75,7 +75,11 @@ LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, const char *fname, int szhint); - +/* From Lua 5.2. */ +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); /* diff --git a/src/lib_aux.c b/src/lib_aux.c index f25ab65a..8fbee71b 100644 --- a/src/lib_aux.c +++ b/src/lib_aux.c @@ -233,83 +233,6 @@ LUALIB_API void luaL_unref(lua_State *L, int t, int ref) } } -/* -- Load Lua code ------------------------------------------------------- */ - -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_loadfile(lua_State *L, const char *filename) -{ - 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_load(L, reader_file, &ctx, chunkname); - 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; -} - -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_loadbuffer(lua_State *L, const char *buf, size_t size, - const char *name) -{ - StringReaderCtx ctx; - ctx.str = buf; - ctx.size = size; - return lua_load(L, reader_string, &ctx, name); -} - -LUALIB_API int luaL_loadstring(lua_State *L, const char *s) -{ - return luaL_loadbuffer(L, s, strlen(s), s); -} - /* -- Default allocator and panic function -------------------------------- */ static int panic(lua_State *L) diff --git a/src/lj_api.c b/src/lj_api.c index a9ea38d8..5a0bd07a 100644 --- a/src/lj_api.c +++ b/src/lj_api.c @@ -23,9 +23,6 @@ #include "lj_frame.h" #include "lj_trace.h" #include "lj_vm.h" -#include "lj_lex.h" -#include "lj_bcdump.h" -#include "lj_parse.h" #include "lj_strscan.h" /* -- Common helper functions --------------------------------------------- */ @@ -1138,47 +1135,6 @@ LUA_API int lua_resume(lua_State *L, int nargs) return LUA_ERRRUN; } -/* -- Load and dump Lua code ---------------------------------------------- */ - -static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) -{ - LexState *ls = (LexState *)ud; - GCproto *pt; - GCfunc *fn; - UNUSED(dummy); - cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ - pt = lj_lex_setup(L, ls) ? 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_load(lua_State *L, lua_Reader reader, void *data, - const char *chunkname) -{ - LexState ls; - int status; - ls.rfunc = reader; - ls.rdata = data; - ls.chunkarg = chunkname ? chunkname : "?"; - lj_str_initbuf(&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_dump(lua_State *L, lua_Writer writer, void *data) -{ - cTValue *o = L->top-1; - api_checknelems(L, 1); - if (tvisfunc(o) && isluafunc(funcV(o))) - return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0); - else - return 1; -} - /* -- GC and memory management -------------------------------------------- */ LUA_API int lua_gc(lua_State *L, int what, int data) diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index 28c5ca08..da40e848 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h @@ -111,6 +111,7 @@ ERRDEF(NOJIT, "JIT compiler permanently disabled by build option") ERRDEF(JITOPT, "unknown or malformed optimization flag " LUA_QS) /* Lexer/parser errors. */ +ERRDEF(XMODE, "attempt to load chunk with wrong mode") ERRDEF(XNEAR, "%s near " LUA_QS) ERRDEF(XELEM, "lexical element too long") ERRDEF(XLINES, "chunk has too many lines") @@ -144,7 +145,6 @@ ERRDEF(XGSCOPE, " jumps into the scope of local " LUA_QS) /* Bytecode reader errors. */ ERRDEF(BCFMT, "cannot load incompatible bytecode") ERRDEF(BCBAD, "cannot load malformed bytecode") -ERRDEF(BCHEAD, "attempt to load bytecode with extra header") #if LJ_HASFFI /* FFI errors. */ diff --git a/src/lj_lex.c b/src/lj_lex.c index e464f420..b54d2a23 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -406,7 +406,7 @@ int lj_lex_setup(lua_State *L, LexState *ls) ** Lua code by looking at the first char. Since this is a potential ** security violation no attempt is made to echo the chunkname either. */ - setstrV(L, L->top++, lj_err_str(L, LJ_ERR_BCHEAD)); + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_BCBAD)); lj_err_throw(L, LUA_ERRSYNTAX); } return 1; diff --git a/src/lj_lex.h b/src/lj_lex.h index 16f35aa5..7a4fd74b 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h @@ -64,6 +64,7 @@ typedef struct LexState { BCLine lastline; /* Line of last token. */ GCstr *chunkname; /* Current chunk name (interned string). */ const char *chunkarg; /* Chunk name argument. */ + const char *mode; /* Allow loading bytecode (b) and/or source text (t). */ VarInfo *vstack; /* Stack for names and extents of local variables. */ MSize sizevstack; /* Size of variable stack. */ MSize vtop; /* Top of variable stack. */ diff --git a/src/lj_load.c b/src/lj_load.c new file mode 100644 index 00000000..e30421e6 --- /dev/null +++ b/src/lj_load.c @@ -0,0 +1,168 @@ +/* +** Load and dump code. +** Copyright (C) 2005-2012 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_str.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_str_initbuf(&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; + api_check(L, L->top > L->base); + if (tvisfunc(o) && isluafunc(funcV(o))) + return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0); + else + return 1; +} + diff --git a/src/ljamalg.c b/src/ljamalg.c index a64c9429..7aae6260 100644 --- a/src/ljamalg.c +++ b/src/ljamalg.c @@ -49,6 +49,7 @@ #include "lj_parse.c" #include "lj_bcread.c" #include "lj_bcwrite.c" +#include "lj_load.c" #include "lj_ctype.c" #include "lj_cdata.c" #include "lj_cconv.c" diff --git a/src/lua.h b/src/lua.h index 9e9357a8..c83fd3bb 100644 --- a/src/lua.h +++ b/src/lua.h @@ -344,6 +344,8 @@ LUA_API int lua_gethookcount (lua_State *L); /* From Lua 5.2. */ LUA_API void *lua_upvalueid (lua_State *L, int idx, int n); LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2); +LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); struct lua_Debug {