static int loadline(lua_State *L) { int status; lua_settop(L, 0); if (!pushline(L, 1)) return -1; /* no input */ for (;;) { /* repeat until gets a complete line */ size_t l; const char *line = lua_tolstring(L, 1, &l); status = luaL_loadbuffer(L, line, l, "=stdin"); if (!incomplete(L, status)) break; /* cannot try to add lines? */ if (!pushline(L, 0)) /* no more input? */ return -1; lua_pushliteral(L, "\n"); /* add a new line... */ lua_insert(L, -2); /* ...between the two lines */ lua_concat(L, 3); /* join them */ } lua_saveline(L, 1); lua_remove(L, 1); /* remove line */ return status; }
/*---------------------------------------------------------------------*/ static void dotty(lua_State *L) { TRACE_LUA_FUNC_START(); int status; while (!stop_processing && (status = loadline(L)) != -1) { lua_saveline(L, 1); lua_remove(L, 1); /* remove line */ if (status == 0) status = docall(L, 0, 0); report(L, status); if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ lua_getglobal(L, "print"); lua_insert(L, 1); if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) TRACE_LOG("%s", lua_pushfstring (L, "error calling " LUA_QL("print") " (%s)", lua_tostring(L, -1))); } } lua_settop(L, 0); /* clear stack */ TRACE_FLUSH(); TRACE_LUA_FUNC_END(); }
/* ** Read a line and try to load (compile) it first as an expression (by ** adding "return " in front of it) and second as a statement. Return ** the final status of load/call with the resulting function (if any) ** in the top of the stack. */ static int loadline (lua_State *L) { int status; lua_settop(L, 0); if (!pushline(L, 1)) return -1; /* no input */ if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ status = multiline(L); /* try as command, maybe with continuation lines */ lua_saveline(L, 1); /* keep history */ lua_remove(L, 1); /* remove line from the stack */ lua_assert(lua_gettop(L) == 1); return status; }
/* ** Try to compile line on the stack as 'return <line>;'; on return, stack ** has either compiled chunk or original line (if compilation failed). */ static int addreturn (lua_State *L) { const char *line = lua_tostring(L, -1); /* original line */ const char *retline = lua_pushfstring(L, "return %s;", line); int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); if (status == LUA_OK) { lua_remove(L, -2); /* remove modified line */ if (line[0] != '\0') /* non empty? */ lua_saveline(L, line); /* keep history */ } else lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ return status; }
/* ** Read multiple lines until a complete Lua statement */ static int multiline (lua_State *L) { for (;;) { /* repeat until gets a complete statement */ size_t len; const char *line = lua_tolstring(L, 1, &len); /* get what it has */ int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ if (!incomplete(L, status) || !pushline(L, 0)) { lua_saveline(L, line); /* keep history */ return status; /* cannot or should not try to add continuation line */ } lua_pushliteral(L, "\n"); /* add newline... */ lua_insert(L, -2); /* ...between the two lines */ lua_concat(L, 3); /* join them */ } }
/*---------------------------------------------------------------------*/ static void do_rshell(lua_State *L, char *rshell_args) { TRACE_LUA_FUNC_START(); int csock, status, rc; char input_line[LUA_MAXINPUT]; uint32_t input_len; char msg_back; csock = connect_to_bricks_server(rshell_args); input_len = 0; while (!stop_processing && (status = loadline(L)) != -1) { strcpy(input_line, lua_tostring(L, 1)); input_len = strlen(input_line); input_line[input_len] = REMOTE_LUA_CMD_DELIM; /* next send the entire command */ /* also sending the last char as REMOTE_LUA_CMD_DELIM that serves */ /* as a delimiter */ rc = write(csock, input_line, input_len + 1); if (rc == -1) goto write_error; /* * keep on reading till you get 'REMOTE_LUA_CMD_DELIM' delimiter * or the server closes the socket */ do { rc = read(csock, &msg_back, 1); if (rc <= 0 || msg_back == REMOTE_LUA_CMD_DELIM) break; rc = write(2, &msg_back, 1); } while (1); fflush(stdout); lua_saveline(L, 1); lua_remove(L, 1); /* remove line */ } lua_settop(L, 0); /* clear stack */ TRACE_FLUSH(); TRACE_LUA_FUNC_END(); close(csock); return; write_error: TRACE_ERR("Failed to send message (%s) of len: %d to server!\n", input_line, input_len); }
/* ** Try to compile line on the stack as 'return <line>'; on return, stack ** has either compiled chunk or original line (if compilation failed). */ static int addreturn (lua_State *L) { int status; size_t len; const char *line; lua_pushliteral(L, "return "); lua_pushvalue(L, -2); /* duplicate line */ lua_concat(L, 2); /* new line is "return ..." */ line = lua_tolstring(L, -1, &len); if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) { lua_remove(L, -3); /* remove original line */ line += sizeof("return")/sizeof(char); /* remove 'return' for history */ if (line[0] != '\0') /* non empty? */ lua_saveline(L, line); /* keep history */ } else lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */ return status; }
static int loadline (lua_State *L) { int status; lua_settop(L, 0); if (!pushline(L, 1)) return -1; for (;;) { status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); if (!incomplete(L, status)) break; if (!pushline(L, 0)) return -1; lua_pushliteral(L, "\n"); lua_insert(L, -2); lua_concat(L, 3); } lua_saveline(L, 1); lua_remove(L, 1); return status; }
static int pushline (lua_State *L, int firstline) { char buffer[LUA_MAXINPUT]; char *b = buffer; size_t l; const char *prmt = get_prompt(L, firstline); if (lua_readline(L, b, prmt) == 0) return 0; /* no input */ l = strlen(b); if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ b[l-1] = '\0'; /* remove it */ if (firstline && b[0] == '=') /* first line starts with `=' ? */ lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ else lua_pushstring(L, b); lua_saveline(L, -1); lua_freeline(L, b); return 1; }
static int load_string (void) { int status; lua_settop(L, 0); if (lua_readline(L, get_prompt(1)) == 0) /* no input? */ return -1; if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */ lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */ lua_remove(L, -2); /* remove original line */ } for (;;) { /* repeat until gets a complete line */ status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); if (!incomplete(status)) break; /* cannot try to add lines? */ if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */ return -1; lua_concat(L, lua_gettop(L)); /* join lines */ } lua_saveline(L, lua_tostring(L, 1)); lua_remove(L, 1); /* remove line */ return status; }
void interpreter_exec_interactively (const std::string &prompt) { // STACK: [] while (true) { // STACK: [] std::string input; { char buffer[LUA_MAXINPUT]; char *b = buffer; if (lua_readline(L, b, prompt.c_str()) == 0) { // end of stdin, exit cleanly break; } input = b; } if (input == "") continue; // trim newline if it has one if (input[input.length()-1] == '\n') input.erase(input.length()-1); if (input == "") continue; lua_pushstring(L, input.c_str()); lua_saveline(L, -1); lua_pop(L, 1); /////////// // PARSE // /////////// // first try with 'return' int status = parse_with_return(input, "[interactive]"); if (status == 0) { ///////////// // EXECUTE // ///////////// // STACK: [func] status = execute_code(); if (status == 0) { // STACK: [retvals...] print_stack(); // STACK: [] } else { // STACK: [err] lua_pop(L, 1); // STACK: [] } } else if (status == LUA_ERRSYNTAX) { // STACK: [err] const char *msg = lua_tostring(L, -1); std::cerr << BOLD YELLOW << "Syntax error: " << msg << RESET << std::endl; lua_pop(L, 1); // STACK: [] } else if (status == LUA_ERRMEM) { std::cerr << "ERROR: Out of memory while parsing interactive input." << std::endl; exit(EXIT_FAILURE); } // STACK: [] } // end the 'prompt' line std::cout << std::endl; }