aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-01 01:21:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-01 01:21:17 -0300
commite82bdb24f3727fbecb3d0596c1a8abc0af4cc687 (patch)
treea4b4c81eb6a8da06bcd418643b6aafa565db4884
parent1a343814d8da9f9c2067d6ca3d82d57c84f91f10 (diff)
downloadlua-e82bdb24f3727fbecb3d0596c1a8abc0af4cc687.tar.gz
lua-e82bdb24f3727fbecb3d0596c1a8abc0af4cc687.tar.bz2
lua-e82bdb24f3727fbecb3d0596c1a8abc0af4cc687.zip
new loader for "all-in-one" C packages
-rw-r--r--loadlib.c154
1 files changed, 89 insertions, 65 deletions
diff --git a/loadlib.c b/loadlib.c
index 0001abb2..063f8546 100644
--- a/loadlib.c
+++ b/loadlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: loadlib.c,v 1.33 2005/07/12 21:17:46 roberto Exp roberto $ 2** $Id: loadlib.c,v 1.34 2005/07/13 19:02:42 roberto Exp roberto $
3** Dynamic library loader for Lua 3** Dynamic library loader for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5** 5**
@@ -38,6 +38,10 @@
38#define LIB_FAIL "open" 38#define LIB_FAIL "open"
39 39
40 40
41/* error codes for ll_loadfunc */
42#define ERRLIB 1
43#define ERRFUNC 2
44
41#define setprogdir(L) ((void)0) 45#define setprogdir(L) ((void)0)
42 46
43 47
@@ -294,43 +298,45 @@ static int gctm (lua_State *L) {
294 298
295 299
296static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { 300static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
297 const char *reason;
298 void **reg = ll_register(L, path); 301 void **reg = ll_register(L, path);
299 if (*reg == NULL) *reg = ll_load(L, path); 302 if (*reg == NULL) *reg = ll_load(L, path);
300 if (*reg == NULL) 303 if (*reg == NULL)
301 reason = LIB_FAIL; 304 return ERRLIB; /* unable to load library */
302 else { 305 else {
303 lua_CFunction f = ll_sym(L, *reg, sym); 306 lua_CFunction f = ll_sym(L, *reg, sym);
304 if (f) { 307 if (f == NULL)
305 lua_pushcfunction(L, f); 308 return ERRFUNC; /* unable to find function */
306 return 1; /* return function */ 309 lua_pushcfunction(L, f);
307 } 310 return 0; /* return function */
308 reason = "init";
309 } 311 }
310 lua_pushnil(L);
311 lua_insert(L, -2);
312 lua_pushstring(L, reason);
313 return 3; /* return nil, ll_error, reason */
314} 312}
315 313
316 314
317static int ll_loadlib (lua_State *L) { 315static int ll_loadlib (lua_State *L) {
318 const char *path = luaL_checkstring(L, 1); 316 const char *path = luaL_checkstring(L, 1);
319 const char *init = luaL_checkstring(L, 2); 317 const char *init = luaL_checkstring(L, 2);
320 return ll_loadfunc(L, path, init); 318 int stat = ll_loadfunc(L, path, init);
319 if (stat == 0) /* no errors? */
320 return 1; /* return the loaded function */
321 else { /* error; error message is on stack top */
322 lua_pushnil(L);
323 lua_insert(L, -2);
324 lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
325 return 3; /* return nil, error message, and where */
326 }
321} 327}
322 328
323 329
324 330
325/* 331/*
326** {====================================================== 332** {======================================================
327** `require' and `module' functions 333** 'require' function
328** ======================================================= 334** =======================================================
329*/ 335*/
330 336
331 337
332static int readable (const char *fname) { 338static int readable (const char *filename) {
333 FILE *f = fopen(fname, "r"); /* try to open file */ 339 FILE *f = fopen(filename, "r"); /* try to open file */
334 if (f == NULL) return 0; /* open failed */ 340 if (f == NULL) return 0; /* open failed */
335 fclose(f); 341 fclose(f);
336 return 1; 342 return 1;
@@ -348,53 +354,85 @@ static const char *pushnexttemplate (lua_State *L, const char *path) {
348} 354}
349 355
350 356
351static const char *findfile (lua_State *L, const char *pname) { 357static const char *findfile (lua_State *L, const char *name,
358 const char *pname) {
352 const char *path; 359 const char *path;
353 const char *name = luaL_checkstring(L, 1);
354 name = luaL_gsub(L, name, ".", LUA_DIRSEP); 360 name = luaL_gsub(L, name, ".", LUA_DIRSEP);
355 lua_getfield(L, LUA_ENVIRONINDEX, pname); 361 lua_getfield(L, LUA_ENVIRONINDEX, pname);
356 path = lua_tostring(L, -1); 362 path = lua_tostring(L, -1);
357 if (path == NULL) 363 if (path == NULL)
358 luaL_error(L, LUA_QL("package.%s") " must be a string", pname); 364 luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
359 while ((path = pushnexttemplate(L, path)) != NULL) { 365 while ((path = pushnexttemplate(L, path)) != NULL) {
360 const char *fname; 366 const char *filename;
361 fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); 367 filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
362 if (readable(fname)) /* does file exist and is readable? */ 368 if (readable(filename)) /* does file exist and is readable? */
363 return fname; /* return that file name */ 369 return filename; /* return that file name */
364 lua_pop(L, 2); /* remove path template and file name */ 370 lua_pop(L, 2); /* remove path template and file name */
365 } 371 }
366 return NULL; /* not found */ 372 return NULL; /* not found */
367} 373}
368 374
369 375
370static void loaderror (lua_State *L, const char *msg) { 376static void loaderror (lua_State *L) {
371 luaL_error(L, "error loading package " LUA_QS " (%s)", 377 luaL_error(L, "error loading package " LUA_QS " (%s)",
372 lua_tostring(L, 1), msg); 378 lua_tostring(L, 1), lua_tostring(L, -1));
373} 379}
374 380
375 381
376static int loader_Lua (lua_State *L) { 382static int loader_Lua (lua_State *L) {
377 const char *fname; 383 const char *filename;
378 fname = findfile(L, "path"); 384 const char *name = luaL_checkstring(L, 1);
379 if (fname == NULL) return 0; /* library not found in this path */ 385 filename = findfile(L, name, "path");
380 if (luaL_loadfile(L, fname) != 0) 386 if (filename == NULL) return 0; /* library not found in this path */
381 loaderror(L, lua_tostring(L, -1)); 387 if (luaL_loadfile(L, filename) != 0)
388 loaderror(L);
382 return 1; /* library loaded successfully */ 389 return 1; /* library loaded successfully */
383} 390}
384 391
385 392
386static int loader_C (lua_State *L) { 393static const char *mkfuncname (lua_State *L, const char *modname) {
387 const char *funcname; 394 const char *funcname;
388 const char *fname = findfile(L, "cpath"); 395 const char *mark = strchr(modname, *LUA_IGMARK);
389 if (fname == NULL) return 0; /* library not found in this path */ 396 if (mark) modname = mark + 1;
390 funcname = luaL_gsub(L, lua_tostring(L, 1), ".", LUA_OFSEP); 397 funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
391 funcname = lua_pushfstring(L, POF"%s", funcname); 398 funcname = lua_pushfstring(L, POF"%s", funcname);
392 if (ll_loadfunc(L, fname, funcname) != 1) 399 lua_remove(L, -2); /* remove 'gsub' result */
393 loaderror(L, lua_tostring(L, -2)); 400 return funcname;
401}
402
403
404static int loader_C (lua_State *L) {
405 const char *funcname;
406 const char *name = luaL_checkstring(L, 1);
407 const char *filename = findfile(L, name, "cpath");
408 if (filename == NULL) return 0; /* library not found in this path */
409 funcname = mkfuncname(L, name);
410 if (ll_loadfunc(L, filename, funcname) != 0)
411 loaderror(L);
394 return 1; /* library loaded successfully */ 412 return 1; /* library loaded successfully */
395} 413}
396 414
397 415
416static int loader_Croot (lua_State *L) {
417 const char *funcname;
418 const char *filename;
419 const char *name = luaL_checkstring(L, 1);
420 const char *p = strchr(name, '.');
421 int stat;
422 if (p == NULL) return 0; /* is root */
423 lua_pushlstring(L, name, p - name);
424 filename = findfile(L, lua_tostring(L, -1), "cpath");
425 if (filename == NULL) return 0; /* root not found */
426 funcname = mkfuncname(L, name);
427 if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
428 if (stat == ERRFUNC) return 0; /* function not found */
429 else
430 loaderror(L); /* real error */
431 }
432 return 1;
433}
434
435
398static int loader_preload (lua_State *L) { 436static int loader_preload (lua_State *L) {
399 lua_getfield(L, LUA_ENVIRONINDEX, "preload"); 437 lua_getfield(L, LUA_ENVIRONINDEX, "preload");
400 if (!lua_istable(L, -1)) 438 if (!lua_istable(L, -1))
@@ -440,36 +478,22 @@ static int require_aux (lua_State *L, const char *name) {
440} 478}
441 479
442 480
443static void require_check (lua_State *L, const char *name) {
444 if (!require_aux(L, name)) { /* error? */
445 /* build and show error message */
446 const char *msg;
447 lua_settop(L, 1);
448 lua_getfield(L, LUA_ENVIRONINDEX, "path");
449 lua_getfield(L, LUA_ENVIRONINDEX, "cpath");
450 msg = lua_pushfstring(L,
451 "package " LUA_QS " not found in following paths:\n"
452 " Lua path: %s\n"
453 " C path: %s\n", name,
454 lua_tostring(L, -2), lua_tostring(L, -1));
455 msg = luaL_gsub(L, msg, LUA_PATHSEP, "\n ");
456 luaL_error(L, msg);
457 }
458}
459
460
461static int ll_require (lua_State *L) { 481static int ll_require (lua_State *L) {
462 const char *name = luaL_checkstring(L, 1); 482 const char *name = luaL_checkstring(L, 1);
463 const char *pt; 483 if (!require_aux(L, name)) /* error? */
464 /* load all parent modules */ 484 luaL_error(L, "package " LUA_QS " not found", name);
465 for (pt = name; (pt = strchr(pt, '.')) != NULL; pt++) {
466 lua_settop(L, 1);
467 lua_pushlstring(L, name, pt - name);
468 require_aux(L, lua_tostring(L, -1));
469 }
470 require_check(L, name); /* load module itself */
471 return 1; 485 return 1;
472} 486}
487
488/* }====================================================== */
489
490
491
492/*
493** {======================================================
494** 'module' function
495** =======================================================
496*/
473 497
474 498
475static void setfenv (lua_State *L) { 499static void setfenv (lua_State *L) {
@@ -524,14 +548,14 @@ static int ll_module (lua_State *L) {
524 return 0; 548 return 0;
525} 549}
526 550
527
528/* }====================================================== */ 551/* }====================================================== */
529 552
530 553
554
531/* auxiliary mark (for internal use) */ 555/* auxiliary mark (for internal use) */
532#define AUXMARK "\1" 556#define AUXMARK "\1"
533 557
534static void setpath (lua_State *L, const char *fname, const char *envname, 558static void setpath (lua_State *L, const char *fieldname, const char *envname,
535 const char *def) { 559 const char *def) {
536 const char *path = getenv(envname); 560 const char *path = getenv(envname);
537 if (path == NULL) /* no environment variable? */ 561 if (path == NULL) /* no environment variable? */
@@ -544,7 +568,7 @@ static void setpath (lua_State *L, const char *fname, const char *envname,
544 lua_remove(L, -2); 568 lua_remove(L, -2);
545 } 569 }
546 setprogdir(L); 570 setprogdir(L);
547 lua_setfield(L, -2, fname); 571 lua_setfield(L, -2, fieldname);
548} 572}
549 573
550 574
@@ -556,7 +580,7 @@ static const luaL_reg ll_funcs[] = {
556 580
557 581
558static const lua_CFunction loaders[] = 582static const lua_CFunction loaders[] =
559 {loader_preload, loader_Lua, loader_C, NULL}; 583 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
560 584
561 585
562LUALIB_API int luaopen_loadlib (lua_State *L) { 586LUALIB_API int luaopen_loadlib (lua_State *L) {