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..f3c8812 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,13 +24,43 @@ #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; @@ -50,15 +80,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 @@ -99,10 +121,236 @@ 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; + + lua_pushvalue (state, -1); + lua_pushstring (state, name); + lua_call (state, 1, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + + return result; + } + + if (lua_gettop (state) != 1) + return 0; + + grub_device_iterate (enum_device); + return push_result (state); +} + +static int +grub_lua_enum_file (lua_State *state) +{ + + 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; + } + + if (lua_gettop (state) != 2) + return 0; + else + { + char *device_name, *arg; + grub_device_t dev; + + arg = (char *) lua_tostring (state, 1); + device_name = grub_file_get_device_name (arg); + dev = grub_device_open (device_name); + if (dev) + { + grub_fs_t fs; + 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; + + if (lua_gettop(state) != 1) + return 0; + + name = lua_tostring (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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 2) + return 0; + + file = lua_touserdata (state, 1); + offset = lua_tointeger (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; + + if (lua_gettop(state) != 2) + return 0; + + file = lua_touserdata (state, 1); + n = lua_tointeger (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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 1) + return 0; + + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->offset); + return 1; +} + 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}, {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..b6d496d 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}