aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/src/luajit.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/src/luajit.c')
-rw-r--r--libraries/luajit-2.0/src/luajit.c553
1 files changed, 553 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/src/luajit.c b/libraries/luajit-2.0/src/luajit.c
new file mode 100644
index 0000000..17d3b5f
--- /dev/null
+++ b/libraries/luajit-2.0/src/luajit.c
@@ -0,0 +1,553 @@
1/*
2** LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc.
3** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
4**
5** Major portions taken verbatim or adapted from the Lua interpreter.
6** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7*/
8
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#define luajit_c
15
16#include "lua.h"
17#include "lauxlib.h"
18#include "lualib.h"
19#include "luajit.h"
20
21#include "lj_arch.h"
22
23#if LJ_TARGET_POSIX
24#include <unistd.h>
25#define lua_stdin_is_tty() isatty(0)
26#elif LJ_TARGET_WINDOWS
27#include <io.h>
28#ifdef __BORLANDC__
29#define lua_stdin_is_tty() isatty(_fileno(stdin))
30#else
31#define lua_stdin_is_tty() _isatty(_fileno(stdin))
32#endif
33#else
34#define lua_stdin_is_tty() 1
35#endif
36
37static lua_State *globalL = NULL;
38static const char *progname = LUA_PROGNAME;
39
40static void lstop(lua_State *L, lua_Debug *ar)
41{
42 (void)ar; /* unused arg. */
43 lua_sethook(L, NULL, 0, 0);
44 /* Avoid luaL_error -- a C hook doesn't add an extra frame. */
45 luaL_where(L, 0);
46 lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1));
47 lua_error(L);
48}
49
50static void laction(int i)
51{
52 signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
53 terminate process (default action) */
54 lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
55}
56
57static void print_usage(void)
58{
59 fprintf(stderr,
60 "usage: %s [options]... [script [args]...].\n"
61 "Available options are:\n"
62 " -e chunk Execute string " LUA_QL("chunk") ".\n"
63 " -l name Require library " LUA_QL("name") ".\n"
64 " -b ... Save or list bytecode.\n"
65 " -j cmd Perform LuaJIT control command.\n"
66 " -O[opt] Control LuaJIT optimizations.\n"
67 " -i Enter interactive mode after executing " LUA_QL("script") ".\n"
68 " -v Show version information.\n"
69 " -- Stop handling options.\n"
70 " - Execute stdin and stop handling options.\n"
71 ,
72 progname);
73 fflush(stderr);
74}
75
76static void l_message(const char *pname, const char *msg)
77{
78 if (pname) fprintf(stderr, "%s: ", pname);
79 fprintf(stderr, "%s\n", msg);
80 fflush(stderr);
81}
82
83static int report(lua_State *L, int status)
84{
85 if (status && !lua_isnil(L, -1)) {
86 const char *msg = lua_tostring(L, -1);
87 if (msg == NULL) msg = "(error object is not a string)";
88 l_message(progname, msg);
89 lua_pop(L, 1);
90 }
91 return status;
92}
93
94static int traceback(lua_State *L)
95{
96 if (!lua_isstring(L, 1)) /* 'message' not a string? */
97 return 1; /* keep it intact */
98 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
99 if (!lua_istable(L, -1)) {
100 lua_pop(L, 1);
101 return 1;
102 }
103 lua_getfield(L, -1, "traceback");
104 if (!lua_isfunction(L, -1)) {
105 lua_pop(L, 2);
106 return 1;
107 }
108 lua_pushvalue(L, 1); /* pass error message */
109 lua_pushinteger(L, 2); /* skip this function and traceback */
110 lua_call(L, 2, 1); /* call debug.traceback */
111 return 1;
112}
113
114static int docall(lua_State *L, int narg, int clear)
115{
116 int status;
117 int base = lua_gettop(L) - narg; /* function index */
118 lua_pushcfunction(L, traceback); /* push traceback function */
119 lua_insert(L, base); /* put it under chunk and args */
120 signal(SIGINT, laction);
121 status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
122 signal(SIGINT, SIG_DFL);
123 lua_remove(L, base); /* remove traceback function */
124 /* force a complete garbage collection in case of errors */
125 if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
126 return status;
127}
128
129static void print_version(void)
130{
131 fprintf(stderr,
132 LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n");
133}
134
135static void print_jit_status(lua_State *L)
136{
137 int n;
138 const char *s;
139 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
140 lua_getfield(L, -1, "jit"); /* Get jit.* module table. */
141 lua_remove(L, -2);
142 lua_getfield(L, -1, "status");
143 lua_remove(L, -2);
144 n = lua_gettop(L);
145 lua_call(L, 0, LUA_MULTRET);
146 fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr);
147 for (n++; (s = lua_tostring(L, n)); n++)
148 fprintf(stderr, " %s", s);
149 fputs("\n", stderr);
150}
151
152static int getargs(lua_State *L, char **argv, int n)
153{
154 int narg;
155 int i;
156 int argc = 0;
157 while (argv[argc]) argc++; /* count total number of arguments */
158 narg = argc - (n + 1); /* number of arguments to the script */
159 luaL_checkstack(L, narg + 3, "too many arguments to script");
160 for (i = n+1; i < argc; i++)
161 lua_pushstring(L, argv[i]);
162 lua_createtable(L, narg, n + 1);
163 for (i = 0; i < argc; i++) {
164 lua_pushstring(L, argv[i]);
165 lua_rawseti(L, -2, i - n);
166 }
167 return narg;
168}
169
170static int dofile(lua_State *L, const char *name)
171{
172 int status = luaL_loadfile(L, name) || docall(L, 0, 1);
173 return report(L, status);
174}
175
176static int dostring(lua_State *L, const char *s, const char *name)
177{
178 int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
179 return report(L, status);
180}
181
182static int dolibrary(lua_State *L, const char *name)
183{
184 lua_getglobal(L, "require");
185 lua_pushstring(L, name);
186 return report(L, docall(L, 1, 1));
187}
188
189static void write_prompt(lua_State *L, int firstline)
190{
191 const char *p;
192 lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
193 p = lua_tostring(L, -1);
194 if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2;
195 fputs(p, stdout);
196 fflush(stdout);
197 lua_pop(L, 1); /* remove global */
198}
199
200static int incomplete(lua_State *L, int status)
201{
202 if (status == LUA_ERRSYNTAX) {
203 size_t lmsg;
204 const char *msg = lua_tolstring(L, -1, &lmsg);
205 const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
206 if (strstr(msg, LUA_QL("<eof>")) == tp) {
207 lua_pop(L, 1);
208 return 1;
209 }
210 }
211 return 0; /* else... */
212}
213
214static int pushline(lua_State *L, int firstline)
215{
216 char buf[LUA_MAXINPUT];
217 write_prompt(L, firstline);
218 if (fgets(buf, LUA_MAXINPUT, stdin)) {
219 size_t len = strlen(buf);
220 if (len > 0 && buf[len-1] == '\n')
221 buf[len-1] = '\0';
222 if (firstline && buf[0] == '=')
223 lua_pushfstring(L, "return %s", buf+1);
224 else
225 lua_pushstring(L, buf);
226 return 1;
227 }
228 return 0;
229}
230
231static int loadline(lua_State *L)
232{
233 int status;
234 lua_settop(L, 0);
235 if (!pushline(L, 1))
236 return -1; /* no input */
237 for (;;) { /* repeat until gets a complete line */
238 status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
239 if (!incomplete(L, status)) break; /* cannot try to add lines? */
240 if (!pushline(L, 0)) /* no more input? */
241 return -1;
242 lua_pushliteral(L, "\n"); /* add a new line... */
243 lua_insert(L, -2); /* ...between the two lines */
244 lua_concat(L, 3); /* join them */
245 }
246 lua_remove(L, 1); /* remove line */
247 return status;
248}
249
250static void dotty(lua_State *L)
251{
252 int status;
253 const char *oldprogname = progname;
254 progname = NULL;
255 while ((status = loadline(L)) != -1) {
256 if (status == 0) status = docall(L, 0, 0);
257 report(L, status);
258 if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
259 lua_getglobal(L, "print");
260 lua_insert(L, 1);
261 if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
262 l_message(progname,
263 lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
264 lua_tostring(L, -1)));
265 }
266 }
267 lua_settop(L, 0); /* clear stack */
268 fputs("\n", stdout);
269 fflush(stdout);
270 progname = oldprogname;
271}
272
273static int handle_script(lua_State *L, char **argv, int n)
274{
275 int status;
276 const char *fname;
277 int narg = getargs(L, argv, n); /* collect arguments */
278 lua_setglobal(L, "arg");
279 fname = argv[n];
280 if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
281 fname = NULL; /* stdin */
282 status = luaL_loadfile(L, fname);
283 lua_insert(L, -(narg+1));
284 if (status == 0)
285 status = docall(L, narg, 0);
286 else
287 lua_pop(L, narg);
288 return report(L, status);
289}
290
291/* Load add-on module. */
292static int loadjitmodule(lua_State *L)
293{
294 lua_getglobal(L, "require");
295 lua_pushliteral(L, "jit.");
296 lua_pushvalue(L, -3);
297 lua_concat(L, 2);
298 if (lua_pcall(L, 1, 1, 0)) {
299 const char *msg = lua_tostring(L, -1);
300 if (msg && !strncmp(msg, "module ", 7)) {
301 err:
302 l_message(progname,
303 "unknown luaJIT command or jit.* modules not installed");
304 return 1;
305 } else {
306 return report(L, 1);
307 }
308 }
309 lua_getfield(L, -1, "start");
310 if (lua_isnil(L, -1)) goto err;
311 lua_remove(L, -2); /* Drop module table. */
312 return 0;
313}
314
315/* Run command with options. */
316static int runcmdopt(lua_State *L, const char *opt)
317{
318 int narg = 0;
319 if (opt && *opt) {
320 for (;;) { /* Split arguments. */
321 const char *p = strchr(opt, ',');
322 narg++;
323 if (!p) break;
324 if (p == opt)
325 lua_pushnil(L);
326 else
327 lua_pushlstring(L, opt, (size_t)(p - opt));
328 opt = p + 1;
329 }
330 if (*opt)
331 lua_pushstring(L, opt);
332 else
333 lua_pushnil(L);
334 }
335 return report(L, lua_pcall(L, narg, 0, 0));
336}
337
338/* JIT engine control command: try jit library first or load add-on module. */
339static int dojitcmd(lua_State *L, const char *cmd)
340{
341 const char *opt = strchr(cmd, '=');
342 lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd));
343 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
344 lua_getfield(L, -1, "jit"); /* Get jit.* module table. */
345 lua_remove(L, -2);
346 lua_pushvalue(L, -2);
347 lua_gettable(L, -2); /* Lookup library function. */
348 if (!lua_isfunction(L, -1)) {
349 lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */
350 if (loadjitmodule(L))
351 return 1;
352 } else {
353 lua_remove(L, -2); /* Drop jit.* table. */
354 }
355 lua_remove(L, -2); /* Drop module name. */
356 return runcmdopt(L, opt ? opt+1 : opt);
357}
358
359/* Optimization flags. */
360static int dojitopt(lua_State *L, const char *opt)
361{
362 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
363 lua_getfield(L, -1, "jit.opt"); /* Get jit.opt.* module table. */
364 lua_remove(L, -2);
365 lua_getfield(L, -1, "start");
366 lua_remove(L, -2);
367 return runcmdopt(L, opt);
368}
369
370/* Save or list bytecode. */
371static int dobytecode(lua_State *L, char **argv)
372{
373 int narg = 0;
374 lua_pushliteral(L, "bcsave");
375 if (loadjitmodule(L))
376 return 1;
377 if (argv[0][2]) {
378 narg++;
379 argv[0][1] = '-';
380 lua_pushstring(L, argv[0]+1);
381 }
382 for (argv++; *argv != NULL; narg++, argv++)
383 lua_pushstring(L, *argv);
384 return report(L, lua_pcall(L, narg, 0, 0));
385}
386
387/* check that argument has no extra characters at the end */
388#define notail(x) {if ((x)[2] != '\0') return -1;}
389
390#define FLAGS_INTERACTIVE 1
391#define FLAGS_VERSION 2
392#define FLAGS_EXEC 4
393#define FLAGS_OPTION 8
394
395static int collectargs(char **argv, int *flags)
396{
397 int i;
398 for (i = 1; argv[i] != NULL; i++) {
399 if (argv[i][0] != '-') /* Not an option? */
400 return i;
401 switch (argv[i][1]) { /* Check option. */
402 case '-':
403 notail(argv[i]);
404 return (argv[i+1] != NULL ? i+1 : 0);
405 case '\0':
406 return i;
407 case 'i':
408 notail(argv[i]);
409 *flags |= FLAGS_INTERACTIVE;
410 /* fallthrough */
411 case 'v':
412 notail(argv[i]);
413 *flags |= FLAGS_VERSION;
414 break;
415 case 'e':
416 *flags |= FLAGS_EXEC;
417 case 'j': /* LuaJIT extension */
418 case 'l':
419 *flags |= FLAGS_OPTION;
420 if (argv[i][2] == '\0') {
421 i++;
422 if (argv[i] == NULL) return -1;
423 }
424 break;
425 case 'O': break; /* LuaJIT extension */
426 case 'b': /* LuaJIT extension */
427 if (*flags) return -1;
428 *flags |= FLAGS_EXEC;
429 return 0;
430 default: return -1; /* invalid option */
431 }
432 }
433 return 0;
434}
435
436static int runargs(lua_State *L, char **argv, int n)
437{
438 int i;
439 for (i = 1; i < n; i++) {
440 if (argv[i] == NULL) continue;
441 lua_assert(argv[i][0] == '-');
442 switch (argv[i][1]) { /* option */
443 case 'e': {
444 const char *chunk = argv[i] + 2;
445 if (*chunk == '\0') chunk = argv[++i];
446 lua_assert(chunk != NULL);
447 if (dostring(L, chunk, "=(command line)") != 0)
448 return 1;
449 break;
450 }
451 case 'l': {
452 const char *filename = argv[i] + 2;
453 if (*filename == '\0') filename = argv[++i];
454 lua_assert(filename != NULL);
455 if (dolibrary(L, filename))
456 return 1; /* stop if file fails */
457 break;
458 }
459 case 'j': { /* LuaJIT extension */
460 const char *cmd = argv[i] + 2;
461 if (*cmd == '\0') cmd = argv[++i];
462 lua_assert(cmd != NULL);
463 if (dojitcmd(L, cmd))
464 return 1;
465 break;
466 }
467 case 'O': /* LuaJIT extension */
468 if (dojitopt(L, argv[i] + 2))
469 return 1;
470 break;
471 case 'b': /* LuaJIT extension */
472 return dobytecode(L, argv+i);
473 default: break;
474 }
475 }
476 return 0;
477}
478
479static int handle_luainit(lua_State *L)
480{
481 const char *init = getenv(LUA_INIT);
482 if (init == NULL)
483 return 0; /* status OK */
484 else if (init[0] == '@')
485 return dofile(L, init+1);
486 else
487 return dostring(L, init, "=" LUA_INIT);
488}
489
490struct Smain {
491 char **argv;
492 int argc;
493 int status;
494};
495
496static int pmain(lua_State *L)
497{
498 struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
499 char **argv = s->argv;
500 int script;
501 int flags = 0;
502 globalL = L;
503 if (argv[0] && argv[0][0]) progname = argv[0];
504 LUAJIT_VERSION_SYM(); /* linker-enforced version check */
505 lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
506 luaL_openlibs(L); /* open libraries */
507 lua_gc(L, LUA_GCRESTART, -1);
508 s->status = handle_luainit(L);
509 if (s->status != 0) return 0;
510 script = collectargs(argv, &flags);
511 if (script < 0) { /* invalid args? */
512 print_usage();
513 s->status = 1;
514 return 0;
515 }
516 if ((flags & FLAGS_VERSION)) print_version();
517 s->status = runargs(L, argv, (script > 0) ? script : s->argc);
518 if (s->status != 0) return 0;
519 if (script)
520 s->status = handle_script(L, argv, script);
521 if (s->status != 0) return 0;
522 if ((flags & FLAGS_INTERACTIVE)) {
523 print_jit_status(L);
524 dotty(L);
525 } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) {
526 if (lua_stdin_is_tty()) {
527 print_version();
528 print_jit_status(L);
529 dotty(L);
530 } else {
531 dofile(L, NULL); /* executes stdin as a file */
532 }
533 }
534 return 0;
535}
536
537int main(int argc, char **argv)
538{
539 int status;
540 struct Smain s;
541 lua_State *L = lua_open(); /* create state */
542 if (L == NULL) {
543 l_message(argv[0], "cannot create state: not enough memory");
544 return EXIT_FAILURE;
545 }
546 s.argc = argc;
547 s.argv = argv;
548 status = lua_cpcall(L, pmain, &s);
549 report(L, status);
550 lua_close(L);
551 return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
552}
553