Merge branch 'master' into v2.1
[luajit-2.0.git] / src / lj_load.c
blob07304487692a86169091693366ae32b1f2c4c6cc
1 /*
2 ** Load and dump code.
3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #include <errno.h>
7 #include <stdio.h>
9 #define lj_load_c
10 #define LUA_CORE
12 #include "lua.h"
13 #include "lauxlib.h"
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"
26 /* -- Load Lua source code and bytecode ----------------------------------- */
28 static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud)
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);
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;
48 LUA_API int lua_loadx(lua_State *L, lua_Reader reader, void *data,
49 const char *chunkname, const char *mode)
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;
64 LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data,
65 const char *chunkname)
67 return lua_loadx(L, reader, data, chunkname, NULL);
70 typedef struct FileReaderCtx {
71 FILE *fp;
72 char buf[LUAL_BUFFERSIZE];
73 } FileReaderCtx;
75 static const char *reader_file(lua_State *L, void *ud, size_t *size)
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;
84 LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename,
85 const char *mode)
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;
96 chunkname = lua_pushfstring(L, "@%s", filename);
97 } else {
98 ctx.fp = stdin;
99 chunkname = "=stdin";
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;
109 if (filename) {
110 L->top--;
111 copyTV(L, L->top-1, L->top);
112 fclose(ctx.fp);
114 return status;
117 LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
119 return luaL_loadfilex(L, filename, NULL);
122 typedef struct StringReaderCtx {
123 const char *str;
124 size_t size;
125 } StringReaderCtx;
127 static const char *reader_string(lua_State *L, void *ud, size_t *size)
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;
137 LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buf, size_t size,
138 const char *name, const char *mode)
140 StringReaderCtx ctx;
141 ctx.str = buf;
142 ctx.size = size;
143 return lua_loadx(L, reader_string, &ctx, name, mode);
146 LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size,
147 const char *name)
149 return luaL_loadbufferx(L, buf, size, name, NULL);
152 LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
154 return luaL_loadbuffer(L, s, strlen(s), s);
157 /* -- Dump bytecode ------------------------------------------------------- */
159 LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data)
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;