Pārlūkot izejas kodu

first full implementation of new package system

Roberto Ierusalimschy 21 gadi atpakaļ
vecāks
revīzija
9be5844713
4 mainītis faili ar 206 papildinājumiem un 129 dzēšanām
  1. 8 114
      lbaselib.c
  2. 179 8
      loadlib.c
  3. 4 4
      lua.c
  4. 15 3
      luaconf.h

+ 8 - 114
lbaselib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lbaselib.c,v 1.158 2004/09/15 20:39:42 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.159 2004/09/29 21:03:14 roberto Exp roberto $
 ** Basic library
 ** Basic library
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -440,105 +440,6 @@ static int luaB_newproxy (lua_State *L) {
 }
 }
 
 
 
 
-/*
-** {======================================================
-** `require' function
-** =======================================================
-*/
-
-
-static const char *getpath (lua_State *L) {
-  /* try first `LUA_PATH' for compatibility */
-  lua_getfield(L, LUA_GLOBALSINDEX, "LUA_PATH");
-  if (!lua_isstring(L, -1)) {
-    lua_pop(L, 1);
-    lua_getfield(L, LUA_GLOBALSINDEX, "_PATH");
-  }
-  if (!lua_isstring(L, -1))
-    luaL_error(L, "global _PATH must be a string");
-  return lua_tostring(L, -1);
-}
-
-
-static int luaB_require (lua_State *L) {
-  const char *name = luaL_checkstring(L, 1);
-  const char *fname;
-  lua_settop(L, 1);
-  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
-  lua_getfield(L, 2, name);
-  if (lua_toboolean(L, -1))  /* is it there? */
-    return 1;  /* package is already loaded; return its result */
-  /* else must load it; first mark it as loaded */
-  lua_pushboolean(L, 1);
-  lua_setfield(L, 2, name);  /* _LOADED[name] = true */
-  fname = luaL_gsub(L, name, ".", LUA_DIRSEP);
-  fname = luaL_searchpath(L, fname, getpath(L));
-  if (fname == NULL || luaL_loadfile(L, fname) != 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_setfield(L, 2, name);
-  lua_getfield(L, 2, name);  /* return _LOADED[name] */
-  return 1;
-}
-
-
-static void setfenv (lua_State *L) {
-  lua_Debug ar;
-  lua_getstack(L, 1, &ar);
-  lua_getinfo(L, "f", &ar);
-  lua_pushvalue(L, -2);
-  lua_setfenv(L, -2);
-}
-
-
-static int luaB_module (lua_State *L) {
-  const char *modname = luaL_checkstring(L, 1);
-  const char *dot;
-  lua_settop(L, 1);
-  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
-  /* try to find given table */
-  luaL_getfield(L, LUA_GLOBALSINDEX, modname);
-  if (lua_isnil(L, -1)) {  /* not found? */
-    lua_pop(L, 1);  /* remove previous result */
-    lua_newtable(L);  /* create it */
-    /* register it with given name */
-    lua_pushvalue(L, -1);
-    luaL_setfield(L, LUA_GLOBALSINDEX, modname);
-  }
-  else if (!lua_istable(L, -1))
-    return luaL_error(L, "name conflict for module `%s'", modname);
-  /* check whether table already has a _NAME field */
-  lua_getfield(L, -1, "_NAME");
-  if (!lua_isnil(L, -1))  /* is table an initialized module? */
-    lua_pop(L, 1);
-  else {  /* no; initialize it */
-    lua_pop(L, 1);
-    lua_newtable(L);  /* create new metatable */
-    lua_pushvalue(L, LUA_GLOBALSINDEX);
-    lua_setfield(L, -2, "__index");  /* mt.__index = _G */
-    lua_setmetatable(L, -2);
-    lua_pushstring(L, modname);
-    lua_setfield(L, -2, "_NAME");
-    dot = strrchr(modname, '.');  /* look for last dot in module name */
-    if (dot == NULL) dot = modname;
-    else dot++;
-    /* set _PACK as package name (full module name minus last part) */
-    lua_pushlstring(L, modname, dot - modname);
-    lua_setfield(L, -2, "_PACK");
-  }
-  lua_pushvalue(L, -1);
-  lua_setfield(L, 2, modname);  /* _LOADED[modname] = new table */
-  setfenv(L);
-  return 0;
-}
-
-
-/* }====================================================== */
-
-
 static const luaL_reg base_funcs[] = {
 static const luaL_reg base_funcs[] = {
   {"error", luaB_error},
   {"error", luaB_error},
   {"getmetatable", luaB_getmetatable},
   {"getmetatable", luaB_getmetatable},
@@ -564,8 +465,6 @@ static const luaL_reg base_funcs[] = {
   {"dofile", luaB_dofile},
   {"dofile", luaB_dofile},
   {"loadstring", luaB_loadstring},
   {"loadstring", luaB_loadstring},
   {"load", luaB_load},
   {"load", luaB_load},
-  {"require", luaB_require},
-  {"module", luaB_module},
   {NULL, NULL}
   {NULL, NULL}
 };
 };
 
 
@@ -713,11 +612,10 @@ static void auxopen (lua_State *L, const char *name,
 
 
 
 
 static void base_open (lua_State *L) {
 static void base_open (lua_State *L) {
-  const char *path;
   lua_pushvalue(L, LUA_GLOBALSINDEX);
   lua_pushvalue(L, LUA_GLOBALSINDEX);
   luaL_openlib(L, NULL, base_funcs, 0);  /* open lib into global table */
   luaL_openlib(L, NULL, base_funcs, 0);  /* open lib into global table */
   lua_pushliteral(L, LUA_VERSION);
   lua_pushliteral(L, LUA_VERSION);
-  lua_setfield(L, LUA_GLOBALSINDEX, "_VERSION");  /* set global _VERSION */
+  lua_setglobal(L, "_VERSION");  /* set global _VERSION */
   /* `ipairs' and `pairs' need auxiliary functions as upvalues */
   /* `ipairs' and `pairs' need auxiliary functions as upvalues */
   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
   auxopen(L, "pairs", luaB_pairs, luaB_next);
   auxopen(L, "pairs", luaB_pairs, luaB_next);
@@ -728,20 +626,16 @@ static void base_open (lua_State *L) {
   lua_pushliteral(L, "kv");
   lua_pushliteral(L, "kv");
   lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
   lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
   lua_pushcclosure(L, luaB_newproxy, 1);
   lua_pushcclosure(L, luaB_newproxy, 1);
-  lua_setfield(L, LUA_GLOBALSINDEX, "newproxy");  /* set global `newproxy' */
-  /* `require' needs a table to keep loaded chunks */
+  lua_setglobal(L, "newproxy");  /* set global `newproxy' */
+  /* create register._LOADED to track loaded modules */
   lua_newtable(L);
   lua_newtable(L);
-  lua_pushvalue(L, -1);
-  lua_setglobal(L, "_LOADED");
   lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
   lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
+  /* create register._PRELOAD to allow pre-loaded modules */
+  lua_newtable(L);
+  lua_setfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
   /* set global _G */
   /* set global _G */
   lua_pushvalue(L, LUA_GLOBALSINDEX);
   lua_pushvalue(L, LUA_GLOBALSINDEX);
-  lua_setfield(L, LUA_GLOBALSINDEX, "_G");
-  /* set global _PATH */
-  path = getenv(LUA_PATH);
-  if (path == NULL) path = LUA_PATH_DEFAULT;
-  lua_pushstring(L, path);
-  lua_setfield(L, LUA_GLOBALSINDEX, "_PATH");
+  lua_setglobal(L, "_G");
 }
 }
 
 
 
 

+ 179 - 8
loadlib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: loadlib.c,v 1.8 2004/10/18 18:07:31 roberto Exp roberto $
+** $Id: loadlib.c,v 1.9 2004/11/11 15:42:57 roberto Exp roberto $
 ** Dynamic library loader for Lua
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 *
 *
@@ -25,6 +25,10 @@
 * loaders on top of which loadlib could be implemented.
 * loaders on top of which loadlib could be implemented.
 */
 */
 
 
+
+#include <string.h>
+
+
 #define loadlib_c
 #define loadlib_c
 #define LUA_LIB
 #define LUA_LIB
 
 
@@ -224,13 +228,180 @@ static int loadlib1 (lua_State *L) {
  }
  }
 }
 }
 
 
-LUALIB_API int luaopen_loadlib (lua_State *L)
-{
- luaL_newmetatable(L, "_LOADLIB");
- lua_pushcfunction(L, gctm);
- lua_setfield(L, -2, "__gc");
- lua_register(L,"loadlib",loadlib1);
- return 0;
+
+
+/*
+** {======================================================
+** `require' and `module' functions
+** =======================================================
+*/
+
+
+static const char *loadLua (lua_State *L, const char *fname, const char *name) {
+  const char *path;
+  /* try first `LUA_PATH' for compatibility */
+  lua_getglobal(L, "LUA_PATH");
+  path = lua_tostring(L, -1);
+  if (!path) {
+    lua_pop(L, 1);
+    luaL_getfield(L, LUA_GLOBALSINDEX, "package.path");
+    path = lua_tostring(L, -1);
+  }
+  if (path == NULL)
+    luaL_error(L, "`package.path' must be a string");
+  fname = luaL_searchpath(L, fname, path);
+  if (fname == NULL) return path;  /* library not found in this path */
+  if (luaL_loadfile(L, fname) != 0)
+    luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -1));
+  return NULL;  /* library loaded successfully */
+}
+
+
+static const char *loadC (lua_State *L, const char *fname, const char *name) {
+  const char *path;
+  const char *funcname;
+  luaL_getfield(L, LUA_GLOBALSINDEX, "package.cpath");
+  path = lua_tostring(L, -1);
+  if (path == NULL)
+    luaL_error(L, "global _CPATH must be a string");
+  fname = luaL_searchpath(L, fname, path);
+  if (fname == NULL) return path;  /* library not found in this path */
+  funcname = luaL_gsub(L, name, ".", "");
+  funcname = lua_pushfstring(L, "%s%s", LUA_POF, funcname);
+  if (loadlib(L, fname, funcname) != 0)
+    luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -1));
+  return NULL;  /* library loaded successfully */
+}
+
+
+static int ll_require (lua_State *L) {
+  const char *name = luaL_checkstring(L, 1);
+  lua_settop(L, 1);
+  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+  lua_getfield(L, 2, name);
+  if (lua_toboolean(L, -1))  /* is it there? */
+    return 1;  /* package is already loaded; return its result */
+  /* else must load it; first mark it as loaded */
+  lua_pushboolean(L, 1);
+  lua_setfield(L, 2, name);  /* _LOADED[name] = true */
+  /* check whether it is preloaded */
+  lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
+  lua_getfield(L, -1, name);
+  if (lua_isnil(L, -1)) {  /* no preload function for that module? */
+    const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP);
+    const char *cpath = loadC(L, fname, name);  /* try a C module */
+    if (cpath) {  /* not found? */
+      const char *path = loadLua(L, fname, name);  /* try a Lua module */
+      if (path) {  /* yet not found? */
+        lua_pushnil(L);
+        lua_setfield(L, 2, name);  /* unmark _LOADED[name] */
+        return luaL_error(L, "package `%s' not found\n"
+                             "  cpath: %s\n  path: %s",
+                             name, cpath, path);
+      }
+    }
+  }
+  lua_pushvalue(L, 1);  /* pass name as argument to module */
+  lua_call(L, 1, 1);  /* run loaded module */
+  if (!lua_isnil(L, -1))  /* non-nil return? */
+    lua_setfield(L, 2, name);  /* update _LOADED[name] with returned value */
+  lua_getfield(L, 2, name);  /* return _LOADED[name] */
+  return 1;
+}
+
+
+static void setfenv (lua_State *L) {
+  lua_Debug ar;
+  lua_getstack(L, 1, &ar);
+  lua_getinfo(L, "f", &ar);
+  lua_pushvalue(L, -2);
+  lua_setfenv(L, -2);
+}
+
+
+static int ll_module (lua_State *L) {
+  const char *modname = luaL_checkstring(L, 1);
+  const char *dot;
+  lua_settop(L, 1);
+  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+  /* try to find given table */
+  luaL_getfield(L, LUA_GLOBALSINDEX, modname);
+  if (lua_isnil(L, -1)) {  /* not found? */
+    lua_pop(L, 1);  /* remove previous result */
+    lua_newtable(L);  /* create it */
+    /* register it with given name */
+    lua_pushvalue(L, -1);
+    luaL_setfield(L, LUA_GLOBALSINDEX, modname);
+  }
+  else if (!lua_istable(L, -1))
+    return luaL_error(L, "name conflict for module `%s'", modname);
+  /* check whether table already has a _NAME field */
+  lua_getfield(L, -1, "_NAME");
+  if (!lua_isnil(L, -1))  /* is table an initialized module? */
+    lua_pop(L, 1);
+  else {  /* no; initialize it */
+    lua_pop(L, 1);
+    lua_newtable(L);  /* create new metatable */
+    lua_pushvalue(L, LUA_GLOBALSINDEX);
+    lua_setfield(L, -2, "__index");  /* mt.__index = _G */
+    lua_setmetatable(L, -2);
+    lua_pushstring(L, modname);
+    lua_setfield(L, -2, "_NAME");
+    dot = strrchr(modname, '.');  /* look for last dot in module name */
+    if (dot == NULL) dot = modname;
+    else dot++;
+    /* set _PACKAGE as package name (full module name minus last part) */
+    lua_pushlstring(L, modname, dot - modname);
+    lua_setfield(L, -2, "_PACKAGE");
+  }
+  lua_pushvalue(L, -1);
+  lua_setfield(L, 2, modname);  /* _LOADED[modname] = new table */
+  setfenv(L);
+  return 0;
+}
+
+
+/* }====================================================== */
+
+
+static const luaL_reg ll_funcs[] = {
+  {"loadlib", loadlib1},
+  {"require", ll_require},
+  {"module", ll_module},
+  {NULL, NULL}
+};
+
+
+
+LUALIB_API int luaopen_loadlib (lua_State *L) {
+  const char *path;
+  /* create new type _LOADLIB */
+  luaL_newmetatable(L, "_LOADLIB");
+  lua_pushcfunction(L, gctm);
+  lua_setfield(L, -2, "__gc");
+  /* create `package' table */
+  lua_newtable(L);
+  lua_pushvalue(L, -1);
+  lua_setglobal(L, "package");
+  /* set field `path' */
+  path = getenv(LUA_PATH);
+  if (path == NULL) path = LUA_PATH_DEFAULT;
+  lua_pushstring(L, path);
+  lua_setfield(L, -2, "path");
+  /* set field `cpath' */
+  path = getenv(LUA_CPATH);
+  if (path == NULL) path = LUA_CPATH_DEFAULT;
+  lua_pushstring(L, path);
+  lua_setfield(L, -2, "cpath");
+  /* set field `loaded' */
+  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+  lua_setfield(L, -2, "loaded");
+  /* set field `preload' */
+  lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
+  lua_setfield(L, -2, "preload");
+  lua_pushvalue(L, LUA_GLOBALSINDEX);
+  luaL_openlib(L, NULL, ll_funcs, 0);  /* open lib into global table */
+  return 1;
 }
 }
 
 
 /*
 /*

+ 4 - 4
lua.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lua.c,v 1.131 2004/08/26 14:19:55 roberto Exp roberto $
+** $Id: lua.c,v 1.132 2004/08/30 18:35:14 roberto Exp roberto $
 ** Lua stand-alone interpreter
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -127,9 +127,9 @@ static int dostring (lua_State *L, const char *s, const char *name) {
 
 
 
 
 static int dolibrary (lua_State *L, const char *name) {
 static int dolibrary (lua_State *L, const char *name) {
-  lua_getfield(L, LUA_GLOBALSINDEX, "_PATH");
+  luaL_getfield(L, LUA_GLOBALSINDEX, "package.path");
   if (!lua_isstring(L, -1)) {
   if (!lua_isstring(L, -1)) {
-    l_message(progname, "global _PATH must be a string");
+    l_message(progname, "`package.path' must be a string");
     return 1;
     return 1;
   }
   }
   name = luaL_searchpath(L, name, lua_tostring(L, -1));
   name = luaL_searchpath(L, name, lua_tostring(L, -1));
@@ -295,7 +295,7 @@ static int handle_argv (lua_State *L, char *argv[], int *interactive) {
             print_usage();
             print_usage();
             return 1;
             return 1;
           }
           }
-          if (dostring(L, chunk, "=<command line>") != 0)
+          if (dostring(L, chunk, "=(command line)") != 0)
             return 1;
             return 1;
           break;
           break;
         }
         }

+ 15 - 3
luaconf.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: luaconf.h,v 1.14 2004/10/06 18:34:47 roberto Exp roberto $
+** $Id: luaconf.h,v 1.15 2004/10/18 18:07:31 roberto Exp roberto $
 ** Configuration file for Lua
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -31,7 +31,11 @@
 */
 */
 
 
 /* default path */
 /* default path */
-#define LUA_PATH_DEFAULT	"?;?.lua"
+#define LUA_PATH_DEFAULT \
+   "./?.lua;/usr/local/share/lua/5.0/?.lua;/usr/local/share/lua/5.0/?/init.lua"
+#define LUA_CPATH_DEFAULT \
+   "./?.so;/usr/local/lib/lua/5.0/?.so;/usr/local/lib/lua/5.0/lib?.so"
+
 
 
 
 
 /* type of numbers in Lua */
 /* type of numbers in Lua */
@@ -272,8 +276,16 @@
 
 
 /* `assert' options */
 /* `assert' options */
 
 
-/* environment variable that holds the search path for packages */
+/* environment variables that hold the search path for packages */
 #define LUA_PATH	"LUA_PATH"
 #define LUA_PATH	"LUA_PATH"
+#define LUA_CPATH	"LUA_CPATH"
+
+/* prefix for open functions in C libraries */
+#if defined(__APPLE__) && defined(__MACH__)
+#define LUA_POF		"_luaopen_"
+#else
+#define LUA_POF		"luaopen_"
+#endif
 
 
 /* directory separator (for submodules) */
 /* directory separator (for submodules) */
 #define LUA_DIRSEP	"/"
 #define LUA_DIRSEP	"/"