X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Futils.cc;h=8588d9ccd6015f1d005d4c669fa3a86de211efe2;hb=a107b95307658af9f881e453362c1388ffac2463;hp=e1cd35398b775ec97d48456be0b3e12724e9d7cc;hpb=500aaa0deeb386df94fddc4474aa6de43331becb;p=ardour.git diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index e1cd35398b..8588d9ccd6 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -25,6 +25,8 @@ #include /* for sprintf */ #include +#include +#include #include #include #include @@ -36,20 +38,18 @@ #include #include #include +#include #include #include -#ifdef HAVE_WORDEXP -#include -#endif - #include "pbd/cpus.h" #include "pbd/error.h" #include "pbd/stacktrace.h" #include "pbd/xml++.h" #include "pbd/basename.h" #include "pbd/strsplit.h" +#include "pbd/replace_all.h" #include "ardour/utils.h" #include "ardour/rc_configuration.h" @@ -75,7 +75,7 @@ legalize_for_path (const string& str) pos += 1; } - return legal; + return string (legal); } string @@ -280,32 +280,101 @@ path_expand (string path) return path; } -#ifdef HAVE_WORDEXP - /* Handle tilde and environment variable expansion in session path */ - string ret = path; + /* tilde expansion */ - wordexp_t expansion; - switch (wordexp (path.c_str(), &expansion, WRDE_NOCMD|WRDE_UNDEF)) { - case 0: - break; - default: - error << string_compose (_("illegal or badly-formed string used for path (%1)"), path) << endmsg; - goto out; + if (path[0] == '~') { + if (path.length() == 1) { + return Glib::get_home_dir(); + } + + if (path[1] == '/') { + path.replace (0, 1, Glib::get_home_dir()); + } else { + /* can't handle ~roger, so just leave it */ + } + } + + /* now do $VAR substitution, since wordexp isn't reliable */ + + 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; + } + + while (true) { + + if (regexec (&compiled_pattern, path.c_str(), nmatches, matches, 0)) { + break; + } + + /* 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 + */ + } + + regfree (&compiled_pattern); + + /* canonicalize */ + + char buf[PATH_MAX+1]; + + if (realpath (path.c_str(), buf)) { + return buf; + } else { + error << string_compose (_("programming error: realpath(%1) failed, errcode %2"), path, errno) << endmsg; + return path; } +} + +string +search_path_expand (string path) +{ + if (path.empty()) { + return path; + } + + vector s; + vector n; + + split (path, s, ':'); - if (expansion.we_wordc > 1) { - error << string_compose (_("path (%1) is ambiguous"), path) << endmsg; - goto out; + for (vector::iterator i = s.begin(); i != s.end(); ++i) { + n.push_back (path_expand (*i)); } - ret = expansion.we_wordv[0]; - out: - wordfree (&expansion); - return ret; + string r; -#else - return path; -#endif + for (vector::iterator i = n.begin(); i != n.end(); ++i) { + if (!r.empty()) { + r += ':'; + } + r += *i; + } + + return r; } #if __APPLE__ @@ -561,6 +630,17 @@ string_is_affirmative (const std::string& str) { /* to be used only with XML data - not intended to handle user input */ + if (str.empty ()) { + return false; + } + + /* the use of g_strncasecmp() is solely to get around issues with + * charsets posed by trying to use C++ for the same + * comparison. switching a std::string to its lower- or upper-case + * version has several issues, but handled by default + * in the way we desire when doing it in C. + */ + return str == "1" || str == "y" || str == "Y" || (!g_strncasecmp(str.c_str(), "yes", str.length())); }