]>
git.zerfleddert.de Git - proxmark3-svn/blob - liblua/lua.c
2 ** $Id: lua.c,v 1.206 2012/09/29 20:07:06 roberto Exp $
3 ** Lua stand-alone interpreter
4 ** See Copyright Notice in lua.h
21 #if !defined(LUA_PROMPT)
22 #define LUA_PROMPT "> "
23 #define LUA_PROMPT2 ">> "
26 #if !defined(LUA_PROGNAME)
27 #define LUA_PROGNAME "lua"
30 #if !defined(LUA_MAXINPUT)
31 #define LUA_MAXINPUT 512
34 #if !defined(LUA_INIT)
35 #define LUA_INIT "LUA_INIT"
38 #define LUA_INITVERSION \
39 LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
43 ** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
44 ** is, whether we're running lua interactively).
46 #if defined(LUA_USE_ISATTY)
48 #define lua_stdin_is_tty() isatty(0)
49 #elif defined(LUA_WIN)
52 #define lua_stdin_is_tty() _isatty(_fileno(stdin))
54 #define lua_stdin_is_tty() 1 /* assume stdin is a tty */
59 ** lua_readline defines how to show a prompt and then read a line from
60 ** the standard input.
61 ** lua_saveline defines how to "save" a read line in a "history".
62 ** lua_freeline defines how to free a line read by lua_readline.
64 #if defined(LUA_USE_READLINE)
67 #include <readline/readline.h>
68 #include <readline/history.h>
69 #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
70 #define lua_saveline(L,idx) \
71 if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \
72 add_history(lua_tostring(L, idx)); /* add it to history */
73 #define lua_freeline(L,b) ((void)L, free(b))
75 #elif !defined(lua_readline)
77 #define lua_readline(L,b,p) \
78 ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
79 fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
80 #define lua_saveline(L,idx) { (void)L; (void)idx; }
81 #define lua_freeline(L,b) { (void)L; (void)b; }
88 static lua_State
*globalL
= NULL
;
90 static const char *progname
= LUA_PROGNAME
;
94 static void lstop (lua_State
*L
, lua_Debug
*ar
) {
95 (void)ar
; /* unused arg. */
96 lua_sethook(L
, NULL
, 0, 0);
97 luaL_error(L
, "interrupted!");
101 static void laction (int i
) {
102 signal(i
, SIG_DFL
); /* if another SIGINT happens before lstop,
103 terminate process (default action) */
104 lua_sethook(globalL
, lstop
, LUA_MASKCALL
| LUA_MASKRET
| LUA_MASKCOUNT
, 1);
108 static void print_usage (const char *badoption
) {
109 luai_writestringerror("%s: ", progname
);
110 if (badoption
[1] == 'e' || badoption
[1] == 'l')
111 luai_writestringerror("'%s' needs argument\n", badoption
);
113 luai_writestringerror("unrecognized option '%s'\n", badoption
);
114 luai_writestringerror(
115 "usage: %s [options] [script [args]]\n"
116 "Available options are:\n"
117 " -e stat execute string " LUA_QL("stat") "\n"
118 " -i enter interactive mode after executing " LUA_QL("script") "\n"
119 " -l name require library " LUA_QL("name") "\n"
120 " -v show version information\n"
121 " -E ignore environment variables\n"
122 " -- stop handling options\n"
123 " - stop handling options and execute stdin\n"
129 static void l_message (const char *pname
, const char *msg
) {
130 if (pname
) luai_writestringerror("%s: ", pname
);
131 luai_writestringerror("%s\n", msg
);
135 static int report (lua_State
*L
, int status
) {
136 if (status
!= LUA_OK
&& !lua_isnil(L
, -1)) {
137 const char *msg
= lua_tostring(L
, -1);
138 if (msg
== NULL
) msg
= "(error object is not a string)";
139 l_message(progname
, msg
);
141 /* force a complete garbage collection in case of errors */
142 lua_gc(L
, LUA_GCCOLLECT
, 0);
148 /* the next function is called unprotected, so it must avoid errors */
149 static void finalreport (lua_State
*L
, int status
) {
150 if (status
!= LUA_OK
) {
151 const char *msg
= (lua_type(L
, -1) == LUA_TSTRING
) ? lua_tostring(L
, -1)
153 if (msg
== NULL
) msg
= "(error object is not a string)";
154 l_message(progname
, msg
);
160 static int traceback (lua_State
*L
) {
161 const char *msg
= lua_tostring(L
, 1);
163 luaL_traceback(L
, L
, msg
, 1);
164 else if (!lua_isnoneornil(L
, 1)) { /* is there an error object? */
165 if (!luaL_callmeta(L
, 1, "__tostring")) /* try its 'tostring' metamethod */
166 lua_pushliteral(L
, "(no error message)");
172 static int docall (lua_State
*L
, int narg
, int nres
) {
174 int base
= lua_gettop(L
) - narg
; /* function index */
175 lua_pushcfunction(L
, traceback
); /* push traceback function */
176 lua_insert(L
, base
); /* put it under chunk and args */
177 globalL
= L
; /* to be available to 'laction' */
178 signal(SIGINT
, laction
);
179 status
= lua_pcall(L
, narg
, nres
, base
);
180 signal(SIGINT
, SIG_DFL
);
181 lua_remove(L
, base
); /* remove traceback function */
186 static void print_version (void) {
187 luai_writestring(LUA_COPYRIGHT
, strlen(LUA_COPYRIGHT
));
192 static int getargs (lua_State
*L
, char **argv
, int n
) {
196 while (argv
[argc
]) argc
++; /* count total number of arguments */
197 narg
= argc
- (n
+ 1); /* number of arguments to the script */
198 luaL_checkstack(L
, narg
+ 3, "too many arguments to script");
199 for (i
=n
+1; i
< argc
; i
++)
200 lua_pushstring(L
, argv
[i
]);
201 lua_createtable(L
, narg
, n
+ 1);
202 for (i
=0; i
< argc
; i
++) {
203 lua_pushstring(L
, argv
[i
]);
204 lua_rawseti(L
, -2, i
- n
);
210 static int dofile (lua_State
*L
, const char *name
) {
211 int status
= luaL_loadfile(L
, name
);
212 if (status
== LUA_OK
) status
= docall(L
, 0, 0);
213 return report(L
, status
);
217 static int dostring (lua_State
*L
, const char *s
, const char *name
) {
218 int status
= luaL_loadbuffer(L
, s
, strlen(s
), name
);
219 if (status
== LUA_OK
) status
= docall(L
, 0, 0);
220 return report(L
, status
);
224 static int dolibrary (lua_State
*L
, const char *name
) {
226 lua_getglobal(L
, "require");
227 lua_pushstring(L
, name
);
228 status
= docall(L
, 1, 1); /* call 'require(name)' */
229 if (status
== LUA_OK
)
230 lua_setglobal(L
, name
); /* global[name] = require return */
231 return report(L
, status
);
235 static const char *get_prompt (lua_State
*L
, int firstline
) {
237 lua_getglobal(L
, firstline
? "_PROMPT" : "_PROMPT2");
238 p
= lua_tostring(L
, -1);
239 if (p
== NULL
) p
= (firstline
? LUA_PROMPT
: LUA_PROMPT2
);
243 /* mark in error messages for incomplete statements */
244 #define EOFMARK "<eof>"
245 #define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
247 static int incomplete (lua_State
*L
, int status
) {
248 if (status
== LUA_ERRSYNTAX
) {
250 const char *msg
= lua_tolstring(L
, -1, &lmsg
);
251 if (lmsg
>= marklen
&& strcmp(msg
+ lmsg
- marklen
, EOFMARK
) == 0) {
256 return 0; /* else... */
260 static int pushline (lua_State
*L
, int firstline
) {
261 char buffer
[LUA_MAXINPUT
];
264 const char *prmt
= get_prompt(L
, firstline
);
265 int readstatus
= lua_readline(L
, b
, prmt
);
266 lua_pop(L
, 1); /* remove result from 'get_prompt' */
268 return 0; /* no input */
270 if (l
> 0 && b
[l
-1] == '\n') /* line ends with newline? */
271 b
[l
-1] = '\0'; /* remove it */
272 if (firstline
&& b
[0] == '=') /* first line starts with `=' ? */
273 lua_pushfstring(L
, "return %s", b
+1); /* change it to `return' */
275 lua_pushstring(L
, b
);
281 static int loadline (lua_State
*L
) {
285 return -1; /* no input */
286 for (;;) { /* repeat until gets a complete line */
288 const char *line
= lua_tolstring(L
, 1, &l
);
289 status
= luaL_loadbuffer(L
, line
, l
, "=stdin");
290 if (!incomplete(L
, status
)) break; /* cannot try to add lines? */
291 if (!pushline(L
, 0)) /* no more input? */
293 lua_pushliteral(L
, "\n"); /* add a new line... */
294 lua_insert(L
, -2); /* ...between the two lines */
295 lua_concat(L
, 3); /* join them */
298 lua_remove(L
, 1); /* remove line */
303 static void dotty (lua_State
*L
) {
305 const char *oldprogname
= progname
;
307 while ((status
= loadline(L
)) != -1) {
308 if (status
== LUA_OK
) status
= docall(L
, 0, LUA_MULTRET
);
310 if (status
== LUA_OK
&& lua_gettop(L
) > 0) { /* any result to print? */
311 luaL_checkstack(L
, LUA_MINSTACK
, "too many results to print");
312 lua_getglobal(L
, "print");
314 if (lua_pcall(L
, lua_gettop(L
)-1, 0, 0) != LUA_OK
)
315 l_message(progname
, lua_pushfstring(L
,
316 "error calling " LUA_QL("print") " (%s)",
317 lua_tostring(L
, -1)));
320 lua_settop(L
, 0); /* clear stack */
322 progname
= oldprogname
;
326 static int handle_script (lua_State
*L
, char **argv
, int n
) {
329 int narg
= getargs(L
, argv
, n
); /* collect arguments */
330 lua_setglobal(L
, "arg");
332 if (strcmp(fname
, "-") == 0 && strcmp(argv
[n
-1], "--") != 0)
333 fname
= NULL
; /* stdin */
334 status
= luaL_loadfile(L
, fname
);
335 lua_insert(L
, -(narg
+1));
336 if (status
== LUA_OK
)
337 status
= docall(L
, narg
, LUA_MULTRET
);
340 return report(L
, status
);
344 /* check that argument has no extra characters at the end */
345 #define noextrachars(x) {if ((x)[2] != '\0') return -1;}
348 /* indices of various argument indicators in array args */
349 #define has_i 0 /* -i */
350 #define has_v 1 /* -v */
351 #define has_e 2 /* -e */
352 #define has_E 3 /* -E */
354 #define num_has 4 /* number of 'has_*' */
357 static int collectargs (char **argv
, int *args
) {
359 for (i
= 1; argv
[i
] != NULL
; i
++) {
360 if (argv
[i
][0] != '-') /* not an option? */
362 switch (argv
[i
][1]) { /* option */
364 noextrachars(argv
[i
]);
365 return (argv
[i
+1] != NULL
? i
+1 : 0);
372 noextrachars(argv
[i
]);
373 args
[has_i
] = 1; /* go through */
375 noextrachars(argv
[i
]);
379 args
[has_e
] = 1; /* go through */
380 case 'l': /* both options need an argument */
381 if (argv
[i
][2] == '\0') { /* no concatenated argument? */
382 i
++; /* try next 'argv' */
383 if (argv
[i
] == NULL
|| argv
[i
][0] == '-')
384 return -(i
- 1); /* no next argument or it is another option */
387 default: /* invalid option; return its index... */
388 return -i
; /* ...as a negative value */
395 static int runargs (lua_State
*L
, char **argv
, int n
) {
397 for (i
= 1; i
< n
; i
++) {
398 lua_assert(argv
[i
][0] == '-');
399 switch (argv
[i
][1]) { /* option */
401 const char *chunk
= argv
[i
] + 2;
402 if (*chunk
== '\0') chunk
= argv
[++i
];
403 lua_assert(chunk
!= NULL
);
404 if (dostring(L
, chunk
, "=(command line)") != LUA_OK
)
409 const char *filename
= argv
[i
] + 2;
410 if (*filename
== '\0') filename
= argv
[++i
];
411 lua_assert(filename
!= NULL
);
412 if (dolibrary(L
, filename
) != LUA_OK
)
413 return 0; /* stop if file fails */
423 static int handle_luainit (lua_State
*L
) {
424 const char *name
= "=" LUA_INITVERSION
;
425 const char *init
= getenv(name
+ 1);
428 init
= getenv(name
+ 1); /* try alternative name */
430 if (init
== NULL
) return LUA_OK
;
431 else if (init
[0] == '@')
432 return dofile(L
, init
+1);
434 return dostring(L
, init
, name
);
438 static int pmain (lua_State
*L
) {
439 int argc
= (int)lua_tointeger(L
, 1);
440 char **argv
= (char **)lua_touserdata(L
, 2);
443 args
[has_i
] = args
[has_v
] = args
[has_e
] = args
[has_E
] = 0;
444 if (argv
[0] && argv
[0][0]) progname
= argv
[0];
445 script
= collectargs(argv
, args
);
446 if (script
< 0) { /* invalid arg? */
447 print_usage(argv
[-script
]);
450 if (args
[has_v
]) print_version();
451 if (args
[has_E
]) { /* option '-E'? */
452 lua_pushboolean(L
, 1); /* signal for libraries to ignore env. vars. */
453 lua_setfield(L
, LUA_REGISTRYINDEX
, "LUA_NOENV");
455 /* open standard libraries */
456 luaL_checkversion(L
);
457 lua_gc(L
, LUA_GCSTOP
, 0); /* stop collector during initialization */
458 luaL_openlibs(L
); /* open libraries */
459 lua_gc(L
, LUA_GCRESTART
, 0);
460 if (!args
[has_E
] && handle_luainit(L
) != LUA_OK
)
461 return 0; /* error running LUA_INIT */
462 /* execute arguments -e and -l */
463 if (!runargs(L
, argv
, (script
> 0) ? script
: argc
)) return 0;
464 /* execute main script (if there is one) */
465 if (script
&& handle_script(L
, argv
, script
) != LUA_OK
) return 0;
466 if (args
[has_i
]) /* -i option? */
468 else if (script
== 0 && !args
[has_e
] && !args
[has_v
]) { /* no arguments? */
469 if (lua_stdin_is_tty()) {
473 else dofile(L
, NULL
); /* executes stdin as a file */
475 lua_pushboolean(L
, 1); /* signal no errors */
480 int main (int argc
, char **argv
) {
482 lua_State
*L
= luaL_newstate(); /* create state */
484 l_message(argv
[0], "cannot create state: not enough memory");
487 /* call 'pmain' in protected mode */
488 lua_pushcfunction(L
, &pmain
);
489 lua_pushinteger(L
, argc
); /* 1st argument */
490 lua_pushlightuserdata(L
, argv
); /* 2nd argument */
491 status
= lua_pcall(L
, 2, 1, 0);
492 result
= lua_toboolean(L
, -1); /* get result */
493 finalreport(L
, status
);
495 return (result
&& status
== LUA_OK
) ? EXIT_SUCCESS
: EXIT_FAILURE
;