| /* |
| ** Load and dump code. |
| ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h |
| */ |
| |
| #include <errno.h> |
| #include <stdio.h> |
| |
| #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; |
| } |
| |