| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- /*
- * Copyright 2009 by egnite GmbH
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- */
- /*
- ** Based on
- ** Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp
- ** Lua stand-alone interpreter
- ** See Copyright Notice in lua.h
- */
- #include <dev/board.h>
- #include <sys/version.h>
- #include <sys/heap.h>
- #include <sys/timer.h>
- #include <sys/confnet.h>
- #include <sys/thread.h>
- #include <gorp/edline.h>
- #include <arpa/inet.h>
- #include <pro/dhcp.h>
- #include <stdio.h>
- #include <io.h>
- #include <string.h>
- #define lua_c
- #include <lua/lua.h>
- #include <lua/lauxlib.h>
- #include <lua/lualib.h>
- #if defined(__AVR_ARCH__) && !defined(__OPTIMIZE__)
- int main(void)
- {
- unsigned long baud = 115200;
- /* Initialize the console. */
- NutRegisterDevice(&DEV_CONSOLE, 0, 0);
- freopen(DEV_CONSOLE.dev_name, "w", stdout);
- _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
- /* Display banner. */
- puts("\nPlease compile the LUA example with optimization enabled\n");
- while(1)
- NutSleep(100);
- }
- #else
- #ifndef NUTLUA_PARSER_EXCLUDED
- #ifdef __AVR__
- #define THREAD_LUASTACK 2048
- #else
- #define THREAD_LUASTACK 8192
- #endif
- static char lua_line_buffer[LUA_MAXINPUT];
- static EDLINE *lua_line_edit;
- /*
- * Report bad state.
- */
- static void report(lua_State * L)
- {
- if (!lua_isnil(L, -1)) {
- const char *msg = lua_tostring(L, -1);
- if (msg == NULL)
- msg = "(error object is not a string)";
- fputs(msg, stderr);
- fputc('\n', stderr);
- fflush(stderr);
- lua_pop(L, 1);
- }
- }
- /*
- * Perform Lua back trace.
- */
- static int traceback(lua_State * L)
- {
- if (!lua_isstring(L, 1)) /* 'message' not a string? */
- return 1; /* keep it intact */
- lua_getfield(L, LUA_GLOBALSINDEX, "debug");
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- return 1;
- }
- lua_getfield(L, -1, "traceback");
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 2);
- return 1;
- }
- lua_pushvalue(L, 1); /* pass error message */
- lua_pushinteger(L, 2); /* skip this function and traceback */
- lua_call(L, 2, 1); /* call debug.traceback */
- return 1;
- }
- /*
- * Execute the chunk on top of the Lua stack.
- */
- static int docall(lua_State * L)
- {
- int status;
- int base; /* function index */
- /* Retrieve the function index and push the traceback
- ** function below the chunk and its arguments. */
- base = lua_gettop(L);
- lua_pushcfunction(L, traceback);
- lua_insert(L, base);
- status = lua_pcall(L, 0, LUA_MULTRET, base);
- /* Remove the traceback function. */
- lua_remove(L, base);
- /* Force a complete garbage collection in case of errors. */
- if (status)
- lua_gc(L, LUA_GCCOLLECT, 0);
- return status;
- }
- /*
- * Retrieve the currently valid prompt.
- */
- static const char *get_prompt(lua_State * L, int firstline)
- {
- const char *p;
- /* Try global settings first. */
- lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
- p = lua_tostring(L, -1);
- if (p == NULL)
- p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
- lua_pop(L, 1);
- return p;
- }
- /*
- * Check if Lua chunk is complete.
- */
- static int is_complete(lua_State * L, int status)
- {
- if (status == LUA_ERRSYNTAX) {
- size_t lmsg;
- const char *msg = lua_tolstring(L, -1, &lmsg);
- const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
- if (strstr(msg, LUA_QL("<eof>")) == tp) {
- lua_pop(L, 1);
- return 0;
- }
- }
- return 1;
- }
- /*
- * Get next line of a Lua chunk.
- */
- static int pushline(lua_State * L, int firstline)
- {
- int l;
- const char *prmt;
- /* Display a prompt. */
- prmt = get_prompt(L, firstline);
- fputs(prmt, stdout);
- fflush(stdout);
- /* Get a new line from the line editor. */
- lua_line_buffer[0] = '\0';
- l = EdLineRead(lua_line_edit, lua_line_buffer, LUA_MAXINPUT);
- if (l >= 0) {
- /* Replace '=' at the beginning with 'return'. */
- if (firstline && lua_line_buffer[0] == '=')
- lua_pushfstring(L, "return %s", &lua_line_buffer[1]);
- else
- lua_pushstring(L, lua_line_buffer);
- }
- return l;
- }
- /*
- * Load complete Lua chunk.
- */
- static int loadchunk(lua_State * L)
- {
- int status = -1;
- /* Clear Lua stack. */
- lua_settop(L, 0);
- if (pushline(L, 1) >= 0) {
- /* Loop until we have a complete chunk. */
- for (;;) {
- status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
- /* If the line is complete, we are done. */
- if (is_complete(L, status))
- break;
- /* Otherwise try to get another line. */
- if (pushline(L, 0) < 0)
- return -1;
- /* Add a linefeed between the two lines and join them. */
- lua_pushliteral(L, "\n");
- lua_insert(L, -2);
- lua_concat(L, 3);
- }
- lua_saveline(L, 1);
- lua_remove(L, 1);
- }
- return status;
- }
- /*
- * Lua line processing loop.
- */
- static int pmain(lua_State * L)
- {
- int status;
- /* Open pre-configured libraries. Garbage collector must be disabled. */
- lua_gc(L, LUA_GCSTOP, 0);
- luaL_openlibs(L);
- lua_gc(L, LUA_GCRESTART, 0);
- /* This loop loads Lua chunks and processes them until we get an
- ** input error. We may later use Ctrl-C or break to exit the
- ** interpreter. Right now this is not supported by our line editor. */
- while ((status = loadchunk(L)) != -1) {
- /* If everything is OK, execute the chunk. */
- if (status == 0)
- status = docall(L);
- /* Report bad state... */
- if (status) {
- report(L);
- }
- /* ...or print result, if any. */
- else if (lua_gettop(L) > 0) {
- lua_getglobal(L, "print");
- lua_insert(L, 1);
- if (lua_pcall(L, lua_gettop(L) - 1, 0, 0) != 0) {
- fprintf(stderr, lua_pushfstring(L, "error calling "
- LUA_QL("print") " (%s)", lua_tostring(L, -1)));
- fputc('\n', stderr);
- fflush(stderr);
- }
- }
- }
- /* Clear Lua stack. */
- lua_settop(L, 0);
- fputc('\n', stdout);
- fflush(stdout);
- return 0;
- }
- /*
- * Lua interpreter thread.
- */
- THREAD(LuaThread, arg)
- {
- lua_State *L;
- for (;;) {
- /* Display second banner line here, so we know
- ** that everything is up and running. */
- printf("Running on Nut/OS %s - %ld bytes free\n", NutVersionString(), (long)NutHeapAvailable());
- /* Open the line editor. */
- lua_line_edit = EdLineOpen(EDIT_MODE_ECHO | EDIT_MODE_HISTORY);
- if (lua_line_edit) {
- /* Register VT100 key mapping. This makes the arrow keys
- ** work when using a VT100 terminal emulator for input. */
- EdLineRegisterKeymap(lua_line_edit, EdLineKeyMapVt100);
- /* Create a Lua state. */
- L = lua_open();
- if (L) {
- if (lua_cpcall(L, &pmain, NULL)) {
- report(L);
- }
- /* Release the Lua state. */
- lua_close(L);
- }
- /* Release the line editor. */
- EdLineClose(lua_line_edit);
- }
- }
- }
- #endif /* NUTLUA_PARSER_EXCLUDED */
- /*
- * Lua interpreter entry.
- */
- int main(void)
- {
- unsigned long baud = 115200;
- /* Initialize the console. */
- NutRegisterDevice(&DEV_CONSOLE, 0, 0);
- freopen(DEV_CONSOLE.dev_name, "w", stdout);
- freopen(DEV_CONSOLE.dev_name, "w", stderr);
- freopen(DEV_CONSOLE.dev_name, "r", stdin);
- _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
- /* Display banner. */
- puts("\n" LUA_RELEASE " " LUA_COPYRIGHT);
- #ifdef NUTLUA_PARSER_EXCLUDED
- puts("Error: Stand-alone interpreter requires parser");
- #else
- #ifdef NUTLUA_IOLIB_TCP
- NutRegisterDevice(&DEV_ETHER, 0, 0);
- if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
- uint8_t mac[6] = { 0x00, 0x06, 0x98, 0x00, 0x00, 0x00 };
- if (NutDhcpIfConfig("eth0", mac, 60000)) {
- uint32_t ip_addr = inet_addr("192.168.192.100");
- uint32_t ip_mask = inet_addr("255.255.255.0");
- NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
- }
- }
- printf("Network interface %s\n", inet_ntoa(confnet.cdn_ip_addr));
- #endif /* NUTLUA_IOLIB_TCP */
- /* Lua is stack hungry and requires to adjust the stack size of our
- ** main thread. To get it run on a standard system we create a new
- ** thread with sufficient stack space. */
- NutThreadCreate("lua", LuaThread, NULL, THREAD_LUASTACK * NUT_THREAD_STACK_MULT + NUT_THREAD_STACK_ADD);
- #endif /* NUTLUA_PARSER_EXCLUDED */
- /* Nothing left to do here. */
- for(;;) {
- NutSleep(1000);
- }
- return 0;
- }
- #endif
|