2 ** LuaJIT frontend. Runs commands
, scripts
, read-eval-print
(REPL
) etc.
3 ** Copyright
(C
) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
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
25 #define lua_stdin_is_tty
() isatty
(0)
26 #elif LJ_TARGET_WINDOWS
29 #define lua_stdin_is_tty
() isatty
(_fileno
(stdin
))
31 #define lua_stdin_is_tty
() _isatty
(_fileno
(stdin
))
34 #define lua_stdin_is_tty
() 1
37 #if
!LJ_TARGET_CONSOLE
41 #include
"lua/luatex-api.h"
43 static lua_State
*globalL
= NULL;
44 static const char
*progname
= LUA_PROGNAME
;
46 #if
!LJ_TARGET_CONSOLE
47 static void lstop
(lua_State
*L
, lua_Debug
*ar
)
49 (void
)ar
; /* unused arg.
*/
50 lua_sethook
(L
, NULL, 0, 0);
51 /* Avoid luaL_error
-- a C hook doesn't add an extra frame.
*/
53 lua_pushfstring
(L
, "%sinterrupted!", lua_tostring
(L
, -1));
57 static void laction
(int i
)
59 signal
(i
, SIG_DFL
); /* if another SIGINT happens before lstop
,
60 terminate process
(default action
) */
61 lua_sethook
(globalL
, lstop
, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT
, 1);
65 static void print_usage
(void
)
68 "usage: %s [options]... [script [args]...].\n"
69 "Available options are:\n"
70 " -e chunk Execute string " LUA_QL
("chunk") ".\n"
71 " -l name Require library " LUA_QL
("name") ".\n"
72 " -b ... Save or list bytecode.\n"
73 " -j cmd Perform LuaJIT control command.\n"
74 " -O[opt] Control LuaJIT optimizations.\n"
75 " -i Enter interactive mode after executing " LUA_QL
("script") ".\n"
76 " -v Show version information.\n"
77 " -E Ignore environment variables.\n"
78 " -- Stop handling options.\n"
79 " - Execute stdin and stop handling options.\n"
85 static void l_message
(const char
*pname
, const char
*msg
)
87 if
(pname
) fprintf
(stderr
, "%s: ", pname
);
88 fprintf
(stderr
, "%s\n", msg
);
92 static int report
(lua_State
*L
, int status
)
94 if
(status
&& !lua_isnil(L, -1)) {
95 const char
*msg
= lua_tostring
(L
, -1);
96 if
(msg
== NULL) msg
= "(error object is not a string)";
97 l_message
(progname
, msg
);
103 static int traceback
(lua_State
*L
)
105 if
(!lua_isstring
(L
, 1)) { /* Non-string error object? Try metamethod.
*/
106 if
(lua_isnoneornil
(L
, 1) ||
107 !luaL_callmeta
(L
, 1, "__tostring") ||
108 !lua_isstring
(L
, -1))
109 return
1; /* Return non-string error object.
*/
110 lua_remove
(L
, 1); /* Replace object by result of __tostring metamethod.
*/
112 luaL_traceback
(L
, L
, lua_tostring
(L
, 1), 1);
116 static int docall
(lua_State
*L
, int narg
, int clear
)
119 int base
= lua_gettop
(L
) - narg
; /* function index
*/
120 lua_pushcfunction
(L
, traceback
); /* push traceback function
*/
121 lua_insert
(L
, base
); /* put it under chunk and args
*/
122 #if
!LJ_TARGET_CONSOLE
123 signal
(SIGINT
, laction
);
125 status
= lua_pcall
(L
, narg
, (clear ?
0 : LUA_MULTRET
), base
);
126 #if
!LJ_TARGET_CONSOLE
127 signal
(SIGINT
, SIG_DFL
);
129 lua_remove
(L
, base
); /* remove traceback function
*/
130 /* force a complete garbage collection in case of errors
*/
131 if
(status
!= 0) lua_gc
(L
, LUA_GCCOLLECT
, 0);
135 static void print_version
(void
)
137 fputs
(LUAJIT_VERSION
" -- " LUAJIT_COPYRIGHT
". " LUAJIT_URL
"\n", stdout
);
140 static void print_jit_status
(lua_State
*L
)
144 lua_getfield
(L
, LUA_REGISTRYINDEX
, "_LOADED");
145 lua_getfield
(L
, -1, "jit"); /* Get jit.
* module table.
*/
147 lua_getfield
(L
, -1, "status");
150 lua_call
(L
, 0, LUA_MULTRET
);
151 fputs
(lua_toboolean
(L
, n
) ?
"JIT: ON" : "JIT: OFF", stdout
);
152 for
(n
++; (s
= lua_tostring
(L
, n
)); n
++) {
159 static int getargs
(lua_State
*L
, char
**argv
, int n
)
164 while
(argv
[argc
]) argc
++; /* count total number of arguments
*/
165 narg
= argc
- (n
+ 1); /* number of arguments to the script
*/
166 luaL_checkstack
(L
, narg
+ 3, "too many arguments to script");
167 for
(i
= n
+1; i
< argc
; i
++)
168 lua_pushstring
(L
, argv
[i
]);
169 lua_createtable
(L
, narg
, n
+ 1);
170 for
(i
= 0; i
< argc
; i
++) {
171 lua_pushstring
(L
, argv
[i
]);
172 lua_rawseti
(L
, -2, i
- n
);
177 static int dofile
(lua_State
*L
, const char
*name
)
179 int status
= luaL_loadfile
(L
, name
) || docall
(L
, 0, 1);
180 return report
(L
, status
);
183 static int dostring
(lua_State
*L
, const char
*s
, const char
*name
)
185 int status
= luaL_loadbuffer
(L
, s
, strlen
(s
), name
) || docall
(L
, 0, 1);
186 return report
(L
, status
);
189 static int dolibrary
(lua_State
*L
, const char
*name
)
191 lua_getglobal
(L
, "require");
192 lua_pushstring
(L
, name
);
193 return report
(L
, docall
(L
, 1, 1));
196 static void write_prompt
(lua_State
*L
, int firstline
)
199 lua_getfield
(L
, LUA_GLOBALSINDEX
, firstline ?
"_PROMPT" : "_PROMPT2");
200 p
= lua_tostring
(L
, -1);
201 if
(p
== NULL) p
= firstline ? LUA_PROMPT
: LUA_PROMPT2
;
204 lua_pop
(L
, 1); /* remove global
*/
207 static int incomplete
(lua_State
*L
, int status
)
209 if
(status
== LUA_ERRSYNTAX
) {
211 const char
*msg
= lua_tolstring
(L
, -1, &lmsg);
212 const char
*tp
= msg
+ lmsg
- (sizeof
(LUA_QL
("<eof>")) - 1);
213 if
(strstr
(msg
, LUA_QL
("<eof>")) == tp
) {
218 return
0; /* else...
*/
221 static int pushline
(lua_State
*L
, int firstline
)
223 char buf
[LUA_MAXINPUT
];
224 write_prompt
(L
, firstline
);
225 if
(fgets
(buf
, LUA_MAXINPUT
, stdin
)) {
226 size_t len
= strlen
(buf
);
227 if
(len
> 0 && buf[len-1] == '\n')
229 if
(firstline
&& buf[0] == '=')
230 lua_pushfstring
(L
, "return %s", buf
+1);
232 lua_pushstring
(L
, buf
);
238 static int loadline
(lua_State
*L
)
243 return
-1; /* no input
*/
244 for
(;;) { /* repeat until gets a complete line
*/
245 status
= luaL_loadbuffer
(L
, lua_tostring
(L
, 1), lua_strlen
(L
, 1), "=stdin");
246 if
(!incomplete
(L
, status
)) break
; /* cannot try to add lines?
*/
247 if
(!pushline
(L
, 0)) /* no more input?
*/
249 lua_pushliteral
(L
, "\n"); /* add a new line...
*/
250 lua_insert
(L
, -2); /* ...between the two lines
*/
251 lua_concat
(L
, 3); /* join them
*/
253 lua_remove
(L
, 1); /* remove line
*/
257 static void dotty
(lua_State
*L
)
260 const char
*oldprogname
= progname
;
262 while
((status
= loadline
(L
)) != -1) {
263 if
(status
== 0) status
= docall
(L
, 0, 0);
265 if
(status
== 0 && lua_gettop(L) > 0) { /* any result to print? */
266 lua_getglobal
(L
, "print");
268 if
(lua_pcall
(L
, lua_gettop
(L
)-1, 0, 0) != 0)
270 lua_pushfstring
(L
, "error calling " LUA_QL
("print") " (%s)",
271 lua_tostring
(L
, -1)));
274 lua_settop
(L
, 0); /* clear stack
*/
277 progname
= oldprogname
;
280 static int handle_script
(lua_State
*L
, char
**argv
, int n
)
284 int narg
= getargs
(L
, argv
, n
); /* collect arguments
*/
285 lua_setglobal
(L
, "arg");
287 if
(strcmp
(fname
, "-") == 0 && strcmp(argv[n-1], "--") != 0)
288 fname
= NULL; /* stdin
*/
289 status
= luaL_loadfile
(L
, fname
);
290 lua_insert
(L
, -(narg
+1));
292 status
= docall
(L
, narg
, 0);
295 return report
(L
, status
);
298 /* Load add-on module.
*/
299 static int loadjitmodule
(lua_State
*L
)
301 lua_getglobal
(L
, "require");
302 lua_pushliteral
(L
, "jit.");
303 lua_pushvalue
(L
, -3);
305 if
(lua_pcall
(L
, 1, 1, 0)) {
306 const char
*msg
= lua_tostring
(L
, -1);
307 if
(msg
&& !strncmp(msg, "module ", 7)) {
310 "unknown luaJIT command or jit.* modules not installed");
316 lua_getfield
(L
, -1, "start");
317 if
(lua_isnil
(L
, -1)) goto err
;
318 lua_remove
(L
, -2); /* Drop module table.
*/
322 /* Run command with options.
*/
323 static int runcmdopt
(lua_State
*L
, const char
*opt
)
327 for
(;;) { /* Split arguments.
*/
328 const char
*p
= strchr
(opt
, '
,'
);
334 lua_pushlstring
(L
, opt
, (size_t
)(p
- opt
));
338 lua_pushstring
(L
, opt
);
342 return report
(L
, lua_pcall
(L
, narg
, 0, 0));
345 /* JIT engine control command
: try jit library first or load add-on module.
*/
346 static int dojitcmd
(lua_State
*L
, const char
*cmd
)
348 const char
*opt
= strchr
(cmd
, '
='
);
349 lua_pushlstring
(L
, cmd
, opt ?
(size_t
)(opt
- cmd
) : strlen
(cmd
));
350 lua_getfield
(L
, LUA_REGISTRYINDEX
, "_LOADED");
351 lua_getfield
(L
, -1, "jit"); /* Get jit.
* module table.
*/
353 lua_pushvalue
(L
, -2);
354 lua_gettable
(L
, -2); /* Lookup library function.
*/
355 if
(!lua_isfunction
(L
, -1)) {
356 lua_pop
(L
, 2); /* Drop non-function and jit.
* table
, keep module name.
*/
357 if
(loadjitmodule
(L
))
360 lua_remove
(L
, -2); /* Drop jit.
* table.
*/
362 lua_remove
(L
, -2); /* Drop module name.
*/
363 return runcmdopt
(L
, opt ? opt
+1 : opt
);
366 /* Optimization flags.
*/
367 static int dojitopt
(lua_State
*L
, const char
*opt
)
369 lua_getfield
(L
, LUA_REGISTRYINDEX
, "_LOADED");
370 lua_getfield
(L
, -1, "jit.opt"); /* Get jit.opt.
* module table.
*/
372 lua_getfield
(L
, -1, "start");
374 return runcmdopt
(L
, opt
);
377 /* Save or list bytecode.
*/
378 static int dobytecode
(lua_State
*L
, char
**argv
)
381 lua_pushliteral
(L
, "bcsave");
382 if
(loadjitmodule
(L
))
387 lua_pushstring
(L
, argv
[0]+1);
389 for
(argv
++; *argv
!= NULL; narg
++, argv
++)
390 lua_pushstring
(L
, *argv
);
391 return report
(L
, lua_pcall
(L
, narg
, 0, 0));
394 /* check that argument has no extra characters at the end
*/
395 #define notail
(x
) {if
((x
)[2] != '\
0'
) return
-1;}
397 #define FLAGS_INTERACTIVE
1
398 #define FLAGS_VERSION
2
400 #define FLAGS_OPTION
8
401 #define FLAGS_NOENV
16
403 static int collectargs
(char
**argv
, int
*flags
)
406 for
(i
= 1; argv
[i
] != NULL; i
++) {
407 if
(argv
[i
][0] != '
-'
) /* Not an option?
*/
409 switch
(argv
[i
][1]) { /* Check option.
*/
412 return
(argv
[i
+1] != NULL ? i
+1 : 0);
417 *flags |
= FLAGS_INTERACTIVE
;
421 *flags |
= FLAGS_VERSION
;
424 *flags |
= FLAGS_EXEC
;
425 case 'j'
: /* LuaJIT extension
*/
427 *flags |
= FLAGS_OPTION
;
428 if
(argv
[i
][2] == '\
0'
) {
430 if
(argv
[i
] == NULL) return
-1;
433 case 'O'
: break
; /* LuaJIT extension
*/
434 case 'b'
: /* LuaJIT extension
*/
435 if
(*flags
) return
-1;
436 *flags |
= FLAGS_EXEC
;
439 *flags |
= FLAGS_NOENV
;
441 default
: return
-1; /* invalid option
*/
447 static int runargs
(lua_State
*L
, char
**argv
, int n
)
450 for
(i
= 1; i
< n
; i
++) {
451 if
(argv
[i
] == NULL) continue
;
452 lua_assert
(argv
[i
][0] == '
-'
);
453 switch
(argv
[i
][1]) { /* option
*/
455 const char
*chunk
= argv
[i
] + 2;
456 if
(*chunk
== '\
0'
) chunk
= argv
[++i
];
457 lua_assert
(chunk
!= NULL);
458 if
(dostring
(L
, chunk
, "=(command line)") != 0)
463 const char
*filename
= argv
[i
] + 2;
464 if
(*filename
== '\
0'
) filename
= argv
[++i
];
465 lua_assert
(filename
!= NULL);
466 if
(dolibrary
(L
, filename
))
467 return
1; /* stop if file fails
*/
470 case 'j'
: { /* LuaJIT extension
*/
471 const char
*cmd
= argv
[i
] + 2;
472 if
(*cmd
== '\
0'
) cmd
= argv
[++i
];
473 lua_assert
(cmd
!= NULL);
474 if
(dojitcmd
(L
, cmd
))
478 case 'O'
: /* LuaJIT extension
*/
479 if
(dojitopt
(L
, argv
[i
] + 2))
482 case 'b'
: /* LuaJIT extension
*/
483 return dobytecode
(L
, argv
+i
);
490 static int handle_luainit
(lua_State
*L
)
492 #if LJ_TARGET_CONSOLE
493 const char
*init
= NULL;
495 const char
*init
= getenv
(LUA_INIT
);
498 return
0; /* status
OK */
499 else if
(init
[0] == 64)
500 return dofile
(L
, init
+1);
502 return dostring
(L
, init
, "=" LUA_INIT
);
511 static int pmain
(lua_State
*L
)
513 struct Smain
*s
= (struct Smain
*)lua_touserdata
(L
, 1);
514 char
**argv
= s-
>argv
;
518 if
(argv
[0] && argv[0][0]) progname = argv[0];
519 LUAJIT_VERSION_SYM
(); /* linker-enforced version check
*/
520 script
= collectargs
(argv
, &flags);
521 if
(script
< 0) { /* invalid args?
*/
526 if
((flags
& FLAGS_NOENV)) {
527 lua_pushboolean
(L
, 1);
528 lua_setfield
(L
, LUA_REGISTRYINDEX
, "LUA_NOENV");
530 lua_gc
(L
, LUA_GCSTOP
, 0); /* stop collector during initialization
*/
531 luaL_openlibs
(L
); /* open libraries
*/
532 lua_gc
(L
, LUA_GCRESTART
, -1);
533 if
(!(flags
& FLAGS_NOENV)) {
534 s-
>status
= handle_luainit
(L
);
535 if
(s-
>status
!= 0) return
0;
537 if
((flags
& FLAGS_VERSION)) print_version();
538 s-
>status
= runargs
(L
, argv
, (script
> 0) ? script
: s-
>argc
);
539 if
(s-
>status
!= 0) return
0;
541 s-
>status
= handle_script
(L
, argv
, script
);
542 if
(s-
>status
!= 0) return
0;
544 if
((flags
& FLAGS_INTERACTIVE)) {
547 } else if
(script
== 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) {
548 if
(lua_stdin_is_tty
()) {
553 dofile
(L
, NULL); /* executes stdin as a file
*/
559 int luac_main
(int argc
, char
**argv
)
563 lua_State
*L
= lua_open
(); /* create state
*/
565 l_message
(argv
[0], "cannot create state: not enough memory");
570 status
= lua_cpcall
(L
, pmain
, &s);
573 return
(status || s.status
) ? EXIT_FAILURE
: EXIT_SUCCESS
;