Commits

Laurens Rodriguez  committed d787cb4

loadlib.c: fixes from Lua 5.2.2
NOTE: This needs additional review about index base 1 problems in function gctm() line 284
By now its just running all the test cases we have.

  • Participants
  • Parent commits 0cfd795

Comments (0)

Files changed (1)

File src/libraries/killa/loadlib.c

 #define KILLA_OFSEP	"_"
 
 
-#define LIBPREFIX	"LOADLIB: "
+/* table (in the registry) that keeps handles for all loaded C libraries */
+#define CLIBS		"_CLIBS"
 
-#define POF		KILLA_POF
 #define LIB_FAIL	"open"
 
 
 #endif
 
 
-
-static void **ll_register (killa_State *L, const char *path) {
-  void **plib;
-  killa_pushfstring(L, "%s%s", LIBPREFIX, path);
-  killa_gettable(L, KILLA_REGISTRYINDEX);  /* check library in registry? */
-  if (!killa_isnull(L, -1))  /* is there an entry? */
-    plib = (void **)killa_touserdata(L, -1);
-  else {  /* no entry yet; create one */
-    killa_pop(L, 1);  /* remove result from gettable */
-    plib = (void **)killa_newuserdata(L, sizeof(const void *));
-    *plib = NULL;
-    killaL_setmetatable(L, "_LOADLIB");
-    killa_pushfstring(L, "%s%s", LIBPREFIX, path);
-    killa_pushvalue(L, -2);
-    killa_settable(L, KILLA_REGISTRYINDEX);
-  }
+static void *ll_checkclib (killa_State *L, const char *path) {
+  void *plib;
+  killa_getfield(L, KILLA_REGISTRYINDEX, CLIBS);
+  killa_getfield(L, -1, path);
+  plib = killa_touserdata(L, -1);  /* plib = CLIBS[path] */
+  killa_pop(L, 2);  /* pop CLIBS table and 'plib' */
   return plib;
 }
 
 
+static void ll_addtoclib (killa_State *L, const char *path, void *plib) {
+  killa_getfield(L, KILLA_REGISTRYINDEX, CLIBS);
+  killa_pushlightuserdata(L, plib);
+  killa_pushvalue(L, -1);
+  killa_setfield(L, -3, path);  /* CLIBS[path] = plib */
+  killa_rawseti(L, -2, killaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
+  killa_pop(L, 1);  /* pop CLIBS table */
+}
+
+
 /*
-** __gc tag method: calls library's `ll_unloadlib' function with the lib
-** handle
+** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
+** handles in list CLIBS
 */
 static int gctm (killa_State *L) {
-  void **lib = (void **)killaL_checkudata(L, 1, "_LOADLIB");
-  if (*lib) ll_unloadlib(*lib);
-  *lib = NULL;  /* mark library as closed */
+  int n = killaL_len(L, 1);
+  for (; n >= 1; n--) {  /* for each handle, in reverse order */
+    killa_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
+    ll_unloadlib(killa_touserdata(L, -1));
+    killa_pop(L, 1);  /* pop handle */
+  }
   return 0;
 }
 
 
 static int ll_loadfunc (killa_State *L, const char *path, const char *sym) {
-  void **reg = ll_register(L, path);
-  if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
-  if (*reg == NULL) return ERRLIB;  /* unable to load library */
+  void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
+  if (reg == NULL) {  /* must load library? */
+    reg = ll_load(L, path, *sym == '*');
+    if (reg == NULL) return ERRLIB;  /* unable to load library */
+    ll_addtoclib(L, path, reg);
+  }
   if (*sym == '*') {  /* loading only library (no function)? */
     killa_pushboolean(L, 1);  /* return 'true' */
     return 0;  /* no errors */
   }
   else {
-    killa_CFunction f = ll_sym(L, *reg, sym);
+    killa_CFunction f = ll_sym(L, reg, sym);
     if (f == NULL)
       return ERRFUNC;  /* unable to find function */
     killa_pushcfunction(L, f);  /* else create new function */
   if (mark) {
     int stat;
     funcname = killa_pushlstring(L, modname, mark - modname);
-    funcname = killa_pushfstring(L, POF"%s", funcname);
+    funcname = killa_pushfstring(L, KILLA_POF"%s", funcname);
     stat = ll_loadfunc(L, filename, funcname);
     if (stat != ERRFUNC) return stat;
     modname = mark + 1;  /* else go ahead and try old-style name */
   }
-  funcname = killa_pushfstring(L, POF"%s", modname);
+  funcname = killa_pushfstring(L, KILLA_POF"%s", modname);
   return ll_loadfunc(L, filename, funcname);
 }
 
   killa_getfield(L, killa_upvalueindex(1), "searchers");  /* will be at index 3 */
   if (!killa_istable(L, 3))
     killaL_error(L, KILLA_QL("package.searchers") " must be a table");
-  /*  iterate over available seachers to find a loader */
+  /*  iterate over available searchers to find a loader */
   for (i = KILLA_BASE; ; i++) {
-    killa_rawgeti(L, 3, i);  /* get a seacher */
+    killa_rawgeti(L, 3, i);  /* get a searcher */
     if (killa_isnull(L, -1)) {  /* no more searchers? */
       killa_pop(L, 1);  /* remove null */
       killaL_pushresult(&msg);  /* create error message */
 };
 
 
-static const killa_CFunction searchers[] =
-  {searcher_preload, searcher_Killa, searcher_C, searcher_Croot, NULL};
-
-
-KILLAMOD_API int killaopen_package (killa_State *L) {
+static void createsearcherstable (killa_State *L) {
+  static const killa_CFunction searchers[] =
+    {searcher_preload, searcher_Killa, searcher_C, searcher_Croot, NULL};
   int i;
-  /* create new type _LOADLIB */
-  killaL_newmetatable(L, "_LOADLIB");
-  killa_pushcfunction(L, gctm);
-  killa_setfield(L, -2, "__gc");
-  /* create `package' table */
-  killaL_newlib(L, pk_funcs);
   /* create 'searchers' table */
   killa_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
   /* fill it with pre-defined searchers */
     killa_pushcclosure(L, searchers[i], 1);
     killa_rawseti(L, -2, i + KILLA_BASE);
   }
+}
+
+
+KILLAMOD_API int killaopen_package (killa_State *L) {
+  /* create table CLIBS to keep track of loaded C libraries */
+  killaL_getsubtable(L, KILLA_REGISTRYINDEX, CLIBS);
+  killa_createtable(L, 0, 1);  /* metatable for CLIBS */
+  killa_pushcfunction(L, gctm);
+  killa_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
+  killa_setmetatable(L, -2);
+  /* create `package' table */
+  killaL_newlib(L, pk_funcs);
+  createsearcherstable(L);
 #if defined(KILLA_COMPAT_LOADERS)
   killa_pushvalue(L, -1);  /* make a copy of 'searchers' table */
   killa_setfield(L, -3, "loaders");  /* put it in field `loaders' */