summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-01-11 13:33:48 (GMT)
committerBrad King <brad.king@kitware.com>2008-01-11 13:33:48 (GMT)
commita6d32b96ed3e6fec59d84e33eb08e7bf6642ffe9 (patch)
tree7994bec071a8f285182afabfcec9aa1379f2e851
parentd7c7ab0927fe944323114ce516433493572b9c4d (diff)
downloadCMake-a6d32b96ed3e6fec59d84e33eb08e7bf6642ffe9.zip
CMake-a6d32b96ed3e6fec59d84e33eb08e7bf6642ffe9.tar.gz
CMake-a6d32b96ed3e6fec59d84e33eb08e7bf6642ffe9.tar.bz2
ENH: Add SystemTools::SplitPathRootComponent and re-implement SplitPath to use it. Add better treatment of user home directory paths.
-rw-r--r--Source/kwsys/SystemTools.cxx133
-rw-r--r--Source/kwsys/SystemTools.hxx.in26
2 files changed, 119 insertions, 40 deletions
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 977133f..dbcf230 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2975,81 +2975,144 @@ kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
}
//----------------------------------------------------------------------------
-void SystemTools::SplitPath(const char* p,
- kwsys_stl::vector<kwsys_stl::string>& components)
+const char* SystemTools::SplitPathRootComponent(const char* p,
+ kwsys_stl::string* root)
{
- components.clear();
// Identify the root component.
const char* c = p;
if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\'))
{
// Network path.
- components.push_back("//");
+ if(root)
+ {
+ *root = "//";
+ }
c += 2;
}
else if(c[0] == '/')
{
// Unix path.
- components.push_back("/");
+ if(root)
+ {
+ *root = "/";
+ }
c += 1;
}
else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\'))
{
// Windows path.
- kwsys_stl::string root = "_:/";
- root[0] = c[0];
- components.push_back(root);
+ if(root)
+ {
+ (*root) = "_:/";
+ (*root)[0] = c[0];
+ }
c += 3;
}
else if(c[0] && c[1] == ':')
{
// Path relative to a windows drive working directory.
- kwsys_stl::string root = "_:";
- root[0] = c[0];
- components.push_back(root);
+ if(root)
+ {
+ (*root) = "_:";
+ (*root)[0] = c[0];
+ }
c += 2;
}
-#ifdef HAVE_GETPWNAM
else if(c[0] == '~')
{
- int numChars = 1;
- while(c[numChars] && c[numChars] != '/')
+ // Home directory. The returned root should always have a
+ // trailing slash so that appending components as
+ // c[0]c[1]/c[2]/... works. The remaining path returned should
+ // skip the first slash if it exists:
+ //
+ // "~" : root = "~/" , return ""
+ // "~/ : root = "~/" , return ""
+ // "~/x : root = "~/" , return "x"
+ // "~u" : root = "~u/", return ""
+ // "~u/" : root = "~u/", return ""
+ // "~u/x" : root = "~u/", return "x"
+ int n = 1;
+ while(c[n] && c[n] != '/')
{
- numChars++;
+ ++n;
}
- const char* homedir;
- if(numChars == 1)
+ if(root)
{
- homedir = getenv("HOME");
+ root->assign(c, n);
+ *root += '/';
}
- else
+ if(c[n] == '/')
+ {
+ ++n;
+ }
+ c += n;
+ }
+ else
+ {
+ // Relative path.
+ if(root)
{
- char user[PATH_MAX];
- strncpy(user, c+1, numChars-1);
- user[numChars] = '\0';
- passwd* pw = getpwnam(user);
- if(p)
+ *root = "";
+ }
+ }
+
+ // Return the remaining path.
+ return c;
+}
+
+//----------------------------------------------------------------------------
+void SystemTools::SplitPath(const char* p,
+ kwsys_stl::vector<kwsys_stl::string>& components,
+ bool expand_home_dir)
+{
+ const char* c = p;
+ components.clear();
+
+ // Identify the root component.
+ {
+ kwsys_stl::string root;
+ c = SystemTools::SplitPathRootComponent(c, &root);
+
+ // Expand home directory references if requested.
+ if(expand_home_dir && !root.empty() && root[0] == '~')
+ {
+ kwsys_stl::string homedir;
+ root = root.substr(0, root.size()-1);
+ if(root.size() == 1)
+ {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if(const char* h = getenv("USERPROFILE"))
{
- homedir = pw->pw_dir;
+ homedir = h;
}
else
+#endif
+ if(const char* h = getenv("HOME"))
{
- homedir = "";
+ homedir = h;
+ }
+ }
+#ifdef HAVE_GETPWNAM
+ else if(passwd* pw = getpwnam(root.c_str()+1))
+ {
+ if(pw->pw_dir)
+ {
+ homedir = pw->pw_dir;
}
}
- kwsys_stl::vector<kwsys_stl::string> home_components;
- SystemTools::SplitPath(homedir, home_components);
- components.insert(components.end(),
- home_components.begin(),
- home_components.end());
- c += numChars;
- }
#endif
+ if(!homedir.empty() && (homedir[homedir.size()-1] == '/' ||
+ homedir[homedir.size()-1] == '\\'))
+ {
+ homedir = homedir.substr(0, homedir.size()-1);
+ }
+ SystemTools::SplitPath(homedir.c_str(), components);
+ }
else
{
- // Relative path.
- components.push_back("");
+ components.push_back(root);
}
+ }
// Parse the remaining components.
const char* first = c;
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 4845851..fa8c7ad 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -351,20 +351,36 @@ public:
const char* in_base);
/**
- * Split a path name into its basic components. The first component
- * is one of the following roots:
- * "/" = UNIX
+ * Split a path name into its root component and the rest of the
+ * path. The root component is one of the following:
+ * "/" = UNIX full path
* "c:/" = Windows full path (can be any drive letter)
* "c:" = Windows drive-letter relative path (can be any drive letter)
* "//" = Network path
+ * "~" = Home path for current user
+ * "~u" = Home path for user 'u'
* "" = Relative path
+ *
+ * A pointer to the rest of the path after the root component is
+ * returned. The root component is stored in the "root" string if
+ * given.
+ */
+ static const char* SplitPathRootComponent(const char* p,
+ kwsys_stl::string* root=0);
+
+ /**
+ * Split a path name into its basic components. The first component
+ * is one of the roots returned by SplitPathRootComponent.
* The remaining components form the path. If there is a trailing
* slash then the last component is the empty string. The
* components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to
- * produce the original path.
+ * produce the original path. Home directory references are
+ * automatically expanded if expand_home_dir is true and this
+ * platform supports them.
*/
static void SplitPath(const char* p,
- kwsys_stl::vector<kwsys_stl::string>& components);
+ kwsys_stl::vector<kwsys_stl::string>& components,
+ bool expand_home_dir = true);
/**
* Join components of a path name into a single string. See