From 8e88e765ee17296a85c5ae372471ed248ce321db Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 19 Apr 2017 11:37:40 +0200 Subject: Mini reorganization --- bam.lua | 3 +- make_cdrom.sh | 16 +- src/bin/bam.lua | 24 -- src/bin/lua/lua.c | 614 ------------------------------------------ src/bin/luac/luac.c | 449 ------------------------------ src/common/include/assert.h | 5 + src/lib/include/assert.h | 5 - src/lib/include/lua/lprefix.h | 1 + src/lib/libc/debug.c | 1 + src/lib/libc/stdio.c | 7 +- src/sysbin/bam.lua | 3 + src/sysbin/login/main.c | 2 +- src/sysbin/lua/lua.c | 614 ++++++++++++++++++++++++++++++++++++++++++ src/sysbin/luac/luac.c | 449 ++++++++++++++++++++++++++++++ src/sysbin/shell/main.c | 3 +- 15 files changed, 1089 insertions(+), 1107 deletions(-) delete mode 100644 src/bin/bam.lua delete mode 100644 src/bin/lua/lua.c delete mode 100644 src/bin/luac/luac.c create mode 100644 src/common/include/assert.h delete mode 100644 src/lib/include/assert.h create mode 120000 src/lib/include/lua/lprefix.h create mode 100644 src/sysbin/lua/lua.c create mode 100644 src/sysbin/luac/luac.c diff --git a/bam.lua b/bam.lua index c1b9254..d3c428a 100644 --- a/bam.lua +++ b/bam.lua @@ -96,7 +96,6 @@ local function cdrom(name, settings) local kernel = require('src/kernel/bam')(settings, common) local lib = require('src/lib/bam')(settings, common) local sysbin = require('src/sysbin/bam')(settings, lib) - local bin = require('src/bin/bam')(settings, lib) if name == "dev" then dev_kernel = kernel @@ -104,7 +103,7 @@ local function cdrom(name, settings) local cdrom = "cdrom." .. name .. ".iso" AddJob(cdrom, "building ISO", "./make_cdrom.sh " .. name) - AddDependency(cdrom, kernel.bin, sysbin, bin, fonts, keymaps) + AddDependency(cdrom, kernel.bin, sysbin, fonts, keymaps) AddDependency(cdrom, Collect('src/syslua/*.lua')) -- diff --git a/make_cdrom.sh b/make_cdrom.sh index 961ae7b..e6ef212 100755 --- a/make_cdrom.sh +++ b/make_cdrom.sh @@ -27,15 +27,13 @@ cp build/$TY/kernel.bin cdrom/boot; $STRIP cdrom/boot/kernel.bin cp build/$TY/sysbin/init.bin cdrom/boot; $STRIP cdrom/boot/init.bin mkdir -p cdrom/sys/bin -for BIN in giosrv.bin login.bin terminal.bin shell.bin; do - cp build/$TY/sysbin/$BIN cdrom/sys/bin - $STRIP cdrom/sys/bin/$BIN -done - -mkdir -p cdrom/bin -for BIN in lua.bin luac.bin; do - cp build/$TY/bin/$BIN cdrom/bin - $STRIP cdrom/bin/$BIN +for BIN in giosrv.bin login.bin terminal.bin shell.bin lua.bin luac.bin; do + if [ -e build/$TY/sysbin/$BIN ]; then + cp build/$TY/sysbin/$BIN cdrom/sys/bin + $STRIP cdrom/sys/bin/$BIN + else + print "Skipping binary $BIN: not found!" + fi done mkdir -p cdrom/sys/fonts diff --git a/src/bin/bam.lua b/src/bin/bam.lua deleted file mode 100644 index d529ece..0000000 --- a/src/bin/bam.lua +++ /dev/null @@ -1,24 +0,0 @@ -return function(s, lib) - local function bin_settings(name) - local s = TableDeepCopy(s.user_settings) - s.link.flags:Add("-T src/lib/linker.ld") - if name == 'lua' or name == 'luac' then - s.cc.includes:Add("src/lib/lua") - end - return s - end - - local function bin_exe(name, deps) - local s = bin_settings(name) - - local src = Collect('src/bin/' .. name .. '/*.c') - local obj = Compile(s, src) - - return Link(s, 'bin/' .. name .. ".bin", {obj, deps}) - end - - return { - bin_exe('lua', {lib.liblua}), - -- bin_exe('luac', {liblua}), - } -end diff --git a/src/bin/lua/lua.c b/src/bin/lua/lua.c deleted file mode 100644 index 8f64451..0000000 --- a/src/bin/lua/lua.c +++ /dev/null @@ -1,614 +0,0 @@ -/* -** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - -// {{ Customization for Kogata -#define LUA_USE_READLINE 1 -// Other customization includes: removing static qualifiers -// }} - -#define lua_c - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - -#if !defined(LUA_INIT_VAR) -#define LUA_INIT_VAR "LUA_INIT" -#endif - -#define LUA_INITVARVERSION \ - LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - - -/* -** lua_stdin_is_tty detects whether the standard input is a 'tty' (that -** is, whether we're running lua interactively). -*/ -#if !defined(lua_stdin_is_tty) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include -#define lua_stdin_is_tty() isatty(0) - -#elif defined(LUA_USE_WINDOWS) /* }{ */ - -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) - -#else /* }{ */ - -/* ISO C definition */ -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ - -#endif /* } */ - -#endif /* } */ - - -/* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. -*/ -#if !defined(lua_readline) /* { */ - -#if defined(LUA_USE_READLINE) /* { */ - -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,line) ((void)L, add_history(line)) -#define lua_freeline(L,b) ((void)L, free(b)) - -#else /* }{ */ - -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,line) { (void)L; (void)line; } -#define lua_freeline(L,b) { (void)L; (void)b; } - -#endif /* } */ - -#endif /* } */ - - - - -lua_State *globalL = NULL; - -const char *progname = LUA_PROGNAME; - - -/* -** Hook set by signal function to stop the interpreter. -*/ -void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); /* reset hook */ - luaL_error(L, "interrupted!"); -} - - -/* -** Function to be called at a C signal. Because a C signal cannot -** just change a Lua state (as there is no proper synchronization), -** this function only sets a hook that, when called, will stop the -** interpreter. -*/ -void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -void print_usage (const char *badoption) { - lua_writestringerror("%s: ", progname); - if (badoption[1] == 'e' || badoption[1] == 'l') - lua_writestringerror("'%s' needs argument\n", badoption); - else - lua_writestringerror("unrecognized option '%s'\n", badoption); - lua_writestringerror( - "usage: %s [options] [script [args]]\n" - "Available options are:\n" - " -e stat execute string 'stat'\n" - " -i enter interactive mode after executing 'script'\n" - " -l name require library 'name'\n" - " -v show version information\n" - " -E ignore environment variables\n" - " -- stop handling options\n" - " - stop handling options and execute stdin\n" - , - progname); -} - - -/* -** Prints an error message, adding the program name in front of it -** (if present) -*/ -void l_message (const char *pname, const char *msg) { - if (pname) lua_writestringerror("%s: ", pname); - lua_writestringerror("%s\n", msg); -} - - -/* -** Check whether 'status' is not OK and, if so, prints the error -** message on the top of the stack. It assumes that the error object -** is a string, as it was either generated by Lua or by 'msghandler'. -*/ -int report (lua_State *L, int status) { - if (status != LUA_OK) { - const char *msg = lua_tostring(L, -1); - l_message(progname, msg); - lua_pop(L, 1); /* remove message */ - } - return status; -} - - -/* -** Message handler used to run all chunks -*/ -int msghandler (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg == NULL) { /* is error object not a string? */ - if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ - lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ - return 1; /* that is the message */ - else - msg = lua_pushfstring(L, "(error object is a %s value)", - luaL_typename(L, 1)); - } - luaL_traceback(L, L, msg, 1); /* append a standard traceback */ - return 1; /* return the traceback */ -} - - -/* -** Interface to 'lua_pcall', which sets appropriate message function -** and C-signal handler. Used to run all chunks. -*/ -int docall (lua_State *L, int narg, int nres) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, msghandler); /* push message handler */ - lua_insert(L, base); /* put it under function and args */ - globalL = L; /* to be available to 'laction' */ - signal(SIGINT, laction); /* set C-signal handler */ - status = lua_pcall(L, narg, nres, base); - signal(SIGINT, SIG_DFL); /* reset C-signal handler */ - lua_remove(L, base); /* remove message handler from the stack */ - return status; -} - - -void print_version (void) { - lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); - lua_writeline(); -} - - -/* -** Create the 'arg' table, which stores all arguments from the -** command line ('argv'). It should be aligned so that, at index 0, -** it has 'argv[script]', which is the script name. The arguments -** to the script (everything after 'script') go to positive indices; -** other arguments (before the script name) go to negative indices. -** If there is no script name, assume interpreter's name as base. -*/ -void createargtable (lua_State *L, char **argv, int argc, int script) { - int i, narg; - if (script == argc) script = 0; /* no script name? */ - narg = argc - (script + 1); /* number of positive indices */ - lua_createtable(L, narg, script + 1); - for (i = 0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - script); - } - lua_setglobal(L, "arg"); -} - - -int dochunk (lua_State *L, int status) { - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -int dofile (lua_State *L, const char *name) { - return dochunk(L, luaL_loadfile(L, name)); -} - - -int dostring (lua_State *L, const char *s, const char *name) { - return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); -} - - -/* -** Calls 'require(name)' and stores the result in a global variable -** with the given name. -*/ -int dolibrary (lua_State *L, const char *name) { - int status; - lua_getglobal(L, "require"); - lua_pushstring(L, name); - status = docall(L, 1, 1); /* call 'require(name)' */ - if (status == LUA_OK) - lua_setglobal(L, name); /* global[name] = require return */ - return report(L, status); -} - - -/* -** Returns the string to be used as a prompt by the interpreter. -*/ -const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - return p; -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - - -/* -** Check whether 'status' signals a syntax error and the error -** message at the top of the stack ends with the above mark for -** incomplete statements. -*/ -int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -/* -** Prompt the user, read a line, and push it into the Lua stack. -*/ -int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); - if (readstatus == 0) - return 0; /* no input (prompt will be popped by caller) */ - lua_pop(L, 1); /* remove prompt */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[--l] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ - lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ - else - lua_pushlstring(L, b, l); - lua_freeline(L, b); - return 1; -} - - -/* -** Try to compile line on the stack as 'return ;'; on return, stack -** has either compiled chunk or original line (if compilation failed). -*/ -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 -*/ -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 */ - } -} - - -/* -** 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. -*/ -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_remove(L, 1); /* remove line from the stack */ - lua_assert(lua_gettop(L) == 1); - return status; -} - - -/* -** Prints (calling the Lua 'print' function) any values on the stack -*/ -void l_print (lua_State *L) { - int n = lua_gettop(L); - if (n > 0) { /* any result to be printed? */ - luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, n, 0, 0) != LUA_OK) - l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", - lua_tostring(L, -1))); - } -} - - -/* -** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and -** print any results. -*/ -void doREPL (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; /* no 'progname' on errors in interactive mode */ - while ((status = loadline(L)) != -1) { - if (status == LUA_OK) - status = docall(L, 0, LUA_MULTRET); - if (status == LUA_OK) l_print(L); - else report(L, status); - } - lua_settop(L, 0); /* clear stack */ - lua_writeline(); - progname = oldprogname; -} - - -/* -** Push on the stack the contents of table 'arg' from 1 to #arg -*/ -int pushargs (lua_State *L) { - int i, n; - if (lua_getglobal(L, "arg") != LUA_TTABLE) - luaL_error(L, "'arg' is not a table"); - n = (int)luaL_len(L, -1); - luaL_checkstack(L, n + 3, "too many arguments to script"); - for (i = 1; i <= n; i++) - lua_rawgeti(L, -i, i); - lua_remove(L, -i); /* remove table from the stack */ - return n; -} - - -int handle_script (lua_State *L, char **argv) { - int status; - const char *fname = argv[0]; - if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - if (status == LUA_OK) { - int n = pushargs(L); /* push arguments to script */ - status = docall(L, n, LUA_MULTRET); - } - return report(L, status); -} - - - -/* bits of various argument indicators in 'args' */ -#define has_error 1 /* bad option */ -#define has_i 2 /* -i */ -#define has_v 4 /* -v */ -#define has_e 8 /* -e */ -#define has_E 16 /* -E */ - -/* -** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code (or an error code if it finds -** any invalid argument). 'first' returns the first not-handled argument -** (either the script name or a bad argument in case of error). -*/ -int collectargs (char **argv, int *first) { - int args = 0; - int i; - for (i = 1; argv[i] != NULL; i++) { - *first = i; - if (argv[i][0] != '-') /* not an option? */ - return args; /* stop handling options */ - switch (argv[i][1]) { /* else check option */ - case '-': /* '--' */ - if (argv[i][2] != '\0') /* extra characters after '--'? */ - return has_error; /* invalid option */ - *first = i + 1; - return args; - case '\0': /* '-' */ - return args; /* script "name" is '-' */ - case 'E': - if (argv[i][2] != '\0') /* extra characters after 1st? */ - return has_error; /* invalid option */ - args |= has_E; - break; - case 'i': - args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ - case 'v': - if (argv[i][2] != '\0') /* extra characters after 1st? */ - return has_error; /* invalid option */ - args |= has_v; - break; - case 'e': - args |= has_e; /* FALLTHROUGH */ - case 'l': /* both options need an argument */ - if (argv[i][2] == '\0') { /* no concatenated argument? */ - i++; /* try next 'argv' */ - if (argv[i] == NULL || argv[i][0] == '-') - return has_error; /* no next argument or it is another option */ - } - break; - default: /* invalid option */ - return has_error; - } - } - *first = i; /* no script name */ - return args; -} - - -/* -** Processes options 'e' and 'l', which involve running Lua code. -** Returns 0 if some code raises an error. -*/ -int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - int option = argv[i][1]; - lua_assert(argv[i][0] == '-'); /* already checked */ - if (option == 'e' || option == 'l') { - int status; - const char *extra = argv[i] + 2; /* both options need an argument */ - if (*extra == '\0') extra = argv[++i]; - lua_assert(extra != NULL); - status = (option == 'e') - ? dostring(L, extra, "=(command line)") - : dolibrary(L, extra); - if (status != LUA_OK) return 0; - } - } - return 1; -} - - -int handle_luainit (lua_State *L) { - const char *name = "=" LUA_INITVARVERSION; - const char *init = getenv(name + 1); - if (init == NULL) { - name = "=" LUA_INIT_VAR; - init = getenv(name + 1); /* try alternative name */ - } - if (init == NULL) return LUA_OK; - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, name); -} - - -/* -** Main body of stand-alone interpreter (to be called in protected mode). -** Reads the options and handles them all. -*/ -int pmain (lua_State *L) { - int argc = (int)lua_tointeger(L, 1); - char **argv = (char **)lua_touserdata(L, 2); - int script; - int args = collectargs(argv, &script); - luaL_checkversion(L); /* check that interpreter has correct version */ - if (argv[0] && argv[0][0]) progname = argv[0]; - if (args == has_error) { /* bad arg? */ - print_usage(argv[script]); /* 'script' has index of bad arg. */ - return 0; - } - if (args & has_v) /* option '-v'? */ - print_version(); - if (args & has_E) { /* option '-E'? */ - lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - luaL_openlibs(L); /* open standard libraries */ - createargtable(L, argv, argc, script); /* create table 'arg' */ - if (!(args & has_E)) { /* no option '-E'? */ - if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ - return 0; /* error running LUA_INIT */ - } - if (!runargs(L, argv, script)) /* execute arguments -e and -l */ - return 0; /* something failed */ - if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script) != LUA_OK) - return 0; - if (args & has_i) /* -i option? */ - doREPL(L); /* do read-eval-print loop */ - else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ - if (lua_stdin_is_tty()) { /* running in interactive mode? */ - print_version(); - doREPL(L); /* do read-eval-print loop */ - } - else dofile(L, NULL); /* executes stdin as a file */ - } - lua_pushboolean(L, 1); /* signal no errors */ - return 1; -} - - -int main (int argc, char **argv) { - int status, result; - lua_State *L = luaL_newstate(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ - lua_pushinteger(L, argc); /* 1st argument */ - lua_pushlightuserdata(L, argv); /* 2nd argument */ - status = lua_pcall(L, 2, 1, 0); /* do the call */ - result = lua_toboolean(L, -1); /* get result */ - report(L, status); - lua_close(L); - return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/src/bin/luac/luac.c b/src/bin/luac/luac.c deleted file mode 100644 index c0c91d0..0000000 --- a/src/bin/luac/luac.c +++ /dev/null @@ -1,449 +0,0 @@ -/* -** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ -** Lua compiler (saves bytecodes to files; also lists bytecodes) -** See Copyright Notice in lua.h -*/ - -#define luac_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include -#include -#include -#include - -#include "lua.h" -#include "lauxlib.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file 'name' (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop+(i)) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - f->sizelineinfo=0; - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=luaL_newstate(); - if (L==NULL) fatal("cannot create state: not enough memory"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,argc); - lua_pushlightuserdata(L,argv); - if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include -#include - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" - -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=tsslen(ts); - printf("%c",'"'); - for (i=0; ik[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMFLT: - { - char buff[100]; - sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); - printf("%s",buff); - if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); - break; - } - case LUA_TNUMINT: - printf(LUA_INTEGER_FMT,ivalue(o)); - break; - case LUA_TSHRSTR: case LUA_TLNGSTR: - PrintString(tsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); - break; - case iABx: - printf("%d",a); - if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); - if (getBMode(o)==OpArgU) printf(" %d",bx); - break; - case iAsBx: - printf("%d %d",a,sbx); - break; - case iAx: - printf("%d",MYK(ax)); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("\t; %s",UPVALNAME(b)); - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABUP: - printf("\t; %s",UPVALNAME(a)); - if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_POW: - case OP_DIV: - case OP_IDIV: - case OP_BAND: - case OP_BOR: - case OP_BXOR: - case OP_SHL: - case OP_SHR: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - case OP_TFORLOOP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); - break; - case OP_EXTRAARG: - printf("\t; "); PrintConstant(f,ax); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; iupvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; ip[i],full); -} diff --git a/src/common/include/assert.h b/src/common/include/assert.h new file mode 100644 index 0000000..655d6f6 --- /dev/null +++ b/src/common/include/assert.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +/* vim: set sts=0 ts=4 sw=4 tw=0 noet :*/ diff --git a/src/lib/include/assert.h b/src/lib/include/assert.h deleted file mode 100644 index 655d6f6..0000000 --- a/src/lib/include/assert.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -/* vim: set sts=0 ts=4 sw=4 tw=0 noet :*/ diff --git a/src/lib/include/lua/lprefix.h b/src/lib/include/lua/lprefix.h new file mode 120000 index 0000000..3c5a9cb --- /dev/null +++ b/src/lib/include/lua/lprefix.h @@ -0,0 +1 @@ +../../lua/lprefix.h \ No newline at end of file diff --git a/src/lib/libc/debug.c b/src/lib/libc/debug.c index f862fe6..d88b204 100644 --- a/src/lib/libc/debug.c +++ b/src/lib/libc/debug.c @@ -4,6 +4,7 @@ #include #include #include +#include void sys_panic(const char* msg, const char* file, int line) { dbg_printf("PANIC in user process\n %s\n at %s:%d\n", msg, file, line); diff --git a/src/lib/libc/stdio.c b/src/lib/libc/stdio.c index dcbcf83..864fb34 100644 --- a/src/lib/libc/stdio.c +++ b/src/lib/libc/stdio.c @@ -322,15 +322,18 @@ int fflush(FILE* stream) { dbg_printf("FFLUSH %p\n", stream); if (!(stream->file_mode & FM_WRITE)) return 0; - if (stream == NULL || stream->fd == 0) return EOF; + if (stream == NULL || stream->fd == 0) { + return EOF; + } if (stream->buf_mode != 0 && stream->out_buf_used > 0) { size_t ret = sc_write(stream->fd, stream->pos, stream->out_buf_used, stream->out_buf); - stream->out_buf_used = 0; if (ret != stream->out_buf_used) { return EOF; } + + stream->out_buf_used = 0; if (!(stream->st.type & (FT_CHARDEV | FT_CHANNEL | FT_DIR))) { stream->pos += ret; } diff --git a/src/sysbin/bam.lua b/src/sysbin/bam.lua index 9e13a8a..c05d8e6 100644 --- a/src/sysbin/bam.lua +++ b/src/sysbin/bam.lua @@ -20,5 +20,8 @@ return function(s, lib) sysbin_exe('login', {lib.libkogata}), sysbin_exe('terminal', {lib.libkogata}), sysbin_exe('shell', {lib.libkogata}), + + sysbin_exe('lua', {lib.liblua}), + -- sysbin_exe('luac', {liblua}), } end diff --git a/src/sysbin/login/main.c b/src/sysbin/login/main.c index d86eb39..2f75dbe 100644 --- a/src/sysbin/login/main.c +++ b/src/sysbin/login/main.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) { if (!ok) PANIC("[login] Could not bind to shell process."); // ok = sc_proc_exec(shell_pid, "sys:/bin/shell.bin"); - ok = sc_proc_exec(shell_pid, "root:/bin/lua.bin"); + ok = sc_proc_exec(shell_pid, "sys:/bin/lua.bin"); if (!ok) PANIC("[login] Could not run shell.bin"); proc_status_t s; diff --git a/src/sysbin/lua/lua.c b/src/sysbin/lua/lua.c new file mode 100644 index 0000000..c67d771 --- /dev/null +++ b/src/sysbin/lua/lua.c @@ -0,0 +1,614 @@ +/* +** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + +// {{ Customization for Kogata +#define LUA_USE_READLINE 1 +// Other customization includes: removing static qualifiers +// }} + +#define lua_c + +#include + + +#include +#include +#include +#include + +#include + +#include +#include + + +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT_VAR) +#define LUA_INIT_VAR "LUA_INIT" +#endif + +#define LUA_INITVARVERSION \ + LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#if !defined(lua_stdin_is_tty) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include +#define lua_stdin_is_tty() isatty(0) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) + +#else /* }{ */ + +/* ISO C definition */ +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ + +#endif /* } */ + +#endif /* } */ + + +/* +** lua_readline defines how to show a prompt and then read a line from +** the standard input. +** lua_saveline defines how to "save" a read line in a "history". +** lua_freeline defines how to free a line read by lua_readline. +*/ +#if !defined(lua_readline) /* { */ + +#if defined(LUA_USE_READLINE) /* { */ + +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,line) ((void)L, add_history(line)) +#define lua_freeline(L,b) ((void)L, free(b)) + +#else /* }{ */ + +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,line) { (void)L; (void)line; } +#define lua_freeline(L,b) { (void)L; (void)b; } + +#endif /* } */ + +#endif /* } */ + + + + +lua_State *globalL = NULL; + +const char *progname = LUA_PROGNAME; + + +/* +** Hook set by signal function to stop the interpreter. +*/ +void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); /* reset hook */ + luaL_error(L, "interrupted!"); +} + + +/* +** Function to be called at a C signal. Because a C signal cannot +** just change a Lua state (as there is no proper synchronization), +** this function only sets a hook that, when called, will stop the +** interpreter. +*/ +void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +void print_usage (const char *badoption) { + lua_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + lua_writestringerror("'%s' needs argument\n", badoption); + else + lua_writestringerror("unrecognized option '%s'\n", badoption); + lua_writestringerror( + "usage: %s [options] [script [args]]\n" + "Available options are:\n" + " -e stat execute string 'stat'\n" + " -i enter interactive mode after executing 'script'\n" + " -l name require library 'name'\n" + " -v show version information\n" + " -E ignore environment variables\n" + " -- stop handling options\n" + " - stop handling options and execute stdin\n" + , + progname); +} + + +/* +** Prints an error message, adding the program name in front of it +** (if present) +*/ +void l_message (const char *pname, const char *msg) { + if (pname) lua_writestringerror("%s: ", pname); + lua_writestringerror("%s\n", msg); +} + + +/* +** Check whether 'status' is not OK and, if so, prints the error +** message on the top of the stack. It assumes that the error object +** is a string, as it was either generated by Lua or by 'msghandler'. +*/ +int report (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = lua_tostring(L, -1); + l_message(progname, msg); + lua_pop(L, 1); /* remove message */ + } + return status; +} + + +/* +** Message handler used to run all chunks +*/ +int msghandler (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg == NULL) { /* is error object not a string? */ + if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ + lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ + return 1; /* that is the message */ + else + msg = lua_pushfstring(L, "(error object is a %s value)", + luaL_typename(L, 1)); + } + luaL_traceback(L, L, msg, 1); /* append a standard traceback */ + return 1; /* return the traceback */ +} + + +/* +** Interface to 'lua_pcall', which sets appropriate message function +** and C-signal handler. Used to run all chunks. +*/ +int docall (lua_State *L, int narg, int nres) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, msghandler); /* push message handler */ + lua_insert(L, base); /* put it under function and args */ + globalL = L; /* to be available to 'laction' */ + signal(SIGINT, laction); /* set C-signal handler */ + status = lua_pcall(L, narg, nres, base); + signal(SIGINT, SIG_DFL); /* reset C-signal handler */ + lua_remove(L, base); /* remove message handler from the stack */ + return status; +} + + +void print_version (void) { + lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + lua_writeline(); +} + + +/* +** Create the 'arg' table, which stores all arguments from the +** command line ('argv'). It should be aligned so that, at index 0, +** it has 'argv[script]', which is the script name. The arguments +** to the script (everything after 'script') go to positive indices; +** other arguments (before the script name) go to negative indices. +** If there is no script name, assume interpreter's name as base. +*/ +void createargtable (lua_State *L, char **argv, int argc, int script) { + int i, narg; + if (script == argc) script = 0; /* no script name? */ + narg = argc - (script + 1); /* number of positive indices */ + lua_createtable(L, narg, script + 1); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - script); + } + lua_setglobal(L, "arg"); +} + + +int dochunk (lua_State *L, int status) { + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +int dofile (lua_State *L, const char *name) { + return dochunk(L, luaL_loadfile(L, name)); +} + + +int dostring (lua_State *L, const char *s, const char *name) { + return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); +} + + +/* +** Calls 'require(name)' and stores the result in a global variable +** with the given name. +*/ +int dolibrary (lua_State *L, const char *name) { + int status; + lua_getglobal(L, "require"); + lua_pushstring(L, name); + status = docall(L, 1, 1); /* call 'require(name)' */ + if (status == LUA_OK) + lua_setglobal(L, name); /* global[name] = require return */ + return report(L, status); +} + + +/* +** Returns the string to be used as a prompt by the interpreter. +*/ +const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + return p; +} + +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + + +/* +** Check whether 'status' signals a syntax error and the error +** message at the top of the stack ends with the above mark for +** incomplete statements. +*/ +int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +/* +** Prompt the user, read a line, and push it into the Lua stack. +*/ +int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + int readstatus = lua_readline(L, b, prmt); + if (readstatus == 0) + return 0; /* no input (prompt will be popped by caller) */ + lua_pop(L, 1); /* remove prompt */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[--l] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ + lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ + else + lua_pushlstring(L, b, l); + lua_freeline(L, b); + return 1; +} + + +/* +** Try to compile line on the stack as 'return ;'; on return, stack +** has either compiled chunk or original line (if compilation failed). +*/ +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 +*/ +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 */ + } +} + + +/* +** 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. +*/ +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_remove(L, 1); /* remove line from the stack */ + lua_assert(lua_gettop(L) == 1); + return status; +} + + +/* +** Prints (calling the Lua 'print' function) any values on the stack +*/ +void l_print (lua_State *L) { + int n = lua_gettop(L); + if (n > 0) { /* any result to be printed? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, n, 0, 0) != LUA_OK) + l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", + lua_tostring(L, -1))); + } +} + + +/* +** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and +** print any results. +*/ +void doREPL (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; /* no 'progname' on errors in interactive mode */ + while ((status = loadline(L)) != -1) { + if (status == LUA_OK) + status = docall(L, 0, LUA_MULTRET); + if (status == LUA_OK) l_print(L); + else report(L, status); + } + lua_settop(L, 0); /* clear stack */ + lua_writeline(); + progname = oldprogname; +} + + +/* +** Push on the stack the contents of table 'arg' from 1 to #arg +*/ +int pushargs (lua_State *L) { + int i, n; + if (lua_getglobal(L, "arg") != LUA_TTABLE) + luaL_error(L, "'arg' is not a table"); + n = (int)luaL_len(L, -1); + luaL_checkstack(L, n + 3, "too many arguments to script"); + for (i = 1; i <= n; i++) + lua_rawgeti(L, -i, i); + lua_remove(L, -i); /* remove table from the stack */ + return n; +} + + +int handle_script (lua_State *L, char **argv) { + int status; + const char *fname = argv[0]; + if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + if (status == LUA_OK) { + int n = pushargs(L); /* push arguments to script */ + status = docall(L, n, LUA_MULTRET); + } + return report(L, status); +} + + + +/* bits of various argument indicators in 'args' */ +#define has_error 1 /* bad option */ +#define has_i 2 /* -i */ +#define has_v 4 /* -v */ +#define has_e 8 /* -e */ +#define has_E 16 /* -E */ + +/* +** Traverses all arguments from 'argv', returning a mask with those +** needed before running any Lua code (or an error code if it finds +** any invalid argument). 'first' returns the first not-handled argument +** (either the script name or a bad argument in case of error). +*/ +int collectargs (char **argv, int *first) { + int args = 0; + int i; + for (i = 1; argv[i] != NULL; i++) { + *first = i; + if (argv[i][0] != '-') /* not an option? */ + return args; /* stop handling options */ + switch (argv[i][1]) { /* else check option */ + case '-': /* '--' */ + if (argv[i][2] != '\0') /* extra characters after '--'? */ + return has_error; /* invalid option */ + *first = i + 1; + return args; + case '\0': /* '-' */ + return args; /* script "name" is '-' */ + case 'E': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_E; + break; + case 'i': + args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ + case 'v': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_v; + break; + case 'e': + args |= has_e; /* FALLTHROUGH */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return has_error; /* no next argument or it is another option */ + } + break; + default: /* invalid option */ + return has_error; + } + } + *first = i; /* no script name */ + return args; +} + + +/* +** Processes options 'e' and 'l', which involve running Lua code. +** Returns 0 if some code raises an error. +*/ +int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + int option = argv[i][1]; + lua_assert(argv[i][0] == '-'); /* already checked */ + if (option == 'e' || option == 'l') { + int status; + const char *extra = argv[i] + 2; /* both options need an argument */ + if (*extra == '\0') extra = argv[++i]; + lua_assert(extra != NULL); + status = (option == 'e') + ? dostring(L, extra, "=(command line)") + : dolibrary(L, extra); + if (status != LUA_OK) return 0; + } + } + return 1; +} + + +int handle_luainit (lua_State *L) { + const char *name = "=" LUA_INITVARVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT_VAR; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, name); +} + + +/* +** Main body of stand-alone interpreter (to be called in protected mode). +** Reads the options and handles them all. +*/ +int pmain (lua_State *L) { + int argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); + int script; + int args = collectargs(argv, &script); + luaL_checkversion(L); /* check that interpreter has correct version */ + if (argv[0] && argv[0][0]) progname = argv[0]; + if (args == has_error) { /* bad arg? */ + print_usage(argv[script]); /* 'script' has index of bad arg. */ + return 0; + } + if (args & has_v) /* option '-v'? */ + print_version(); + if (args & has_E) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + luaL_openlibs(L); /* open standard libraries */ + createargtable(L, argv, argc, script); /* create table 'arg' */ + if (!(args & has_E)) { /* no option '-E'? */ + if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ + return 0; /* error running LUA_INIT */ + } + if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + return 0; /* something failed */ + if (script < argc && /* execute main script (if there is one) */ + handle_script(L, argv + script) != LUA_OK) + return 0; + if (args & has_i) /* -i option? */ + doREPL(L); /* do read-eval-print loop */ + else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + if (lua_stdin_is_tty()) { /* running in interactive mode? */ + print_version(); + doREPL(L); /* do read-eval-print loop */ + } + else dofile(L, NULL); /* executes stdin as a file */ + } + lua_pushboolean(L, 1); /* signal no errors */ + return 1; +} + + +int main (int argc, char **argv) { + int status, result; + lua_State *L = luaL_newstate(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); /* do the call */ + result = lua_toboolean(L, -1); /* get result */ + report(L, status); + lua_close(L); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/src/sysbin/luac/luac.c b/src/sysbin/luac/luac.c new file mode 100644 index 0000000..c0c91d0 --- /dev/null +++ b/src/sysbin/luac/luac.c @@ -0,0 +1,449 @@ +/* +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ +** Lua compiler (saves bytecodes to files; also lists bytecodes) +** See Copyright Notice in lua.h +*/ + +#define luac_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include +#include +#include +#include + +#include "lua.h" +#include "lauxlib.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +static void PrintFunction(const Proto* f, int full); +#define luaU_print PrintFunction + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\n" + " -o name output to file 'name' (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n" + " - stop handling options and process stdin\n" + ,progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i)) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); + f=toproto(L,-1); + for (i=0; ip[i]=toproto(L,i-n-1); + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; + } + f->sizelineinfo=0; + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +static int pmain(lua_State* L) +{ + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=luaL_newstate(); + if (L==NULL) fatal("cannot create state: not enough memory"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,argc); + lua_pushlightuserdata(L,argv); + if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} + +/* +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" + +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=tsslen(ts); + printf("%c",'"'); + for (i=0; ik[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMFLT: + { + char buff[100]; + sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); + printf("%s",buff); + if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); + break; + } + case LUA_TNUMINT: + printf(LUA_INTEGER_FMT,ivalue(o)); + break; + case LUA_TSHRSTR: case LUA_TLNGSTR: + PrintString(tsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_POW: + case OP_DIV: + case OP_IDIV: + case OP_BAND: + case OP_BOR: + case OP_BXOR: + case OP_SHL: + case OP_SHR: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + case OP_TFORLOOP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); + break; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? getstr(f->source) : "=?"; + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) PrintDebug(f); + for (i=0; ip[i],full); +} diff --git a/src/sysbin/shell/main.c b/src/sysbin/shell/main.c index e27b4e9..3f45332 100644 --- a/src/sysbin/shell/main.c +++ b/src/sysbin/shell/main.c @@ -34,9 +34,10 @@ void cat(char* file) { while (true) { size_t r = sc_read(f, p, 128, buf); p += r; - fwrite(buf, r, 1, stdout); + fwrite(buf, 1, r, stdout); if (r < 128) break; } + printf("\n -> %d bytes\n", p); sc_close(f); } else { printf("Could not open file '%s'\n", file); -- cgit v1.2.3