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