summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2004-12-07 12:00:00 +0000
committerrepogen <>2004-12-07 12:00:00 +0000
commit226f7859b5392b6680b7e703f9cc7f7f101fd365 (patch)
tree4345e84719d7f9ccf8d62fa007cbd386f235c58a /src/lib
parentd8fd22e11b391cf183068049bebbee9702c8f78f (diff)
downloadlua-github-5.1-work3.tar.gz
Lua 5.1-work35.1-work3
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/lauxlib.c78
-rw-r--r--src/lib/lbaselib.c76
-rw-r--r--src/lib/ldblib.c9
-rw-r--r--src/lib/loadlib.c397
-rw-r--r--src/lib/loslib.c8
-rw-r--r--src/lib/lstrlib.c50
6 files changed, 433 insertions, 185 deletions
diff --git a/src/lib/lauxlib.c b/src/lib/lauxlib.c
index 7c14d001..615be8f2 100644
--- a/src/lib/lauxlib.c
+++ b/src/lib/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.124 2004/09/03 13:17:14 roberto Exp $
+** $Id: lauxlib.c,v 1.126 2004/09/29 21:03:14 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -239,16 +239,22 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup) {
if (libname) {
/* check whether lib already exists */
- lua_getglobal(L, libname);
- if (lua_isnil(L, -1)) { /* no? */
- lua_pop(L, 1);
+ luaL_getfield(L, LUA_GLOBALSINDEX, libname);
+ if (lua_isnil(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
lua_newtable(L); /* create it */
if (lua_getmetatable(L, LUA_GLOBALSINDEX))
lua_setmetatable(L, -2); /* share metatable with global table */
- lua_pushvalue(L, -1);
/* register it with given name */
- lua_setglobal(L, libname);
+ lua_pushvalue(L, -1);
+ luaL_setfield(L, LUA_GLOBALSINDEX, libname);
}
+ else if (!lua_istable(L, -1))
+ luaL_error(L, "name conflict for library `%s'", libname);
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_pushvalue(L, -2);
+ lua_setfield(L, -2, libname); /* _LOADED[modname] = new table */
+ lua_pop(L, 1); /* remove _LOADED table */
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
}
for (; l->name; l++) {
@@ -352,8 +358,8 @@ static const char *pushnexttemplate (lua_State *L, const char *path) {
}
-static const char *luaL_gsub (lua_State *L, const char *s,
- const char *p, const char *r) {
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
+ const char *r) {
const char *wild;
int l = strlen(p);
luaL_Buffer b;
@@ -381,16 +387,68 @@ LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name,
}
fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
lua_remove(L, -2); /* remove path template */
- f = fopen(fname, "r"); /* try to read it */
+ f = fopen(fname, "r"); /* try to open it */
if (f) {
+ int err;
+ getc(f); /* try to read file */
+ err = ferror(f);
fclose(f);
- return fname;
+ if (err == 0) /* open and read sucessful? */
+ return fname; /* return that file name */
}
lua_pop(L, 1); /* remove file name */
}
}
+LUALIB_API const char *luaL_getfield (lua_State *L, int idx,
+ const char *fname) {
+ const char *e;
+ lua_pushvalue(L, idx);
+ while ((e = strchr(fname, '.')) != NULL) {
+ lua_pushlstring(L, fname, e - fname);
+ lua_rawget(L, -2);
+ lua_remove(L, -2); /* remove previous table */
+ fname = e + 1;
+ if (!lua_istable(L, -1)) return fname;
+ }
+ lua_pushstring(L, fname);
+ lua_rawget(L, -2); /* get last field */
+ lua_remove(L, -2); /* remove previous table */
+ return NULL;
+}
+
+
+LUALIB_API const char *luaL_setfield (lua_State *L, int idx,
+ const char *fname) {
+ const char *e;
+ lua_pushvalue(L, idx);
+ while ((e = strchr(fname, '.')) != NULL) {
+ lua_pushlstring(L, fname, e - fname);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) { /* no such field? */
+ lua_pop(L, 1); /* remove this nil */
+ lua_newtable(L); /* create a new table for field */
+ lua_pushlstring(L, fname, e - fname);
+ lua_pushvalue(L, -2);
+ lua_settable(L, -4); /* set new table into field */
+ }
+ lua_remove(L, -2); /* remove previous table */
+ fname = e + 1;
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 2); /* remove table and value */
+ return fname;
+ }
+ }
+ lua_pushstring(L, fname);
+ lua_pushvalue(L, -3); /* move value to the top */
+ lua_rawset(L, -3); /* set last field */
+ lua_pop(L, 2); /* remove value and table */
+ return NULL;
+}
+
+
+
/*
** {======================================================
** Generic Buffer manipulation
diff --git a/src/lib/lbaselib.c b/src/lib/lbaselib.c
index 82a8f509..8c628097 100644
--- a/src/lib/lbaselib.c
+++ b/src/lib/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.158 2004/09/15 20:39:42 roberto Exp $
+** $Id: lbaselib.c,v 1.161 2004/12/06 17:53:42 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -181,10 +181,10 @@ static int luaB_gcinfo (lua_State *L) {
static int luaB_collectgarbage (lua_State *L) {
- static const char *const opts[] = {"stop", "restart", "collect", "count",
- "step", NULL};
- static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART,
- LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCSTEP};
+ static const char *const opts[] = {"stop", "restart", "collect",
+ "count", "step", "setstepmul", "setincmode", NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETSTEPMUL, LUA_GCSETINCMODE};
int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
int ex = luaL_optint(L, 2, 0);
luaL_argcheck(L, o >= 0, 1, "invalid option");
@@ -440,50 +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_getfield(L, lua_upvalueindex(1), 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, lua_upvalueindex(1), name); /* _LOADED[name] = true */
- fname = luaL_searchpath(L, name, 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, lua_upvalueindex(1), name);
- lua_getfield(L, lua_upvalueindex(1), name); /* return _LOADED[name] */
- return 1;
-}
-
-/* }====================================================== */
-
-
static const luaL_reg base_funcs[] = {
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
@@ -656,11 +612,10 @@ static void auxopen (lua_State *L, const char *name,
static void base_open (lua_State *L) {
- const char *path;
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
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 auxliliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next);
@@ -671,21 +626,16 @@ static void base_open (lua_State *L) {
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
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_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ /* create register._PRELOAD to allow pre-loaded modules */
lua_newtable(L);
- lua_pushvalue(L, -1);
- lua_setglobal(L, "_LOADED");
- lua_pushcclosure(L, luaB_require, 1);
- lua_setfield(L, LUA_GLOBALSINDEX, "require");
+ lua_setfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
/* set global _G */
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");
}
diff --git a/src/lib/ldblib.c b/src/lib/ldblib.c
index 4ec5f393..36d647aa 100644
--- a/src/lib/ldblib.c
+++ b/src/lib/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.87 2004/08/13 18:02:36 roberto Exp $
+** $Id: ldblib.c,v 1.89 2004/11/17 12:02:41 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -261,7 +261,7 @@ static int debug (lua_State *L) {
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
- if (luaL_loadbuffer(L, buffer, strlen(buffer), "=debug command") ||
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0)) {
fputs(lua_tostring(L, -1), stderr);
fputs("\n", stderr);
@@ -275,14 +275,15 @@ static int debug (lua_State *L) {
#define LEVELS2 10 /* size of the second part of the stack */
static int errorfb (lua_State *L) {
- int level = 1; /* skip level 0 (it's this function) */
+ int level = 0;
int firstpart = 1; /* still before eventual `...' */
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
+ if (L == L1) level++; /* skip level 0 (it's this function) */
if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
- else if (!lua_isstring(L, arg+1)) return 1; /* no string message */
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, &ar)) {
diff --git a/src/lib/loadlib.c b/src/lib/loadlib.c
index 8b98a2bf..63bc0bcc 100644
--- a/src/lib/loadlib.c
+++ b/src/lib/loadlib.c
@@ -1,31 +1,35 @@
/*
-** $Id: loadlib.c,v 1.6 2004/04/30 20:13:38 roberto Exp $
+** $Id: loadlib.c,v 1.11 2004/11/19 15:52:12 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
*
-* This Lua library exports a single function, called loadlib, which is
-* called from Lua as loadlib(lib,init), where lib is the full name of the
-* library to be loaded (including the complete path) and init is the name
-* of a function to be called after the library is loaded. Typically, this
-* function will register other functions, thus making the complete library
-* available to Lua. The init function is *not* automatically called by
-* loadlib. Instead, loadlib returns the init function as a Lua function
-* that the client can call when it thinks is appropriate. In the case of
-* errors, loadlib returns nil and two strings describing the error.
-* The first string is supplied by the operating system; it should be
-* informative and useful for error messages. The second string is "open",
-* "init", or "absent" to identify the error and is meant to be used for
-* making decisions without having to look into the first string (whose
-* format is system-dependent).
-*
-* This module contains an implementation of loadlib for Unix systems that
-* have dlfcn, an implementation for Windows, and a stub for other systems.
-* See the list at the end of this file for some links to available
-* implementations of dlfcn and interfaces to other native dynamic loaders
-* on top of which loadlib could be implemented.
-*
+* This Lua library exports a single function, called loadlib, which
+* is called from Lua as loadlib(lib,init), where lib is the full
+* name of the library to be loaded (including the complete path) and
+* init is the name of a function to be called after the library is
+* loaded. Typically, this function will register other functions, thus
+* making the complete library available to Lua. The init function is
+* *not* automatically called by loadlib. Instead, loadlib returns the
+* init function as a Lua function that the client can call when it
+* thinks is appropriate. In the case of errors, loadlib returns nil and
+* two strings describing the error. The first string is supplied by
+* the operating system; it should be informative and useful for error
+* messages. The second string is "open", "init", or "absent" to identify
+* the error and is meant to be used for making decisions without having
+* to look into the first string (whose format is system-dependent).
+* This module contains an implementation of loadlib for Unix systems
+* that have dlfcn, an implementation for Darwin (Mac OS X), an
+* implementation for Windows, and a stub for other systems. See
+* the list at the end of this file for some links to available
+* implementations of dlfcn and interfaces to other native dynamic
+* loaders on top of which loadlib could be implemented.
*/
+
+#include <stdlib.h>
+#include <string.h>
+
+
#define loadlib_c
#define LUA_LIB
@@ -34,11 +38,14 @@
#include "lualib.h"
-#undef LOADLIB
+#define ERR_OPEN 1
+#define ERR_FUNCTION 2
+
+
+static void registerlib (lua_State *L, const void *lib);
-#ifdef USE_DLOPEN
-#define LOADLIB
+#if defined(USE_DLOPEN)
/*
* This is an implementation of loadlib based on the dlfcn interface.
* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
@@ -48,53 +55,41 @@
#include <dlfcn.h>
-static int loadlib(lua_State *L)
+#define freelib dlclose
+
+static int loadlib(lua_State *L, const char *path, const char *init)
{
- const char *path=luaL_checkstring(L,1);
- const char *init=luaL_checkstring(L,2);
void *lib=dlopen(path,RTLD_NOW);
if (lib!=NULL)
{
lua_CFunction f=(lua_CFunction) dlsym(lib,init);
if (f!=NULL)
{
- lua_pushlightuserdata(L,lib);
- lua_pushcclosure(L,f,1);
- return 1;
+ registerlib(L, lib);
+ lua_pushcfunction(L,f);
+ return 0;
}
}
- /* else return appropriate error messages */
- lua_pushnil(L);
+ /* else return appropriate error message */
lua_pushstring(L,dlerror());
- lua_pushstring(L,(lib!=NULL) ? "init" : "open");
- if (lib!=NULL) dlclose(lib);
- return 3;
+ if (lib!=NULL) {
+ dlclose(lib);
+ return ERR_FUNCTION; /* error loading function */
+ }
+ else return ERR_OPEN; /* error loading library */
}
-#endif
-
-
-
-/*
-** In Windows, default is to use dll; otherwise, default is not to use dll
-*/
-#ifndef USE_DLL
-#ifdef _WIN32
-#define USE_DLL 1
-#else
-#define USE_DLL 0
-#endif
-#endif
-#if USE_DLL
-#define LOADLIB
+#elif defined(USE_DLL)
/*
* This is an implementation of loadlib for Windows using native functions.
*/
#include <windows.h>
+#define freelib(lib) FreeLibrary((HINSTANCE)lib)
+
static void pusherror(lua_State *L)
{
int error=GetLastError();
@@ -106,61 +101,310 @@ static void pusherror(lua_State *L)
lua_pushfstring(L,"system error %d\n",error);
}
-static int loadlib(lua_State *L)
+static int loadlib(lua_State *L, const char *path, const char *init)
{
- const char *path=luaL_checkstring(L,1);
- const char *init=luaL_checkstring(L,2);
HINSTANCE lib=LoadLibrary(path);
if (lib!=NULL)
{
lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init);
if (f!=NULL)
{
- lua_pushlightuserdata(L,lib);
- lua_pushcclosure(L,f,1);
+ registerlib(L, lib);
+ lua_pushcfunction(L,f);
return 1;
}
}
- lua_pushnil(L);
pusherror(L);
- lua_pushstring(L,(lib!=NULL) ? "init" : "open");
- if (lib!=NULL) FreeLibrary(lib);
- return 3;
+ if (lib!=NULL) {
+ FreeLibrary(lib);
+ return ERR_OPEN;
+ }
+ else return ERR_FUNCTION;
}
-#endif
+/* Native Mac OS X / Darwin Implementation */
+#elif defined(USE_DYLD)
+
+#include <mach-o/dyld.h>
+
+
+/* Mach cannot unload images (?) */
+#define freelib(lib) ((void)lib)
+
+static void pusherror (lua_State *L)
+{
+ const char *err_str;
+ const char *err_file;
+ NSLinkEditErrors err;
+ int err_num;
+ NSLinkEditError(&err, &err_num, &err_file, &err_str);
+ lua_pushstring(L, err_str);
+}
+
+static int loadlib (lua_State *L, const char *path, const char *init) {
+ const struct mach_header *lib;
+ /* this would be a rare case, but prevents crashing if it happens */
+ if(!_dyld_present()) {
+ lua_pushstring(L,"dyld not present.");
+ return ERR_OPEN;
+ }
+ lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if(lib != NULL) {
+ NSSymbol init_sym = NSLookupSymbolInImage(lib, init,
+ NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
+ NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ if(init_sym != NULL) {
+ lua_CFunction f = (lua_CFunction)NSAddressOfSymbol(init_sym);
+ registerlib(L, lib);
+ lua_pushcfunction(L,f);
+ return 0;
+ }
+ }
+ /* else an error ocurred */
+ pusherror(L);
+ /* Can't unload image */
+ return (lib != NULL) ? ERR_FUNCTION : ERR_OPEN;
+}
+
-#ifndef LOADLIB
-/* Fallback for other systems */
-/*
-** Those systems support dlopen, so they should have defined USE_DLOPEN.
-** The default (no)implementation gives them a special error message.
-*/
-#if defined(linux) || defined(sun) || defined(sgi) || defined(BSD) || defined(_WIN32)
-#define LOADLIB "`loadlib' not installed (check your Lua configuration)"
#else
-#define LOADLIB "`loadlib' not supported"
-#endif
+/* Fallback for other systems */
+
+#define freelib(lib) ((void)lib)
static int loadlib(lua_State *L)
{
+ registerlib(L, NULL); /* to avoid warnings */
lua_pushnil(L);
- lua_pushliteral(L,LOADLIB);
+ lua_pushliteral(L,"`loadlib' not supported");
lua_pushliteral(L,"absent");
return 3;
}
+
#endif
-LUALIB_API int luaopen_loadlib (lua_State *L)
+
+/*
+** common code for all implementations: put a library into the registry
+** so that, when Lua closes its state, the library's __gc metamethod
+** will be called to unload the library.
+*/
+static void registerlib (lua_State *L, const void *lib)
+{
+ const void **plib = (const void **)lua_newuserdata(L, sizeof(const void *));
+ *plib = lib;
+ luaL_getmetatable(L, "_LOADLIB");
+ lua_setmetatable(L, -2);
+ lua_pushboolean(L, 1);
+ lua_settable(L, LUA_REGISTRYINDEX); /* registry[lib] = true */
+}
+
+/*
+** __gc tag method: calls library's `freelib' function with the lib
+** handle
+*/
+static int gctm (lua_State *L)
{
- lua_register(L,"loadlib",loadlib);
+ void *lib = *(void **)luaL_checkudata(L, 1, "_LOADLIB");
+ freelib(lib);
return 0;
}
+
+static int loadlib1 (lua_State *L) {
+ const char *path=luaL_checkstring(L,1);
+ const char *init=luaL_checkstring(L,2);
+ int res = loadlib(L,path,init);
+ if (res == 0) /* no error? */
+ return 1; /* function is at stack top */
+ else { /* error */
+ lua_pushnil(L);
+ lua_insert(L,-2); /* insert nil before error message */
+ lua_pushstring(L, (res==ERR_OPEN)?"open":"init");
+ return 3;
+ }
+}
+
+
+
+/*
+** {======================================================
+** `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;
+}
+
/*
* Here are some links to available implementations of dlfcn and
* interfaces to other native dynamic loaders on top of which loadlib
@@ -179,9 +423,6 @@ LUALIB_API int luaopen_loadlib (lua_State *L)
* Macintosh, Windows
* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
*
-* Mac OS X/Darwin
-* http://www.opendarwin.org/projects/dlcompat/
-*
* GLIB has wrapper code for BeOS, OS2, Unix and Windows
* http://cvs.gnome.org/lxr/source/glib/gmodule/
*
diff --git a/src/lib/loslib.c b/src/lib/loslib.c
index c5726cfe..4f1d2d03 100644
--- a/src/lib/loslib.c
+++ b/src/lib/loslib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loslib.c,v 1.2 2004/08/05 19:30:37 roberto Exp $
+** $Id: loslib.c,v 1.3 2004/10/08 18:57:16 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -20,7 +20,7 @@
#include "lualib.h"
-static int pushresult (lua_State *L, int i, const char *filename) {
+static int os_pushresult (lua_State *L, int i, const char *filename) {
if (i) {
lua_pushboolean(L, 1);
return 1;
@@ -45,14 +45,14 @@ static int io_execute (lua_State *L) {
static int io_remove (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
- return pushresult(L, remove(filename) == 0, filename);
+ return os_pushresult(L, remove(filename) == 0, filename);
}
static int io_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2);
- return pushresult(L, rename(fromname, toname) == 0, fromname);
+ return os_pushresult(L, rename(fromname, toname) == 0, fromname);
}
diff --git a/src/lib/lstrlib.c b/src/lib/lstrlib.c
index 7fa205c0..a9c002fb 100644
--- a/src/lib/lstrlib.c
+++ b/src/lib/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.106 2004/08/09 13:30:33 roberto Exp $
+** $Id: lstrlib.c,v 1.109 2004/12/01 15:46:06 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -24,8 +24,6 @@
#define uchar(c) ((unsigned char)(c))
-typedef lua_Integer sint32; /* a signed version for size_t */
-
static int str_len (lua_State *L) {
size_t l;
@@ -35,19 +33,19 @@ static int str_len (lua_State *L) {
}
-static sint32 posrelat (sint32 pos, size_t len) {
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
/* relative string position: negative means back from end */
- return (pos>=0) ? pos : (sint32)len+pos+1;
+ return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
}
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 start = posrelat(luaL_checkinteger(L, 2), l);
- sint32 end = posrelat(luaL_optinteger(L, 3, -1), l);
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
- if (end > (sint32)l) end = (sint32)l;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
if (start <= end)
lua_pushlstring(L, s+start-1, end-start+1);
else lua_pushliteral(L, "");
@@ -107,8 +105,8 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 posi = posrelat(luaL_optinteger(L, 2, 1), l);
- sint32 pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
int n, i;
if (posi <= 0) posi = 1;
if ((size_t)pose > l) pose = l;
@@ -173,7 +171,7 @@ typedef struct MatchState {
int level; /* total number of captures (finished or unfinished) */
struct {
const char *init;
- sint32 len;
+ ptrdiff_t len;
} capture[MAX_CAPTURES];
} MatchState;
@@ -198,7 +196,7 @@ static int capture_to_close (MatchState *ms) {
}
-static const char *luaI_classend (MatchState *ms, const char *p) {
+static const char *classend (MatchState *ms, const char *p) {
switch (*p++) {
case ESC: {
if (*p == '\0')
@@ -250,7 +248,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
while (++p < ec) {
if (*p == ESC) {
p++;
- if (match_class(c, *p))
+ if (match_class(c, uchar(*p)))
return sig;
}
else if ((*(p+1) == '-') && (p+2 < ec)) {
@@ -264,10 +262,10 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
}
-static int luaI_singlematch (int c, const char *p, const char *ep) {
+static int singlematch (int c, const char *p, const char *ep) {
switch (*p) {
case '.': return 1; /* matches any char */
- case ESC: return match_class(c, *(p+1));
+ case ESC: return match_class(c, uchar(*(p+1)));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
}
@@ -299,8 +297,8 @@ static const char *matchbalance (MatchState *ms, const char *s,
static const char *max_expand (MatchState *ms, const char *s,
const char *p, const char *ep) {
- sint32 i = 0; /* counts maximum expand for item */
- while ((s+i)<ms->src_end && luaI_singlematch(uchar(*(s+i)), p, ep))
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
i++;
/* keeps trying to match with the maximum repetitions */
while (i>=0) {
@@ -318,7 +316,7 @@ static const char *min_expand (MatchState *ms, const char *s,
const char *res = match(ms, s, ep+1);
if (res != NULL)
return res;
- else if (s<ms->src_end && luaI_singlematch(uchar(*s), p, ep))
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
s++; /* try with one more repetition */
else return NULL;
}
@@ -385,7 +383,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
p += 2;
if (*p != '[')
luaL_error(ms->L, "missing `[' after `%%f' in pattern");
- ep = luaI_classend(ms, p); /* points to what is next */
+ ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) ||
!matchbracketclass(uchar(*s), p, ep-1)) return NULL;
@@ -393,7 +391,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
}
default: {
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
- s = match_capture(ms, s, *(p+1));
+ s = match_capture(ms, s, uchar(*(p+1)));
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(ms, s, p+2) */
}
@@ -410,8 +408,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
else goto dflt;
}
default: dflt: { /* it is a pattern item */
- const char *ep = luaI_classend(ms, p); /* points to what is next */
- int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
+ const char *ep = classend(ms, p); /* points to what is next */
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
switch (*ep) {
case '?': { /* optional */
const char *res;
@@ -490,9 +488,9 @@ static int str_find (lua_State *L) {
size_t l1, l2;
const char *s = luaL_checklstring(L, 1, &l1);
const char *p = luaL_checklstring(L, 2, &l2);
- sint32 init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
if (init < 0) init = 0;
- else if ((size_t)(init) > l1) init = (sint32)l1;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
if (lua_toboolean(L, 4) || /* explicit request? */
strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */
/* do a plain search */
@@ -642,7 +640,7 @@ static int str_gsub (lua_State *L) {
#define MAX_FORMAT 20
-static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
luaL_putchar(b, '"');
@@ -726,7 +724,7 @@ static int str_format (lua_State *L) {
break;
}
case 'q': {
- luaI_addquoted(L, &b, arg);
+ addquoted(L, &b, arg);
continue; /* skip the `addsize' at the end */
}
case 's': {