lua.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*
  2. ** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
  3. ** Lua stand-alone interpreter
  4. ** See Copyright Notice in lua.h
  5. */
  6. // #include "c_signal.h"
  7. #include "c_stdio.h"
  8. #include "c_stdlib.h"
  9. #include "c_string.h"
  10. #include "user_interface.h"
  11. #include "user_version.h"
  12. #include "driver/readline.h"
  13. #include "driver/uart.h"
  14. #define lua_c
  15. #include "lua.h"
  16. #include "lauxlib.h"
  17. #include "lualib.h"
  18. #include "legc.h"
  19. #include "os_type.h"
  20. lua_State *globalL = NULL;
  21. lua_Load gLoad;
  22. static const char *progname = LUA_PROGNAME;
  23. #if 0
  24. static void lstop (lua_State *L, lua_Debug *ar) {
  25. (void)ar; /* unused arg. */
  26. lua_sethook(L, NULL, 0, 0);
  27. luaL_error(L, "interrupted!");
  28. }
  29. static void laction (int i) {
  30. // signal(i, SIG_DFL);
  31. /* if another SIGINT happens before lstop,
  32. terminate process (default action) */
  33. lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
  34. }
  35. static void print_usage (void) {
  36. #if defined(LUA_USE_STDIO)
  37. c_fprintf(c_stderr,
  38. #else
  39. luai_writestringerror(
  40. #endif
  41. "usage: %s [options] [script [args]].\n"
  42. "Available options are:\n"
  43. " -e stat execute string " LUA_QL("stat") "\n"
  44. " -l name require library " LUA_QL("name") "\n"
  45. " -m limit set memory limit. (units are in Kbytes)\n"
  46. " -i enter interactive mode after executing " LUA_QL("script") "\n"
  47. " -v show version information\n"
  48. " -- stop handling options\n"
  49. " - execute stdin and stop handling options\n"
  50. ,
  51. progname);
  52. #if defined(LUA_USE_STDIO)
  53. c_fflush(c_stderr);
  54. #endif
  55. }
  56. #endif
  57. static void l_message (const char *pname, const char *msg) {
  58. #if defined(LUA_USE_STDIO)
  59. if (pname) c_fprintf(c_stderr, "%s: ", pname);
  60. c_fprintf(c_stderr, "%s\n", msg);
  61. c_fflush(c_stderr);
  62. #else
  63. if (pname) luai_writestringerror("%s: ", pname);
  64. luai_writestringerror("%s\n", msg);
  65. #endif
  66. }
  67. static int report (lua_State *L, int status) {
  68. if (status && !lua_isnil(L, -1)) {
  69. const char *msg = lua_tostring(L, -1);
  70. if (msg == NULL) msg = "(error object is not a string)";
  71. l_message(progname, msg);
  72. lua_pop(L, 1);
  73. }
  74. return status;
  75. }
  76. static int traceback (lua_State *L) {
  77. if (!lua_isstring(L, 1)) /* 'message' not a string? */
  78. return 1; /* keep it intact */
  79. lua_getfield(L, LUA_GLOBALSINDEX, "debug");
  80. if (!lua_istable(L, -1) && !lua_isrotable(L, -1)) {
  81. lua_pop(L, 1);
  82. return 1;
  83. }
  84. lua_getfield(L, -1, "traceback");
  85. if (!lua_isfunction(L, -1) && !lua_islightfunction(L, -1)) {
  86. lua_pop(L, 2);
  87. return 1;
  88. }
  89. lua_pushvalue(L, 1); /* pass error message */
  90. lua_pushinteger(L, 2); /* skip this function and traceback */
  91. lua_call(L, 2, 1); /* call debug.traceback */
  92. return 1;
  93. }
  94. static int docall (lua_State *L, int narg, int clear) {
  95. int status;
  96. int base = lua_gettop(L) - narg; /* function index */
  97. lua_pushcfunction(L, traceback); /* push traceback function */
  98. lua_insert(L, base); /* put it under chunk and args */
  99. // signal(SIGINT, laction);
  100. status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
  101. // signal(SIGINT, SIG_DFL);
  102. lua_remove(L, base); /* remove traceback function */
  103. /* force a complete garbage collection in case of errors */
  104. if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
  105. return status;
  106. }
  107. static void print_version (lua_State *L) {
  108. lua_pushliteral (L, "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK ");
  109. lua_pushstring (L, SDK_VERSION);
  110. lua_concat (L, 2);
  111. const char *msg = lua_tostring (L, -1);
  112. l_message (NULL, msg);
  113. lua_pop (L, 1);
  114. }
  115. static int getargs (lua_State *L, char **argv, int n) {
  116. int narg;
  117. int i;
  118. int argc = 0;
  119. while (argv[argc]) argc++; /* count total number of arguments */
  120. narg = argc - (n + 1); /* number of arguments to the script */
  121. luaL_checkstack(L, narg + 3, "too many arguments to script");
  122. for (i=n+1; i < argc; i++)
  123. lua_pushstring(L, argv[i]);
  124. lua_createtable(L, narg, n + 1);
  125. for (i=0; i < argc; i++) {
  126. lua_pushstring(L, argv[i]);
  127. lua_rawseti(L, -2, i - n);
  128. }
  129. return narg;
  130. }
  131. #if 0
  132. static int dofile (lua_State *L, const char *name) {
  133. int status = luaL_loadfile(L, name) || docall(L, 0, 1);
  134. return report(L, status);
  135. }
  136. #else
  137. static int dofsfile (lua_State *L, const char *name) {
  138. int status = luaL_loadfsfile(L, name) || docall(L, 0, 1);
  139. return report(L, status);
  140. }
  141. #endif
  142. static int dostring (lua_State *L, const char *s, const char *name) {
  143. int status = luaL_loadbuffer(L, s, c_strlen(s), name) || docall(L, 0, 1);
  144. return report(L, status);
  145. }
  146. static int dolibrary (lua_State *L, const char *name) {
  147. lua_getglobal(L, "require");
  148. lua_pushstring(L, name);
  149. return report(L, docall(L, 1, 1));
  150. }
  151. static const char *get_prompt (lua_State *L, int firstline) {
  152. const char *p;
  153. lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
  154. p = lua_tostring(L, -1);
  155. if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
  156. lua_pop(L, 1); /* remove global */
  157. return p;
  158. }
  159. static int incomplete (lua_State *L, int status) {
  160. if (status == LUA_ERRSYNTAX) {
  161. size_t lmsg;
  162. const char *msg = lua_tolstring(L, -1, &lmsg);
  163. const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
  164. if (c_strstr(msg, LUA_QL("<eof>")) == tp) {
  165. lua_pop(L, 1);
  166. return 1;
  167. }
  168. }
  169. return 0; /* else... */
  170. }
  171. #if 0
  172. static int pushline (lua_State *L, int firstline) {
  173. char buffer[LUA_MAXINPUT];
  174. char *b = buffer;
  175. size_t l;
  176. const char *prmt = get_prompt(L, firstline);
  177. if (lua_readline(L, b, prmt) == 0)
  178. return 0; /* no input */
  179. l = c_strlen(b);
  180. if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
  181. b[l-1] = '\0'; /* remove it */
  182. if (firstline && b[0] == '=') /* first line starts with `=' ? */
  183. lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
  184. else
  185. lua_pushstring(L, b);
  186. lua_freeline(L, b);
  187. return 1;
  188. }
  189. static int loadline (lua_State *L) {
  190. int status;
  191. lua_settop(L, 0);
  192. if (!pushline(L, 1))
  193. return -1; /* no input */
  194. for (;;) { /* repeat until gets a complete line */
  195. status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
  196. if (!incomplete(L, status)) break; /* cannot try to add lines? */
  197. if (!pushline(L, 0)) /* no more input? */
  198. return -1;
  199. lua_pushliteral(L, "\n"); /* add a new line... */
  200. lua_insert(L, -2); /* ...between the two lines */
  201. lua_concat(L, 3); /* join them */
  202. }
  203. lua_saveline(L, 1);
  204. lua_remove(L, 1); /* remove line */
  205. return status;
  206. }
  207. static void dotty (lua_State *L) {
  208. int status;
  209. const char *oldprogname = progname;
  210. progname = NULL;
  211. while ((status = loadline(L)) != -1) {
  212. if (status == 0) status = docall(L, 0, 0);
  213. report(L, status);
  214. if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
  215. lua_getglobal(L, "print");
  216. lua_insert(L, 1);
  217. if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
  218. l_message(progname, lua_pushfstring(L,
  219. "error calling " LUA_QL("print") " (%s)",
  220. lua_tostring(L, -1)));
  221. }
  222. }
  223. lua_settop(L, 0); /* clear stack */
  224. #if defined(LUA_USE_STDIO)
  225. c_fputs("\n", c_stdout);
  226. c_fflush(c_stdout);
  227. #else
  228. luai_writeline();
  229. #endif
  230. progname = oldprogname;
  231. }
  232. static int handle_script (lua_State *L, char **argv, int n) {
  233. int status;
  234. const char *fname;
  235. int narg = getargs(L, argv, n); /* collect arguments */
  236. lua_setglobal(L, "arg");
  237. fname = argv[n];
  238. if (c_strcmp(fname, "-") == 0 && c_strcmp(argv[n-1], "--") != 0)
  239. fname = NULL; /* stdin */
  240. status = luaL_loadfile(L, fname);
  241. lua_insert(L, -(narg+1));
  242. if (status == 0)
  243. status = docall(L, narg, 0);
  244. else
  245. lua_pop(L, narg);
  246. return report(L, status);
  247. }
  248. #endif
  249. /* check that argument has no extra characters at the end */
  250. #define notail(x) {if ((x)[2] != '\0') return -1;}
  251. static int collectargs (char **argv, int *pi, int *pv, int *pe) {
  252. int i;
  253. for (i = 1; argv[i] != NULL; i++) {
  254. if (argv[i][0] != '-') /* not an option? */
  255. return i;
  256. switch (argv[i][1]) { /* option */
  257. case '-':
  258. notail(argv[i]);
  259. return (argv[i+1] != NULL ? i+1 : 0);
  260. case '\0':
  261. return i;
  262. case 'i':
  263. notail(argv[i]);
  264. *pi = 1; /* go through */
  265. case 'v':
  266. notail(argv[i]);
  267. *pv = 1;
  268. break;
  269. case 'e':
  270. *pe = 1; /* go through */
  271. case 'm': /* go through */
  272. case 'l':
  273. if (argv[i][2] == '\0') {
  274. i++;
  275. if (argv[i] == NULL) return -1;
  276. }
  277. break;
  278. default: return -1; /* invalid option */
  279. }
  280. }
  281. return 0;
  282. }
  283. static int runargs (lua_State *L, char **argv, int n) {
  284. int i;
  285. for (i = 1; i < n; i++) {
  286. if (argv[i] == NULL) continue;
  287. lua_assert(argv[i][0] == '-');
  288. switch (argv[i][1]) { /* option */
  289. case 'e': {
  290. const char *chunk = argv[i] + 2;
  291. if (*chunk == '\0') chunk = argv[++i];
  292. lua_assert(chunk != NULL);
  293. if (dostring(L, chunk, "=(command line)") != 0)
  294. return 1;
  295. break;
  296. }
  297. case 'm': {
  298. const char *limit = argv[i] + 2;
  299. int memlimit=0;
  300. if (*limit == '\0') limit = argv[++i];
  301. lua_assert(limit != NULL);
  302. memlimit = c_atoi(limit);
  303. lua_gc(L, LUA_GCSETMEMLIMIT, memlimit);
  304. break;
  305. }
  306. case 'l': {
  307. const char *filename = argv[i] + 2;
  308. if (*filename == '\0') filename = argv[++i];
  309. lua_assert(filename != NULL);
  310. if (dolibrary(L, filename))
  311. return 1; /* stop if file fails */
  312. break;
  313. }
  314. default: break;
  315. }
  316. }
  317. return 0;
  318. }
  319. static int handle_luainit (lua_State *L) {
  320. const char *init = c_getenv(LUA_INIT);
  321. if (init == NULL) return 0; /* status OK */
  322. else if (init[0] == '@')
  323. #if 0
  324. return dofile(L, init+1);
  325. #else
  326. return dofsfile(L, init+1);
  327. #endif
  328. else
  329. return dostring(L, init, "=" LUA_INIT);
  330. }
  331. struct Smain {
  332. int argc;
  333. char **argv;
  334. int status;
  335. };
  336. static int pmain (lua_State *L) {
  337. struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
  338. char **argv = s->argv;
  339. int script;
  340. int has_i = 0, has_v = 0, has_e = 0;
  341. globalL = L;
  342. if (argv[0] && argv[0][0]) progname = argv[0];
  343. lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
  344. luaL_openlibs(L); /* open libraries */
  345. lua_gc(L, LUA_GCRESTART, 0);
  346. print_version(L);
  347. s->status = handle_luainit(L);
  348. #if 0
  349. if (s->status != 0) return 0;
  350. #endif
  351. script = collectargs(argv, &has_i, &has_v, &has_e);
  352. if (script < 0) { /* invalid args? */
  353. #if 0
  354. print_usage();
  355. #endif
  356. s->status = 1;
  357. return 0;
  358. }
  359. // if (has_v) print_version();
  360. s->status = runargs(L, argv, (script > 0) ? script : s->argc);
  361. if (s->status != 0) return 0;
  362. #if 0
  363. if (script)
  364. s->status = handle_script(L, argv, script);
  365. if (s->status != 0) return 0;
  366. if (has_i)
  367. dotty(L);
  368. else if (script == 0 && !has_e && !has_v) {
  369. if (lua_stdin_is_tty()) {
  370. print_version();
  371. dotty(L);
  372. }
  373. else dofile(L, NULL); /* executes stdin as a file */
  374. }
  375. #endif
  376. return 0;
  377. }
  378. static void dojob(lua_Load *load);
  379. static bool readline(lua_Load *load);
  380. char line_buffer[LUA_MAXINPUT];
  381. #ifdef LUA_RPC
  382. int main (int argc, char **argv) {
  383. #else
  384. int lua_main (int argc, char **argv) {
  385. #endif
  386. int status;
  387. struct Smain s;
  388. lua_State *L = lua_open(); /* create state */
  389. if (L == NULL) {
  390. l_message(argv[0], "cannot create state: not enough memory");
  391. return EXIT_FAILURE;
  392. }
  393. s.argc = argc;
  394. s.argv = argv;
  395. status = lua_cpcall(L, &pmain, &s);
  396. report(L, status);
  397. gLoad.L = L;
  398. gLoad.firstline = 1;
  399. gLoad.done = 0;
  400. gLoad.line = line_buffer;
  401. gLoad.len = LUA_MAXINPUT;
  402. gLoad.line_position = 0;
  403. gLoad.prmt = get_prompt(L, 1);
  404. dojob(&gLoad);
  405. NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
  406. legc_set_mode( L, EGC_ALWAYS, 4096 );
  407. // legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
  408. // lua_close(L);
  409. return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
  410. }
  411. void lua_handle_input (bool force)
  412. {
  413. while (gLoad.L && (force || readline (&gLoad)))
  414. {
  415. dojob (&gLoad);
  416. force = false;
  417. }
  418. }
  419. void donejob(lua_Load *load){
  420. lua_close(load->L);
  421. }
  422. static void dojob(lua_Load *load){
  423. size_t l, rs;
  424. int status;
  425. char *b = load->line;
  426. lua_State *L = load->L;
  427. const char *oldprogname = progname;
  428. progname = NULL;
  429. do{
  430. if(load->done == 1){
  431. l = c_strlen(b);
  432. if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
  433. b[l-1] = '\0'; /* remove it */
  434. if (load->firstline && b[0] == '=') /* first line starts with `=' ? */
  435. lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
  436. else
  437. lua_pushstring(L, b);
  438. if(load->firstline != 1){
  439. lua_pushliteral(L, "\n"); /* add a new line... */
  440. lua_insert(L, -2); /* ...between the two lines */
  441. lua_concat(L, 3); /* join them */
  442. }
  443. status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
  444. if (!incomplete(L, status)) { /* cannot try to add lines? */
  445. lua_remove(L, 1); /* remove line */
  446. if (status == 0) {
  447. status = docall(L, 0, 0);
  448. }
  449. report(L, status);
  450. if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
  451. lua_getglobal(L, "print");
  452. lua_insert(L, 1);
  453. if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
  454. l_message(progname, lua_pushfstring(L,
  455. "error calling " LUA_QL("print") " (%s)",
  456. lua_tostring(L, -1)));
  457. }
  458. load->firstline = 1;
  459. load->prmt = get_prompt(L, 1);
  460. lua_settop(L, 0);
  461. /* force a complete garbage collection in case of errors */
  462. if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
  463. } else {
  464. load->firstline = 0;
  465. load->prmt = get_prompt(L, 0);
  466. }
  467. }
  468. }while(0);
  469. progname = oldprogname;
  470. load->done = 0;
  471. load->line_position = 0;
  472. c_memset(load->line, 0, load->len);
  473. c_puts(load->prmt);
  474. }
  475. #ifndef uart_putc
  476. #define uart_putc uart0_putc
  477. #endif
  478. extern bool uart_on_data_cb(const char *buf, size_t len);
  479. extern bool uart0_echo;
  480. extern bool run_input;
  481. extern uint16_t need_len;
  482. extern int16_t end_char;
  483. static char last_nl_char = '\0';
  484. static bool readline(lua_Load *load){
  485. // NODE_DBG("readline() is called.\n");
  486. bool need_dojob = false;
  487. char ch;
  488. while (uart_getc(&ch))
  489. {
  490. if(run_input)
  491. {
  492. char tmp_last_nl_char = last_nl_char;
  493. // reset marker, will be finally set below when newline is processed
  494. last_nl_char = '\0';
  495. /* handle CR & LF characters
  496. filters second char of LF&CR (\n\r) or CR&LF (\r\n) sequences */
  497. if ((ch == '\r' && tmp_last_nl_char == '\n') || // \n\r sequence -> skip \r
  498. (ch == '\n' && tmp_last_nl_char == '\r')) // \r\n sequence -> skip \n
  499. {
  500. continue;
  501. }
  502. /* backspace key */
  503. else if (ch == 0x7f || ch == 0x08)
  504. {
  505. if (load->line_position > 0)
  506. {
  507. if(uart0_echo) uart_putc(0x08);
  508. if(uart0_echo) uart_putc(' ');
  509. if(uart0_echo) uart_putc(0x08);
  510. load->line_position--;
  511. }
  512. load->line[load->line_position] = 0;
  513. continue;
  514. }
  515. /* EOT(ctrl+d) */
  516. // else if (ch == 0x04)
  517. // {
  518. // if (load->line_position == 0)
  519. // // No input which makes lua interpreter close
  520. // donejob(load);
  521. // else
  522. // continue;
  523. // }
  524. /* end of line */
  525. if (ch == '\r' || ch == '\n')
  526. {
  527. last_nl_char = ch;
  528. load->line[load->line_position] = 0;
  529. if(uart0_echo) uart_putc('\n');
  530. uart_on_data_cb(load->line, load->line_position);
  531. if (load->line_position == 0)
  532. {
  533. /* Get a empty line, then go to get a new line */
  534. c_puts(load->prmt);
  535. continue;
  536. } else {
  537. load->done = 1;
  538. need_dojob = true;
  539. break;
  540. }
  541. }
  542. /* other control character or not an acsii character */
  543. // if (ch < 0x20 || ch >= 0x80)
  544. // {
  545. // continue;
  546. // }
  547. /* echo */
  548. if(uart0_echo) uart_putc(ch);
  549. /* it's a large line, discard it */
  550. if ( load->line_position + 1 >= load->len ){
  551. load->line_position = 0;
  552. }
  553. }
  554. load->line[load->line_position] = ch;
  555. load->line_position++;
  556. if(!run_input)
  557. {
  558. if( ((need_len!=0) && (load->line_position >= need_len)) || \
  559. (load->line_position >= load->len) || \
  560. ((end_char>=0) && ((unsigned char)ch==(unsigned char)end_char)) )
  561. {
  562. uart_on_data_cb(load->line, load->line_position);
  563. load->line_position = 0;
  564. }
  565. }
  566. ch = 0;
  567. }
  568. if( (load->line_position > 0) && (!run_input) && (need_len==0) && (end_char<0) )
  569. {
  570. uart_on_data_cb(load->line, load->line_position);
  571. load->line_position = 0;
  572. }
  573. return need_dojob;
  574. }