فهرست منبع

new scheme to search paths

Roberto Ierusalimschy 21 سال پیش
والد
کامیت
0c49857c1a
3فایلهای تغییر یافته به همراه80 افزوده شده و 75 حذف شده
  1. 51 1
      lauxlib.c
  2. 6 1
      lauxlib.h
  3. 23 73
      lbaselib.c

+ 51 - 1
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.115 2004/06/02 19:06:14 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.116 2004/06/17 14:06:52 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -342,6 +342,56 @@ LUALIB_API int luaL_getn (lua_State *L, int t) {
 
 
 
+
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+  const char *l;
+  if (*path == '\0') return NULL;  /* no more templates */
+  if (*path == LUA_PATH_SEP) path++;  /* skip separator */
+  l = strchr(path, LUA_PATH_SEP);  /* find next separator */
+  if (l == NULL) l = path+strlen(path);
+  lua_pushlstring(L, path, l - path);  /* template */
+  return l;
+}
+
+
+static void pushcomposename (lua_State *L) {
+  const char *tem = lua_tostring(L, -1);
+  const char *wild;
+  int n = 1;
+  while ((wild = strchr(tem, LUA_PATH_MARK)) != NULL) {
+    /* is there stack space for prefix, name, and eventual last suffix? */
+    luaL_checkstack(L, 3, "too many marks in a path component");
+    lua_pushlstring(L, tem, wild - tem);  /* push prefix */
+    lua_pushvalue(L, 1);  /* push package name (in place of MARK) */
+    tem = wild + 1;  /* continue after MARK */
+    n += 2;
+  }
+  lua_pushstring(L, tem);  /* push last suffix (`n' already includes this) */
+  lua_concat(L, n);
+}
+
+
+LUALIB_API int luaL_searchpath (lua_State *L, const char *name,
+                                const char *path, luaL_Loader f, void *data) {
+  int status;
+  const char *p = path;
+  int top = lua_gettop(L);
+  do {
+    lua_settop(L, top);
+    if ((p = pushnexttemplate(L, p)) == NULL) {
+      lua_pushfstring(L, "cound not find `%s' in path `%s'", name, path);
+      return LUA_ERRFILE;
+    }
+    pushcomposename(L);
+    lua_remove(L, -2);  /* remove path template */
+    lua_assert(lua_gettop(L) == top + 1);
+    status = f(data, lua_tostring(L, -1));  /* try to load it */
+    lua_remove(L, top+1);  /* remove file name */
+  } while (status == LUA_ERRFILE);
+  return status;
+}
+
+
 /*
 ** {======================================================
 ** Generic Buffer manipulation

+ 6 - 1
lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.65 2004/05/31 19:27:14 roberto Exp roberto $
+** $Id: lauxlib.h,v 1.66 2004/06/02 17:37:03 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -25,6 +25,8 @@ typedef struct luaL_reg {
 } luaL_reg;
 
 
+typedef int (*luaL_Loader)(void *data, const char *name);
+
 LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
                                const luaL_reg *l, int nup);
 LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e);
@@ -54,6 +56,9 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
 
 LUALIB_API int luaL_findstring (const char *st, const char *const lst[]);
 
+LUALIB_API int luaL_searchpath (lua_State *L, const char *name,
+                                const char *path, luaL_Loader f, void *data);
+
 LUALIB_API int luaL_ref (lua_State *L, int t);
 LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
 

+ 23 - 73
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.147 2004/06/15 13:31:30 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.148 2004/06/21 16:45:09 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -261,7 +261,11 @@ static int luaB_loadstring (lua_State *L) {
 
 static int luaB_loadfile (lua_State *L) {
   const char *fname = luaL_optstring(L, 1, NULL);
-  return load_aux(L, luaL_loadfile(L, fname));
+  const char *path = luaL_optstring(L, 2, NULL);
+  int status = (path == NULL)
+               ? luaL_loadfile(L, fname)
+               : luaL_searchpath(L, fname, path, (luaL_Loader)luaL_loadfile, L);
+  return load_aux(L, status);
 }
 
 
@@ -455,7 +459,6 @@ static const char *getpath (lua_State *L) {
   const char *path;
   lua_getglobal(L, LUA_PATH);  /* try global variable */
   path = lua_tostring(L, -1);
-  lua_pop(L, 1);
   if (path) return path;
   path = getenv(LUA_PATH);  /* else try environment variable */
   if (path) return path;
@@ -463,81 +466,28 @@ static const char *getpath (lua_State *L) {
 }
 
 
-static const char *pushnextpath (lua_State *L, const char *path) {
-  const char *l;
-  if (*path == '\0') return NULL;  /* no more paths */
-  if (*path == LUA_PATH_SEP) path++;  /* skip separator */
-  l = strchr(path, LUA_PATH_SEP);  /* find next separator */
-  if (l == NULL) l = path+strlen(path);
-  lua_pushlstring(L, path, l - path);  /* directory name */
-  return l;
-}
-
-
-static void pushcomposename (lua_State *L) {
-  const char *path = lua_tostring(L, -1);
-  const char *wild;
-  int n = 1;
-  while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
-    /* is there stack space for prefix, name, and eventual last suffix? */
-    luaL_checkstack(L, 3, "too many marks in a path component");
-    lua_pushlstring(L, path, wild - path);  /* push prefix */
-    lua_pushvalue(L, 1);  /* push package name (in place of MARK) */
-    path = wild + 1;  /* continue after MARK */
-    n += 2;
-  }
-  lua_pushstring(L, path);  /* push last suffix (`n' already includes this) */
-  lua_concat(L, n);
-}
-
-
 static int luaB_require (lua_State *L) {
-  const char *path;
-  int status = LUA_ERRFILE;  /* not found (yet) */
-  luaL_checkstring(L, 1);
-  lua_settop(L, 1);
+  const char *name = luaL_checkstring(L, 1);
+  const char *path = getpath(L);
   lua_getglobal(L, REQTAB);
-  if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
-  path = getpath(L);
-  lua_pushvalue(L, 1);  /* check package's name in book-keeping table */
-  lua_rawget(L, 2);
+  if (!lua_istable(L, -1))
+    return luaL_error(L, "global `" REQTAB "' is not a table");
+  lua_getfield(L, -1, name);
   if (lua_toboolean(L, -1))  /* is it there? */
     return 1;  /* package is already loaded; return its result */
-  else {  /* must load it */
-    while (status == LUA_ERRFILE) {
-      lua_settop(L, 3);  /* reset stack position */
-      if ((path = pushnextpath(L, path)) == NULL) break;
-      pushcomposename(L);
-      status = luaL_loadfile(L, lua_tostring(L, -1));  /* try to load it */
-    }
-  }
-  switch (status) {
-    case 0: {
-      lua_getglobal(L, "_REQUIREDNAME");  /* save previous name */
-      lua_insert(L, -2);  /* put it below function */
-      lua_pushvalue(L, 1);
-      lua_setglobal(L, "_REQUIREDNAME");  /* set new name */
-      lua_call(L, 0, 1);  /* run loaded module */
-      lua_insert(L, -2);  /* put result below previous name */
-      lua_setglobal(L, "_REQUIREDNAME");  /* reset to previous name */
-      if (lua_isnil(L, -1)) {  /* no/nil return? */
-        lua_pushboolean(L, 1);
-        lua_replace(L, -2);  /* replace to true */
-      }
-      lua_pushvalue(L, 1);
-      lua_pushvalue(L, -2);
-      lua_rawset(L, 2);  /* mark it as loaded */
-      return 1;  /* return value */
-    }
-    case LUA_ERRFILE: {  /* file not found */
-      return luaL_error(L, "could not load package `%s' from path `%s'",
-                            lua_tostring(L, 1), getpath(L));
-    }
-    default: {
-      return luaL_error(L, "error loading package `%s' (%s)",
-                           lua_tostring(L, 1), lua_tostring(L, -1));
-    }
+  /* else must load it */
+  if (luaL_searchpath(L, name, path, (luaL_Loader)luaL_loadfile, L) != 0)
+    return luaL_error(L, "error loading package `%s' (%s)", name,
+                         lua_tostring(L, -1));
+  lua_pushvalue(L, 1);  /* pass name as argument to module */
+  lua_call(L, 1, 1);  /* run loaded module */
+  if (lua_isnil(L, -1)) {  /* nil return? */
+    lua_pop(L, 1);  /* remove it */
+    lua_pushboolean(L, 1);  /* replace to true */
   }
+  lua_pushvalue(L, -1);  /* duplicate result (to return it) */
+  lua_setfield(L, -4, name);  /* mark `name' as loaded */
+  return 1;  /* return value */
 }
 
 /* }====================================================== */