diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -519,15 +519,14 @@ lua_mod_SOURCES = script/lua/lapi.c script/lua/lcode.c script/lua/ldebug.c \ script/lua/lstate.c script/lua/lstring.c script/lua/ltable.c \ script/lua/ltm.c script/lua/lundump.c script/lua/lvm.c \ script/lua/lzio.c script/lua/lauxlib.c script/lua/lbaselib.c \ - script/lua/linit.c script/lua/ltablib.c \ + script/lua/linit.c script/lua/ltablib.c script/lua/lstrlib.c \ script/lua/grub_main.c script/lua/grub_lib.c lua_mod_CFLAGS = $(COMMON_CFLAGS) lua_mod_LDFLAGS = $(COMMON_LDFLAGS) # Extra libraries for lua # script/lua/lmathlib.c script/lua/loslib.c script/lua/liolib.c -# script/lua/lstrlib.c script/lua/ldblib.c script/lua/ltablib.c -# script/lua/loadlib.c +# script/lua/ldblib.c script/lua/loadlib.c # Common Video Subsystem specific modules. pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..9875e8b 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,18 +24,47 @@ #include #include #include +#include +#include +#include + +static int +save_errno (lua_State *state) +{ + int saved_errno; + + saved_errno = grub_errno; + grub_errno = 0; + + lua_pushinteger (state, saved_errno); + lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno"); + + if (saved_errno) + lua_pushstring (state, grub_errmsg); + else + lua_pushnil (state); + + lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg"); + + return saved_errno; +} + +static int +push_result (lua_State *state) +{ + lua_pushinteger (state, save_errno (state)); + return 1; +} static int grub_lua_run (lua_State *state) { int n; char **args; - grub_err_t result; - - if (! lua_gettop(state)) - return 0; + const char *s; - if ((! grub_parser_split_cmdline (lua_tostring (state, 1), 0, &n, &args)) + s = luaL_checkstring (state, 1); + if ((! grub_parser_split_cmdline (s, 0, &n, &args)) && (n >= 0)) { grub_command_t cmd; @@ -50,15 +79,7 @@ grub_lua_run (lua_State *state) grub_free (args); } - result = grub_errno; - grub_errno = 0; - - lua_pushinteger(state, result); - - if (result) - lua_pushstring (state, grub_errmsg); - - return (result) ? 2 : 1; + return push_result (state); } static int @@ -66,12 +87,12 @@ grub_lua_getenv (lua_State *state) { int n, i; - n = lua_gettop(state); + n = lua_gettop (state); for (i = 1; i <= n; i++) { const char *name, *value; - name = lua_tostring (state, i); + name = luaL_checkstring (state, i); value = grub_env_get (name); if (value) lua_pushstring (state, value); @@ -87,11 +108,8 @@ grub_lua_setenv (lua_State *state) { const char *name, *value; - if (lua_gettop(state) != 2) - return 0; - - name = lua_tostring (state, 1); - value = lua_tostring (state, 2); + name = luaL_checkstring (state, 1); + value = luaL_checkstring (state, 2); if (name[0]) grub_env_set (name, value); @@ -99,10 +117,330 @@ grub_lua_setenv (lua_State *state) return 0; } +static int +grub_lua_enum_device (lua_State *state) +{ + auto int enum_device (const char *name); + int enum_device (const char *name) + { + int result; + grub_device_t dev; + + result = 0; + dev = grub_device_open (name); + if (dev) + { + grub_fs_t fs; + + fs = grub_fs_probe (dev); + if (fs) + { + lua_pushvalue (state, 1); + lua_pushstring (state, name); + lua_pushstring (state, fs->name); + if (! fs->uuid) + lua_pushnil (state); + else + { + int err; + char *uuid; + + err = fs->uuid (dev, &uuid); + if (err) + { + grub_errno = 0; + lua_pushnil (state); + } + else + { + lua_pushstring (state, uuid); + grub_free (uuid); + } + } + + lua_call (state, 3, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + } + else + grub_errno = 0; + grub_device_close (dev); + } + else + save_errno (state); + + return result; + } + + luaL_checktype (state, 1, LUA_TFUNCTION); + grub_device_iterate (enum_device); + return push_result (state); +} + +static int +grub_lua_enum_file (lua_State *state) +{ + char *device_name; + const char *arg; + grub_device_t dev; + + auto int enum_file (const char *name, const struct grub_dirhook_info *info); + int enum_file (const char *name, const struct grub_dirhook_info *info) + { + int result; + + lua_pushvalue (state, 1); + lua_pushstring (state, name); + lua_pushinteger (state, info->dir != 0); + lua_call (state, 2, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + + return result; + } + + luaL_checktype (state, 1, LUA_TFUNCTION); + arg = luaL_checkstring (state, 2); + device_name = grub_file_get_device_name (arg); + dev = grub_device_open (device_name); + if (dev) + { + grub_fs_t fs; + const char *path; + + fs = grub_fs_probe (dev); + path = grub_strchr (arg, ')'); + if (! path) + path = arg; + else + path++; + + if (fs) + { + (fs->dir) (dev, path, enum_file); + } + + grub_device_close (dev); + } + + grub_free (device_name); + + return push_result (state); +} + +static int +grub_lua_file_open (lua_State *state) +{ + grub_file_t file; + const char *name; + + name = luaL_checkstring (state, 1); + file = grub_file_open (name); + save_errno (state); + + if (! file) + return 0; + + lua_pushlightuserdata (state, file); + return 1; +} + +static int +grub_lua_file_close (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + grub_file_close (file); + + return push_result (state); +} + +static int +grub_lua_file_seek (lua_State *state) +{ + grub_file_t file; + grub_off_t offset; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + offset = luaL_checkinteger (state, 2); + + offset = grub_file_seek (file, offset); + save_errno (state); + + lua_pushinteger (state, offset); + return 1; +} + +static int +grub_lua_file_read (lua_State *state) +{ + grub_file_t file; + luaL_Buffer b; + int n; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + n = luaL_checkinteger (state, 2); + + luaL_buffinit (state, &b); + while (n) + { + char *p; + int nr; + + nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n; + p = luaL_prepbuffer (&b); + + nr = grub_file_read (file, p, nr); + if (nr <= 0) + break; + + luaL_addsize (&b, nr); + n -= nr; + } + + save_errno (state); + luaL_pushresult (&b); + return 1; +} + +static int +grub_lua_file_getline (lua_State *state) +{ + grub_file_t file; + char *line; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + line = grub_file_getline (file); + save_errno (state); + + if (! line) + return 0; + + lua_pushstring (state, line); + grub_free (line); + return 1; +} + +static int +grub_lua_file_getsize (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->size); + return 1; +} + +static int +grub_lua_file_getpos (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->offset); + return 1; +} + +static int +grub_lua_file_eof (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushboolean (state, file->offset >= file->size); + return 1; +} + +static int +grub_lua_file_exist (lua_State *state) +{ + int result, i, n; + + result = 1; + n = lua_gettop (state); + for (i = 1; i <= n; i++) + { + grub_file_t file; + const char *name; + + name = luaL_checkstring (state, i); + file = grub_file_open (name); + if (file) + { + grub_file_close (file); + } + else + { + result = 0; + grub_errno = 0; + break; + } + } + + lua_pushboolean (state, result); + return 1; +} + +static int +grub_lua_add_menu (lua_State *state) +{ + int n; + const char *source; + + source = luaL_checklstring (state, 1, 0); + n = lua_gettop (state) - 1; + if (n > 0) + { + const char *args[sizeof (char *) * n]; + char *p; + int i; + + for (i = 0; i < n; i++) + args[i] = luaL_checkstring (state, 2 + i); + + p = grub_strdup (source); + if (! p) + return push_result (state); + + grub_normal_add_menu_entry (n, args, p); + } + else + { + lua_pushstring (state, "not enough parameter"); + lua_error (state); + } + + return push_result (state); +} + luaL_Reg grub_lua_lib[] = { {"run", grub_lua_run}, {"getenv", grub_lua_getenv}, {"setenv", grub_lua_setenv}, + {"enum_device", grub_lua_enum_device}, + {"enum_file", grub_lua_enum_file}, + {"file_open", grub_lua_file_open}, + {"file_close", grub_lua_file_close}, + {"file_seek", grub_lua_file_seek}, + {"file_read", grub_lua_file_read}, + {"file_getline", grub_lua_file_getline}, + {"file_getsize", grub_lua_file_getsize}, + {"file_getpos", grub_lua_file_getpos}, + {"file_eof", grub_lua_file_eof}, + {"file_exist", grub_lua_file_exist}, + {"add_menu", grub_lua_add_menu}, {0, 0} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -77,26 +77,28 @@ iscntrl (int c) } static inline int -strcspn(const char *s1, const char *s2) +isupper (int c) { - int size = 0; - - while (*s1) - { - const char *p = s2; + return ((c >= 'A') && (c <= 'Z')); +} - while (*p) - { - if (*s1 == *p) - return size; - p++; - } +static inline int +islower (int c) +{ + return ((c >= 'a') && (c <= 'z')); +} - s1++; - size++; - } +static inline int +ispunct (int c) +{ + return ((! isspace (c)) && (! isalnum (c))); +} - return size; +static inline int +isxdigit (int c) +{ + return (isdigit (c) || ((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))); } static inline int @@ -105,4 +107,8 @@ abs (int c) return (c >= 0) ? : -c; } +int strcspn (const char *s1, const char *s2); +char *strpbrk (const char *s1, const char *s2); +void *memchr (const void *s, int c, size_t n); + #endif diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b39141f 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #include #include +static const char * +scan_str (const char *s1, const char *s2) +{ + while (*s1) + { + const char *p = s2; + + while (*p) + { + if (*s1 == *p) + return s1; + p++; + } + + s1++; + } + + return s1; +} + +int +strcspn (const char *s1, const char *s2) +{ + const char *r; + + r = scan_str (s1, s2); + return r - s1; +} + +char * +strpbrk (const char *s1, const char *s2) +{ + const char *r; + + r = scan_str (s1, s2); + return (*r) ? (char *) r : 0; +} + +void * +memchr (const void *s, int c, size_t n) +{ + const unsigned char *p = s; + + while (n) + { + if (*p == c) + return (void *) p; + + n--; + p++; + } + + return 0; +} + static lua_State *state; /* Call `grub_error' to report a Lua error. The error message string must be diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -20,7 +20,7 @@ static const luaL_Reg lualibs[] = { {LUA_TABLIBNAME, luaopen_table}, // {LUA_IOLIBNAME, luaopen_io}, // {LUA_OSLIBNAME, luaopen_os}, -// {LUA_STRLIBNAME, luaopen_string}, + {LUA_STRLIBNAME, luaopen_string}, // {LUA_MATHLIBNAME, luaopen_math}, // {LUA_DBLIBNAME, luaopen_debug}, {NULL, NULL}