on a177213 help sign in
245 lines 6.6 kB history raw
1// Copied straight from https://www.lua.org/source/5.1/lua.c.html
2// with some of the cli stuff stripped out.
4/*
5** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
6** Lua stand-alone interpreter
7** See Copyright Notice in lua.h
8*/
10#include <signal.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
15#define lua_c
16#define LUA_USE_LINUX
18#include <lua.h>
20#include <lauxlib.h>
21#include <luaconf.h>
22#include <lualib.h>
24extern lua_State *pry_L;
26static const char *progname = LUA_PROGNAME;
28static void lstop(lua_State *L, lua_Debug *ar) {
29 (void)ar; /* unused arg. */
30 lua_sethook(L, NULL, 0, 0);
31 luaL_error(L, "interrupted!");
34static void laction(int i) {
35 signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
36 terminate process (default action) */
37 lua_sethook(pry_L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
40static void l_message(const char *pname, const char *msg) {
41 if (pname)
42 fprintf(stderr, "%s: ", pname);
43 fprintf(stderr, "%s\n", msg);
44 fflush(stderr);
47static int report(lua_State *L, int status) {
48 if (status && !lua_isnil(L, -1)) {
49 const char *msg = lua_tostring(L, -1);
50 if (msg == NULL)
51 msg = "(error object is not a string)";
52 l_message(progname, msg);
53 lua_pop(L, 1);
54 }
55 return status;
58static int traceback(lua_State *L) {
59 if (!lua_isstring(L, 1)) /* 'message' not a string? */
60 return 1; /* keep it intact */
61 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
62 if (!lua_istable(L, -1)) {
63 lua_pop(L, 1);
64 return 1;
65 }
66 lua_getfield(L, -1, "traceback");
67 if (!lua_isfunction(L, -1)) {
68 lua_pop(L, 2);
69 return 1;
70 }
71 lua_pushvalue(L, 1); /* pass error message */
72 lua_pushinteger(L, 2); /* skip this function and traceback */
73 lua_call(L, 2, 1); /* call debug.traceback */
74 return 1;
77static int docall(lua_State *L, int narg, int clear) {
78 int status;
79 int base = lua_gettop(L) - narg; /* function index */
80 lua_pushcfunction(L, traceback); /* push traceback function */
81 lua_insert(L, base); /* put it under chunk and args */
82 signal(SIGINT, laction);
83 status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
84 signal(SIGINT, SIG_DFL);
85 lua_remove(L, base); /* remove traceback function */
86 /* force a complete garbage collection in case of errors */
87 if (status != 0)
88 lua_gc(L, LUA_GCCOLLECT, 0);
89 return status;
92static void print_version(void) {
93 l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
96static int getargs(lua_State *L, char **argv, int n) {
97 int narg;
98 int i;
99 int argc = 0;
100 while (argv[argc])
101 argc++; /* count total number of arguments */
102 narg = argc - (n + 1); /* number of arguments to the script */
103 luaL_checkstack(L, narg + 3, "too many arguments to script");
104 for (i = n + 1; i < argc; i++)
105 lua_pushstring(L, argv[i]);
106 lua_createtable(L, narg, n + 1);
107 for (i = 0; i < argc; i++) {
108 lua_pushstring(L, argv[i]);
109 lua_rawseti(L, -2, i - n);
110 }
111 return narg;
114int dostring(lua_State *L, const char *s, const char *name) {
115 int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
116 return report(L, status);
119static const char *get_prompt(lua_State *L, int firstline) {
120 const char *p;
121 lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
122 p = lua_tostring(L, -1);
123 if (p == NULL)
124 p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
125 lua_pop(L, 1); /* remove global */
126 return p;
129static int incomplete(lua_State *L, int status) {
130 if (status == LUA_ERRSYNTAX) {
131 size_t lmsg;
132 const char *msg = lua_tolstring(L, -1, &lmsg);
133 const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
134 if (strstr(msg, LUA_QL("<eof>")) == tp) {
135 lua_pop(L, 1);
136 return 1;
137 }
138 }
140 return 0; /* else... */
143static int pushline(lua_State *L, int firstline) {
144 char buffer[LUA_MAXINPUT];
145 char *b = buffer;
146 size_t l;
147 const char *prmt = get_prompt(L, firstline);
148 if (lua_readline(L, b, prmt) == 0)
149 return 0; /* no input */
150 l = strlen(b);
151 if (l > 0 && b[l - 1] == '\n') /* line ends with newline? */
152 b[l - 1] = '\0'; /* remove it */
153 if (firstline && b[0] == '=') /* first line starts with `=' ? */
154 lua_pushfstring(L, "return %s", b + 1); /* change it to `return' */
155 else
156 lua_pushstring(L, b);
157 lua_freeline(L, b);
158 return 1;
161static int try_expression(lua_State *L) {
162 lua_pushliteral(L, "return ");
163 lua_pushvalue(L, 1);
164 lua_concat(L, 2);
166 int rstatus =
167 luaL_loadbuffer(L, lua_tostring(L, -1), lua_strlen(L, -1), "=stdin");
169 if (rstatus) {
170 lua_pop(L, 2);
171 return 1;
172 }
174 lua_remove(L, 2);
176 return 0;
179static int loadline(lua_State *L) {
180 int status = 0;
181 lua_settop(L, 0);
182 if (!pushline(L, 1))
183 return -1; /* no input */
185 for (;;) { /* repeat until gets a complete line */
186 status = try_expression(L);
187 if (!status)
188 break;
190 status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
192 if (!incomplete(L, status))
193 break; /* cannot try to add lines? */
195 if (!pushline(L, 0)) /* no more input? */
196 return -1;
197 lua_pushliteral(L, "\n"); /* add a new line... */
198 lua_insert(L, -2); /* ...between the two lines */
199 lua_concat(L, 3); /* join them */
200 }
202 lua_saveline(L, 1);
203 lua_remove(L, 1); /* remove line */
204 return status;
207void dotty(lua_State *L) {
208 int status;
209 const char *oldprogname = progname;
210 progname = NULL;
211 while ((status = loadline(L)) != -1) {
212 if (status == 0)
213 status = docall(L, 0, 0);
214 report(L, status);
215 if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
216 lua_getglobal(L, "print");
217 lua_insert(L, 1);
218 if (lua_pcall(L, lua_gettop(L) - 1, 0, 0) != 0)
219 l_message(progname,
220 lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
221 lua_tostring(L, -1)));
222 }
223 }
224 lua_settop(L, 0); /* clear stack */
225 fputs("\n", stdout);
226 fflush(stdout);
227 progname = oldprogname;
230int handle_script(lua_State *L, char **argv, int n) {
231 int status;
232 const char *fname;
233 int narg = getargs(L, argv, n); /* collect arguments */
234 lua_setglobal(L, "arg");
235 fname = argv[n];
236 if (strcmp(fname, "-") == 0 && strcmp(argv[n - 1], "--") != 0)
237 fname = NULL; /* stdin */
238 status = luaL_loadfile(L, fname);
239 lua_insert(L, -(narg + 1));
240 if (status == 0)
241 status = docall(L, narg, 0);
242 else
243 lua_pop(L, narg);
244 return report(L, status);