1dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
2dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $
3dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** Dynamic library loader for Lua
4dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** See Copyright Notice in lua.h
5dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com**
6dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** This module contains an implementation of loadlib for Unix systems
7dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** that have dlfcn, an implementation for Windows, and a stub for other
8dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** systems.
9dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
10dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
11dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
12dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
13dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** if needed, includes windows header before everything else
14dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
15dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(_WIN32)
16dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include <windows.h>
17dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
18dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
19dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
20dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include <stdlib.h>
21dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include <string.h>
22dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
23dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
24dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define loadlib_c
25dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_LIB
26dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
27dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include "lua.h"
28dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
29dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include "lauxlib.h"
30dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include "lualib.h"
31dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
32dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
33dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
34dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_PATH and LUA_CPATH are the names of the environment
35dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** variables that Lua check to set its paths.
36dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
37dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined(LUA_PATH)
38dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_PATH	"LUA_PATH"
39dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
40dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
41dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined(LUA_CPATH)
42dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_CPATH	"LUA_CPATH"
43dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
44dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
45dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_PATHSUFFIX		"_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
46dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
47dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_PATHVERSION		LUA_PATH LUA_PATHSUFFIX
48dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_CPATHVERSION	LUA_CPATH LUA_PATHSUFFIX
49dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
50dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
51dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_PATH_SEP is the character that separates templates in a path.
52dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_PATH_MARK is the string that marks the substitution points in a
53dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** template.
54dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_EXEC_DIR in a Windows path is replaced by the executable's
55dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** directory.
56dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_IGMARK is a mark to ignore all before it when building the
57dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** luaopen_ function name.
58dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
59dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined (LUA_PATH_SEP)
60dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_PATH_SEP		";"
61dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
62dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined (LUA_PATH_MARK)
63dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_PATH_MARK		"?"
64dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
65dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined (LUA_EXEC_DIR)
66dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_EXEC_DIR		"!"
67dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
68dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined (LUA_IGMARK)
69dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_IGMARK		"-"
70dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
71dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
72dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
73dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
74dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_CSUBSEP is the character that replaces dots in submodule names
75dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** when searching for a C loader.
76dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** LUA_LSUBSEP is the character that replaces dots in submodule names
77dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** when searching for a Lua loader.
78dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
79dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined(LUA_CSUBSEP)
80dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_CSUBSEP		LUA_DIRSEP
81dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
82dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
83dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined(LUA_LSUBSEP)
84dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_LSUBSEP		LUA_DIRSEP
85dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
86dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
87dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
88dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* prefix for open functions in C libraries */
89dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_POF		"luaopen_"
90dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
91dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* separator for open functions in C libraries */
92dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_OFSEP	"_"
93dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
94dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
95dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* table (in the registry) that keeps handles for all loaded C libraries */
96dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define CLIBS		"_CLIBS"
97dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
98dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LIB_FAIL	"open"
99dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
100dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
101dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* error codes for ll_loadfunc */
102dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define ERRLIB		1
103dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define ERRFUNC		2
104dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
105dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define setprogdir(L)		((void)0)
106dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
107dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
108dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
109dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** system-dependent functions
110dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
111dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void ll_unloadlib (void *lib);
112dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void *ll_load (lua_State *L, const char *path, int seeglb);
113dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
114dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
115dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
116dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
117dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(LUA_USE_DLOPEN)
118dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
119dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** {========================================================================
120dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** This is an implementation of loadlib based on the dlfcn interface.
121dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
122dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
123dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** as an emulation layer on top of native functions.
124dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** =========================================================================
125dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
126dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
127dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include <dlfcn.h>
128dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
129dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void ll_unloadlib (void *lib) {
130dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  dlclose(lib);
131dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
132dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
133dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
134dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void *ll_load (lua_State *L, const char *path, int seeglb) {
135dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
136dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lib == NULL) lua_pushstring(L, dlerror());
137dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return lib;
138dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
139dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
140dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
141dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
142dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
143dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (f == NULL) lua_pushstring(L, dlerror());
144dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return f;
145dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
146dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
147dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* }====================================================== */
148dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
149dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
150dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
151dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#elif defined(LUA_DL_DLL)
152dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
153dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** {======================================================================
154dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** This is an implementation of loadlib for Windows using native functions.
155dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** =======================================================================
156dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
157dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
158dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#undef setprogdir
159dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
160dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
161dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** optional flags for LoadLibraryEx
162dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
163dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if !defined(LUA_LLE_FLAGS)
164dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LUA_LLE_FLAGS	0
165dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
166dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
167dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
168dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void setprogdir (lua_State *L) {
169dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  char buff[MAX_PATH + 1];
170dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  char *lb;
171dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  DWORD nsize = sizeof(buff)/sizeof(char);
172dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  DWORD n = GetModuleFileNameA(NULL, buff, nsize);
173dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
174dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_error(L, "unable to get ModuleFileName");
175dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {
176dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    *lb = '\0';
177dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
178dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_remove(L, -2);  /* remove original string */
179dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
180dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
181dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
182dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
183dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void pusherror (lua_State *L) {
184dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int error = GetLastError();
185dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  char buffer[128];
186dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
187dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
188dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushstring(L, buffer);
189dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else
190dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushfstring(L, "system error %d\n", error);
191dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
192dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
193dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void ll_unloadlib (void *lib) {
194dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  FreeLibrary((HMODULE)lib);
195dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
196dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
197dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
198dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void *ll_load (lua_State *L, const char *path, int seeglb) {
199dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
200dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  (void)(seeglb);  /* not used: symbols are 'global' by default */
201dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lib == NULL) pusherror(L);
202dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return lib;
203dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
204dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
205dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
206dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
207dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
208dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (f == NULL) pusherror(L);
209dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return f;
210dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
211dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
212dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* }====================================================== */
213dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
214dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
215dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#else
216dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
217dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** {======================================================
218dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** Fallback for other systems
219dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** =======================================================
220dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
221dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
222dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#undef LIB_FAIL
223dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define LIB_FAIL	"absent"
224dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
225dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
226dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define DLMSG	"dynamic libraries not enabled; check your Lua installation"
227dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
228dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
229dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void ll_unloadlib (void *lib) {
230dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  (void)(lib);  /* not used */
231dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
232dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
233dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
234dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void *ll_load (lua_State *L, const char *path, int seeglb) {
235dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  (void)(path); (void)(seeglb);  /* not used */
236dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushliteral(L, DLMSG);
237dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return NULL;
238dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
239dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
240dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
241dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
242dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  (void)(lib); (void)(sym);  /* not used */
243dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushliteral(L, DLMSG);
244dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return NULL;
245dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
246dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
247dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* }====================================================== */
248dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
249dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
250dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
251dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void *ll_checkclib (lua_State *L, const char *path) {
252dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  void *plib;
253dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
254dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, -1, path);
255dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
256dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
257dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return plib;
258dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
259dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
260dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
261dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void ll_addtoclib (lua_State *L, const char *path, void *plib) {
262dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
263dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushlightuserdata(L, plib);
264dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -1);
265dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
266dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
267dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 1);  /* pop CLIBS table */
268dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
269dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
270dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
271dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
272dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
273dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** handles in list CLIBS
274dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
275dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int gctm (lua_State *L) {
276dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int n = luaL_len(L, 1);
277dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  for (; n >= 1; n--) {  /* for each handle, in reverse order */
278dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
279dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    ll_unloadlib(lua_touserdata(L, -1));
280dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pop(L, 1);  /* pop handle */
281dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
282dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 0;
283dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
284dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
285dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
286dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
287dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
288dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (reg == NULL) {  /* must load library? */
289dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    reg = ll_load(L, path, *sym == '*');
290dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (reg == NULL) return ERRLIB;  /* unable to load library */
291dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    ll_addtoclib(L, path, reg);
292dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
293dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (*sym == '*') {  /* loading only library (no function)? */
294dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushboolean(L, 1);  /* return 'true' */
295dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 0;  /* no errors */
296dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
297dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {
298dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_CFunction f = ll_sym(L, reg, sym);
299dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (f == NULL)
300dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      return ERRFUNC;  /* unable to find function */
301dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushcfunction(L, f);  /* else create new function */
302dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 0;  /* no errors */
303dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
304dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
305dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
306dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
307dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_loadlib (lua_State *L) {
308dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *path = luaL_checkstring(L, 1);
309dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *init = luaL_checkstring(L, 2);
310dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int stat = ll_loadfunc(L, path, init);
311dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (stat == 0)  /* no errors? */
312dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 1;  /* return the loaded function */
313dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {  /* error; error message is on stack top */
314dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushnil(L);
315dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_insert(L, -2);
316dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
317dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 3;  /* return nil, error message, and where */
318dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
319dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
320dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
321dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
322dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
323dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
324dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** {======================================================
325dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** 'require' function
326dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** =======================================================
327dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
328dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
329dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
330dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int readable (const char *filename) {
331dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  FILE *f = fopen(filename, "r");  /* try to open file */
332dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (f == NULL) return 0;  /* open failed */
333dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  fclose(f);
334dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 1;
335dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
336dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
337dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
338dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic const char *pushnexttemplate (lua_State *L, const char *path) {
339dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *l;
340dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
341dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (*path == '\0') return NULL;  /* no more templates */
342dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
343dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (l == NULL) l = path + strlen(path);
344dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushlstring(L, path, l - path);  /* template */
345dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return l;
346dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
347dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
348dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
349dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic const char *searchpath (lua_State *L, const char *name,
350dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                             const char *path,
351dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                             const char *sep,
352dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                             const char *dirsep) {
353dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_Buffer msg;  /* to build error message */
354dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_buffinit(L, &msg);
355dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (*sep != '\0')  /* non-empty separator? */
356dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
357dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  while ((path = pushnexttemplate(L, path)) != NULL) {
358dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    const char *filename = luaL_gsub(L, lua_tostring(L, -1),
359dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                     LUA_PATH_MARK, name);
360dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_remove(L, -2);  /* remove path template */
361dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (readable(filename))  /* does file exist and is readable? */
362dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      return filename;  /* return that file name */
363dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
364dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_remove(L, -2);  /* remove file name */
365dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_addvalue(&msg);  /* concatenate error msg. entry */
366dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
367dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_pushresult(&msg);  /* create error message */
368dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return NULL;  /* not found */
369dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
370dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
371dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
372dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_searchpath (lua_State *L) {
373dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *f = searchpath(L, luaL_checkstring(L, 1),
374dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                luaL_checkstring(L, 2),
375dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                luaL_optstring(L, 3, "."),
376dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                luaL_optstring(L, 4, LUA_DIRSEP));
377dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (f != NULL) return 1;
378dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {  /* error message is on top of the stack */
379dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushnil(L);
380dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_insert(L, -2);
381dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 2;  /* return nil + error message */
382dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
383dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
384dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
385dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
386dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic const char *findfile (lua_State *L, const char *name,
387dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                           const char *pname,
388dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                           const char *dirsep) {
389dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *path;
390dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, lua_upvalueindex(1), pname);
391dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  path = lua_tostring(L, -1);
392dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (path == NULL)
393dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
394dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return searchpath(L, name, path, ".", dirsep);
395dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
396dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
397dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
398dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int checkload (lua_State *L, int stat, const char *filename) {
399dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (stat) {  /* module loaded successfully? */
400dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushstring(L, filename);  /* will be 2nd argument to module */
401dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 2;  /* return open function and file name */
402dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
403dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else
404dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return luaL_error(L, "error loading module " LUA_QS
405dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                         " from file " LUA_QS ":\n\t%s",
406dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                          lua_tostring(L, 1), filename, lua_tostring(L, -1));
407dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
408dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
409dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
410dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int searcher_Lua (lua_State *L) {
411dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *filename;
412dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *name = luaL_checkstring(L, 1);
413dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  filename = findfile(L, name, "path", LUA_LSUBSEP);
414dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (filename == NULL) return 1;  /* module not found in this path */
415dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
416dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
417dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
418dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
419dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int loadfunc (lua_State *L, const char *filename, const char *modname) {
420dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *funcname;
421dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *mark;
422dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
423dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  mark = strchr(modname, *LUA_IGMARK);
424dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (mark) {
425dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    int stat;
426dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    funcname = lua_pushlstring(L, modname, mark - modname);
427dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
428dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    stat = ll_loadfunc(L, filename, funcname);
429dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (stat != ERRFUNC) return stat;
430dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    modname = mark + 1;  /* else go ahead and try old-style name */
431dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
432dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  funcname = lua_pushfstring(L, LUA_POF"%s", modname);
433dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return ll_loadfunc(L, filename, funcname);
434dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
435dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
436dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
437dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int searcher_C (lua_State *L) {
438dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *name = luaL_checkstring(L, 1);
439dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
440dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (filename == NULL) return 1;  /* module not found in this path */
441dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return checkload(L, (loadfunc(L, filename, name) == 0), filename);
442dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
443dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
444dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
445dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int searcher_Croot (lua_State *L) {
446dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *filename;
447dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *name = luaL_checkstring(L, 1);
448dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *p = strchr(name, '.');
449dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int stat;
450dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (p == NULL) return 0;  /* is root */
451dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushlstring(L, name, p - name);
452dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
453dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (filename == NULL) return 1;  /* root not found */
454dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if ((stat = loadfunc(L, filename, name)) != 0) {
455dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (stat != ERRFUNC)
456dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      return checkload(L, 0, filename);  /* real error */
457dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    else {  /* open function not found */
458dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
459dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                         name, filename);
460dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      return 1;
461dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    }
462dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
463dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushstring(L, filename);  /* will be 2nd argument to module */
464dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 2;
465dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
466dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
467dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
468dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int searcher_preload (lua_State *L) {
469dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *name = luaL_checkstring(L, 1);
470dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
471dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, -1, name);
472dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lua_isnil(L, -1))  /* not found? */
473dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
474dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 1;
475dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
476dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
477dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
478dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void findloader (lua_State *L, const char *name) {
479dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int i;
480dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_Buffer msg;  /* to build error message */
481dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_buffinit(L, &msg);
482dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
483dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (!lua_istable(L, 3))
484dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_error(L, LUA_QL("package.searchers") " must be a table");
485dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /*  iterate over available searchers to find a loader */
486dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  for (i = 1; ; i++) {
487dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_rawgeti(L, 3, i);  /* get a searcher */
488dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (lua_isnil(L, -1)) {  /* no more searchers? */
489dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pop(L, 1);  /* remove nil */
490dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      luaL_pushresult(&msg);  /* create error message */
491dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      luaL_error(L, "module " LUA_QS " not found:%s",
492dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                    name, lua_tostring(L, -1));
493dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    }
494dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushstring(L, name);
495dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_call(L, 1, 2);  /* call it */
496dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (lua_isfunction(L, -2))  /* did it find a loader? */
497dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      return;  /* module loader found */
498dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
499dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pop(L, 1);  /* remove extra return */
500dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      luaL_addvalue(&msg);  /* concatenate error message */
501dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    }
502dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    else
503dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pop(L, 2);  /* remove both returns */
504dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
505dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
506dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
507dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
508dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_require (lua_State *L) {
509dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *name = luaL_checkstring(L, 1);
510dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_settop(L, 1);  /* _LOADED table will be at index 2 */
511dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
512dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, 2, name);  /* _LOADED[name] */
513dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lua_toboolean(L, -1))  /* is it there? */
514dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    return 1;  /* package is already loaded */
515dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* else must load package */
516dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 1);  /* remove 'getfield' result */
517dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  findloader(L, name);
518dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushstring(L, name);  /* pass name as argument to module loader */
519dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_insert(L, -2);  /* name is 1st argument (before search data) */
520dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_call(L, 2, 1);  /* run loader to load module */
521dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (!lua_isnil(L, -1))  /* non-nil return? */
522dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
523dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, 2, name);
524dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lua_isnil(L, -1)) {   /* module did not set a value? */
525dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushboolean(L, 1);  /* use true as result */
526dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushvalue(L, -1);  /* extra copy to be returned */
527dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_setfield(L, 2, name);  /* _LOADED[name] = true */
528dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
529dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 1;
530dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
531dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
532dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* }====================================================== */
533dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
534dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
535dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
536dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
537dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** {======================================================
538dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** 'module' function
539dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** =======================================================
540dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
541dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(LUA_COMPAT_MODULE)
542dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
543dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
544dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** changes the environment variable of calling function
545dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
546dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void set_env (lua_State *L) {
547dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_Debug ar;
548dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (lua_getstack(L, 1, &ar) == 0 ||
549dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
550dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_iscfunction(L, -1))
551dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_error(L, LUA_QL("module") " not called from a Lua function");
552dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -2);  /* copy new environment table to top */
553dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setupvalue(L, -2, 1);
554dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 1);  /* remove function */
555dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
556dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
557dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
558dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void dooptions (lua_State *L, int n) {
559dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int i;
560dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  for (i = 2; i <= n; i++) {
561dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
562dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pushvalue(L, i);  /* get option (a function) */
563dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_pushvalue(L, -2);  /* module */
564dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com      lua_call(L, 1, 0);
565dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    }
566dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
567dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
568dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
569dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
570dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void modinit (lua_State *L, const char *modname) {
571dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *dot;
572dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -1);
573dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "_M");  /* module._M = module */
574dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushstring(L, modname);
575dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "_NAME");
576dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  dot = strrchr(modname, '.');  /* look for last dot in module name */
577dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (dot == NULL) dot = modname;
578dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else dot++;
579dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* set _PACKAGE as package name (full module name minus last part) */
580dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushlstring(L, modname, dot - modname);
581dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "_PACKAGE");
582dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
583dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
584dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
585dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_module (lua_State *L) {
586dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *modname = luaL_checkstring(L, 1);
587dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int lastarg = lua_gettop(L);  /* last parameter */
588dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_pushmodule(L, modname, 1);  /* get/create module table */
589dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* check whether table already has a _NAME field */
590dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, -1, "_NAME");
591dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (!lua_isnil(L, -1))  /* is table an initialized module? */
592dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pop(L, 1);
593dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {  /* no; initialize it */
594dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pop(L, 1);
595dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    modinit(L, modname);
596dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
597dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -1);
598dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  set_env(L);
599dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  dooptions(L, lastarg);
600dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 1;
601dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
602dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
603dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
604dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int ll_seeall (lua_State *L) {
605dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_checktype(L, 1, LUA_TTABLE);
606dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (!lua_getmetatable(L, 1)) {
607dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_createtable(L, 0, 1); /* create new metatable */
608dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushvalue(L, -1);
609dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_setmetatable(L, 1);
610dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
611dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushglobaltable(L);
612dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "__index");  /* mt.__index = _G */
613dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 0;
614dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
615dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
616dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
617dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* }====================================================== */
618dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
619dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
620dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
621dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/* auxiliary mark (for internal use) */
622dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#define AUXMARK		"\1"
623dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
624dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
625dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/*
626dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com** return registry.LUA_NOENV as a boolean
627dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com*/
628dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic int noenv (lua_State *L) {
629dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int b;
630dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
631dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  b = lua_toboolean(L, -1);
632dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 1);  /* remove value */
633dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return b;
634dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
635dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
636dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
637dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void setpath (lua_State *L, const char *fieldname, const char *envname1,
638dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                                   const char *envname2, const char *def) {
639dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  const char *path = getenv(envname1);
640dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (path == NULL)  /* no environment variable? */
641dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    path = getenv(envname2);  /* try alternative name */
642dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  if (path == NULL || noenv(L))  /* no environment variable? */
643dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushstring(L, def);  /* use default */
644dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  else {
645dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
646dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
647dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                              LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
648dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    luaL_gsub(L, path, AUXMARK, def);
649dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_remove(L, -2);
650dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
651dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  setprogdir(L);
652dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, fieldname);
653dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
654dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
655dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
656dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic const luaL_Reg pk_funcs[] = {
657dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {"loadlib", ll_loadlib},
658dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {"searchpath", ll_searchpath},
659dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(LUA_COMPAT_MODULE)
660dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {"seeall", ll_seeall},
661dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
662dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {NULL, NULL}
663dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com};
664dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
665dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
666dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic const luaL_Reg ll_funcs[] = {
667dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(LUA_COMPAT_MODULE)
668dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {"module", ll_module},
669dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
670dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {"require", ll_require},
671dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  {NULL, NULL}
672dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com};
673dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
674dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
675dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comstatic void createsearcherstable (lua_State *L) {
676dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  static const lua_CFunction searchers[] =
677dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
678dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  int i;
679dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* create 'searchers' table */
680dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
681dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* fill it with pre-defined searchers */
682dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  for (i=0; searchers[i] != NULL; i++) {
683dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
684dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_pushcclosure(L, searchers[i], 1);
685dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com    lua_rawseti(L, -2, i+1);
686dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  }
687dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
688dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
689dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
690dff7e11c2000d6745261de046d76b1500a05ece9reed@google.comLUAMOD_API int luaopen_package (lua_State *L) {
691dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* create table CLIBS to keep track of loaded C libraries */
692dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
693dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_createtable(L, 0, 1);  /* metatable for CLIBS */
694dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushcfunction(L, gctm);
695dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
696dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setmetatable(L, -2);
697dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* create `package' table */
698dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_newlib(L, pk_funcs);
699dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  createsearcherstable(L);
700dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#if defined(LUA_COMPAT_LOADERS)
701dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
702dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
703dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#endif
704dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
705dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* set field 'path' */
706dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
707dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* set field 'cpath' */
708dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
709dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* store config information */
710dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
711dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com                     LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
712dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "config");
713dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* set field `loaded' */
714dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
715dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "loaded");
716dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  /* set field `preload' */
717dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
718dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_setfield(L, -2, "preload");
719dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushglobaltable(L);
720dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
721dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  luaL_setfuncs(L, ll_funcs, 1);  /* open lib into global table */
722dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  lua_pop(L, 1);  /* pop global table */
723dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com  return 1;  /* return 'package' table */
724dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com}
725dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com
726