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