From 28112bfb7f0f1f689310716b8feea1b4e52e5b1f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 11 Nov 2011 03:06:06 +0000 Subject: [PATCH] use home-grown solution for path_expand(), rather than wordexp() which is broken in different ways on different platforms git-svn-id: svn://localhost/ardour2/branches/3.0@10535 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/utils.cc | 102 +++++++++++++++++++++++-------------------- libs/ardour/wscript | 1 - 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 3c6963bbc1..0549698383 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -25,6 +25,7 @@ #include /* for sprintf */ #include +#include #include #include #include @@ -37,14 +38,11 @@ #include #include #include +#include #include #include -#ifdef HAVE_WORDEXP -#include -#endif - #include "pbd/cpus.h" #include "pbd/error.h" #include "pbd/stacktrace.h" @@ -282,58 +280,68 @@ path_expand (string path) return path; } -#ifdef HAVE_WORDEXP - /* Handle tilde and environment variable expansion in session path */ - string ret = path; - string quoted; - wordexp_t expansion; + /* tilde expansion */ - /* wordexp cannot be forced (it appears) into either - - (1) NOT doing field splitting - (2) splitting based on something other than whitespace - - (despite the documentation claiming that it obeys IFS etc). + if (path[0] == '~') { + if (path.length() == 1) { + return Glib::get_home_dir(); + } - so, quote the most likely spaces to occur in a path, and that should - be about as much as we can do. - */ + if (path[1] == '/') { + path.replace (0, 1, Glib::get_home_dir()); + } else { + /* can't handle ~roger, so just leave it */ + } + } - quoted = path; - replace_all (quoted, " ", "\\ "); + /* now do $VAR substitution, since wordexp isn't reliable */ - switch (wordexp (quoted.c_str(), &expansion, WRDE_NOCMD|WRDE_UNDEF)) { - case 0: - break; - case WRDE_NOSPACE: - /* see docs on wordexp() */ - wordfree (&expansion); - /* fallthru */ - default: - error << string_compose (_("illegal or badly-formed string used for path (%1)"), path) << endmsg; - goto out; - } + regex_t compiled_pattern; + const int nmatches = 100; + regmatch_t matches[nmatches]; + + if (regcomp (&compiled_pattern, "\\$([a-zA-Z_][a-zA-Z0-9_]*|\\{[a-zA-Z_][a-zA-Z0-9_]*\\})", REG_EXTENDED)) { + cerr << "bad regcomp\n"; + return path; + } - if (expansion.we_wordc > 1) { - string all; - for (unsigned int i = 0; i < expansion.we_wordc; ++i) { - if (i > 0) { - all += " | "; - } - all += expansion.we_wordv[i]; + while (true) { + + cerr << "working on " << path << endl; + + if (regexec (&compiled_pattern, path.c_str(), nmatches, matches, 0)) { + break; } - error << string_compose (_("path (%1) is ambiguous: %2"), path, all) << endmsg; - goto out; + + /* matches[0] gives the entire match */ + + string match = path.substr (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so); + + /* try to get match from the environment */ + + if (match[1] == '{') { + /* ${FOO} form */ + match = match.substr (2, match.length() - 3); + } + + char* matched_value = getenv (match.c_str()); + + if (matched_value) { + path.replace (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so, matched_value); + } else { + path.replace (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so, string()); + } + + /* go back and do it again with whatever remains after the + * substitution + */ } - ret = expansion.we_wordv[0]; - out: - wordfree (&expansion); - return ret; + /* canonicalize */ -#else - return path; -#endif + char buf[PATH_MAX+1]; + realpath (path.c_str(), buf); + return buf; } #if __APPLE__ diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 7716ad1fad..4582d79b4f 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -278,7 +278,6 @@ def configure(conf): conf.define('CURRENT_SESSION_FILE_VERSION', CURRENT_SESSION_FILE_VERSION) conf.check(header_name='sys/vfs.h', define_name='HAVE_SYS_VFS_H',mandatory=False) - conf.check(header_name='wordexp.h', define_name='HAVE_WORDEXP',mandatory=False) conf.check(header_name='jack/session.h', uselib = [ 'JACK' ], define_name='HAVE_JACK_SESSION')