Showing the changes to src/lua.c (1 of 39 files). Show all
Unified · Split
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lua.c,v 1.150 2005/09/06 17:19:33 roberto Exp $ | |
| 2 | +** $Id: lua.c,v 1.154 2005/10/24 17:38:47 roberto Exp $ | |
| 3 | 3 | ** Lua stand-alone interpreter |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -43,12 +43,13 @@ static void print_usage (void) { · 37 unmodified lines | ||
| 43 | 43 | fprintf(stderr, |
| 44 | 44 | "usage: %s [options] [script [args]].\n" |
| 45 | 45 | "Available options are:\n" |
| 46 | − " - execute stdin as a file\n" | |
| 47 | 46 | " -e stat execute string " LUA_QL("stat") "\n" |
| 48 | − " -i enter interactive mode after executing " LUA_QL("script") "\n" | |
| 49 | 47 | " -l name require library " LUA_QL("name") "\n" |
| 48 | + " -i enter interactive mode after executing " LUA_QL("script") "\n" | |
| 50 | 49 | " -v show version information\n" |
| 51 | − " -- stop handling options\n" , | |
| 50 | + " -- stop handling options\n" | |
| 51 | + " - execute stdin and stop handling options\n" | |
| 52 | + , | |
| 52 | 53 | progname); |
| 53 | 54 | fflush(stderr); |
| 54 | 55 | } |
| @@ -99,6 +100,8 @@ static int docall (lua_State *L, int narg, int clear) { · 44 unmodified lines | ||
| 99 | 100 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); |
| 100 | 101 | signal(SIGINT, SIG_DFL); |
| 101 | 102 | lua_remove(L, base); /* remove traceback function */ |
| 103 | + /* force a complete garbage collection in case of errors */ | |
| 104 | + if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); | |
| 102 | 105 | return status; |
| 103 | 106 | } |
| 104 | 107 | |
| @@ -108,9 +111,12 @@ static void print_version (void) { · 3 unmodified lines | ||
| 108 | 111 | } |
| 109 | 112 | |
| 110 | 113 | |
| 111 | −static int getargs (lua_State *L, int argc, char **argv, int n) { | |
| 112 | − int narg = argc - (n + 1); /* number of arguments to the script */ | |
| 114 | +static int getargs (lua_State *L, char **argv, int n) { | |
| 115 | + int narg; | |
| 113 | 116 | int i; |
| 117 | + int argc = 0; | |
| 118 | + while (argv[argc]) argc++; /* count total number of arguments */ | |
| 119 | + narg = argc - (n + 1); /* number of arguments to the script */ | |
| 114 | 120 | luaL_checkstack(L, narg + 3, "too many arguments to script"); |
| 115 | 121 | for (i=n+1; i < argc; i++) |
| 116 | 122 | lua_pushstring(L, argv[i]); |
| @@ -229,86 +235,71 @@ static void dotty (lua_State *L) { · 112 unmodified lines | ||
| 229 | 235 | } |
| 230 | 236 | |
| 231 | 237 | |
| 232 | −#define clearinteractive(i) (*i &= 2) | |
| 238 | +static int handle_script (lua_State *L, char **argv, int n) { | |
| 239 | + int status; | |
| 240 | + const char *fname; | |
| 241 | + int narg = getargs(L, argv, n); /* collect arguments */ | |
| 242 | + lua_setglobal(L, "arg"); | |
| 243 | + fname = argv[n]; | |
| 244 | + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) | |
| 245 | + fname = NULL; /* stdin */ | |
| 246 | + status = luaL_loadfile(L, fname); | |
| 247 | + lua_insert(L, -(narg+1)); | |
| 248 | + if (status == 0) | |
| 249 | + status = docall(L, narg, 0); | |
| 250 | + else | |
| 251 | + lua_pop(L, narg); | |
| 252 | + return report(L, status); | |
| 253 | +} | |
| 233 | 254 | |
| 234 | −static int handle_argv (lua_State *L, int argc, char **argv, int *interactive) { | |
| 235 | − if (argv[1] == NULL) { /* no arguments? */ | |
| 236 | − *interactive = 0; | |
| 237 | − if (lua_stdin_is_tty()) | |
| 238 | − dotty(L); | |
| 239 | − else | |
| 240 | − dofile(L, NULL); /* executes stdin as a file */ | |
| 241 | − } | |
| 242 | − else { /* other arguments; loop over them */ | |
| 243 | − int i; | |
| 244 | − for (i = 1; argv[i] != NULL; i++) { | |
| 245 | − if (argv[i][0] != '-') break; /* not an option? */ | |
| 246 | − switch (argv[i][1]) { /* option */ | |
| 247 | − case '-': { /* `--' */ | |
| 248 | − if (argv[i][2] != '\0') { | |
| 249 | − print_usage(); | |
| 250 | − return 1; | |
| 251 | − } | |
| 252 | − i++; /* skip this argument */ | |
| 253 | − goto endloop; /* stop handling arguments */ | |
| 254 | − } | |
| 255 | − case '\0': { | |
| 256 | − clearinteractive(interactive); | |
| 257 | − dofile(L, NULL); /* executes stdin as a file */ | |
| 258 | − break; | |
| 259 | − } | |
| 260 | − case 'i': { | |
| 261 | − *interactive = 2; /* force interactive mode after arguments */ | |
| 262 | − break; | |
| 263 | − } | |
| 264 | − case 'v': { | |
| 265 | − clearinteractive(interactive); | |
| 266 | − print_version(); | |
| 267 | − break; | |
| 268 | − } | |
| 269 | − case 'e': { | |
| 270 | − const char *chunk = argv[i] + 2; | |
| 271 | − clearinteractive(interactive); | |
| 272 | − if (*chunk == '\0') chunk = argv[++i]; | |
| 273 | − if (chunk == NULL) { | |
| 274 | − print_usage(); | |
| 275 | − return 1; | |
| 276 | − } | |
| 277 | − if (dostring(L, chunk, "=(command line)") != 0) | |
| 278 | − return 1; | |
| 279 | − break; | |
| 280 | − } | |
| 281 | − case 'l': { | |
| 282 | − const char *filename = argv[i] + 2; | |
| 283 | − if (*filename == '\0') filename = argv[++i]; | |
| 284 | − if (filename == NULL) { | |
| 285 | − print_usage(); | |
| 286 | − return 1; | |
| 287 | − } | |
| 288 | − if (dolibrary(L, filename)) | |
| 289 | − return 1; /* stop if file fails */ | |
| 290 | − break; | |
| 255 | + | |
| 256 | +static int collectargs (char **argv, int *pi, int *pv, int *pe) { | |
| 257 | + int i; | |
| 258 | + for (i = 1; argv[i] != NULL; i++) { | |
| 259 | + if (argv[i][0] != '-') /* not an option? */ | |
| 260 | + return i; | |
| 261 | + switch (argv[i][1]) { /* option */ | |
| 262 | + case '-': return (argv[i+1] != NULL ? i+1 : 0); | |
| 263 | + case '\0': return i; | |
| 264 | + case 'i': *pi = 1; break; | |
| 265 | + case 'v': *pv = 1; break; | |
| 266 | + case 'e': *pe = 1; /* go through */ | |
| 267 | + case 'l': | |
| 268 | + if (argv[i][2] == '\0') { | |
| 269 | + i++; | |
| 270 | + if (argv[i] == NULL) return -1; | |
| 291 | 271 | } |
| 292 | − default: { | |
| 293 | − clearinteractive(interactive); | |
| 294 | − print_usage(); | |
| 272 | + break; | |
| 273 | + default: return -1; /* invalid option */ | |
| 274 | + } | |
| 275 | + } | |
| 276 | + return 0; | |
| 277 | +} | |
| 278 | + | |
| 279 | + | |
| 280 | +static int runargs (lua_State *L, char **argv, int n) { | |
| 281 | + int i; | |
| 282 | + for (i = 1; i < n; i++) { | |
| 283 | + if (argv[i] == NULL) continue; | |
| 284 | + lua_assert(argv[i][0] == '-'); | |
| 285 | + switch (argv[i][1]) { /* option */ | |
| 286 | + case 'e': { | |
| 287 | + const char *chunk = argv[i] + 2; | |
| 288 | + if (*chunk == '\0') chunk = argv[++i]; | |
| 289 | + lua_assert(chunk != NULL); | |
| 290 | + if (dostring(L, chunk, "=(command line)") != 0) | |
| 295 | 291 | return 1; |
| 296 | − } | |
| 292 | + break; | |
| 297 | 293 | } |
| 298 | − } endloop: | |
| 299 | − if (argv[i] != NULL) { | |
| 300 | − int status; | |
| 301 | − const char *filename = argv[i]; | |
| 302 | − int narg = getargs(L, argc, argv, i); /* collect arguments */ | |
| 303 | − lua_setglobal(L, "arg"); | |
| 304 | − clearinteractive(interactive); | |
| 305 | − status = luaL_loadfile(L, filename); | |
| 306 | − lua_insert(L, -(narg+1)); | |
| 307 | − if (status == 0) | |
| 308 | − status = docall(L, narg, 0); | |
| 309 | − else | |
| 310 | − lua_pop(L, narg); | |
| 311 | − return report(L, status); | |
| 294 | + case 'l': { | |
| 295 | + const char *filename = argv[i] + 2; | |
| 296 | + if (*filename == '\0') filename = argv[++i]; | |
| 297 | + lua_assert(filename != NULL); | |
| 298 | + if (dolibrary(L, filename)) | |
| 299 | + return 1; /* stop if file fails */ | |
| 300 | + break; | |
| 301 | + } | |
| 302 | + default: break; | |
| 312 | 303 | } |
| 313 | 304 | } |
| 314 | 305 | return 0; |
| @@ -334,17 +325,32 @@ struct Smain { · 19 unmodified lines | ||
| 334 | 325 | |
| 335 | 326 | static int pmain (lua_State *L) { |
| 336 | 327 | struct Smain *s = (struct Smain *)lua_touserdata(L, 1); |
| 337 | − int status; | |
| 338 | − int interactive = 1; | |
| 339 | − if (s->argv[0] && s->argv[0][0]) progname = s->argv[0]; | |
| 328 | + char **argv = s->argv; | |
| 329 | + int script; | |
| 330 | + int has_i = 0, has_v = 0, has_e = 0; | |
| 340 | 331 | globalL = L; |
| 332 | + if (argv[0] && argv[0][0]) progname = argv[0]; | |
| 341 | 333 | luaL_openlibs(L); /* open libraries */ |
| 342 | − status = handle_luainit(L); | |
| 343 | − if (status == 0) { | |
| 344 | − status = handle_argv(L, s->argc, s->argv, &interactive); | |
| 345 | − if (status == 0 && interactive) dotty(L); | |
| 334 | + s->status = handle_luainit(L); | |
| 335 | + if (s->status != 0) return 0; | |
| 336 | + script = collectargs(argv, &has_i, &has_v, &has_e); | |
| 337 | + if (script < 0) { /* invalid args? */ | |
| 338 | + print_usage(); | |
| 339 | + s->status = 1; | |
| 340 | + return 0; | |
| 341 | + } | |
| 342 | + if (has_v) print_version(); | |
| 343 | + s->status = runargs(L, argv, (script > 0) ? script : s->argc); | |
| 344 | + if (s->status != 0) return 0; | |
| 345 | + if (script) | |
| 346 | + s->status = handle_script(L, argv, script); | |
| 347 | + if (s->status != 0) return 0; | |
| 348 | + if (has_i) | |
| 349 | + dotty(L); | |
| 350 | + else if (script == 0 && !has_e && !has_v) { | |
| 351 | + if (lua_stdin_is_tty()) dotty(L); | |
| 352 | + else dofile(L, NULL); /* executes stdin as a file */ | |
| 346 | 353 | } |
| 347 | − s->status = status; | |
| 348 | 354 | return 0; |
| 349 | 355 | } |
| 350 | 356 | |