elua lib: add elua_util_ APIs
authorDaniel Kolesa <d.kolesa@samsung.com>
Fri, 10 Apr 2015 15:36:26 +0000 (16:36 +0100)
committerDaniel Kolesa <d.kolesa@osg.samsung.com>
Wed, 6 May 2015 14:05:20 +0000 (15:05 +0100)
src/lib/elua/Elua.h
src/lib/elua/elua.c

index 6d49303..cb1edc1 100644 (file)
@@ -98,6 +98,14 @@ EAPI int elua_io_popen(lua_State *L);
 EAPI int elua_module_init(lua_State *L);
 EAPI int elua_module_system_init(lua_State *L);
 
+EAPI int elua_util_require(Elua_State *es, const char *libname);
+EAPI int elua_util_file_run(Elua_State *es, const char *fname);
+EAPI int elua_util_string_run(Elua_State *es, const char *chunk,
+                              const char *chname);
+EAPI Eina_Bool elua_util_app_load(Elua_State *es, const char *appname);
+EAPI int elua_util_script_run(Elua_State *es, int argc, char **argv, int n,
+                              int *quit);
+
 #endif
 
 #ifdef __cplusplus
index 1827e1e..df96e1d 100644 (file)
@@ -350,3 +350,151 @@ elua_module_system_init(lua_State *L)
    lua_concat(L, 2);
    return 2;
 }
+
+/* Utility functions - these could be written using the other APIs */
+
+static int
+_elua_traceback(lua_State *L)
+{
+   lua_getglobal(L, "debug");
+   if (!lua_istable(L, -1))
+     {
+        lua_pop(L, 1);
+        return 1;
+     }
+   lua_getfield(L, -1, "traceback");
+   if (!lua_isfunction(L, -1))
+     {
+        lua_pop(L, 2);
+        return 1;
+     }
+   lua_pushvalue(L, 1);
+   lua_pushinteger(L, 2);
+   lua_call(L, 2, 1);
+   return 1;
+}
+
+static int
+_elua_docall(Elua_State *es, int narg, int nret)
+{
+   int status;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   int bs = lua_gettop(es->luastate) - narg;
+   lua_pushcfunction(es->luastate, _elua_traceback);
+   lua_insert(es->luastate, bs);
+   status = lua_pcall(es->luastate, narg, nret, bs);
+   lua_remove(es->luastate, bs);
+   if (status)
+      lua_gc(es->luastate, LUA_GCCOLLECT, 0);
+   return status;
+}
+
+static int
+_elua_getargs(Elua_State *es, int argc, char **argv, int n)
+{
+   int i;
+   int narg = argc - (n + 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   luaL_checkstack(es->luastate, narg + 3, "too many arguments to script");
+   for (i = n + 1; i < argc; ++i)
+     {
+        lua_pushstring(es->luastate, argv[i]);
+     }
+   lua_createtable(es->luastate, narg, n + 1);
+   for (i = 0; i < argc; ++i)
+     {
+        lua_pushstring(es->luastate, argv[i]);
+        lua_rawseti(es->luastate, -2, i - n);
+     }
+   return narg;
+}
+
+EAPI int
+elua_util_require(Elua_State *es, const char *libname)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(es->requireref, -1);
+   lua_pushstring(es->luastate, libname);
+   return elua_report_error(es, es->progname,
+                            lua_pcall(es->luastate, 1, 0, 0));
+}
+
+EAPI int
+elua_util_file_run(Elua_State *es, const char *fname)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   return elua_report_error(es, es->progname,
+                            elua_io_loadfile(es, fname)
+                            || _elua_docall(es, 0, 1));
+}
+
+EAPI int
+elua_util_string_run(Elua_State *es, const char *chunk, const char *chname)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   return elua_report_error(es, es->progname,
+                            luaL_loadbuffer(es->luastate, chunk, strlen(chunk),
+                                            chname)
+                            || _elua_docall(es, 0, 0));
+}
+
+EAPI Eina_Bool
+elua_util_app_load(Elua_State *es, const char *appname)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(es->apploadref, EINA_FALSE);
+   lua_pushstring(es->luastate, appname);
+   lua_call(es->luastate, 1, 2);
+   if (lua_isnil(es->luastate, -2))
+     {
+        lua_remove(es->luastate, -2);
+        return EINA_FALSE;
+     }
+   lua_pop(es->luastate, 1);
+   return EINA_TRUE;
+}
+
+EAPI int
+elua_util_script_run(Elua_State *es, int argc, char **argv, int n, int *quit)
+{
+   int status, narg;
+   const char *fname;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(n < argc, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(es->luastate, -1);
+   fname = argv[n];
+   narg = _elua_getargs(es, argc, argv, n);
+   lua_setglobal(es->luastate, "arg");
+   if (fname[0] == '-' && !fname[1]) fname = NULL;
+   if (fname)
+     {
+        /* check if there is a file of that name */
+        FILE *f = fopen(fname, "r");
+        if (f)
+          {
+             fclose(f);
+             status = elua_io_loadfile(es, fname);
+          }
+        else
+          status = !elua_util_app_load(es, fname);
+     }
+   else
+     status = elua_io_loadfile(es, fname);
+   lua_insert(es->luastate, -(narg + 1));
+   if (!status)
+     status = _elua_docall(es, narg, 1);
+   else
+     lua_pop(es->luastate, narg);
+   if (!status)
+     {
+        *quit = lua_toboolean(es->luastate, -1);
+        lua_pop(es->luastate, 1);
+     }
+   return elua_report_error(es, es->progname, status);
+}