aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2017-04-19 15:34:04 +0200
committerAlex Auvolat <alex@adnab.me>2017-04-19 15:34:04 +0200
commite53a39d9ec28b24ea0d408f1500e987d005cd651 (patch)
tree639c93f2a17aabee7759cd16645b4d7da693ae4c /src
parentd4a89538d381bb62b4c7c864b09d3d8274cf0bdb (diff)
downloadkogata-e53a39d9ec28b24ea0d408f1500e987d005cd651.tar.gz
kogata-e53a39d9ec28b24ea0d408f1500e987d005cd651.zip
Lua shell :)
Diffstat (limited to 'src')
-rw-r--r--src/sysbin/lx/lxinit.c48
-rw-r--r--src/sysbin/lx/lxlib.h15
-rw-r--r--src/sysbin/lx/lxsyslib.c221
-rw-r--r--src/sysbin/lx/main.c50
-rw-r--r--src/syslua/lx/lxinit.lua48
-rw-r--r--src/syslua/lx/shell.lua88
-rw-r--r--src/syslua/lx/sysdef.lua36
7 files changed, 445 insertions, 61 deletions
diff --git a/src/sysbin/lx/lxinit.c b/src/sysbin/lx/lxinit.c
new file mode 100644
index 0000000..c0059c7
--- /dev/null
+++ b/src/sysbin/lx/lxinit.c
@@ -0,0 +1,48 @@
+
+
+#define lxinit_c
+#define LUA_LIB
+
+/*
+** If you embed Lua in your program and need to open the standard
+** libraries, call luaL_openlibs in your program. If you need a
+** different set of libraries, copy this file to your project and edit
+** it to suit your needs.
+**
+** You can also *preload* libraries, so that a later 'require' can
+** open the library, which is already linked to the application.
+** For that, do the following code:
+**
+** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
+** lua_pushcfunction(L, luaopen_modname);
+** lua_setfield(L, -2, modname);
+** lua_pop(L, 1); // remove _PRELOAD table
+*/
+
+#include <lua/lprefix.h>
+
+
+#include <stddef.h>
+
+#include <lua/lua.h>
+
+#include <lua/lualib.h>
+#include <lua/lauxlib.h>
+
+#include "lxlib.h"
+
+
+static const luaL_Reg loadedlibs[] = {
+ {LX_SYSLIBNAME, lx_open_sys},
+ {NULL, NULL}
+};
+
+LUALIB_API void lx_openlibs (lua_State *L) {
+ const luaL_Reg *lib;
+ /* "require" functions from 'loadedlibs' and set results to global table */
+ for (lib = loadedlibs; lib->func; lib++) {
+ luaL_requiref(L, lib->name, lib->func, 1);
+ lua_pop(L, 1); /* remove lib */
+ }
+}
+
diff --git a/src/sysbin/lx/lxlib.h b/src/sysbin/lx/lxlib.h
new file mode 100644
index 0000000..e65ab6f
--- /dev/null
+++ b/src/sysbin/lx/lxlib.h
@@ -0,0 +1,15 @@
+/*
+** Lua eXtended libraries
+*/
+#pragma once
+
+#include <lua/lua.h>
+
+
+#define LX_SYSLIBNAME "lx.sys"
+LUAMOD_API int (lx_open_sys) (lua_State *L);
+
+
+/* open all previous libraries */
+LUALIB_API void (lx_openlibs) (lua_State *L);
+
diff --git a/src/sysbin/lx/lxsyslib.c b/src/sysbin/lx/lxsyslib.c
new file mode 100644
index 0000000..5bfec3e
--- /dev/null
+++ b/src/sysbin/lx/lxsyslib.c
@@ -0,0 +1,221 @@
+/*
+** Lua eXtended system library
+*/
+
+#define lxsyslib_c
+#define LUA_LIB
+
+#include <lua/lprefix.h>
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <lua/lua.h>
+
+#include <lua/lauxlib.h>
+#include <lua/lualib.h>
+
+#include "lxlib.h"
+
+
+
+static void setintfield (lua_State *L, const char *key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static void setstrfield (lua_State *L, const char *key, const char* value) {
+ lua_pushstring(L, value);
+ lua_setfield(L, -2, key);
+}
+
+
+static int sys_dbg_print(lua_State *L) {
+ const char *str = luaL_checkstring(L, 1);
+ sc_dbg_print(str);
+ return 0;
+}
+
+static int sys_yield(lua_State *L) {
+ sc_yield();
+ return 0;
+}
+
+static int sys_exit(lua_State *L) {
+ int code = luaL_checkinteger(L, 1);
+ sc_exit(code);
+ return 0;
+}
+
+static int sys_usleep(lua_State *L) {
+ int usecs = luaL_checkinteger(L, 1);
+ sc_usleep(usecs);
+ return 0;
+}
+
+/*
+ Missing syscalls :
+ - sys_new_thread, exit_thread -> into specific threading library
+ - mmap, mmap_file, mchmap, munmap -> into specific memory-related library ??
+*/
+
+static int sys_create(lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ int type = luaL_checkinteger(L, 2);
+ lua_pushboolean(L, sc_create(name, type));
+ return 1;
+}
+
+static int sys_delete(lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ lua_pushboolean(L, sc_delete(name));
+ return 1;
+}
+
+static int sys_move(lua_State *L) {
+ const char *oldname = luaL_checkstring(L, 1);
+ const char *newname = luaL_checkstring(L, 2);
+ lua_pushboolean(L, sc_move(oldname, newname));
+ return 1;
+}
+
+static int sys_stat(lua_State *L) {
+ const char* name = luaL_checkstring(L, 1);
+ stat_t s;
+ if (sc_stat(name, &s)) {
+ lua_createtable(L, 0, 3);
+ setintfield(L, "type", s.type);
+ setintfield(L, "access", s.access);
+ setintfield(L, "size", s.size);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
+static int sys_open(lua_State *L) {
+ const char* name = luaL_checkstring(L, 1);
+ int mode = luaL_checkinteger(L, 2);
+ fd_t fh = sc_open(name, mode);
+ if (fh) {
+ lua_pushinteger(L, fh);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int sys_close(lua_State *L) {
+ int fd = luaL_checkinteger(L, 1);
+ sc_close(fd);
+ return 0;
+}
+
+static int sys_read(lua_State *L) {
+ int fd = luaL_checkinteger(L, 1);
+ int offset = luaL_checkinteger(L, 2);
+ int len = luaL_checkinteger(L, 3);
+
+ luaL_Buffer b;
+ char* bufptr = luaL_buffinitsize(L, &b, len);
+ int ret = sc_read(fd, offset, len, bufptr);
+
+ luaL_pushresultsize(&b, ret);
+ lua_pushinteger(L, ret);
+ return 2;
+}
+
+static int sys_write(lua_State *L) {
+ int fd = luaL_checkinteger(L, 1);
+ int offset = luaL_checkinteger(L, 2);
+ const char* str = luaL_checkstring(L, 3);
+ int len = luaL_len(L, 3);
+
+ int ret = sc_write(fd, offset, len, str);
+ lua_pushinteger(L, ret);
+ return 1;
+}
+
+static int sys_readdir(lua_State *L) {
+ int fd = luaL_checkinteger(L, 1);
+ int ent_no = luaL_checkinteger(L, 2);
+
+ dirent_t d;
+ bool ret = sc_readdir(fd, ent_no, &d);
+ if (ret) {
+ lua_createtable(L, 0, 4);
+ setstrfield(L, "name", d.name);
+ setintfield(L, "type", d.st.type);
+ setintfield(L, "access", d.st.access);
+ setintfield(L, "size", d.st.size);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int sys_stat_open(lua_State *L) {
+ int fd = luaL_checkinteger(L, 1);
+ stat_t s;
+ if (sc_stat_open(fd, &s)) {
+ lua_createtable(L, 0, 3);
+ setintfield(L, "type", s.type);
+ setintfield(L, "access", s.access);
+ setintfield(L, "size", s.size);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int sys_ioctl(lua_State *L) {
+ // TODO
+ return 0;
+}
+
+static int sys_fctl(lua_State *L) {
+ // TODO
+ return 0;
+}
+
+static int sys_select(lua_State *L) {
+ // TODO
+ return 0;
+}
+
+
+static const luaL_Reg syslib[] = {
+ {"dbg_print", sys_dbg_print},
+ {"yield", sys_yield},
+ {"exit", sys_exit},
+ {"usleep", sys_usleep},
+ {"create", sys_create},
+ {"delete", sys_delete},
+ {"move", sys_move},
+ {"stat", sys_stat},
+ {"open", sys_open},
+ {"close", sys_close},
+ {"read", sys_read},
+ {"write", sys_write},
+ {"readdir", sys_readdir},
+ {"stat_open", sys_stat_open},
+
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUAMOD_API int lx_open_sys (lua_State *L) {
+ luaL_newlib(L, syslib);
+ return 1;
+}
+
+
+/* vim: set sts=2 ts=2 sw=2 tw=0 et :*/
diff --git a/src/sysbin/lx/main.c b/src/sysbin/lx/main.c
index ecfecd8..b7e08d9 100644
--- a/src/sysbin/lx/main.c
+++ b/src/sysbin/lx/main.c
@@ -16,6 +16,8 @@
#include <lua/lauxlib.h>
#include <lua/lualib.h>
+#include "lxlib.h"
+
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
@@ -183,20 +185,6 @@ int dostring (lua_State *L, const char *s, const char *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.
@@ -349,36 +337,6 @@ void doREPL (lua_State *L) {
}
-/*
-** 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);
-}
-
-
int handle_luainit (lua_State *L) {
const char *name = "=" LUA_INITVARVERSION;
@@ -395,10 +353,11 @@ int handle_luainit (lua_State *L) {
int pmain (lua_State *L) {
int status;
luaL_checkversion(L); /* check that interpreter has correct version */
-
+
print_version();
luaL_openlibs(L); /* open standard libraries */
+ lx_openlibs(L);
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
return 0; /* error running LUA_INIT */
@@ -409,7 +368,6 @@ int pmain (lua_State *L) {
if (status != LUA_OK) {
// no main, launch a REPL
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 */
diff --git a/src/syslua/lx/lxinit.lua b/src/syslua/lx/lxinit.lua
index 6b23aa8..1c8d116 100644
--- a/src/syslua/lx/lxinit.lua
+++ b/src/syslua/lx/lxinit.lua
@@ -3,20 +3,38 @@ print "Lua eXtended helpers for Kogata v1"
do
local old_tostring = tostring
function tostring(x)
- if type(x) == "table" then
- if next(x) == nil then
- return '{}'
- end
- local q = '{\n '
- for k, v in pairs(x) do
- if q:len() > 4 then
- q = q .. ',\n '
- end
- q = q .. k .. ': ' .. tostring(v):gsub('\n', '\n ')
- end
- return q .. '\n}'
- else
- return old_tostring(x)
- end
+ local seen = {}
+ function aux(x)
+ if type(x) == "table" then
+ if next(x) == nil then
+ return '{}'
+ end
+
+ if seen[x] then
+ return '...'
+ end
+ seen[x] = true
+
+ local q = '{\n '
+ for k, v in pairs(x) do
+ if q:len() > 4 then
+ q = q .. ',\n '
+ end
+ q = q .. k .. ': ' .. aux(v):gsub('\n', '\n ')
+ end
+ return q .. '\n}'
+ else
+ return old_tostring(x)
+ end
+ end
+ return aux(x)
end
end
+
+
+function string.split(str, sep)
+ local sep, fields = sep or ":", {}
+ local pattern = string.format("([^%s]*)", sep)
+ str:gsub(pattern, function(c) fields[#fields+1] = c end)
+ return fields
+end
diff --git a/src/syslua/lx/shell.lua b/src/syslua/lx/shell.lua
new file mode 100644
index 0000000..62f210f
--- /dev/null
+++ b/src/syslua/lx/shell.lua
@@ -0,0 +1,88 @@
+local sys = require 'lx.sys'
+local sysdef = require 'lx.sysdef'
+
+local _cwd = 'root:/'
+
+function pathcat(path1, path2)
+ assert(path1, "invalid argument")
+ if not path2 then
+ return path1
+ end
+
+ function explode_path(path)
+ local _, _, dr, p = string.find(path, '^(%w+):(.*)$')
+ if not dr or not p then
+ dr, p = nil, path
+ end
+ local pp = string.split(p, '/')
+ if #pp > 1 and pp[#pp] == '' then
+ table.remove(pp)
+ end
+ return dr, pp
+ end
+
+ function implode_path(dr, p)
+ assert(p[1] == '', 'bad first path component')
+ return dr .. ':' .. table.concat(p, '/')
+ end
+
+ local dr2, p2 = explode_path(path2)
+ if dr2 then
+ return implode_path(dr2, p2)
+ else
+ local dr, p1 = explode_path(path1)
+ assert(p1[1] == '', 'bad path1!')
+ local p = p1
+ if p2[1] == '' then
+ p = {}
+ end
+ for _, v in pairs(p2) do
+ if v == '..' then
+ table.remove(p)
+ elseif v ~= '.' then
+ table.insert(p, v)
+ end
+ end
+ return implode_path(dr, p)
+ end
+end
+
+function cd(path)
+ -- TODO path simplification etc
+ local newcwd = pathcat(_cwd, path)
+ local s = sys.stat(newcwd)
+ if not s then
+ print("not found: " .. newcwd)
+ elseif s.type & sysdef.FT_DIR == 0 then
+ print("not a directory: " .. newcwd)
+ else
+ _cwd = newcwd
+ print(_cwd)
+ end
+end
+
+function cwd()
+ return _cwd
+end
+
+function ls(path)
+ path = pathcat(_cwd, path)
+
+ local fd = sys.open(path, sysdef.FM_READDIR)
+ if not fd then
+ print("Could not open " .. path)
+ else
+ local i = 0
+ while true do
+ x = sys.readdir(fd, i)
+ if not x then break end
+ if x.type & sysdef.FT_DIR ~= 0 then
+ x.name = x.name .. '/'
+ end
+ print(x.type, x.access, x.size, x.name)
+ i = i + 1
+ end
+ sys.close(fd)
+ end
+end
+
diff --git a/src/syslua/lx/sysdef.lua b/src/syslua/lx/sysdef.lua
new file mode 100644
index 0000000..7c0d14f
--- /dev/null
+++ b/src/syslua/lx/sysdef.lua
@@ -0,0 +1,36 @@
+-- Constant definitions based on common/include/proto/fs.h
+
+return {
+ -- FILE TYPES
+ FT_REGULAR = 0,
+ FT_DIR = 0x01,
+ FT_DEV = 0x02,
+ FT_BLOCKDEV = 0x04,
+ FT_CHARDEV = 0x08,
+ FT_CHANNEL = 0x10,
+ FT_FRAMEBUFFER = 0x20,
+
+ -- FILE MODES
+ FM_READ = 0x01,
+ FM_WRITE = 0x02,
+ FM_READDIR = 0x04,
+ FM_MMAP = 0x08,
+ FM_CREATE = 0x10,
+ FM_TRUNC = 0x20,
+ FM_APPEND = 0x40,
+ FM_IOCTL = 0x100,
+ FM_BLOCKING = 0x200,
+ FM_DCREATE = 0x1000,
+ FM_DMOVE = 0x2000,
+ FM_DDELETE = 0x4000,
+ FM_ALL_MODES = 0xFFFF,
+
+ -- IOCTL calls
+ IOCTL_BLOCKDEV_GET_BLOCK_SIZE = 40,
+ IOCTL_BLOCKDEV_GET_BLOCK_COUNT = 41,
+
+ -- Modes for select call
+ SEL_READ = 0x01,
+ SEL_WRITE = 0x02,
+ SEL_ERROR = 0x04,
+}