aboutsummaryrefslogtreecommitdiff
path: root/lua.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-02-07 15:27:12 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-02-07 15:27:12 -0200
commitcb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c (patch)
tree41c2a6c4dfc0d05f8e800f8a021033d052fd8137 /lua.c
parentc6a108e0122c8ddc57f8d12a151908abec4fe562 (diff)
downloadlua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.tar.gz
lua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.tar.bz2
lua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.zip
incomplete lines (by lhf)
Diffstat (limited to 'lua.c')
-rw-r--r--lua.c242
1 files changed, 132 insertions, 110 deletions
diff --git a/lua.c b/lua.c
index 0453cf74..01c29bfc 100644
--- a/lua.c
+++ b/lua.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ 2** $Id: lua.c,v 1.74 2001/12/10 22:09:51 lhf Exp $
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*/
@@ -33,34 +33,26 @@ static int isatty (int x) { return x==0; } /* assume stdin is a tty */
33#endif 33#endif
34 34
35 35
36#ifndef PROMPT2
37#define PROMPT2 ">> "
38#endif
39
40
36#ifndef LUA_USERINIT 41#ifndef LUA_USERINIT
37#define LUA_USERINIT(L) openstdlibs(L) 42#define LUA_USERINIT(L) openstdlibs(L)
38#endif 43#endif
39 44
40 45
41
42static lua_State *L = NULL; 46static lua_State *L = NULL;
43 47
44 48
45typedef void (*handler)(int); /* type for signal actions */
46
47static void laction (int i);
48
49
50static lua_Hook old_linehook = NULL; 49static lua_Hook old_linehook = NULL;
51static lua_Hook old_callhook = NULL; 50static lua_Hook old_callhook = NULL;
52 51
53 52
54
55static handler lreset (void) {
56 return signal(SIGINT, laction);
57}
58
59
60static void lstop (void) { 53static void lstop (void) {
61 lua_setlinehook(L, old_linehook); 54 lua_setlinehook(L, old_linehook);
62 lua_setcallhook(L, old_callhook); 55 lua_setcallhook(L, old_callhook);
63 lreset();
64 lua_error(L, "interrupted!"); 56 lua_error(L, "interrupted!");
65} 57}
66 58
@@ -74,35 +66,36 @@ static void laction (int i) {
74} 66}
75 67
76 68
69/* Lua gives no message in such cases, so we provide one */
70static void report (int result) {
71 if (result == LUA_ERRMEM)
72 fprintf(stderr, LUA_PROGNAME "memory allocation error\n");
73 else if (result == LUA_ERRERR)
74 fprintf(stderr, LUA_PROGNAME "error in error message\n");
75}
76
77
77static int ldo (int (*f)(lua_State *l, const char *), const char *name, 78static int ldo (int (*f)(lua_State *l, const char *), const char *name,
78 int clear) { 79 int clear) {
79 int res; 80 int result;
80 handler h = lreset();
81 int top = lua_gettop(L); 81 int top = lua_gettop(L);
82 res = f(L, name); /* dostring | dofile */ 82 signal(SIGINT, laction);
83 signal(SIGINT, h); /* restore old action */ 83 result = f(L, name); /* dostring | dofile */
84 if (clear) 84 signal(SIGINT, SIG_DFL);
85 lua_settop(L, top); /* remove eventual results */ 85 if (clear) lua_settop(L, top); /* remove eventual results */
86 /* Lua gives no message in such cases, so lua.c provides one */ 86 report(result);
87 if (res == LUA_ERRMEM) { 87 return result;
88 fprintf(stderr, LUA_PROGNAME "memory allocation error\n");
89 }
90 else if (res == LUA_ERRERR)
91 fprintf(stderr, LUA_PROGNAME "error in error message\n");
92 return res;
93} 88}
94 89
95 90
96static void print_message (void) { 91static void print_usage (void) {
97 fprintf(stderr, 92 fprintf(stderr,
98 "usage: lua [options]. Available options are:\n" 93 "usage: lua [options]. Available options are:\n"
99 " - execute stdin as a file\n" 94 " - execute stdin as a file\n"
100 " -c close Lua when exiting\n" 95 " -c close Lua when exiting\n"
101 " -e stat execute string `stat'\n" 96 " -e stat execute string `stat'\n"
102 " -f name execute file `name' with remaining arguments in table `arg'\n" 97 " -f name execute file `name' with remaining arguments in table `arg'\n"
103 " -i enter interactive mode with prompt\n" 98 " -i enter interactive mode\n"
104 " -q enter interactive mode without prompt\n"
105 " -sNUM set stack size to NUM (must be the first option)\n"
106 " -v print version information\n" 99 " -v print version information\n"
107 " a=b set global `a' to string `b'\n" 100 " a=b set global `a' to string `b'\n"
108 " name execute file `name'\n" 101 " name execute file `name'\n"
@@ -130,11 +123,12 @@ static void getargs (char *argv[]) {
130 /* arg[i] = argv[i] */ 123 /* arg[i] = argv[i] */
131 lua_pushnumber(L, i); 124 lua_pushnumber(L, i);
132 lua_pushstring(L, argv[i]); 125 lua_pushstring(L, argv[i]);
133 lua_settable(L, -3); 126 lua_rawset(L, -3);
134 } 127 }
135 /* arg.n = maximum index in table `arg' */ 128 /* arg.n = maximum index in table `arg' */
129 lua_pushliteral(L, "n");
136 lua_pushnumber(L, i-1); 130 lua_pushnumber(L, i-1);
137 lua_setstr(L, -2, "n"); 131 lua_rawset(L, -3);
138} 132}
139 133
140 134
@@ -145,12 +139,12 @@ static int l_getargs (lua_State *l) {
145} 139}
146 140
147 141
148static int file_input (const char *argv) { 142static int file_input (const char *name) {
149 int result = ldo(lua_dofile, argv, 1); 143 int result = ldo(lua_dofile, name, 1);
150 if (result) { 144 if (result) {
151 if (result == LUA_ERRFILE) { 145 if (result == LUA_ERRFILE) {
152 fprintf(stderr, LUA_PROGNAME "cannot execute file "); 146 fprintf(stderr, LUA_PROGNAME "cannot execute file ");
153 perror(argv); 147 perror(name);
154 } 148 }
155 return EXIT_FAILURE; 149 return EXIT_FAILURE;
156 } 150 }
@@ -159,73 +153,119 @@ static int file_input (const char *argv) {
159} 153}
160 154
161 155
156#ifdef USE_READLINE
157#include <readline/readline.h>
158#include <readline/history.h>
159#define save_line(b) if (strcspn(b, " \t\n") != 0) add_history(b)
160#define push_line(b) if (incomplete) lua_pushstring(L, "\n"); lua_pushstring(L, b); free(b)
161#else
162#define save_line(b)
163#define push_line(b) lua_pushstring(L, b)
164
162/* maximum length of an input line */ 165/* maximum length of an input line */
163#ifndef MAXINPUT 166#ifndef MAXINPUT
164#define MAXINPUT 512 167#define MAXINPUT 512
165#endif 168#endif
166 169
167 170
168static const char *get_prompt (int prompt) { 171static char *readline (const char *prompt) {
169 if (!prompt) 172 static char buffer[MAXINPUT];
170 return ""; 173 if (prompt) {
171 else { 174 fputs(prompt, stdout);
172 const char *s; 175 fflush(stdout);
173 lua_getglobal(L, "_PROMPT");
174 s = lua_tostring(L, -1);
175 if (!s) s = PROMPT;
176 lua_pop(L, 1); /* remove global */
177 return s;
178 } 176 }
177 return fgets(buffer, sizeof(buffer), stdin);
179} 178}
179#endif
180 180
181 181
182static void manual_input (int version, int prompt) { 182static const char *get_prompt (int incomplete) {
183 if (version) print_version(); 183 const char *p = NULL;
184 for (;;) { 184 lua_getglobal(L, incomplete ? "_PROMPT2" : "_PROMPT");
185 int firstline = 1; 185 p = lua_tostring(L, -1);
186 int toprint = 0; 186 if (p == NULL) p = (incomplete ? PROMPT2 : PROMPT);
187 fputs(get_prompt(prompt), stdout); /* show prompt */ 187 lua_pop(L, 1); /* remove global */
188 for(;;) { 188 return p;
189 char buffer[MAXINPUT]; 189}
190 size_t l; 190
191 if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 191
192 printf("\n"); 192static int incomplete = 0;
193 return; 193
194 } 194static int trap_eof (lua_State *l) {
195 if (firstline && buffer[0] == '=') { 195 const char *s = lua_tostring(l, 1);
196 buffer[0] = ' '; 196 if (strstr(s, "last token read: `<eof>'") != NULL)
197 lua_pushstring(L, "return"); 197 incomplete = 1;
198 toprint = 1; 198 else
199 } 199 fprintf(stderr, "error: %s\n", s);
200 l = strlen(buffer); 200 return 0;
201 if (buffer[l-1] == '\n' && buffer[l-2] == '\\') { 201}
202 buffer[l-2] = '\n'; 202
203 lua_pushlstring(L, buffer, l-1); 203
204 } 204static int load_string (int *toprint) {
205 else { 205 lua_getglobal(L, LUA_ERRORMESSAGE);
206 lua_pushlstring(L, buffer, l); 206 lua_pushvalue(L, 1);
207 break; 207 lua_setglobal(L, LUA_ERRORMESSAGE);
208 } 208 incomplete = 0;
209 firstline = 0; 209 for (;;) { /* repeat until gets a complete line */
210 int result;
211 char *buffer = readline(get_prompt(incomplete));
212 if (buffer == NULL) { /* input end? */
213 lua_settop(L, 2);
214 lua_setglobal(L, LUA_ERRORMESSAGE);
215 return 0;
216 }
217 *toprint = !incomplete && buffer[0] == '=';
218 if (*toprint) {
219 buffer[0] = ' ';
220 lua_pushstring(L, "return");
210 } 221 }
211 lua_concat(L, lua_gettop(L)); 222 push_line(buffer);
212 ldo(lua_dostring, lua_tostring(L, 1), 0); 223 lua_concat(L, lua_gettop(L)-2);
213 lua_remove(L, 1); /* remove ran string */ 224 incomplete = 0;
214 if (toprint && lua_gettop(L) > 0) { /* any result to print? */ 225 result = lua_loadbuffer(L, lua_tostring(L, 3), lua_strlen(L, 3), "=stdin");
226 if (incomplete) continue; /* repeat loop to get rest of `line' */
227 save_line(lua_tostring(L, 3));
228 lua_remove(L, 3);
229 if (result == 0) {
230 lua_insert(L, 2); /* swap compiled chunk with old _ERRORMESSAGE */
231 lua_setglobal(L, LUA_ERRORMESSAGE); /* restore old _ERRORMESSAGE */
232 return 1;
233 }
234 else
235 report(result);
236 }
237}
238
239
240static int lcall (lua_State *l, const char *name) {
241 (void)name; /* to avoid warnings */
242 return lua_call(l, 0, LUA_MULTRET);
243}
244
245
246static void manual_input (int version) {
247 int toprint = 0;
248 if (version) print_version();
249 lua_pushcfunction(L, trap_eof); /* set up handler for incomplete lines */
250 while (load_string(&toprint)) {
251 ldo(lcall, NULL, 0);
252 if (toprint && lua_gettop(L) > 1) { /* any result to print? */
215 lua_getglobal(L, "print"); 253 lua_getglobal(L, "print");
216 lua_insert(L, 1); 254 lua_insert(L, 2);
217 lua_call(L, lua_gettop(L)-1, 0); 255 lua_call(L, lua_gettop(L)-2, 0);
218 } 256 }
219 else 257 else
220 lua_settop(L, 0); /* remove eventual results */ 258 lua_settop(L, 1); /* remove eventual results */
221 } 259 }
260 printf("\n");
261 lua_settop(L, 0); /* remove trap_eof */
222} 262}
223 263
224 264
225static int handle_argv (char *argv[], int *toclose) { 265static int handle_argv (char *argv[], int *toclose) {
226 if (*argv == NULL) { /* no more arguments? */ 266 if (*argv == NULL) { /* no more arguments? */
227 if (isatty(0)) { 267 if (isatty(0)) {
228 manual_input(1, 1); 268 manual_input(1);
229 } 269 }
230 else 270 else
231 ldo(lua_dofile, NULL, 1); /* executes stdin as a file */ 271 ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
@@ -241,16 +281,12 @@ static int handle_argv (char *argv[], int *toclose) {
241 return EXIT_FAILURE; /* stop if file fails */ 281 return EXIT_FAILURE; /* stop if file fails */
242 } 282 }
243 else switch (argv[i][1]) { /* option */ 283 else switch (argv[i][1]) { /* option */
244 case 0: { 284 case '\0': {
245 ldo(lua_dofile, NULL, 1); /* executes stdin as a file */ 285 ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
246 break; 286 break;
247 } 287 }
248 case 'i': { 288 case 'i': {
249 manual_input(0, 1); 289 manual_input(0);
250 break;
251 }
252 case 'q': {
253 manual_input(0, 0);
254 break; 290 break;
255 } 291 }
256 case 'c': { 292 case 'c': {
@@ -264,7 +300,7 @@ static int handle_argv (char *argv[], int *toclose) {
264 case 'e': { 300 case 'e': {
265 i++; 301 i++;
266 if (argv[i] == NULL) { 302 if (argv[i] == NULL) {
267 print_message(); 303 print_usage();
268 return EXIT_FAILURE; 304 return EXIT_FAILURE;
269 } 305 }
270 if (ldo(lua_dostring, argv[i], 1) != 0) { 306 if (ldo(lua_dostring, argv[i], 1) != 0) {
@@ -277,7 +313,7 @@ static int handle_argv (char *argv[], int *toclose) {
277 case 'f': { 313 case 'f': {
278 i++; 314 i++;
279 if (argv[i] == NULL) { 315 if (argv[i] == NULL) {
280 print_message(); 316 print_usage();
281 return EXIT_FAILURE; 317 return EXIT_FAILURE;
282 } 318 }
283 getargs(argv+i); /* collect remaining arguments */ 319 getargs(argv+i); /* collect remaining arguments */
@@ -285,13 +321,12 @@ static int handle_argv (char *argv[], int *toclose) {
285 return file_input(argv[i]); /* stop scanning arguments */ 321 return file_input(argv[i]); /* stop scanning arguments */
286 } 322 }
287 case 's': { 323 case 's': {
288 if (i == 0) break; /* option already handled */ 324 fprintf(stderr, LUA_PROGNAME
289 fprintf(stderr, 325 "option `-s' is deprecated (dynamic stack now)\n");
290 LUA_PROGNAME "stack size (`-s') must be the first option\n"); 326 break;
291 return EXIT_FAILURE;
292 } 327 }
293 default: { 328 default: {
294 print_message(); 329 print_usage();
295 return EXIT_FAILURE; 330 return EXIT_FAILURE;
296 } 331 }
297 } 332 }
@@ -301,20 +336,6 @@ static int handle_argv (char *argv[], int *toclose) {
301} 336}
302 337
303 338
304static int getstacksize (int argc, char *argv[]) {
305 int stacksize = 0;
306 if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 's') {
307 stacksize = strtol(&argv[1][2], NULL, 10);
308 if (stacksize <= 0) {
309 fprintf(stderr, LUA_PROGNAME "invalid stack size ('%.20s')\n",
310 &argv[1][2]);
311 exit(EXIT_FAILURE);
312 }
313 }
314 return stacksize;
315}
316
317
318static void register_getargs (char *argv[]) { 339static void register_getargs (char *argv[]) {
319 lua_newuserdatabox(L, argv); 340 lua_newuserdatabox(L, argv);
320 lua_pushcclosure(L, l_getargs, 1); 341 lua_pushcclosure(L, l_getargs, 1);
@@ -334,7 +355,8 @@ static void openstdlibs (lua_State *l) {
334int main (int argc, char *argv[]) { 355int main (int argc, char *argv[]) {
335 int status; 356 int status;
336 int toclose = 0; 357 int toclose = 0;
337 L = lua_open(getstacksize(argc, argv)); /* create state */ 358 (void)argc; /* unused parameter: avoid warnings */
359 L = lua_open(0); /* create state */
338 LUA_USERINIT(L); /* open libraries */ 360 LUA_USERINIT(L); /* open libraries */
339 register_getargs(argv); /* create `getargs' function */ 361 register_getargs(argv); /* create `getargs' function */
340 status = handle_argv(argv+1, &toclose); 362 status = handle_argv(argv+1, &toclose);