ref: 01d4cb8f03958e86a1c01ce3b2f6fb08df9a89db
dir: /lua9.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h> char flag[] = { ['i'] = 0, /* interactive */ ['v'] = 0, /* print version */ ['w'] = 0, /* enable warnings */ }; void usage(void) { fprint(2, "usage: %s [-ivw] [script] [arg ...]\n", argv0); exits("usage"); } int iscons(int fd) { int n, c; char buf[64]; if(fd2path(fd, buf, sizeof buf) != 0) sysfatal("fd2path: %r"); n = strlen(buf); c = strlen("/dev/cons"); return n >= c && strcmp(buf + n - c, "/dev/cons") == 0; } void luaerror(lua_State *L) { fprint(2, "%s: %s\n", argv0, lua_tostring(L, -1)); lua_pop(L, 1); } int pcallerror(lua_State *L) { const char *m; m = lua_tostring(L, 1); if(m == nil){ if(luaL_callmeta(L, 1, "__tostring") && lua_type(L, -1) == LUA_TSTRING) return 1; else m = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1)); } luaL_traceback(L, L, m, 1); return 1; } int pcall(lua_State *L, int narg, int nres) { int r, base; base = lua_gettop(L) - narg; lua_pushcfunction(L, pcallerror); lua_insert(L, base); r = lua_pcall(L, narg, nres, base); lua_remove(L, base); return r; } int pushargs(lua_State *L) { int i, n; /* Push the 'arg' array to stack */ if(lua_getglobal(L, "arg") != LUA_TTABLE) luaL_error(L, "'arg' is not a table"); n = luaL_len(L, -1); luaL_checkstack(L, n + 1, "too many arguments"); for(i = 1; i <= n; i++) lua_rawgeti(L, -i, i); lua_remove(L, -i); return n; } int runrepl(lua_State *L) { int r, narg; char *ln; Biobuf bin; if(Binit(&bin, 0, OREAD) == -1) sysfatal("Binit: %r"); r = LUA_OK; while(fprint(2, "> "), (ln = Brdstr(&bin, '\n', 1)) != nil){ if(luaL_loadstring(L, ln) != LUA_OK){ luaerror(L); continue; } narg = pushargs(L); if((r = pcall(L, narg, LUA_MULTRET)) != LUA_OK) luaerror(L); } Bterm(&bin); return r; } int runfile(lua_State *L, char *file) { int narg, r; if((r = luaL_loadfile(L, file)) == LUA_OK){ narg = pushargs(L); r = pcall(L, narg, LUA_MULTRET); } if(r != LUA_OK) luaerror(L); return r; } int luamain(lua_State *L) { int argc, i; char **argv, *file; argc = lua_tointeger(L, 1); argv = lua_touserdata(L, 2); file = argv[0]; if(flag['w']) lua_warning(L, "@on", 0); /* Signal for libraries to ignore LUA_* env. vars */ lua_pushboolean(L, 1); lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); luaL_openlibs(L); /* GC in generational mode */ lua_gc(L, LUA_GCGEN, 0, 0); /* Create global 'arg' table */ lua_createtable(L, argc, 0); lua_pushstring(L, argv0); lua_rawseti(L, -2, 0); for(i = 1; i < argc; i++){ lua_pushstring(L, argv[i]); lua_rawseti(L, -2, i); } lua_setglobal(L, "arg"); if(file == nil){ file = "/fd/0"; if(flag['i'] && iscons(0)) file = nil; } if(file != nil) runfile(L, file); if(flag['i']) runrepl(L); lua_pushboolean(L, 1); return 1; } void main(int argc, char *argv[]) { int r, v; lua_State *L; ARGBEGIN{ case 'i': flag['i'] = 1; break; case 'v': flag['v'] = 1; break; case 'w': flag['w'] = 1; break; default: usage(); }ARGEND; if(flag['v']){ print("%s\n", LUA_COPYRIGHT); exits(nil); } setfcr(getfcr() & ~(FPZDIV | FPOVFL | FPINVAL)); if((L = luaL_newstate()) == NULL) sysfatal("out of memory"); lua_pushcfunction(L, luamain); lua_pushinteger(L, argc); lua_pushlightuserdata(L, argv); r = lua_pcall(L, 2, 1, 0); if(r != LUA_OK) luaerror(L); v = lua_toboolean(L, -1); lua_close(L); exits(r == LUA_OK && v == 1 ? nil : "errors"); }