• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** $Id: lua.c,v 1.206.1.1 2013/04/12 18:48:47 roberto Exp $
3 ** Lua stand-alone interpreter
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #define lua_c
14 
15 #include "lua.h"
16 
17 #include "lauxlib.h"
18 #include "lualib.h"
19 
20 
21 #if !defined(LUA_PROMPT)
22 #define LUA_PROMPT		"> "
23 #define LUA_PROMPT2		">> "
24 #endif
25 
26 #if !defined(LUA_PROGNAME)
27 #define LUA_PROGNAME		"lua"
28 #endif
29 
30 #if !defined(LUA_MAXINPUT)
31 #define LUA_MAXINPUT		512
32 #endif
33 
34 #if !defined(LUA_INIT)
35 #define LUA_INIT		"LUA_INIT"
36 #endif
37 
38 #define LUA_INITVERSION  \
39 	LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
40 
41 
42 /*
43 ** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
44 ** is, whether we're running lua interactively).
45 */
46 #if defined(LUA_USE_ISATTY)
47 #include <unistd.h>
48 #define lua_stdin_is_tty()	isatty(0)
49 #elif defined(LUA_WIN)
50 #include <io.h>
51 #include <stdio.h>
52 #define lua_stdin_is_tty()	_isatty(_fileno(stdin))
53 #else
54 #define lua_stdin_is_tty()	1  /* assume stdin is a tty */
55 #endif
56 
57 
58 /*
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.
63 */
64 #if defined(LUA_USE_READLINE)
65 
66 #include <stdio.h>
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))
74 
75 #elif !defined(lua_readline)
76 
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; }
82 
83 #endif
84 
85 
86 
87 
88 static lua_State *globalL = NULL;
89 
90 static const char *progname = LUA_PROGNAME;
91 
92 
93 
lstop(lua_State * L,lua_Debug * ar)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!");
98 }
99 
100 
laction(int i)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);
105 }
106 
107 
print_usage(const char * badoption)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);
112   else
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"
124   ,
125   progname);
126 }
127 
128 
l_message(const char * pname,const char * msg)129 static void l_message (const char *pname, const char *msg) {
130   if (pname) luai_writestringerror("%s: ", pname);
131   luai_writestringerror("%s\n", msg);
132 }
133 
134 
report(lua_State * L,int status)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);
140     lua_pop(L, 1);
141     /* force a complete garbage collection in case of errors */
142     lua_gc(L, LUA_GCCOLLECT, 0);
143   }
144   return status;
145 }
146 
147 
148 /* the next function is called unprotected, so it must avoid errors */
finalreport(lua_State * L,int status)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)
152                                                        : NULL;
153     if (msg == NULL) msg = "(error object is not a string)";
154     l_message(progname, msg);
155     lua_pop(L, 1);
156   }
157 }
158 
159 
traceback(lua_State * L)160 static int traceback (lua_State *L) {
161   const char *msg = lua_tostring(L, 1);
162   if (msg)
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)");
167   }
168   return 1;
169 }
170 
171 
docall(lua_State * L,int narg,int nres)172 static int docall (lua_State *L, int narg, int nres) {
173   int status;
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 */
182   return status;
183 }
184 
185 
print_version(void)186 static void print_version (void) {
187   luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
188   luai_writeline();
189 }
190 
191 
getargs(lua_State * L,char ** argv,int n)192 static int getargs (lua_State *L, char **argv, int n) {
193   int narg;
194   int i;
195   int argc = 0;
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);
205   }
206   return narg;
207 }
208 
209 
dofile(lua_State * L,const char * name)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);
214 }
215 
216 
dostring(lua_State * L,const char * s,const char * name)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);
221 }
222 
223 
dolibrary(lua_State * L,const char * name)224 static int dolibrary (lua_State *L, const char *name) {
225   int status;
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);
232 }
233 
234 
get_prompt(lua_State * L,int firstline)235 static const char *get_prompt (lua_State *L, int firstline) {
236   const char *p;
237   lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
238   p = lua_tostring(L, -1);
239   if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
240   return p;
241 }
242 
243 /* mark in error messages for incomplete statements */
244 #define EOFMARK		"<eof>"
245 #define marklen		(sizeof(EOFMARK)/sizeof(char) - 1)
246 
incomplete(lua_State * L,int status)247 static int incomplete (lua_State *L, int status) {
248   if (status == LUA_ERRSYNTAX) {
249     size_t lmsg;
250     const char *msg = lua_tolstring(L, -1, &lmsg);
251     if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
252       lua_pop(L, 1);
253       return 1;
254     }
255   }
256   return 0;  /* else... */
257 }
258 
259 
pushline(lua_State * L,int firstline)260 static int pushline (lua_State *L, int firstline) {
261   char buffer[LUA_MAXINPUT];
262   char *b = buffer;
263   size_t l;
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' */
267   if (readstatus == 0)
268     return 0;  /* no input */
269   l = strlen(b);
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' */
274   else
275     lua_pushstring(L, b);
276   lua_freeline(L, b);
277   return 1;
278 }
279 
280 
loadline(lua_State * L)281 static int loadline (lua_State *L) {
282   int status;
283   lua_settop(L, 0);
284   if (!pushline(L, 1))
285     return -1;  /* no input */
286   for (;;) {  /* repeat until gets a complete line */
287     size_t l;
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? */
292       return -1;
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 */
296   }
297   lua_saveline(L, 1);
298   lua_remove(L, 1);  /* remove line */
299   return status;
300 }
301 
302 
dotty(lua_State * L)303 static void dotty (lua_State *L) {
304   int status;
305   const char *oldprogname = progname;
306   progname = NULL;
307   while ((status = loadline(L)) != -1) {
308     if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
309     report(L, status);
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");
313       lua_insert(L, 1);
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)));
318     }
319   }
320   lua_settop(L, 0);  /* clear stack */
321   luai_writeline();
322   progname = oldprogname;
323 }
324 
325 
handle_script(lua_State * L,char ** argv,int n)326 static int handle_script (lua_State *L, char **argv, int n) {
327   int status;
328   const char *fname;
329   int narg = getargs(L, argv, n);  /* collect arguments */
330   lua_setglobal(L, "arg");
331   fname = argv[n];
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);
338   else
339     lua_pop(L, narg);
340   return report(L, status);
341 }
342 
343 
344 /* check that argument has no extra characters at the end */
345 #define noextrachars(x)		{if ((x)[2] != '\0') return -1;}
346 
347 
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 */
353 
354 #define num_has		4	/* number of 'has_*' */
355 
356 
collectargs(char ** argv,int * args)357 static int collectargs (char **argv, int *args) {
358   int i;
359   for (i = 1; argv[i] != NULL; i++) {
360     if (argv[i][0] != '-')  /* not an option? */
361         return i;
362     switch (argv[i][1]) {  /* option */
363       case '-':
364         noextrachars(argv[i]);
365         return (argv[i+1] != NULL ? i+1 : 0);
366       case '\0':
367         return i;
368       case 'E':
369         args[has_E] = 1;
370         break;
371       case 'i':
372         noextrachars(argv[i]);
373         args[has_i] = 1;  /* go through */
374       case 'v':
375         noextrachars(argv[i]);
376         args[has_v] = 1;
377         break;
378       case 'e':
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 */
385         }
386         break;
387       default:  /* invalid option; return its index... */
388         return -i;  /* ...as a negative value */
389     }
390   }
391   return 0;
392 }
393 
394 
runargs(lua_State * L,char ** argv,int n)395 static int runargs (lua_State *L, char **argv, int n) {
396   int i;
397   for (i = 1; i < n; i++) {
398     lua_assert(argv[i][0] == '-');
399     switch (argv[i][1]) {  /* option */
400       case 'e': {
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)
405           return 0;
406         break;
407       }
408       case 'l': {
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 */
414         break;
415       }
416       default: break;
417     }
418   }
419   return 1;
420 }
421 
422 
handle_luainit(lua_State * L)423 static int handle_luainit (lua_State *L) {
424   const char *name = "=" LUA_INITVERSION;
425   const char *init = getenv(name + 1);
426   if (init == NULL) {
427     name = "=" LUA_INIT;
428     init = getenv(name + 1);  /* try alternative name */
429   }
430   if (init == NULL) return LUA_OK;
431   else if (init[0] == '@')
432     return dofile(L, init+1);
433   else
434     return dostring(L, init, name);
435 }
436 
437 
pmain(lua_State * L)438 static int pmain (lua_State *L) {
439   int argc = (int)lua_tointeger(L, 1);
440   char **argv = (char **)lua_touserdata(L, 2);
441   int script;
442   int args[num_has];
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]);
448     return 0;
449   }
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");
454   }
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? */
467     dotty(L);
468   else if (script == 0 && !args[has_e] && !args[has_v]) {  /* no arguments? */
469     if (lua_stdin_is_tty()) {
470       print_version();
471       dotty(L);
472     }
473     else dofile(L, NULL);  /* executes stdin as a file */
474   }
475   lua_pushboolean(L, 1);  /* signal no errors */
476   return 1;
477 }
478 
479 
main(int argc,char ** argv)480 int main (int argc, char **argv) {
481   int status, result;
482   lua_State *L = luaL_newstate();  /* create state */
483   if (L == NULL) {
484     l_message(argv[0], "cannot create state: not enough memory");
485     return EXIT_FAILURE;
486   }
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);
494   lua_close(L);
495   return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
496 }
497 
498