lua.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. ** $Id: lua.c,v 1.72 2001/11/27 20:56:47 roberto Exp $
  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_pushliteral(L, "n");
  100. lua_pushnumber(L, i-1);
  101. lua_settable(L, -3);
  102. }
  103. static int l_getargs (lua_State *l) {
  104. char **argv = (char **)lua_touserdata(l, lua_upvalueindex(1));
  105. getargs(argv);
  106. return 1;
  107. }
  108. static int file_input (const char *argv) {
  109. int result = ldo(lua_dofile, argv, 1);
  110. if (result) {
  111. if (result == LUA_ERRFILE) {
  112. fprintf(stderr, LUA_PROGNAME "cannot execute file ");
  113. perror(argv);
  114. }
  115. return EXIT_FAILURE;
  116. }
  117. else
  118. return EXIT_SUCCESS;
  119. }
  120. /* maximum length of an input line */
  121. #ifndef MAXINPUT
  122. #define MAXINPUT 512
  123. #endif
  124. static const char *get_prompt (int prompt) {
  125. if (!prompt)
  126. return "";
  127. else {
  128. const char *s;
  129. lua_getglobal(L, "_PROMPT");
  130. s = lua_tostring(L, -1);
  131. if (!s) s = PROMPT;
  132. lua_pop(L, 1); /* remove global */
  133. return s;
  134. }
  135. }
  136. static void manual_input (int version, int prompt) {
  137. if (version) print_version();
  138. for (;;) {
  139. int firstline = 1;
  140. int toprint = 0;
  141. fputs(get_prompt(prompt), stdout); /* show prompt */
  142. for(;;) {
  143. char buffer[MAXINPUT];
  144. size_t l;
  145. if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
  146. printf("\n");
  147. return;
  148. }
  149. if (firstline && buffer[0] == '=') {
  150. buffer[0] = ' ';
  151. lua_pushstring(L, "return");
  152. toprint = 1;
  153. }
  154. l = strlen(buffer);
  155. if (buffer[l-1] == '\n' && buffer[l-2] == '\\') {
  156. buffer[l-2] = '\n';
  157. lua_pushlstring(L, buffer, l-1);
  158. }
  159. else {
  160. lua_pushlstring(L, buffer, l);
  161. break;
  162. }
  163. firstline = 0;
  164. }
  165. lua_concat(L, lua_gettop(L));
  166. ldo(lua_dostring, lua_tostring(L, 1), 0);
  167. lua_remove(L, 1); /* remove ran string */
  168. if (toprint && lua_gettop(L) > 0) { /* any result to print? */
  169. lua_getglobal(L, "print");
  170. lua_insert(L, 1);
  171. lua_call(L, lua_gettop(L)-1, 0);
  172. }
  173. else
  174. lua_settop(L, 0); /* remove eventual results */
  175. }
  176. }
  177. static int handle_argv (char *argv[], int *toclose) {
  178. if (*argv == NULL) { /* no more arguments? */
  179. if (isatty(0)) {
  180. manual_input(1, 1);
  181. }
  182. else
  183. ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
  184. }
  185. else { /* other arguments; loop over them */
  186. int i;
  187. for (i = 0; argv[i] != NULL; i++) {
  188. if (argv[i][0] != '-') { /* not an option? */
  189. if (strchr(argv[i], '='))
  190. assign(argv[i]);
  191. else
  192. if (file_input(argv[i]) != EXIT_SUCCESS)
  193. return EXIT_FAILURE; /* stop if file fails */
  194. }
  195. else switch (argv[i][1]) { /* option */
  196. case 0: {
  197. ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
  198. break;
  199. }
  200. case 'i': {
  201. manual_input(0, 1);
  202. break;
  203. }
  204. case 'q': {
  205. manual_input(0, 0);
  206. break;
  207. }
  208. case 'c': {
  209. *toclose = 1;
  210. break;
  211. }
  212. case 'v': {
  213. print_version();
  214. break;
  215. }
  216. case 'e': {
  217. i++;
  218. if (argv[i] == NULL) {
  219. print_message();
  220. return EXIT_FAILURE;
  221. }
  222. if (ldo(lua_dostring, argv[i], 1) != 0) {
  223. fprintf(stderr, LUA_PROGNAME "error running argument `%.99s'\n",
  224. argv[i]);
  225. return EXIT_FAILURE;
  226. }
  227. break;
  228. }
  229. case 'f': {
  230. i++;
  231. if (argv[i] == NULL) {
  232. print_message();
  233. return EXIT_FAILURE;
  234. }
  235. getargs(argv+i); /* collect remaining arguments */
  236. lua_setglobal(L, "arg");
  237. return file_input(argv[i]); /* stop scanning arguments */
  238. }
  239. case 's': {
  240. if (i == 0) break; /* option already handled */
  241. fprintf(stderr,
  242. LUA_PROGNAME "stack size (`-s') must be the first option\n");
  243. return EXIT_FAILURE;
  244. }
  245. default: {
  246. print_message();
  247. return EXIT_FAILURE;
  248. }
  249. }
  250. }
  251. }
  252. return EXIT_SUCCESS;
  253. }
  254. static int getstacksize (int argc, char *argv[]) {
  255. int stacksize = 0;
  256. if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 's') {
  257. stacksize = strtol(&argv[1][2], NULL, 10);
  258. if (stacksize <= 0) {
  259. fprintf(stderr, LUA_PROGNAME "invalid stack size ('%.20s')\n",
  260. &argv[1][2]);
  261. exit(EXIT_FAILURE);
  262. }
  263. }
  264. return stacksize;
  265. }
  266. static void register_getargs (char *argv[]) {
  267. lua_newuserdatabox(L, argv);
  268. lua_pushcclosure(L, l_getargs, 1);
  269. lua_setglobal(L, "getargs");
  270. }
  271. static void openstdlibs (lua_State *l) {
  272. lua_baselibopen(l);
  273. lua_iolibopen(l);
  274. lua_strlibopen(l);
  275. lua_mathlibopen(l);
  276. lua_dblibopen(l);
  277. }
  278. int main (int argc, char *argv[]) {
  279. int status;
  280. int toclose = 0;
  281. L = lua_open(getstacksize(argc, argv)); /* create state */
  282. LUA_USERINIT(L); /* open libraries */
  283. register_getargs(argv); /* create `getargs' function */
  284. status = handle_argv(argv+1, &toclose);
  285. if (toclose)
  286. lua_close(L);
  287. return status;
  288. }