diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-07 15:27:12 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-02-07 15:27:12 -0200 |
commit | cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c (patch) | |
tree | 41c2a6c4dfc0d05f8e800f8a021033d052fd8137 /lua.c | |
parent | c6a108e0122c8ddc57f8d12a151908abec4fe562 (diff) | |
download | lua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.tar.gz lua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.tar.bz2 lua-cb50fcf42d9ab2d04f6f28a30a0ca5cc6e58054c.zip |
incomplete lines (by lhf)
Diffstat (limited to 'lua.c')
-rw-r--r-- | lua.c | 242 |
1 files changed, 132 insertions, 110 deletions
@@ -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 | |||
42 | static lua_State *L = NULL; | 46 | static lua_State *L = NULL; |
43 | 47 | ||
44 | 48 | ||
45 | typedef void (*handler)(int); /* type for signal actions */ | ||
46 | |||
47 | static void laction (int i); | ||
48 | |||
49 | |||
50 | static lua_Hook old_linehook = NULL; | 49 | static lua_Hook old_linehook = NULL; |
51 | static lua_Hook old_callhook = NULL; | 50 | static lua_Hook old_callhook = NULL; |
52 | 51 | ||
53 | 52 | ||
54 | |||
55 | static handler lreset (void) { | ||
56 | return signal(SIGINT, laction); | ||
57 | } | ||
58 | |||
59 | |||
60 | static void lstop (void) { | 53 | static 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 */ | ||
70 | static 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 | |||
77 | static int ldo (int (*f)(lua_State *l, const char *), const char *name, | 78 | static 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 | ||
96 | static void print_message (void) { | 91 | static 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 | ||
148 | static int file_input (const char *argv) { | 142 | static 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 | ||
168 | static const char *get_prompt (int prompt) { | 171 | static 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 | ||
182 | static void manual_input (int version, int prompt) { | 182 | static 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"); | 192 | static int incomplete = 0; |
193 | return; | 193 | |
194 | } | 194 | static 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 | } | 204 | static 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 | |||
240 | static 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 | |||
246 | static 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 | ||
225 | static int handle_argv (char *argv[], int *toclose) { | 265 | static 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 | ||
304 | static 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 | |||
318 | static void register_getargs (char *argv[]) { | 339 | static 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) { | |||
334 | int main (int argc, char *argv[]) { | 355 | int 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); |