00001
00002
00003
00004
00005
00006
00007
00008 #include <signal.h>
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012
00013 #define lua_c
00014
00015 #include "lua.h"
00016
00017 #include "lauxlib.h"
00018 #include "lualib.h"
00019
00020
00021
00022 static lua_State *globalL = NULL;
00023
00024 static const char *progname = LUA_PROGNAME;
00025
00026
00027
00028 static void lstop (lua_State *L, lua_Debug *ar) {
00029 (void)ar;
00030 lua_sethook(L, NULL, 0, 0);
00031 luaL_error(L, "interrupted!");
00032 }
00033
00034
00035 static void laction (int i) {
00036 signal(i, SIG_DFL);
00037
00038 lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
00039 }
00040
00041
00042 static void print_usage (void) {
00043 fprintf(stderr,
00044 "usage: %s [options] [script [args]].\n"
00045 "Available options are:\n"
00046 " -e stat execute string " LUA_QL("stat") "\n"
00047 " -l name require library " LUA_QL("name") "\n"
00048 " -i enter interactive mode after executing " LUA_QL("script") "\n"
00049 " -v show version information\n"
00050 " -- stop handling options\n"
00051 " - execute stdin and stop handling options\n"
00052 ,
00053 progname);
00054 fflush(stderr);
00055 }
00056
00057
00058 static void l_message (const char *pname, const char *msg) {
00059 if (pname) fprintf(stderr, "%s: ", pname);
00060 fprintf(stderr, "%s\n", msg);
00061 fflush(stderr);
00062 }
00063
00064
00065 static int report (lua_State *L, int status) {
00066 if (status && !lua_isnil(L, -1)) {
00067 const char *msg = lua_tostring(L, -1);
00068 if (msg == NULL) msg = "(error object is not a string)";
00069 l_message(progname, msg);
00070 lua_pop(L, 1);
00071 }
00072 return status;
00073 }
00074
00075
00076 static int traceback (lua_State *L) {
00077 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
00078 if (!lua_istable(L, -1)) {
00079 lua_pop(L, 1);
00080 return 1;
00081 }
00082 lua_getfield(L, -1, "traceback");
00083 if (!lua_isfunction(L, -1)) {
00084 lua_pop(L, 2);
00085 return 1;
00086 }
00087 lua_pushvalue(L, 1);
00088 lua_pushinteger(L, 2);
00089 lua_call(L, 2, 1);
00090 return 1;
00091 }
00092
00093
00094 static int docall (lua_State *L, int narg, int clear) {
00095 int status;
00096 int base = lua_gettop(L) - narg;
00097 lua_pushcfunction(L, traceback);
00098 lua_insert(L, base);
00099 signal(SIGINT, laction);
00100 status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
00101 signal(SIGINT, SIG_DFL);
00102 lua_remove(L, base);
00103
00104 if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
00105 return status;
00106 }
00107
00108
00109 static void print_version (void) {
00110 l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
00111 }
00112
00113
00114 static int getargs (lua_State *L, char **argv, int n) {
00115 int narg;
00116 int i;
00117 int argc = 0;
00118 while (argv[argc]) argc++;
00119 narg = argc - (n + 1);
00120 luaL_checkstack(L, narg + 3, "too many arguments to script");
00121 for (i=n+1; i < argc; i++)
00122 lua_pushstring(L, argv[i]);
00123 lua_createtable(L, narg, n + 1);
00124 for (i=0; i < argc; i++) {
00125 lua_pushstring(L, argv[i]);
00126 lua_rawseti(L, -2, i - n);
00127 }
00128 return narg;
00129 }
00130
00131
00132 static int dofile (lua_State *L, const char *name) {
00133 int status = luaL_loadfile(L, name) || docall(L, 0, 1);
00134 return report(L, status);
00135 }
00136
00137
00138 static int dostring (lua_State *L, const char *s, const char *name) {
00139 int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
00140 return report(L, status);
00141 }
00142
00143
00144 static int dolibrary (lua_State *L, const char *name) {
00145 lua_getglobal(L, "require");
00146 lua_pushstring(L, name);
00147 return report(L, lua_pcall(L, 1, 0, 0));
00148 }
00149
00150
00151 static const char *get_prompt (lua_State *L, int firstline) {
00152 const char *p;
00153 lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
00154 p = lua_tostring(L, -1);
00155 if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
00156 lua_pop(L, 1);
00157 return p;
00158 }
00159
00160
00161 static int incomplete (lua_State *L, int status) {
00162 if (status == LUA_ERRSYNTAX) {
00163 size_t lmsg;
00164 const char *msg = lua_tolstring(L, -1, &lmsg);
00165 const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
00166 if (strstr(msg, LUA_QL("<eof>")) == tp) {
00167 lua_pop(L, 1);
00168 return 1;
00169 }
00170 }
00171 return 0;
00172 }
00173
00174
00175 static int pushline (lua_State *L, int firstline) {
00176 char buffer[LUA_MAXINPUT];
00177 char *b = buffer;
00178 size_t l;
00179 const char *prmt = get_prompt(L, firstline);
00180 if (lua_readline(L, b, prmt) == 0)
00181 return 0;
00182 l = strlen(b);
00183 if (l > 0 && b[l-1] == '\n')
00184 b[l-1] = '\0';
00185 if (firstline && b[0] == '=')
00186 lua_pushfstring(L, "return %s", b+1);
00187 else
00188 lua_pushstring(L, b);
00189 lua_freeline(L, b);
00190 return 1;
00191 }
00192
00193
00194 static int loadline (lua_State *L) {
00195 int status;
00196 lua_settop(L, 0);
00197 if (!pushline(L, 1))
00198 return -1;
00199 for (;;) {
00200 status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
00201 if (!incomplete(L, status)) break;
00202 if (!pushline(L, 0))
00203 return -1;
00204 lua_pushliteral(L, "\n");
00205 lua_insert(L, -2);
00206 lua_concat(L, 3);
00207 }
00208 lua_saveline(L, 1);
00209 lua_remove(L, 1);
00210 return status;
00211 }
00212
00213
00214 static void dotty (lua_State *L) {
00215 int status;
00216 const char *oldprogname = progname;
00217 progname = NULL;
00218 while ((status = loadline(L)) != -1) {
00219 if (status == 0) status = docall(L, 0, 0);
00220 report(L, status);
00221 if (status == 0 && lua_gettop(L) > 0) {
00222 lua_getglobal(L, "print");
00223 lua_insert(L, 1);
00224 if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
00225 l_message(progname, lua_pushfstring(L,
00226 "error calling " LUA_QL("print") " (%s)",
00227 lua_tostring(L, -1)));
00228 }
00229 }
00230 lua_settop(L, 0);
00231 fputs("\n", stdout);
00232 fflush(stdout);
00233 progname = oldprogname;
00234 }
00235
00236
00237 static int handle_script (lua_State *L, char **argv, int n) {
00238 int status;
00239 const char *fname;
00240 int narg = getargs(L, argv, n);
00241 lua_setglobal(L, "arg");
00242 fname = argv[n];
00243 if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
00244 fname = NULL;
00245 status = luaL_loadfile(L, fname);
00246 lua_insert(L, -(narg+1));
00247 if (status == 0)
00248 status = docall(L, narg, 0);
00249 else
00250 lua_pop(L, narg);
00251 return report(L, status);
00252 }
00253
00254
00255
00256 #define notail(x) {if ((x)[2] != '\0') return -1;}
00257
00258
00259 static int collectargs (char **argv, int *pi, int *pv, int *pe) {
00260 int i;
00261 for (i = 1; argv[i] != NULL; i++) {
00262 if (argv[i][0] != '-')
00263 return i;
00264 switch (argv[i][1]) {
00265 case '-':
00266 notail(argv[i]);
00267 return (argv[i+1] != NULL ? i+1 : 0);
00268 case '\0':
00269 return i;
00270 case 'i':
00271 notail(argv[i]);
00272 *pi = 1;
00273 case 'v':
00274 notail(argv[i]);
00275 *pv = 1;
00276 break;
00277 case 'e':
00278 *pe = 1;
00279 case 'l':
00280 if (argv[i][2] == '\0') {
00281 i++;
00282 if (argv[i] == NULL) return -1;
00283 }
00284 break;
00285 default: return -1;
00286 }
00287 }
00288 return 0;
00289 }
00290
00291
00292 static int runargs (lua_State *L, char **argv, int n) {
00293 int i;
00294 for (i = 1; i < n; i++) {
00295 if (argv[i] == NULL) continue;
00296 lua_assert(argv[i][0] == '-');
00297 switch (argv[i][1]) {
00298 case 'e': {
00299 const char *chunk = argv[i] + 2;
00300 if (*chunk == '\0') chunk = argv[++i];
00301 lua_assert(chunk != NULL);
00302 if (dostring(L, chunk, "=(command line)") != 0)
00303 return 1;
00304 break;
00305 }
00306 case 'l': {
00307 const char *filename = argv[i] + 2;
00308 if (*filename == '\0') filename = argv[++i];
00309 lua_assert(filename != NULL);
00310 if (dolibrary(L, filename))
00311 return 1;
00312 break;
00313 }
00314 default: break;
00315 }
00316 }
00317 return 0;
00318 }
00319
00320
00321 static int handle_luainit (lua_State *L) {
00322 const char *init = getenv(LUA_INIT);
00323 if (init == NULL) return 0;
00324 else if (init[0] == '@')
00325 return dofile(L, init+1);
00326 else
00327 return dostring(L, init, "=" LUA_INIT);
00328 }
00329
00330
00331 struct Smain {
00332 int argc;
00333 char **argv;
00334 int status;
00335 };
00336
00337
00338 static int pmain (lua_State *L) {
00339 struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
00340 char **argv = s->argv;
00341 int script;
00342 int has_i = 0, has_v = 0, has_e = 0;
00343 globalL = L;
00344 if (argv[0] && argv[0][0]) progname = argv[0];
00345 lua_gc(L, LUA_GCSTOP, 0);
00346 luaL_openlibs(L);
00347 lua_gc(L, LUA_GCRESTART, 0);
00348 s->status = handle_luainit(L);
00349 if (s->status != 0) return 0;
00350 script = collectargs(argv, &has_i, &has_v, &has_e);
00351 if (script < 0) {
00352 print_usage();
00353 s->status = 1;
00354 return 0;
00355 }
00356 if (has_v) print_version();
00357 s->status = runargs(L, argv, (script > 0) ? script : s->argc);
00358 if (s->status != 0) return 0;
00359 if (script)
00360 s->status = handle_script(L, argv, script);
00361 if (s->status != 0) return 0;
00362 if (has_i)
00363 dotty(L);
00364 else if (script == 0 && !has_e && !has_v) {
00365 if (lua_stdin_is_tty()) {
00366 print_version();
00367 dotty(L);
00368 }
00369 else dofile(L, NULL);
00370 }
00371 return 0;
00372 }
00373
00374
00375 int main (int argc, char **argv) {
00376 int status;
00377 struct Smain s;
00378 lua_State *L = lua_open();
00379 if (L == NULL) {
00380 l_message(argv[0], "cannot create state: not enough memory");
00381 return EXIT_FAILURE;
00382 }
00383 s.argc = argc;
00384 s.argv = argv;
00385 status = lua_cpcall(L, &pmain, &s);
00386 report(L, status);
00387 lua_close(L);
00388 return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
00389 }
00390