|
@@ -290,22 +290,33 @@ static int noenv (lua_State *L) {
|
|
|
static void setpath (lua_State *L, const char *fieldname,
|
|
|
const char *envname,
|
|
|
const char *dft) {
|
|
|
+ const char *dftmark;
|
|
|
const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
|
|
|
- const char *path = getenv(nver); /* use versioned name */
|
|
|
- if (path == NULL) /* no environment variable? */
|
|
|
+ const char *path = getenv(nver); /* try versioned name */
|
|
|
+ if (path == NULL) /* no versioned environment variable? */
|
|
|
path = getenv(envname); /* try unversioned name */
|
|
|
if (path == NULL || noenv(L)) /* no environment variable? */
|
|
|
lua_pushstring(L, dft); /* use default */
|
|
|
- else {
|
|
|
- /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
|
|
|
- path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
|
|
|
- LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
|
|
|
- luaL_gsub(L, path, AUXMARK, dft);
|
|
|
- lua_remove(L, -2); /* remove result from 1st 'gsub' */
|
|
|
+ else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
|
|
|
+ lua_pushstring(L, path); /* nothing to change */
|
|
|
+ else { /* path contains a ";;": insert default path in its place */
|
|
|
+ size_t len = strlen(path);
|
|
|
+ luaL_Buffer b;
|
|
|
+ luaL_buffinit(L, &b);
|
|
|
+ if (path < dftmark) { /* is there a prefix before ';;'? */
|
|
|
+ luaL_addlstring(&b, path, dftmark - path); /* add it */
|
|
|
+ luaL_addchar(&b, *LUA_PATH_SEP);
|
|
|
+ }
|
|
|
+ luaL_addstring(&b, dft); /* add default */
|
|
|
+ if (dftmark < path + len - 2) { /* is there a sufix after ';;'? */
|
|
|
+ luaL_addchar(&b, *LUA_PATH_SEP);
|
|
|
+ luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark);
|
|
|
+ }
|
|
|
+ luaL_pushresult(&b);
|
|
|
}
|
|
|
setprogdir(L);
|
|
|
lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
|
|
|
- lua_pop(L, 1); /* pop versioned variable name */
|
|
|
+ lua_pop(L, 1); /* pop versioned variable name ('nver') */
|
|
|
}
|
|
|
|
|
|
/* }================================================================== */
|
|
@@ -421,17 +432,26 @@ static int readable (const char *filename) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-static const char *pushnextfilename (lua_State *L, const char *path) {
|
|
|
- const char *l;
|
|
|
- if (*path == *LUA_PATH_SEP)
|
|
|
- path++; /* skip separator */
|
|
|
- if (*path == '\0')
|
|
|
+/*
|
|
|
+** Get the next name in '*path' = 'name1;name2;name3;...', changing
|
|
|
+** the ending ';' to '\0' to create a zero-terminated string. Return
|
|
|
+** NULL when list ends.
|
|
|
+*/
|
|
|
+static const char *getnextfilename (char **path, char *end) {
|
|
|
+ char *sep;
|
|
|
+ char *name = *path;
|
|
|
+ if (name == end)
|
|
|
return NULL; /* no more names */
|
|
|
- l = strchr(path, *LUA_PATH_SEP); /* find next separator */
|
|
|
- if (l == NULL) /* no more separators? */
|
|
|
- l = path + strlen(path); /* go until the end */
|
|
|
- lua_pushlstring(L, path, l - path); /* file name */
|
|
|
- return l; /* rest of the path */
|
|
|
+ else if (*name == '\0') { /* from previous iteration? */
|
|
|
+ *name = *LUA_PATH_SEP; /* restore separator */
|
|
|
+ name++; /* skip it */
|
|
|
+ }
|
|
|
+ sep = strchr(name, *LUA_PATH_SEP); /* find next separator */
|
|
|
+ if (sep == NULL) /* separator not found? */
|
|
|
+ sep = end; /* name goes until the end */
|
|
|
+ *sep = '\0'; /* finish file name */
|
|
|
+ *path = sep; /* will start next search from here */
|
|
|
+ return name;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -442,12 +462,12 @@ static const char *pushnextfilename (lua_State *L, const char *path) {
|
|
|
** no file 'blublu.so'
|
|
|
*/
|
|
|
static void pusherrornotfound (lua_State *L, const char *path) {
|
|
|
- if (*path == *LUA_PATH_SEP)
|
|
|
- path++; /* skip separator */
|
|
|
- lua_pushstring(L, "\n\tno file '");
|
|
|
- luaL_gsub(L, path, LUA_PATH_SEP, "'\n\tno file '");
|
|
|
- lua_pushstring(L, "'");
|
|
|
- lua_concat(L, 3);
|
|
|
+ luaL_Buffer b;
|
|
|
+ luaL_buffinit(L, &b);
|
|
|
+ luaL_addstring(&b, "\n\tno file '");
|
|
|
+ luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '");
|
|
|
+ luaL_addstring(&b, "'");
|
|
|
+ luaL_pushresult(&b);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -455,17 +475,24 @@ static const char *searchpath (lua_State *L, const char *name,
|
|
|
const char *path,
|
|
|
const char *sep,
|
|
|
const char *dirsep) {
|
|
|
+ luaL_Buffer buff;
|
|
|
+ char *pathname; /* path with name inserted */
|
|
|
+ char *endpathname; /* its end */
|
|
|
+ const char *filename;
|
|
|
/* separator is non-empty and appears in 'name'? */
|
|
|
if (*sep != '\0' && strchr(name, *sep) != NULL)
|
|
|
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
|
|
|
- /* replace marks ('?') in 'path' by the file name */
|
|
|
- path = luaL_gsub(L, path, LUA_PATH_MARK, name);
|
|
|
- while ((path = pushnextfilename(L, path)) != NULL) {
|
|
|
- const char *filename = lua_tostring(L, -1);
|
|
|
+ luaL_buffinit(L, &buff);
|
|
|
+ /* add path to the buffer, replacing marks ('?') with the file name */
|
|
|
+ luaL_addgsub(&buff, path, LUA_PATH_MARK, name);
|
|
|
+ luaL_addchar(&buff, '\0');
|
|
|
+ pathname = luaL_buffaddr(&buff); /* writable list of file names */
|
|
|
+ endpathname = pathname + luaL_bufflen(&buff) - 1;
|
|
|
+ while ((filename = getnextfilename(&pathname, endpathname)) != NULL) {
|
|
|
if (readable(filename)) /* does file exist and is readable? */
|
|
|
- return filename; /* return that file name */
|
|
|
- lua_pop(L, 1); /* else remove file name */
|
|
|
+ return lua_pushstring(L, filename); /* save and return name */
|
|
|
}
|
|
|
+ luaL_pushresult(&buff); /* push path to create error message */
|
|
|
pusherrornotfound(L, lua_tostring(L, -1)); /* create error message */
|
|
|
return NULL; /* not found */
|
|
|
}
|