/trunk/Examples/lua/lua.c
C | 438 lines | 339 code | 77 blank | 22 comment | 75 complexity | 0f8e5c22a378034c6f9641b4f49b450f MD5 | raw file
1/* 2** Lua stand-alone interpreter 3** See Copyright Notice in lua.h 4*/ 5 6 7#include <signal.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11 12#define lua_c 13 14#include "lua.h" 15 16#include "lauxlib.h" 17#include "lualib.h" 18 19 20/* 21** generic extra include file 22*/ 23#ifdef LUA_USERCONFIG 24#include LUA_USERCONFIG 25#endif 26 27 28/* 29** definition of `isatty' 30*/ 31#ifdef _POSIX_C_SOURCE 32#include <unistd.h> 33#define stdin_is_tty() isatty(0) 34#else 35#define stdin_is_tty() 1 /* assume stdin is a tty */ 36#endif 37 38 39 40#ifndef PROMPT 41#define PROMPT "> " 42#endif 43 44 45#ifndef PROMPT2 46#define PROMPT2 ">> " 47#endif 48 49#ifndef PROGNAME 50#define PROGNAME "lua" 51#endif 52 53#ifndef lua_userinit 54#define lua_userinit(L) openstdlibs(L) 55#endif 56 57 58#ifndef LUA_EXTRALIBS 59#define LUA_EXTRALIBS /* empty */ 60#endif 61 62 63static lua_State *L = NULL; 64 65static const char *progname = PROGNAME; 66 67extern int Example_Init(lua_State* L); 68 69static const luaL_reg lualibs[] = { 70 {"base", luaopen_base}, 71 {"table", luaopen_table}, 72 {"io", luaopen_io}, 73 {"string", luaopen_string}, 74 {"math", luaopen_math}, 75 {"debug", luaopen_debug}, 76 {"loadlib", luaopen_loadlib}, 77 /* add your libraries here */ 78 {"example", Example_Init}, 79 LUA_EXTRALIBS 80 {NULL, NULL} 81}; 82 83 84 85static void lstop (lua_State *l, lua_Debug *ar) { 86 (void)ar; /* unused arg. */ 87 lua_sethook(l, NULL, 0, 0); 88 luaL_error(l, "interrupted!"); 89} 90 91 92static void laction (int i) { 93 signal(i, SIG_DFL); /* if another SIGINT happens before lstop, 94 terminate process (default action) */ 95 lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); 96} 97 98 99static void print_usage (void) { 100 fprintf(stderr, 101 "usage: %s [options] [script [args]].\n" 102 "Available options are:\n" 103 " - execute stdin as a file\n" 104 " -e stat execute string `stat'\n" 105 " -i enter interactive mode after executing `script'\n" 106 " -l name load and run library `name'\n" 107 " -v show version information\n" 108 " -- stop handling options\n" , 109 progname); 110} 111 112 113static void l_message (const char *pname, const char *msg) { 114 if (pname) fprintf(stderr, "%s: ", pname); 115 fprintf(stderr, "%s\n", msg); 116} 117 118 119static int report (int status) { 120 const char *msg; 121 if (status) { 122 msg = lua_tostring(L, -1); 123 if (msg == NULL) msg = "(error with no message)"; 124 l_message(progname, msg); 125 lua_pop(L, 1); 126 } 127 return status; 128} 129 130 131static int lcall (int narg, int clear) { 132 int status; 133 int base = lua_gettop(L) - narg; /* function index */ 134 lua_pushliteral(L, "_TRACEBACK"); 135 lua_rawget(L, LUA_GLOBALSINDEX); /* get traceback function */ 136 lua_insert(L, base); /* put it under chunk and args */ 137 signal(SIGINT, laction); 138 status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); 139 signal(SIGINT, SIG_DFL); 140 lua_remove(L, base); /* remove traceback function */ 141 return status; 142} 143 144 145static void print_version (void) { 146 l_message(NULL, LUA_VERSION " " LUA_COPYRIGHT); 147} 148 149 150static void getargs (char *argv[], int n) { 151 int i; 152 lua_newtable(L); 153 for (i=0; argv[i]; i++) { 154 lua_pushnumber(L, i - n); 155 lua_pushstring(L, argv[i]); 156 lua_rawset(L, -3); 157 } 158 /* arg.n = maximum index in table `arg' */ 159 lua_pushliteral(L, "n"); 160 lua_pushnumber(L, i-n-1); 161 lua_rawset(L, -3); 162} 163 164 165static int docall (int status) { 166 if (status == 0) status = lcall(0, 1); 167 return report(status); 168} 169 170 171static int file_input (const char *name) { 172 return docall(luaL_loadfile(L, name)); 173} 174 175 176static int dostring (const char *s, const char *name) { 177 return docall(luaL_loadbuffer(L, s, strlen(s), name)); 178} 179 180 181static int load_file (const char *name) { 182 lua_pushliteral(L, "require"); 183 lua_rawget(L, LUA_GLOBALSINDEX); 184 if (!lua_isfunction(L, -1)) { /* no `require' defined? */ 185 lua_pop(L, 1); 186 return file_input(name); 187 } 188 else { 189 lua_pushstring(L, name); 190 return report(lcall(1, 1)); 191 } 192} 193 194 195/* 196** this macro can be used by some `history' system to save lines 197** read in manual input 198*/ 199#ifndef lua_saveline 200#define lua_saveline(L,line) /* empty */ 201#endif 202 203 204/* 205** this macro defines a function to show the prompt and reads the 206** next line for manual input 207*/ 208#ifndef lua_readline 209#define lua_readline(L,prompt) readline(L,prompt) 210 211/* maximum length of an input line */ 212#ifndef MAXINPUT 213#define MAXINPUT 512 214#endif 215 216 217static int readline (lua_State *l, const char *prompt) { 218 static char buffer[MAXINPUT]; 219 if (prompt) { 220 fputs(prompt, stdout); 221 fflush(stdout); 222 } 223 if (fgets(buffer, sizeof(buffer), stdin) == NULL) 224 return 0; /* read fails */ 225 else { 226 lua_pushstring(l, buffer); 227 return 1; 228 } 229} 230 231#endif 232 233 234static const char *get_prompt (int firstline) { 235 const char *p = NULL; 236 lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2"); 237 lua_rawget(L, LUA_GLOBALSINDEX); 238 p = lua_tostring(L, -1); 239 if (p == NULL) p = (firstline ? PROMPT : PROMPT2); 240 lua_pop(L, 1); /* remove global */ 241 return p; 242} 243 244 245static int incomplete (int status) { 246 if (status == LUA_ERRSYNTAX && 247 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) { 248 lua_pop(L, 1); 249 return 1; 250 } 251 else 252 return 0; 253} 254 255 256static int load_string (void) { 257 int status; 258 lua_settop(L, 0); 259 if (lua_readline(L, get_prompt(1)) == 0) /* no input? */ 260 return -1; 261 if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */ 262 lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */ 263 lua_remove(L, -2); /* remove original line */ 264 } 265 for (;;) { /* repeat until gets a complete line */ 266 status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); 267 if (!incomplete(status)) break; /* cannot try to add lines? */ 268 if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */ 269 return -1; 270 lua_concat(L, lua_gettop(L)); /* join lines */ 271 } 272 lua_saveline(L, lua_tostring(L, 1)); 273 lua_remove(L, 1); /* remove line */ 274 return status; 275} 276 277 278static void manual_input (void) { 279 int status; 280 const char *oldprogname = progname; 281 progname = NULL; 282 while ((status = load_string()) != -1) { 283 if (status == 0) status = lcall(0, 0); 284 report(status); 285 if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ 286 lua_getglobal(L, "print"); 287 lua_insert(L, 1); 288 if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) 289 l_message(progname, lua_pushfstring(L, "error calling `print' (%s)", 290 lua_tostring(L, -1))); 291 } 292 } 293 lua_settop(L, 0); /* clear stack */ 294 fputs("\n", stdout); 295 progname = oldprogname; 296} 297 298 299static int handle_argv (char *argv[], int *interactive) { 300 if (argv[1] == NULL) { /* no more arguments? */ 301 if (stdin_is_tty()) { 302 print_version(); 303 manual_input(); 304 } 305 else 306 file_input(NULL); /* executes stdin as a file */ 307 } 308 else { /* other arguments; loop over them */ 309 int i; 310 for (i = 1; argv[i] != NULL; i++) { 311 if (argv[i][0] != '-') break; /* not an option? */ 312 switch (argv[i][1]) { /* option */ 313 case '-': { /* `--' */ 314 if (argv[i][2] != '\0') { 315 print_usage(); 316 return 1; 317 } 318 i++; /* skip this argument */ 319 goto endloop; /* stop handling arguments */ 320 } 321 case '\0': { 322 file_input(NULL); /* executes stdin as a file */ 323 break; 324 } 325 case 'i': { 326 *interactive = 1; 327 break; 328 } 329 case 'v': { 330 print_version(); 331 break; 332 } 333 case 'e': { 334 const char *chunk = argv[i] + 2; 335 if (*chunk == '\0') chunk = argv[++i]; 336 if (chunk == NULL) { 337 print_usage(); 338 return 1; 339 } 340 if (dostring(chunk, "=<command line>") != 0) 341 return 1; 342 break; 343 } 344 case 'l': { 345 const char *filename = argv[i] + 2; 346 if (*filename == '\0') filename = argv[++i]; 347 if (filename == NULL) { 348 print_usage(); 349 return 1; 350 } 351 if (load_file(filename)) 352 return 1; /* stop if file fails */ 353 break; 354 } 355 case 'c': { 356 l_message(progname, "option `-c' is deprecated"); 357 break; 358 } 359 case 's': { 360 l_message(progname, "option `-s' is deprecated"); 361 break; 362 } 363 default: { 364 print_usage(); 365 return 1; 366 } 367 } 368 } endloop: 369 if (argv[i] != NULL) { 370 const char *filename = argv[i]; 371 getargs(argv, i); /* collect arguments */ 372 lua_setglobal(L, "arg"); 373 return file_input(filename); /* stop scanning arguments */ 374 } 375 } 376 return 0; 377} 378 379 380static void openstdlibs (lua_State *l) { 381 const luaL_reg *lib = lualibs; 382 for (; lib->func; lib++) { 383 lib->func(l); /* open library */ 384 lua_settop(l, 0); /* discard any results */ 385 } 386} 387 388 389static int handle_luainit (void) { 390 const char *init = getenv("LUA_INIT"); 391 if (init == NULL) return 0; /* status OK */ 392 else if (init[0] == '@') 393 return file_input(init+1); 394 else 395 return dostring(init, "=LUA_INIT"); 396} 397 398 399struct Smain { 400 int argc; 401 char **argv; 402 int status; 403}; 404 405 406static int pmain (lua_State *l) { 407 struct Smain *s = (struct Smain *)lua_touserdata(l, 1); 408 int status; 409 int interactive = 0; 410 if (s->argv[0] && s->argv[0][0]) progname = s->argv[0]; 411 L = l; 412 lua_userinit(l); /* open libraries */ 413 status = handle_luainit(); 414 if (status == 0) { 415 status = handle_argv(s->argv, &interactive); 416 if (status == 0 && interactive) manual_input(); 417 } 418 s->status = status; 419 return 0; 420} 421 422 423int main (int argc, char *argv[]) { 424 int status; 425 struct Smain s; 426 lua_State *l = lua_open(); /* create state */ 427 if (l == NULL) { 428 l_message(argv[0], "cannot create state: not enough memory"); 429 return EXIT_FAILURE; 430 } 431 s.argc = argc; 432 s.argv = argv; 433 status = lua_cpcall(l, &pmain, &s); 434 report(status); 435 lua_close(l); 436 return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; 437} 438