Fix: problems whith bare $ORIGIN without relative dir

actually the iterator was written quite contrieved;
now doing the token replacement as a separate first
step -- makes matters way simpler
This commit is contained in:
Fischlurch 2011-02-15 00:16:25 +01:00
parent aef929b3d9
commit dca5b81710
2 changed files with 27 additions and 40 deletions

View file

@ -39,7 +39,7 @@ namespace lib {
regex SearchPathSplitter::EXTRACT_PATHSPEC ("(\\$?ORIGIN/?)?([^:]*)");
const regex SearchPathSplitter::EXTRACT_PATHSPEC ("[^:]+");
/** @internal helper to figure out the installation directory,
@ -62,6 +62,22 @@ namespace lib {
}
/** @internal helper to replace all $ORIGIN prefixes in a given string
* by the directory holding the current executable
* @note also picks ORIGIN, $ORIGIN/, ORIGIN/
*/
string
replaceTokens (string const& src)
{
static const regex PICK_ORIGIN_TOKEN ("\\$?ORIGIN/?");
static const string expandedOriginDir
= fsys::path (findExePath()).remove_leaf().directory_string();
return boost::regex_replace(src, PICK_ORIGIN_TOKEN, expandedOriginDir);
}
string
@ -85,7 +101,7 @@ namespace lib {
throw error::Config ("Module \""+moduleName+"\" not found"
+ (searchPath.empty()? ".":" in search path: "+searchPath));
} }
} // namespace lib

View file

@ -53,15 +53,17 @@ namespace lib {
/** retrieve the location of the executable */
string findExePath();
/** replace $ORIGIN tokens in the given string
* @return copy with expansions applied */
string replaceTokens (string const& src);
/**
* Helper: Access a path Specification as a sequence of filesystem Paths.
* This iterator class dissects a ':'-separated path list. The individual
* components may use the symbol \c $ORIGIN to denote the directory holding
* the current executable. After resolving this symbol, a valid absolute or
* relative filesystem path should result, which must not denote an existing
* file (directory is OK).
* @note #fetch picks the current component and advances the iteration.
* the current executable.
* @note #next picks the current component and advances the iteration.
*/
class SearchPathSplitter
: public BoolCheckable<SearchPathSplitter
@ -71,11 +73,11 @@ namespace lib {
sregex_iterator pos_,
end_;
static regex EXTRACT_PATHSPEC;
static const regex EXTRACT_PATHSPEC;
public:
SearchPathSplitter (string const& searchPath)
: pathSpec_(searchPath)
: pathSpec_(replaceTokens (searchPath))
, pos_(pathSpec_.begin(),pathSpec_.end(), EXTRACT_PATHSPEC)
, end_()
{ }
@ -93,41 +95,10 @@ namespace lib {
throw error::Logic ("Search path exhausted."
,LUMIERA_ERROR_ITER_EXHAUST);
string currentPathElement = resolveRelative();
string currentPathElement = pos_->str();
++pos_;
return currentPathElement;
}
private:
/** maybe resolve a path spec given relative to
* the current Executable location ($ORIGIN) */
string
resolveRelative ()
{
if (containsORIGINToken())
return asAbsolutePath();
else
return getFullPath();
}
SubMatch found(int group=0) { return (*pos_)[group]; }
bool containsORIGINToken() { return found(1).matched; }
string getRelativePath() { return found(2); }
string getFullPath() { return found(); }
string
asAbsolutePath()
{
fsys::path exePathName (findExePath());
fsys::path modPathName (exePathName.remove_leaf() / getRelativePath());
if (fsys::exists(modPathName) && !fsys::is_directory (modPathName))
throw error::Invalid ("Error in search path: component \""+modPathName.string()+"\" is not a directory"
,LUMIERA_ERROR_FILE_NOT_DIRECTORY);
return modPathName.directory_string();
}
};