lua.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. * Copyright 2009 by egnite GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*
  35. ** Based on
  36. ** Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp
  37. ** Lua stand-alone interpreter
  38. ** See Copyright Notice in lua.h
  39. */
  40. #include <dev/board.h>
  41. #include <sys/version.h>
  42. #include <sys/heap.h>
  43. #include <sys/timer.h>
  44. #include <sys/confnet.h>
  45. #include <sys/thread.h>
  46. #include <gorp/edline.h>
  47. #include <arpa/inet.h>
  48. #include <pro/dhcp.h>
  49. #include <stdio.h>
  50. #include <io.h>
  51. #include <string.h>
  52. #define lua_c
  53. #include <lua/lua.h>
  54. #include <lua/lauxlib.h>
  55. #include <lua/lualib.h>
  56. #if defined(__AVR_ARCH__) && !defined(__OPTIMIZE__)
  57. int main(void)
  58. {
  59. unsigned long baud = 115200;
  60. /* Initialize the console. */
  61. NutRegisterDevice(&DEV_CONSOLE, 0, 0);
  62. freopen(DEV_CONSOLE.dev_name, "w", stdout);
  63. _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
  64. /* Display banner. */
  65. puts("\nPlease compile the LUA example with optimization enabled\n");
  66. while(1)
  67. NutSleep(100);
  68. }
  69. #else
  70. #ifndef NUTLUA_PARSER_EXCLUDED
  71. #ifdef __AVR__
  72. #define THREAD_LUASTACK 2048
  73. #else
  74. #define THREAD_LUASTACK 8192
  75. #endif
  76. static char lua_line_buffer[LUA_MAXINPUT];
  77. static EDLINE *lua_line_edit;
  78. /*
  79. * Report bad state.
  80. */
  81. static void report(lua_State * L)
  82. {
  83. if (!lua_isnil(L, -1)) {
  84. const char *msg = lua_tostring(L, -1);
  85. if (msg == NULL)
  86. msg = "(error object is not a string)";
  87. fputs(msg, stderr);
  88. fputc('\n', stderr);
  89. fflush(stderr);
  90. lua_pop(L, 1);
  91. }
  92. }
  93. /*
  94. * Perform Lua back trace.
  95. */
  96. static int traceback(lua_State * L)
  97. {
  98. if (!lua_isstring(L, 1)) /* 'message' not a string? */
  99. return 1; /* keep it intact */
  100. lua_getfield(L, LUA_GLOBALSINDEX, "debug");
  101. if (!lua_istable(L, -1)) {
  102. lua_pop(L, 1);
  103. return 1;
  104. }
  105. lua_getfield(L, -1, "traceback");
  106. if (!lua_isfunction(L, -1)) {
  107. lua_pop(L, 2);
  108. return 1;
  109. }
  110. lua_pushvalue(L, 1); /* pass error message */
  111. lua_pushinteger(L, 2); /* skip this function and traceback */
  112. lua_call(L, 2, 1); /* call debug.traceback */
  113. return 1;
  114. }
  115. /*
  116. * Execute the chunk on top of the Lua stack.
  117. */
  118. static int docall(lua_State * L)
  119. {
  120. int status;
  121. int base; /* function index */
  122. /* Retrieve the function index and push the traceback
  123. ** function below the chunk and its arguments. */
  124. base = lua_gettop(L);
  125. lua_pushcfunction(L, traceback);
  126. lua_insert(L, base);
  127. status = lua_pcall(L, 0, LUA_MULTRET, base);
  128. /* Remove the traceback function. */
  129. lua_remove(L, base);
  130. /* Force a complete garbage collection in case of errors. */
  131. if (status)
  132. lua_gc(L, LUA_GCCOLLECT, 0);
  133. return status;
  134. }
  135. /*
  136. * Retrieve the currently valid prompt.
  137. */
  138. static const char *get_prompt(lua_State * L, int firstline)
  139. {
  140. const char *p;
  141. /* Try global settings first. */
  142. lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
  143. p = lua_tostring(L, -1);
  144. if (p == NULL)
  145. p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
  146. lua_pop(L, 1);
  147. return p;
  148. }
  149. /*
  150. * Check if Lua chunk is complete.
  151. */
  152. static int is_complete(lua_State * L, int status)
  153. {
  154. if (status == LUA_ERRSYNTAX) {
  155. size_t lmsg;
  156. const char *msg = lua_tolstring(L, -1, &lmsg);
  157. const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
  158. if (strstr(msg, LUA_QL("<eof>")) == tp) {
  159. lua_pop(L, 1);
  160. return 0;
  161. }
  162. }
  163. return 1;
  164. }
  165. /*
  166. * Get next line of a Lua chunk.
  167. */
  168. static int pushline(lua_State * L, int firstline)
  169. {
  170. int l;
  171. const char *prmt;
  172. /* Display a prompt. */
  173. prmt = get_prompt(L, firstline);
  174. fputs(prmt, stdout);
  175. fflush(stdout);
  176. /* Get a new line from the line editor. */
  177. lua_line_buffer[0] = '\0';
  178. l = EdLineRead(lua_line_edit, lua_line_buffer, LUA_MAXINPUT);
  179. if (l >= 0) {
  180. /* Replace '=' at the beginning with 'return'. */
  181. if (firstline && lua_line_buffer[0] == '=')
  182. lua_pushfstring(L, "return %s", &lua_line_buffer[1]);
  183. else
  184. lua_pushstring(L, lua_line_buffer);
  185. }
  186. return l;
  187. }
  188. /*
  189. * Load complete Lua chunk.
  190. */
  191. static int loadchunk(lua_State * L)
  192. {
  193. int status = -1;
  194. /* Clear Lua stack. */
  195. lua_settop(L, 0);
  196. if (pushline(L, 1) >= 0) {
  197. /* Loop until we have a complete chunk. */
  198. for (;;) {
  199. status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
  200. /* If the line is complete, we are done. */
  201. if (is_complete(L, status))
  202. break;
  203. /* Otherwise try to get another line. */
  204. if (pushline(L, 0) < 0)
  205. return -1;
  206. /* Add a linefeed between the two lines and join them. */
  207. lua_pushliteral(L, "\n");
  208. lua_insert(L, -2);
  209. lua_concat(L, 3);
  210. }
  211. lua_saveline(L, 1);
  212. lua_remove(L, 1);
  213. }
  214. return status;
  215. }
  216. /*
  217. * Lua line processing loop.
  218. */
  219. static int pmain(lua_State * L)
  220. {
  221. int status;
  222. /* Open pre-configured libraries. Garbage collector must be disabled. */
  223. lua_gc(L, LUA_GCSTOP, 0);
  224. luaL_openlibs(L);
  225. lua_gc(L, LUA_GCRESTART, 0);
  226. /* This loop loads Lua chunks and processes them until we get an
  227. ** input error. We may later use Ctrl-C or break to exit the
  228. ** interpreter. Right now this is not supported by our line editor. */
  229. while ((status = loadchunk(L)) != -1) {
  230. /* If everything is OK, execute the chunk. */
  231. if (status == 0)
  232. status = docall(L);
  233. /* Report bad state... */
  234. if (status) {
  235. report(L);
  236. }
  237. /* ...or print result, if any. */
  238. else if (lua_gettop(L) > 0) {
  239. lua_getglobal(L, "print");
  240. lua_insert(L, 1);
  241. if (lua_pcall(L, lua_gettop(L) - 1, 0, 0) != 0) {
  242. fprintf(stderr, lua_pushfstring(L, "error calling "
  243. LUA_QL("print") " (%s)", lua_tostring(L, -1)));
  244. fputc('\n', stderr);
  245. fflush(stderr);
  246. }
  247. }
  248. }
  249. /* Clear Lua stack. */
  250. lua_settop(L, 0);
  251. fputc('\n', stdout);
  252. fflush(stdout);
  253. return 0;
  254. }
  255. /*
  256. * Lua interpreter thread.
  257. */
  258. THREAD(LuaThread, arg)
  259. {
  260. lua_State *L;
  261. for (;;) {
  262. /* Display second banner line here, so we know
  263. ** that everything is up and running. */
  264. printf("Running on Nut/OS %s - %ld bytes free\n", NutVersionString(), (long)NutHeapAvailable());
  265. /* Open the line editor. */
  266. lua_line_edit = EdLineOpen(EDIT_MODE_ECHO | EDIT_MODE_HISTORY);
  267. if (lua_line_edit) {
  268. /* Register VT100 key mapping. This makes the arrow keys
  269. ** work when using a VT100 terminal emulator for input. */
  270. EdLineRegisterKeymap(lua_line_edit, EdLineKeyMapVt100);
  271. /* Create a Lua state. */
  272. L = lua_open();
  273. if (L) {
  274. if (lua_cpcall(L, &pmain, NULL)) {
  275. report(L);
  276. }
  277. /* Release the Lua state. */
  278. lua_close(L);
  279. }
  280. /* Release the line editor. */
  281. EdLineClose(lua_line_edit);
  282. }
  283. }
  284. }
  285. #endif /* NUTLUA_PARSER_EXCLUDED */
  286. /*
  287. * Lua interpreter entry.
  288. */
  289. int main(void)
  290. {
  291. unsigned long baud = 115200;
  292. /* Initialize the console. */
  293. NutRegisterDevice(&DEV_CONSOLE, 0, 0);
  294. freopen(DEV_CONSOLE.dev_name, "w", stdout);
  295. freopen(DEV_CONSOLE.dev_name, "w", stderr);
  296. freopen(DEV_CONSOLE.dev_name, "r", stdin);
  297. _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
  298. /* Display banner. */
  299. puts("\n" LUA_RELEASE " " LUA_COPYRIGHT);
  300. #ifdef NUTLUA_PARSER_EXCLUDED
  301. puts("Error: Stand-alone interpreter requires parser");
  302. #else
  303. #ifdef NUTLUA_IOLIB_TCP
  304. NutRegisterDevice(&DEV_ETHER, 0, 0);
  305. if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
  306. uint8_t mac[6] = { 0x00, 0x06, 0x98, 0x00, 0x00, 0x00 };
  307. if (NutDhcpIfConfig("eth0", mac, 60000)) {
  308. uint32_t ip_addr = inet_addr("192.168.192.100");
  309. uint32_t ip_mask = inet_addr("255.255.255.0");
  310. NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
  311. }
  312. }
  313. printf("Network interface %s\n", inet_ntoa(confnet.cdn_ip_addr));
  314. #endif /* NUTLUA_IOLIB_TCP */
  315. /* Lua is stack hungry and requires to adjust the stack size of our
  316. ** main thread. To get it run on a standard system we create a new
  317. ** thread with sufficient stack space. */
  318. NutThreadCreate("lua", LuaThread, NULL, THREAD_LUASTACK * NUT_THREAD_STACK_MULT + NUT_THREAD_STACK_ADD);
  319. #endif /* NUTLUA_PARSER_EXCLUDED */
  320. /* Nothing left to do here. */
  321. for(;;) {
  322. NutSleep(1000);
  323. }
  324. return 0;
  325. }
  326. #endif