1 /*
2 ** Load and dump code.
3 ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4 */
5 
6 #include <errno.h>
7 #include <stdio.h>
8 
9 #define lj_load_c
10 #define LUA_CORE
11 
12 #include "lua.h"
13 #include "lauxlib.h"
14 
15 #include "lj_obj.h"
16 #include "lj_gc.h"
17 #include "lj_err.h"
18 #include "lj_buf.h"
19 #include "lj_func.h"
20 #include "lj_frame.h"
21 #include "lj_vm.h"
22 #include "lj_lex.h"
23 #include "lj_bcdump.h"
24 #include "lj_parse.h"
25 
26 /* -- Load Lua source code and bytecode ----------------------------------- */
27 
cpparser(lua_State * L,lua_CFunction dummy,void * ud)28 static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud)
29 {
30   LexState *ls = (LexState *)ud;
31   GCproto *pt;
32   GCfunc *fn;
33   int bc;
34   UNUSED(dummy);
35   cframe_errfunc(L->cframe) = -1;  /* Inherit error function. */
36   bc = lj_lex_setup(L, ls);
37   if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) {
38     setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE));
39     lj_err_throw(L, LUA_ERRSYNTAX);
40   }
41   pt = bc ? lj_bcread(ls) : lj_parse(ls);
42   fn = lj_func_newL_empty(L, pt, tabref(L->env));
43   /* Don't combine above/below into one statement. */
44   setfuncV(L, L->top++, fn);
45   return NULL;
46 }
47 
lua_loadx(lua_State * L,lua_Reader reader,void * data,const char * chunkname,const char * mode)48 LUA_API int lua_loadx(lua_State *L, lua_Reader reader, void *data,
49 		      const char *chunkname, const char *mode)
50 {
51   LexState ls;
52   int status;
53   ls.rfunc = reader;
54   ls.rdata = data;
55   ls.chunkarg = chunkname ? chunkname : "?";
56   ls.mode = mode;
57   lj_buf_init(L, &ls.sb);
58   status = lj_vm_cpcall(L, NULL, &ls, cpparser);
59   lj_lex_cleanup(L, &ls);
60   lj_gc_check(L);
61   return status;
62 }
63 
lua_load(lua_State * L,lua_Reader reader,void * data,const char * chunkname)64 LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data,
65 		     const char *chunkname)
66 {
67   return lua_loadx(L, reader, data, chunkname, NULL);
68 }
69 
70 typedef struct FileReaderCtx {
71   FILE *fp;
72   char buf[LUAL_BUFFERSIZE];
73 } FileReaderCtx;
74 
reader_file(lua_State * L,void * ud,size_t * size)75 static const char *reader_file(lua_State *L, void *ud, size_t *size)
76 {
77   FileReaderCtx *ctx = (FileReaderCtx *)ud;
78   UNUSED(L);
79   if (feof(ctx->fp)) return NULL;
80   *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp);
81   return *size > 0 ? ctx->buf : NULL;
82 }
83 
luaL_loadfilex(lua_State * L,const char * filename,const char * mode)84 LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename,
85 			      const char *mode)
86 {
87   FileReaderCtx ctx;
88   int status;
89   const char *chunkname;
90   if (filename) {
91     ctx.fp = fopen(filename, "rb");
92     if (ctx.fp == NULL) {
93       lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno));
94       return LUA_ERRFILE;
95     }
96     chunkname = lua_pushfstring(L, "@%s", filename);
97   } else {
98     ctx.fp = stdin;
99     chunkname = "=stdin";
100   }
101   status = lua_loadx(L, reader_file, &ctx, chunkname, mode);
102   if (ferror(ctx.fp)) {
103     L->top -= filename ? 2 : 1;
104     lua_pushfstring(L, "cannot read %s: %s", chunkname+1, strerror(errno));
105     if (filename)
106       fclose(ctx.fp);
107     return LUA_ERRFILE;
108   }
109   if (filename) {
110     L->top--;
111     copyTV(L, L->top-1, L->top);
112     fclose(ctx.fp);
113   }
114   return status;
115 }
116 
luaL_loadfile(lua_State * L,const char * filename)117 LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
118 {
119   return luaL_loadfilex(L, filename, NULL);
120 }
121 
122 typedef struct StringReaderCtx {
123   const char *str;
124   size_t size;
125 } StringReaderCtx;
126 
reader_string(lua_State * L,void * ud,size_t * size)127 static const char *reader_string(lua_State *L, void *ud, size_t *size)
128 {
129   StringReaderCtx *ctx = (StringReaderCtx *)ud;
130   UNUSED(L);
131   if (ctx->size == 0) return NULL;
132   *size = ctx->size;
133   ctx->size = 0;
134   return ctx->str;
135 }
136 
luaL_loadbufferx(lua_State * L,const char * buf,size_t size,const char * name,const char * mode)137 LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buf, size_t size,
138 				const char *name, const char *mode)
139 {
140   StringReaderCtx ctx;
141   ctx.str = buf;
142   ctx.size = size;
143   return lua_loadx(L, reader_string, &ctx, name, mode);
144 }
145 
luaL_loadbuffer(lua_State * L,const char * buf,size_t size,const char * name)146 LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size,
147 			       const char *name)
148 {
149   return luaL_loadbufferx(L, buf, size, name, NULL);
150 }
151 
luaL_loadstring(lua_State * L,const char * s)152 LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
153 {
154   return luaL_loadbuffer(L, s, strlen(s), s);
155 }
156 
157 /* -- Dump bytecode ------------------------------------------------------- */
158 
lua_dump(lua_State * L,lua_Writer writer,void * data)159 LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data)
160 {
161   cTValue *o = L->top-1;
162   lj_checkapi(L->top > L->base, "top slot empty");
163   if (tvisfunc(o) && isluafunc(funcV(o)))
164     return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0);
165   else
166     return 1;
167 }
168 
169