~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/lua/src/loadlib.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

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