aboutsummaryrefslogtreecommitdiff
path: root/lua.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-03-06 17:30:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-03-06 17:30:17 -0300
commit464658b16a1a539fd590e1696bfcfb572a77fe13 (patch)
tree0a0ce3328d98b0e94555b9ab5ff12541c1721d22 /lua.c
parentbdcde45d05f321fb6608e58bf24e1920fa3a3a23 (diff)
downloadlua-464658b16a1a539fd590e1696bfcfb572a77fe13.tar.gz
lua-464658b16a1a539fd590e1696bfcfb572a77fe13.tar.bz2
lua-464658b16a1a539fd590e1696bfcfb572a77fe13.zip
better modularization of the code for the REPL
Diffstat (limited to 'lua.c')
-rw-r--r--lua.c401
1 files changed, 203 insertions, 198 deletions
diff --git a/lua.c b/lua.c
index b0e7e1b9..2e95c40b 100644
--- a/lua.c
+++ b/lua.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.c,v 1.232 2017/05/24 21:11:19 roberto Exp roberto $ 2** $Id: lua.c,v 1.233 2018/02/06 15:32:36 roberto Exp roberto $
3** Lua stand-alone interpreter 3** Lua stand-alone interpreter
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -21,20 +21,10 @@
21#include "lualib.h" 21#include "lualib.h"
22 22
23 23
24
25#if !defined(LUA_PROMPT)
26#define LUA_PROMPT "> "
27#define LUA_PROMPT2 ">> "
28#endif
29
30#if !defined(LUA_PROGNAME) 24#if !defined(LUA_PROGNAME)
31#define LUA_PROGNAME "lua" 25#define LUA_PROGNAME "lua"
32#endif 26#endif
33 27
34#if !defined(LUA_MAXINPUT)
35#define LUA_MAXINPUT 512
36#endif
37
38#if !defined(LUA_INIT_VAR) 28#if !defined(LUA_INIT_VAR)
39#define LUA_INIT_VAR "LUA_INIT" 29#define LUA_INIT_VAR "LUA_INIT"
40#endif 30#endif
@@ -42,65 +32,6 @@
42#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX 32#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
43 33
44 34
45/*
46** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
47** is, whether we're running lua interactively).
48*/
49#if !defined(lua_stdin_is_tty) /* { */
50
51#if defined(LUA_USE_POSIX) /* { */
52
53#include <unistd.h>
54#define lua_stdin_is_tty() isatty(0)
55
56#elif defined(LUA_USE_WINDOWS) /* }{ */
57
58#include <io.h>
59#include <windows.h>
60
61#define lua_stdin_is_tty() _isatty(_fileno(stdin))
62
63#else /* }{ */
64
65/* ISO C definition */
66#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
67
68#endif /* } */
69
70#endif /* } */
71
72
73/*
74** lua_readline defines how to show a prompt and then read a line from
75** the standard input.
76** lua_saveline defines how to "save" a read line in a "history".
77** lua_freeline defines how to free a line read by lua_readline.
78*/
79#if !defined(lua_readline) /* { */
80
81#if defined(LUA_USE_READLINE) /* { */
82
83#include <readline/readline.h>
84#include <readline/history.h>
85#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
86#define lua_saveline(L,line) ((void)L, add_history(line))
87#define lua_freeline(L,b) ((void)L, free(b))
88
89#else /* }{ */
90
91#define lua_readline(L,b,p) \
92 ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
93 fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
94#define lua_saveline(L,line) { (void)L; (void)line; }
95#define lua_freeline(L,b) { (void)L; (void)b; }
96
97#endif /* } */
98
99#endif /* } */
100
101
102
103
104static lua_State *globalL = NULL; 35static lua_State *globalL = NULL;
105 36
106static const char *progname = LUA_PROGNAME; 37static const char *progname = LUA_PROGNAME;
@@ -269,6 +200,207 @@ static int dolibrary (lua_State *L, const char *name) {
269 200
270 201
271/* 202/*
203** Push on the stack the contents of table 'arg' from 1 to #arg
204*/
205static int pushargs (lua_State *L) {
206 int i, n;
207 if (lua_getglobal(L, "arg") != LUA_TTABLE)
208 luaL_error(L, "'arg' is not a table");
209 n = (int)luaL_len(L, -1);
210 luaL_checkstack(L, n + 3, "too many arguments to script");
211 for (i = 1; i <= n; i++)
212 lua_rawgeti(L, -i, i);
213 lua_remove(L, -i); /* remove table from the stack */
214 return n;
215}
216
217
218static int handle_script (lua_State *L, char **argv) {
219 int status;
220 const char *fname = argv[0];
221 if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
222 fname = NULL; /* stdin */
223 status = luaL_loadfile(L, fname);
224 if (status == LUA_OK) {
225 int n = pushargs(L); /* push arguments to script */
226 status = docall(L, n, LUA_MULTRET);
227 }
228 return report(L, status);
229}
230
231
232/* bits of various argument indicators in 'args' */
233#define has_error 1 /* bad option */
234#define has_i 2 /* -i */
235#define has_v 4 /* -v */
236#define has_e 8 /* -e */
237#define has_E 16 /* -E */
238
239
240/*
241** Traverses all arguments from 'argv', returning a mask with those
242** needed before running any Lua code (or an error code if it finds
243** any invalid argument). 'first' returns the first not-handled argument
244** (either the script name or a bad argument in case of error).
245*/
246static int collectargs (char **argv, int *first) {
247 int args = 0;
248 int i;
249 for (i = 1; argv[i] != NULL; i++) {
250 *first = i;
251 if (argv[i][0] != '-') /* not an option? */
252 return args; /* stop handling options */
253 switch (argv[i][1]) { /* else check option */
254 case '-': /* '--' */
255 if (argv[i][2] != '\0') /* extra characters after '--'? */
256 return has_error; /* invalid option */
257 *first = i + 1;
258 return args;
259 case '\0': /* '-' */
260 return args; /* script "name" is '-' */
261 case 'E':
262 if (argv[i][2] != '\0') /* extra characters after 1st? */
263 return has_error; /* invalid option */
264 args |= has_E;
265 break;
266 case 'i':
267 args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
268 case 'v':
269 if (argv[i][2] != '\0') /* extra characters after 1st? */
270 return has_error; /* invalid option */
271 args |= has_v;
272 break;
273 case 'e':
274 args |= has_e; /* FALLTHROUGH */
275 case 'l': /* both options need an argument */
276 if (argv[i][2] == '\0') { /* no concatenated argument? */
277 i++; /* try next 'argv' */
278 if (argv[i] == NULL || argv[i][0] == '-')
279 return has_error; /* no next argument or it is another option */
280 }
281 break;
282 default: /* invalid option */
283 return has_error;
284 }
285 }
286 *first = i; /* no script name */
287 return args;
288}
289
290
291/*
292** Processes options 'e' and 'l', which involve running Lua code.
293** Returns 0 if some code raises an error.
294*/
295static int runargs (lua_State *L, char **argv, int n) {
296 int i;
297 for (i = 1; i < n; i++) {
298 int option = argv[i][1];
299 lua_assert(argv[i][0] == '-'); /* already checked */
300 if (option == 'e' || option == 'l') {
301 int status;
302 const char *extra = argv[i] + 2; /* both options need an argument */
303 if (*extra == '\0') extra = argv[++i];
304 lua_assert(extra != NULL);
305 status = (option == 'e')
306 ? dostring(L, extra, "=(command line)")
307 : dolibrary(L, extra);
308 if (status != LUA_OK) return 0;
309 }
310 }
311 return 1;
312}
313
314
315static int handle_luainit (lua_State *L) {
316 const char *name = "=" LUA_INITVARVERSION;
317 const char *init = getenv(name + 1);
318 if (init == NULL) {
319 name = "=" LUA_INIT_VAR;
320 init = getenv(name + 1); /* try alternative name */
321 }
322 if (init == NULL) return LUA_OK;
323 else if (init[0] == '@')
324 return dofile(L, init+1);
325 else
326 return dostring(L, init, name);
327}
328
329
330/*
331** {==================================================================
332** Read-Eval-Print Loop (REPL)
333** ===================================================================
334*/
335
336#if !defined(LUA_PROMPT)
337#define LUA_PROMPT "> "
338#define LUA_PROMPT2 ">> "
339#endif
340
341#if !defined(LUA_MAXINPUT)
342#define LUA_MAXINPUT 512
343#endif
344
345
346/*
347** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
348** is, whether we're running lua interactively).
349*/
350#if !defined(lua_stdin_is_tty) /* { */
351
352#if defined(LUA_USE_POSIX) /* { */
353
354#include <unistd.h>
355#define lua_stdin_is_tty() isatty(0)
356
357#elif defined(LUA_USE_WINDOWS) /* }{ */
358
359#include <io.h>
360#include <windows.h>
361
362#define lua_stdin_is_tty() _isatty(_fileno(stdin))
363
364#else /* }{ */
365
366/* ISO C definition */
367#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
368
369#endif /* } */
370
371#endif /* } */
372
373
374/*
375** lua_readline defines how to show a prompt and then read a line from
376** the standard input.
377** lua_saveline defines how to "save" a read line in a "history".
378** lua_freeline defines how to free a line read by lua_readline.
379*/
380#if !defined(lua_readline) /* { */
381
382#if defined(LUA_USE_READLINE) /* { */
383
384#include <readline/readline.h>
385#include <readline/history.h>
386#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
387#define lua_saveline(L,line) ((void)L, add_history(line))
388#define lua_freeline(L,b) ((void)L, free(b))
389
390#else /* }{ */
391
392#define lua_readline(L,b,p) \
393 ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
394 fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
395#define lua_saveline(L,line) { (void)L; (void)line; }
396#define lua_freeline(L,b) { (void)L; (void)b; }
397
398#endif /* } */
399
400#endif /* } */
401
402
403/*
272** Returns the string to be used as a prompt by the interpreter. 404** Returns the string to be used as a prompt by the interpreter.
273*/ 405*/
274static const char *get_prompt (lua_State *L, int firstline) { 406static const char *get_prompt (lua_State *L, int firstline) {
@@ -418,134 +550,7 @@ static void doREPL (lua_State *L) {
418 progname = oldprogname; 550 progname = oldprogname;
419} 551}
420 552
421 553/* }================================================================== */
422/*
423** Push on the stack the contents of table 'arg' from 1 to #arg
424*/
425static int pushargs (lua_State *L) {
426 int i, n;
427 if (lua_getglobal(L, "arg") != LUA_TTABLE)
428 luaL_error(L, "'arg' is not a table");
429 n = (int)luaL_len(L, -1);
430 luaL_checkstack(L, n + 3, "too many arguments to script");
431 for (i = 1; i <= n; i++)
432 lua_rawgeti(L, -i, i);
433 lua_remove(L, -i); /* remove table from the stack */
434 return n;
435}
436
437
438static int handle_script (lua_State *L, char **argv) {
439 int status;
440 const char *fname = argv[0];
441 if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
442 fname = NULL; /* stdin */
443 status = luaL_loadfile(L, fname);
444 if (status == LUA_OK) {
445 int n = pushargs(L); /* push arguments to script */
446 status = docall(L, n, LUA_MULTRET);
447 }
448 return report(L, status);
449}
450
451
452
453/* bits of various argument indicators in 'args' */
454#define has_error 1 /* bad option */
455#define has_i 2 /* -i */
456#define has_v 4 /* -v */
457#define has_e 8 /* -e */
458#define has_E 16 /* -E */
459
460/*
461** Traverses all arguments from 'argv', returning a mask with those
462** needed before running any Lua code (or an error code if it finds
463** any invalid argument). 'first' returns the first not-handled argument
464** (either the script name or a bad argument in case of error).
465*/
466static int collectargs (char **argv, int *first) {
467 int args = 0;
468 int i;
469 for (i = 1; argv[i] != NULL; i++) {
470 *first = i;
471 if (argv[i][0] != '-') /* not an option? */
472 return args; /* stop handling options */
473 switch (argv[i][1]) { /* else check option */
474 case '-': /* '--' */
475 if (argv[i][2] != '\0') /* extra characters after '--'? */
476 return has_error; /* invalid option */
477 *first = i + 1;
478 return args;
479 case '\0': /* '-' */
480 return args; /* script "name" is '-' */
481 case 'E':
482 if (argv[i][2] != '\0') /* extra characters after 1st? */
483 return has_error; /* invalid option */
484 args |= has_E;
485 break;
486 case 'i':
487 args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
488 case 'v':
489 if (argv[i][2] != '\0') /* extra characters after 1st? */
490 return has_error; /* invalid option */
491 args |= has_v;
492 break;
493 case 'e':
494 args |= has_e; /* FALLTHROUGH */
495 case 'l': /* both options need an argument */
496 if (argv[i][2] == '\0') { /* no concatenated argument? */
497 i++; /* try next 'argv' */
498 if (argv[i] == NULL || argv[i][0] == '-')
499 return has_error; /* no next argument or it is another option */
500 }
501 break;
502 default: /* invalid option */
503 return has_error;
504 }
505 }
506 *first = i; /* no script name */
507 return args;
508}
509
510
511/*
512** Processes options 'e' and 'l', which involve running Lua code.
513** Returns 0 if some code raises an error.
514*/
515static int runargs (lua_State *L, char **argv, int n) {
516 int i;
517 for (i = 1; i < n; i++) {
518 int option = argv[i][1];
519 lua_assert(argv[i][0] == '-'); /* already checked */
520 if (option == 'e' || option == 'l') {
521 int status;
522 const char *extra = argv[i] + 2; /* both options need an argument */
523 if (*extra == '\0') extra = argv[++i];
524 lua_assert(extra != NULL);
525 status = (option == 'e')
526 ? dostring(L, extra, "=(command line)")
527 : dolibrary(L, extra);
528 if (status != LUA_OK) return 0;
529 }
530 }
531 return 1;
532}
533
534
535
536static int handle_luainit (lua_State *L) {
537 const char *name = "=" LUA_INITVARVERSION;
538 const char *init = getenv(name + 1);
539 if (init == NULL) {
540 name = "=" LUA_INIT_VAR;
541 init = getenv(name + 1); /* try alternative name */
542 }
543 if (init == NULL) return LUA_OK;
544 else if (init[0] == '@')
545 return dofile(L, init+1);
546 else
547 return dostring(L, init, name);
548}
549 554
550 555
551/* 556/*