summaryrefslogtreecommitdiff
path: root/lbaselib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-15 17:54:41 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-15 17:54:41 -0300
commit391c5459cbfb2a01a66b318f42cf780d952704b7 (patch)
tree1b2251c3b7cd7da0580ea29b75d93241e77af7c0 /lbaselib.c
parent62dd4cbe91617741a9f8e594201ad510d073b12d (diff)
downloadlua-391c5459cbfb2a01a66b318f42cf780d952704b7.tar.gz
lua-391c5459cbfb2a01a66b318f42cf780d952704b7.tar.bz2
lua-391c5459cbfb2a01a66b318f42cf780d952704b7.zip
new implementation for `require' (with templates)
Diffstat (limited to 'lbaselib.c')
-rw-r--r--lbaselib.c175
1 files changed, 119 insertions, 56 deletions
diff --git a/lbaselib.c b/lbaselib.c
index 2aaafe43..227d576c 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.66 2002/04/09 20:19:06 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.67 2002/04/12 19:57:29 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -200,6 +200,23 @@ static int luaB_next (lua_State *L) {
200} 200}
201 201
202 202
203static int luaB_nexti (lua_State *L) {
204 lua_Number i = lua_tonumber(L, 2);
205 luaL_check_type(L, 1, LUA_TTABLE);
206 if (i == 0) { /* `for' start? */
207 lua_getglobal(L, "nexti"); /* return generator, */
208 lua_pushvalue(L, 1); /* state, */
209 lua_pushnumber(L, 1); /* and initial value */
210 return 3;
211 }
212 else { /* `for' step */
213 lua_pushnumber(L, i+1); /* next value */
214 lua_rawgeti(L, 1, i);
215 return (lua_isnil(L, -1)) ? 0 : 2;
216 }
217}
218
219
203static int passresults (lua_State *L, int status, int oldtop) { 220static int passresults (lua_State *L, int status, int oldtop) {
204 if (status == 0) { 221 if (status == 0) {
205 int nresults = lua_gettop(L) - oldtop; 222 int nresults = lua_gettop(L) - oldtop;
@@ -259,58 +276,6 @@ static int luaB_assert (lua_State *L) {
259} 276}
260 277
261 278
262#define LUA_PATH "LUA_PATH"
263
264#define LUA_PATH_SEP ";"
265
266#ifndef LUA_PATH_DEFAULT
267#define LUA_PATH_DEFAULT "./"
268#endif
269
270static int luaB_require (lua_State *L) {
271 const char *path;
272 luaL_check_string(L, 1);
273 lua_settop(L, 1);
274 lua_getglobal(L, LUA_PATH); /* get path */
275 if (lua_isstring(L, 2)) /* is LUA_PATH defined? */
276 path = lua_tostring(L, 2);
277 else { /* LUA_PATH not defined */
278 lua_pop(L, 1); /* pop old global value */
279 path = getenv(LUA_PATH); /* try environment variable */
280 if (path == NULL) path = LUA_PATH_DEFAULT; /* else use default */
281 lua_pushstring(L, path);
282 lua_pushvalue(L, -1); /* duplicate to leave a copy on stack */
283 lua_setglobal(L, LUA_PATH);
284 }
285 lua_pushvalue(L, 1); /* check package's name in book-keeping table */
286 lua_gettable(L, lua_upvalueindex(1));
287 if (!lua_isnil(L, -1)) /* is it there? */
288 return 0; /* package is already loaded */
289 else { /* must load it */
290 for (;;) { /* traverse path */
291 int res;
292 int l = strcspn(path, LUA_PATH_SEP); /* find separator */
293 lua_pushlstring(L, path, l); /* directory name */
294 lua_pushvalue(L, 1); /* package name */
295 lua_concat(L, 2); /* concat directory with package name */
296 res = lua_dofile(L, lua_tostring(L, -1)); /* try to load it */
297 lua_settop(L, 2); /* pop string and eventual results from dofile */
298 if (res == 0) break; /* ok; file done */
299 else if (res != LUA_ERRFILE)
300 lua_error(L, NULL); /* error running package; propagate it */
301 if (*(path+l) == '\0') /* no more directories? */
302 luaL_verror(L, "could not load package `%.20s' from path `%.200s'",
303 lua_tostring(L, 1), lua_tostring(L, 2));
304 path += l+1; /* try next directory */
305 }
306 }
307 lua_pushvalue(L, 1);
308 lua_pushnumber(L, 1);
309 lua_settable(L, lua_upvalueindex(1)); /* mark it as loaded */
310 return 0;
311}
312
313
314static int aux_unpack (lua_State *L, int arg) { 279static int aux_unpack (lua_State *L, int arg) {
315 int n, i; 280 int n, i;
316 luaL_check_type(L, arg, LUA_TTABLE); 281 luaL_check_type(L, arg, LUA_TTABLE);
@@ -395,6 +360,104 @@ static int luaB_tostring (lua_State *L) {
395} 360}
396 361
397 362
363
364/*
365** {======================================================
366** `require' function
367** =======================================================
368*/
369
370
371/* name of global that holds table with loaded packages */
372#define REQTAB "_LOADED"
373
374/* name of global that holds the search path for packages */
375#define LUA_PATH "LUA_PATH"
376
377#ifndef LUA_PATH_SEP
378#define LUA_PATH_SEP ';'
379#endif
380
381#ifndef LUA_PATH_DEFAULT
382#define LUA_PATH_DEFAULT "?.lua"
383#endif
384
385
386static const char *getpath (lua_State *L) {
387 const char *path;
388 lua_getglobal(L, LUA_PATH); /* try global variable */
389 path = lua_tostring(L, -1);
390 if (path) return path;
391 path = getenv(LUA_PATH); /* else try environment variable */
392 if (path) return path;
393 return LUA_PATH_DEFAULT; /* else use default */
394}
395
396
397static const char *nextpath (lua_State *L, const char *path) {
398 const char *l;
399 if (*path == '\0') return NULL; /* no more pathes */
400 if (*path == LUA_PATH_SEP) path++; /* skip separator */
401 l = strchr(path, LUA_PATH_SEP); /* find next separator */
402 if (l == NULL) l = path+strlen(path);
403 lua_pushlstring(L, path, l - path); /* directory name */
404 return l;
405}
406
407
408static void composename (lua_State *L) {
409 const char *path = lua_tostring(L, -1);
410 const char *wild = strchr(path, '?');
411 if (wild == NULL) return; /* no wild char; path is the file name */
412 lua_pushlstring(L, path, wild - path);
413 lua_pushvalue(L, 1); /* package name */
414 lua_pushstring(L, wild + 1);
415 lua_concat(L, 3);
416}
417
418
419static int luaB_require (lua_State *L) {
420 const char *path;
421 int status = LUA_ERRFILE; /* not found (yet) */
422 luaL_check_string(L, 1);
423 lua_settop(L, 1);
424 lua_pushvalue(L, 1);
425 lua_setglobal(L, "_REQUIREDNAME");
426 lua_getglobal(L, REQTAB);
427 if (!lua_istable(L, 2)) lua_error(L, REQTAB " is not a table");
428 path = getpath(L);
429 lua_pushvalue(L, 1); /* check package's name in book-keeping table */
430 lua_gettable(L, 2);
431 if (!lua_isnil(L, -1)) /* is it there? */
432 return 0; /* package is already loaded */
433 else { /* must load it */
434 while (status == LUA_ERRFILE && (path = nextpath(L, path)) != NULL) {
435 composename(L);
436 status = lua_dofile(L, lua_tostring(L, -1)); /* try to load it */
437 lua_settop(L, 3); /* pop string and eventual results from dofile */
438 }
439 }
440 switch (status) {
441 case 0: {
442 lua_pushvalue(L, 1);
443 lua_pushboolean(L, 1);
444 lua_settable(L, 2); /* mark it as loaded */
445 return 0;
446 }
447 case LUA_ERRFILE: { /* file not found */
448 luaL_verror(L, "could not load package `%.20s' from path `%.200s'",
449 lua_tostring(L, 1), lua_tostring(L, 3));
450 }
451 default: { /* error loading package */
452 lua_error(L, NULL);
453 return 0; /* to avoid warnings */
454 }
455 }
456}
457
458/* }====================================================== */
459
460
398static const luaL_reg base_funcs[] = { 461static const luaL_reg base_funcs[] = {
399 {LUA_ALERT, luaB__ALERT}, 462 {LUA_ALERT, luaB__ALERT},
400 {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE}, 463 {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE},
@@ -402,6 +465,7 @@ static const luaL_reg base_funcs[] = {
402 {"metatable", luaB_metatable}, 465 {"metatable", luaB_metatable},
403 {"globals", luaB_globals}, 466 {"globals", luaB_globals},
404 {"next", luaB_next}, 467 {"next", luaB_next},
468 {"nexti", luaB_nexti},
405 {"print", luaB_print}, 469 {"print", luaB_print},
406 {"tonumber", luaB_tonumber}, 470 {"tonumber", luaB_tonumber},
407 {"tostring", luaB_tostring}, 471 {"tostring", luaB_tostring},
@@ -417,6 +481,7 @@ static const luaL_reg base_funcs[] = {
417 {"loadstring", luaB_loadstring}, 481 {"loadstring", luaB_loadstring},
418 {"dofile", luaB_dofile}, 482 {"dofile", luaB_dofile},
419 {"dostring", luaB_dostring}, 483 {"dostring", luaB_dostring},
484 {"require", luaB_require},
420 {NULL, NULL} 485 {NULL, NULL}
421}; 486};
422 487
@@ -511,10 +576,8 @@ static void base_open (lua_State *L) {
511LUALIB_API int lua_baselibopen (lua_State *L) { 576LUALIB_API int lua_baselibopen (lua_State *L) {
512 base_open(L); 577 base_open(L);
513 co_open(L); 578 co_open(L);
514 /* `require' needs an empty table as upvalue */
515 lua_newtable(L); 579 lua_newtable(L);
516 lua_pushcclosure(L, luaB_require, 1); 580 lua_setglobal(L, REQTAB);
517 lua_setglobal(L, "require");
518 return 0; 581 return 0;
519} 582}
520 583