[cmake-commits] king committed SystemTools.cxx 1.217 1.218 SystemTools.hxx.in 1.70 1.71

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Jan 11 08:33:50 EST 2008


Update of /cvsroot/CMake/CMake/Source/kwsys
In directory public:/mounts/ram/cvs-serv16541/Source/kwsys

Modified Files:
	SystemTools.cxx SystemTools.hxx.in 
Log Message:
ENH: Add SystemTools::SplitPathRootComponent and re-implement SplitPath to use it.  Add better treatment of user home directory paths.


Index: SystemTools.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/kwsys/SystemTools.cxx,v
retrieving revision 1.217
retrieving revision 1.218
diff -u -d -r1.217 -r1.218
--- SystemTools.cxx	15 Dec 2007 01:31:27 -0000	1.217
+++ SystemTools.cxx	11 Jan 2008 13:33:48 -0000	1.218
@@ -2975,81 +2975,144 @@
 }
 
 //----------------------------------------------------------------------------
-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] == '/')
       {
-      char user[PATH_MAX];
-      strncpy(user, c+1, numChars-1);
-      user[numChars] = '\0';
-      passwd* pw = getpwnam(user);
-      if(p)
+      ++n;
+      }
+    c += n;
+    }
+  else
+    {
+    // Relative path.
+    if(root)
+      {
+      *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;

Index: SystemTools.hxx.in
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/kwsys/SystemTools.hxx.in,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -d -r1.70 -r1.71
--- SystemTools.hxx.in	15 Dec 2007 01:31:27 -0000	1.70
+++ SystemTools.hxx.in	11 Jan 2008 13:33:48 -0000	1.71
@@ -351,20 +351,36 @@
                                             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



More information about the Cmake-commits mailing list