lua.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. ** $Id: lua.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
  3. ** Lua stand-alone interpreter
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <signal.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "lua.h"
  11. #include "luadebug.h"
  12. #include "lualib.h"
  13. #ifdef _POSIX_SOURCE
  14. #include <unistd.h>
  15. #else
  16. static int isatty (int x) { return x==0; } /* assume stdin is a tty */
  17. #endif
  18. #ifndef LUA_PROGNAME
  19. #define LUA_PROGNAME "lua: "
  20. #endif
  21. #ifndef PROMPT
  22. #define PROMPT "> "
  23. #endif
  24. #ifndef LUA_USERINIT
  25. #define LUA_USERINIT(L) openstdlibs(L)
  26. #endif
  27. static lua_State *L = NULL;
  28. typedef void (*handler)(int); /* type for signal actions */
  29. static void laction (int i);
  30. static lua_Hook old_linehook = NULL;
  31. static lua_Hook old_callhook = NULL;
  32. static handler lreset (void) {
  33. return signal(SIGINT, laction);
  34. }
  35. static void lstop (void) {
  36. lua_setlinehook(L, old_linehook);
  37. lua_setcallhook(L, old_callhook);
  38. lreset();
  39. lua_error(L, "interrupted!");
  40. }
  41. static void laction (int i) {
  42. (void)i; /* to avoid warnings */
  43. signal(SIGINT, SIG_DFL); /* if another SIGINT happens before lstop,
  44. terminate process (default action) */
  45. old_linehook = lua_setlinehook(L, (lua_Hook)lstop);
  46. old_callhook = lua_setcallhook(L, (lua_Hook)lstop);
  47. }
  48. static int ldo (int (*f)(lua_State *l, const char *), const char *name,
  49. int clear) {
  50. int res;
  51. handler h = lreset();
  52. int top = lua_gettop(L);
  53. res = f(L, name); /* dostring | dofile */
  54. signal(SIGINT, h); /* restore old action */
  55. if (clear)
  56. lua_settop(L, top); /* remove eventual results */
  57. /* Lua gives no message in such cases, so lua.c provides one */
  58. if (res == LUA_ERRMEM) {
  59. fprintf(stderr, LUA_PROGNAME "memory allocation error\n");
  60. }
  61. else if (res == LUA_ERRERR)
  62. fprintf(stderr, LUA_PROGNAME "error in error message\n");
  63. return res;
  64. }
  65. static void print_message (void) {
  66. fprintf(stderr,
  67. "usage: lua [options]. Available options are:\n"
  68. " - execute stdin as a file\n"
  69. " -c close Lua when exiting\n"
  70. " -e stat execute string `stat'\n"
  71. " -f name execute file `name' with remaining arguments in table `arg'\n"
  72. " -i enter interactive mode with prompt\n"
  73. " -q enter interactive mode without prompt\n"
  74. " -sNUM set stack size to NUM (must be the first option)\n"
  75. " -v print version information\n"
  76. " a=b set global `a' to string `b'\n"
  77. " name execute file `name'\n"
  78. );
  79. }
  80. static void print_version (void) {
  81. printf("%.80s %.80s\n", LUA_VERSION, LUA_COPYRIGHT);
  82. }
  83. static void assign (char *arg) {
  84. char *eq = strchr(arg, '=');
  85. *eq = '\0'; /* spilt `arg' in two strings (name & value) */
  86. lua_pushstring(L, eq+1);
  87. lua_setglobal(L, arg);
  88. }
  89. static void getargs (char *argv[]) {
  90. int i;
  91. lua_newtable(L);
  92. for (i=0; argv[i]; i++) {
  93. /* arg[i] = argv[i] */
  94. lua_pushnumber(L, i);
  95. lua_pushstring(L, argv[i]);
  96. lua_settable(L, -3);
  97. }
  98. /* arg.n = maximum index in table `arg' */
  99. lua_pushnumber(L, i-1);
  100. lua_setstr(L, -2, "n");
  101. }
  102. static int l_getargs (lua_State *l) {
  103. char **argv = (char **)lua_touserdata(l, lua_upvalueindex(1));
  104. getargs(argv);
  105. return 1;
  106. }
  107. static int file_input (const char *argv) {
  108. int result = ldo(lua_dofile, argv, 1);
  109. if (result) {
  110. if (result == LUA_ERRFILE) {
  111. fprintf(stderr, LUA_PROGNAME "cannot execute file ");
  112. perror(argv);
  113. }
  114. return EXIT_FAILURE;
  115. }
  116. else
  117. return EXIT_SUCCESS;
  118. }
  119. /* maximum length of an input line */
  120. #ifndef MAXINPUT
  121. #define MAXINPUT 512
  122. #endif
  123. static const char *get_prompt (int prompt) {
  124. if (!prompt)
  125. return "";
  126. else {
  127. const char *s;
  128. lua_getglobal(L, "_PROMPT");
  129. s = lua_tostring(L, -1);
  130. if (!s) s = PROMPT;
  131. lua_pop(L, 1); /* remove global */
  132. return s;
  133. }
  134. }
  135. static void manual_input (int version, int prompt) {
  136. if (version) print_version();
  137. for (;;) {
  138. int firstline = 1;
  139. int toprint = 0;
  140. fputs(get_prompt(prompt), stdout); /* show prompt */
  141. for(;;) {
  142. char buffer[MAXINPUT];
  143. size_t l;
  144. if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
  145. printf("\n");
  146. return;
  147. }
  148. if (firstline && buffer[0] == '=') {
  149. buffer[0] = ' ';
  150. lua_pushstring(L, "return");
  151. toprint = 1;
  152. }
  153. l = strlen(buffer);
  154. if (buffer[l-1] == '\n' && buffer[l-2] == '\\') {
  155. buffer[l-2] = '\n';
  156. lua_pushlstring(L, buffer, l-1);
  157. }
  158. else {
  159. lua_pushlstring(L, buffer, l);
  160. break;
  161. }
  162. firstline = 0;
  163. }
  164. lua_concat(L, lua_gettop(L));
  165. ldo(lua_dostring, lua_tostring(L, 1), 0);
  166. lua_remove(L, 1); /* remove ran string */
  167. if (toprint && lua_gettop(L) > 0) { /* any result to print? */
  168. lua_getglobal(L, "print");
  169. lua_insert(L, 1);
  170. lua_call(L, lua_gettop(L)-1, 0);
  171. }
  172. else
  173. lua_settop(L, 0); /* remove eventual results */
  174. }
  175. }
  176. static int handle_argv (char *argv[], int *toclose) {
  177. if (*argv == NULL) { /* no more arguments? */
  178. if (isatty(0)) {
  179. manual_input(1, 1);
  180. }
  181. else
  182. ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
  183. }
  184. else { /* other arguments; loop over them */
  185. int i;
  186. for (i = 0; argv[i] != NULL; i++) {
  187. if (argv[i][0] != '-') { /* not an option? */
  188. if (strchr(argv[i], '='))
  189. assign(argv[i]);
  190. else
  191. if (file_input(argv[i]) != EXIT_SUCCESS)
  192. return EXIT_FAILURE; /* stop if file fails */
  193. }
  194. else switch (argv[i][1]) { /* option */
  195. case 0: {
  196. ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
  197. break;
  198. }
  199. case 'i': {
  200. manual_input(0, 1);
  201. break;
  202. }
  203. case 'q': {
  204. manual_input(0, 0);
  205. break;
  206. }
  207. case 'c': {
  208. *toclose = 1;
  209. break;
  210. }
  211. case 'v': {
  212. print_version();
  213. break;
  214. }
  215. case 'e': {
  216. i++;
  217. if (argv[i] == NULL) {
  218. print_message();
  219. return EXIT_FAILURE;
  220. }
  221. if (ldo(lua_dostring, argv[i], 1) != 0) {
  222. fprintf(stderr, LUA_PROGNAME "error running argument `%.99s'\n",
  223. argv[i]);
  224. return EXIT_FAILURE;
  225. }
  226. break;
  227. }
  228. case 'f': {
  229. i++;
  230. if (argv[i] == NULL) {
  231. print_message();
  232. return EXIT_FAILURE;
  233. }
  234. getargs(argv+i); /* collect remaining arguments */
  235. lua_setglobal(L, "arg");
  236. return file_input(argv[i]); /* stop scanning arguments */
  237. }
  238. case 's': {
  239. if (i == 0) break; /* option already handled */
  240. fprintf(stderr,
  241. LUA_PROGNAME "stack size (`-s') must be the first option\n");
  242. return EXIT_FAILURE;
  243. }
  244. default: {
  245. print_message();
  246. return EXIT_FAILURE;
  247. }
  248. }
  249. }
  250. }
  251. return EXIT_SUCCESS;
  252. }
  253. static int getstacksize (int argc, char *argv[]) {
  254. int stacksize = 0;
  255. if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 's') {
  256. stacksize = strtol(&argv[1][2], NULL, 10);
  257. if (stacksize <= 0) {
  258. fprintf(stderr, LUA_PROGNAME "invalid stack size ('%.20s')\n",
  259. &argv[1][2]);
  260. exit(EXIT_FAILURE);
  261. }
  262. }
  263. return stacksize;
  264. }
  265. static void register_getargs (char *argv[]) {
  266. lua_newuserdatabox(L, argv);
  267. lua_pushcclosure(L, l_getargs, 1);
  268. lua_setglobal(L, "getargs");
  269. }
  270. static void openstdlibs (lua_State *l) {
  271. lua_baselibopen(l);
  272. lua_iolibopen(l);
  273. lua_strlibopen(l);
  274. lua_mathlibopen(l);
  275. lua_dblibopen(l);
  276. }
  277. int main (int argc, char *argv[]) {
  278. int status;
  279. int toclose = 0;
  280. L = lua_open(getstacksize(argc, argv)); /* create state */
  281. LUA_USERINIT(L); /* open libraries */
  282. register_getargs(argv); /* create `getargs' function */
  283. status = handle_argv(argv+1, &toclose);
  284. if (toclose)
  285. lua_close(L);
  286. return status;
  287. }