'searchpath' creates less temporary strings

When creating error messages, package loaders may create dozens of
temporary strings (one or more for each tried template). This change
reduces the number of these strings, and avoid creating some of
them if the search is successful.
This commit is contained in:
Roberto Ierusalimschy 2018-07-09 13:29:08 -03:00
parent de2caf7ee4
commit ccf6d098f6
1 changed files with 34 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: loadlib.c,v 1.131 2017/12/13 12:51:42 roberto Exp roberto $ ** $Id: loadlib.c,v 1.133 2018/07/06 13:38:38 roberto Exp $
** Dynamic library loader for Lua ** Dynamic library loader for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
** **
@ -421,14 +421,33 @@ static int readable (const char *filename) {
} }
static const char *pushnexttemplate (lua_State *L, const char *path) { static const char *pushnextfilename (lua_State *L, const char *path) {
const char *l; const char *l;
while (*path == *LUA_PATH_SEP) path++; /* skip separators */ if (*path == *LUA_PATH_SEP)
if (*path == '\0') return NULL; /* no more templates */ path++; /* skip separator */
if (*path == '\0')
return NULL; /* no more names */
l = strchr(path, *LUA_PATH_SEP); /* find next separator */ l = strchr(path, *LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path + strlen(path); if (l == NULL) /* no more separators? */
lua_pushlstring(L, path, l - path); /* template */ l = path + strlen(path); /* go until the end */
return l; lua_pushlstring(L, path, l - path); /* file name */
return l; /* rest of the path */
}
/*
** Given a path such as ";blabla.so;blublu.so", pushes the string
**
** no file 'blabla.so'
** 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);
} }
@ -436,21 +455,18 @@ static const char *searchpath (lua_State *L, const char *name,
const char *path, const char *path,
const char *sep, const char *sep,
const char *dirsep) { const char *dirsep) {
luaL_Buffer msg; /* to build error message */ /* separator is non-empty and appears in 'name'? */
if (*sep != '\0') /* non-empty separator? */ if (*sep != '\0' && strchr(name, *sep) != NULL)
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
luaL_buffinit(L, &msg); /* replace marks ('?') in 'path' by the file name */
while ((path = pushnexttemplate(L, path)) != NULL) { path = luaL_gsub(L, path, LUA_PATH_MARK, name);
const char *filename = luaL_gsub(L, lua_tostring(L, -1), while ((path = pushnextfilename(L, path)) != NULL) {
LUA_PATH_MARK, name); const char *filename = lua_tostring(L, -1);
lua_remove(L, -2); /* remove path template */
if (readable(filename)) /* does file exist and is readable? */ if (readable(filename)) /* does file exist and is readable? */
return filename; /* return that file name */ return filename; /* return that file name */
lua_pushfstring(L, "\n\tno file '%s'", filename); lua_pop(L, 1); /* else remove file name */
lua_remove(L, -2); /* remove file name */
luaL_addvalue(&msg); /* concatenate error msg. entry */
} }
luaL_pushresult(&msg); /* create error message */ pusherrornotfound(L, lua_tostring(L, -1)); /* create error message */
return NULL; /* not found */ return NULL; /* not found */
} }