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
28static 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
48LUA_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
64LUA_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
70typedef struct FileReaderCtx {
71 FILE *fp;
72 char buf[LUAL_BUFFERSIZE];
73} FileReaderCtx;
74
75static 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
84LUALIB_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
117LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
118{
119 return luaL_loadfilex(L, filename, NULL);
120}
121
122typedef struct StringReaderCtx {
123 const char *str;
124 size_t size;
125} StringReaderCtx;
126
127static 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
137LUALIB_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
146LUALIB_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
152LUALIB_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
159LUA_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