Browse Source

bring in latest filename code from panda

David Rose 22 years ago
parent
commit
fa5f359fa3
5 changed files with 162 additions and 62 deletions
  1. 1 1
      ppremake/configure.in
  2. 52 15
      ppremake/dSearchPath.cxx
  3. 9 6
      ppremake/dSearchPath.h
  4. 99 40
      ppremake/filename.cxx
  5. 1 0
      ppremake/filename.h

+ 1 - 1
ppremake/configure.in

@@ -42,7 +42,7 @@ AC_SUBST(libm)
 
 
 dnl Checks for header files.
 dnl Checks for header files.
 AC_HEADER_STDC
 AC_HEADER_STDC
-AC_CHECK_HEADERS(malloc.h alloca.h unistd.h utime.h io.h minmax.h dirent.h sys/types.h sys/time.h sys/utime.h sys/wait.h string.h regex.h getopt.h)
+AC_CHECK_HEADERS(malloc.h alloca.h unistd.h utime.h io.h minmax.h dirent.h glob.h sys/types.h sys/time.h sys/utime.h sys/wait.h string.h regex.h getopt.h)
 
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 dnl Checks for typedefs, structures, and compiler characteristics.
 
 

+ 52 - 15
ppremake/dSearchPath.cxx

@@ -85,12 +85,22 @@ get_num_files() const {
 //       Access: Public
 //       Access: Public
 //  Description: Returns the nth file on the result list.
 //  Description: Returns the nth file on the result list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Filename DSearchPath::Results::
+const Filename &DSearchPath::Results::
 get_file(int n) const {
 get_file(int n) const {
   assert(n >= 0 && n < (int)_files.size());
   assert(n >= 0 && n < (int)_files.size());
   return _files[n];
   return _files[n];
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DSearchPath::Results::add_file
+//       Access: Public
+//  Description: Adds a new file to the result list.
+////////////////////////////////////////////////////////////////////
+void DSearchPath::Results::
+add_file(const Filename &file) {
+  _files.push_back(file);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DSearchPath::Default Constructor
 //     Function: DSearchPath::Default Constructor
 //       Access: Public
 //       Access: Public
@@ -246,7 +256,7 @@ get_num_directories() const {
 //       Access: Public
 //       Access: Public
 //  Description: Returns the nth directory on the search list.
 //  Description: Returns the nth directory on the search list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Filename DSearchPath::
+const Filename &DSearchPath::
 get_directory(int n) const {
 get_directory(int n) const {
   assert(n >= 0 && n < (int)_directories.size());
   assert(n >= 0 && n < (int)_directories.size());
   return _directories[n];
   return _directories[n];
@@ -262,11 +272,22 @@ get_directory(int n) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Filename DSearchPath::
 Filename DSearchPath::
 find_file(const Filename &filename) const {
 find_file(const Filename &filename) const {
-  Directories::const_iterator di;
-  for (di = _directories.begin(); di != _directories.end(); ++di) {
-    Filename match((*di), filename);
-    if (match.exists()) {
-      return match;
+  if (filename.is_local()) {
+    Directories::const_iterator di;
+    for (di = _directories.begin(); di != _directories.end(); ++di) {
+      Filename match((*di), filename);
+      if (match.exists()) {
+        if ((*di) == "." && filename.is_fully_qualified()) {
+          // A special case for the "." directory: to avoid prefixing
+          // an endless stream of ./ in front of files, if the
+          // filename already has a ./ prefixed
+          // (i.e. is_fully_qualified() is true), we don't
+          // prefix another one.
+          return filename;
+        } else {
+          return match;
+        }
+      }
     }
     }
   }
   }
 
 
@@ -280,21 +301,37 @@ find_file(const Filename &filename) const {
 //               the indicated file, in order.  Fills up the results
 //               the indicated file, in order.  Fills up the results
 //               list with *all* of the matching filenames found, if
 //               list with *all* of the matching filenames found, if
 //               any.  Returns the number of matches found.
 //               any.  Returns the number of matches found.
+//
+//               It is the responsibility of the the caller to clear
+//               the results list first; otherwise, the newly-found
+//               files will be appended to the list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int DSearchPath::
 int DSearchPath::
 find_all_files(const Filename &filename,
 find_all_files(const Filename &filename,
                DSearchPath::Results &results) const {
                DSearchPath::Results &results) const {
-  results._files.clear();
-
-  Directories::const_iterator di;
-  for (di = _directories.begin(); di != _directories.end(); ++di) {
-    Filename match((*di), filename);
-    if (match.exists()) {
-      results._files.push_back(match);
+  int num_added = 0;
+
+  if (filename.is_local()) {
+    Directories::const_iterator di;
+    for (di = _directories.begin(); di != _directories.end(); ++di) {
+      Filename match((*di), filename);
+      if (match.exists()) {
+        if ((*di) == "." && filename.is_fully_qualified()) {
+          // A special case for the "." directory: to avoid prefixing
+          // an endless stream of ./ in front of files, if the
+          // filename already has a ./ prefixed
+          // (i.e. is_fully_qualified() is true), we don't
+          // prefix another one.
+          results.add_file(filename);
+        } else {
+          results.add_file(match);
+        }
+        num_added++;
+      }
     }
     }
   }
   }
 
 
-  return results._files.size();
+  return num_added;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 9 - 6
ppremake/dSearchPath.h

@@ -22,9 +22,10 @@
 #include "ppremake.h"
 #include "ppremake.h"
 
 
 #include "filename.h"
 #include "filename.h"
-
 #include <vector>
 #include <vector>
 
 
+#define pvector std::vector
+
 ///////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////
 //       Class : DSearchPath
 //       Class : DSearchPath
 // Description : This class stores a list of directories that can be
 // Description : This class stores a list of directories that can be
@@ -45,12 +46,14 @@ public:
 
 
     void clear();
     void clear();
     int get_num_files() const;
     int get_num_files() const;
-    Filename get_file(int n) const;
+    const Filename &get_file(int n) const;
+
+  public:
+    void add_file(const Filename &file);
 
 
   private:
   private:
-    typedef vector<Filename> Files;
+    typedef pvector<Filename> Files;
     Files _files;
     Files _files;
-    friend class DSearchPath;
   };
   };
 
 
 PUBLISHED:
 PUBLISHED:
@@ -70,7 +73,7 @@ PUBLISHED:
 
 
   bool is_empty() const;
   bool is_empty() const;
   int get_num_directories() const;
   int get_num_directories() const;
-  Filename get_directory(int n) const;
+  const Filename &get_directory(int n) const;
 
 
   Filename find_file(const Filename &filename) const;
   Filename find_file(const Filename &filename) const;
   int find_all_files(const Filename &filename, Results &results) const;
   int find_all_files(const Filename &filename, Results &results) const;
@@ -83,7 +86,7 @@ PUBLISHED:
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;
 
 
 private:
 private:
-  typedef vector<Filename> Directories;
+  typedef pvector<Filename> Directories;
   Directories _directories;
   Directories _directories;
 };
 };
 
 

+ 99 - 40
ppremake/filename.cxx

@@ -33,6 +33,10 @@
 #include <fcntl.h>
 #include <fcntl.h>
 #endif
 #endif
 
 
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif
+
 #ifdef HAVE_DIRENT_H
 #ifdef HAVE_DIRENT_H
 #include <dirent.h>
 #include <dirent.h>
 #endif
 #endif
@@ -705,44 +709,14 @@ make_canonical() {
     return false;
     return false;
   }
   }
 
 
-  // Temporarily save the current working directory.
-  Filename cwd = ExecutionEnvironment::get_cwd();
-
-  if (is_directory()) {
-    // If the filename itself represents a directory and not a
-    // filename, cd to the named directory, not the one above it.
-    string dirname = to_os_specific();
-
-    if (chdir(dirname.c_str()) < 0) {
-      return false;
-    }
-    (*this) = ExecutionEnvironment::get_cwd();
-
-  } else {
-    // Otherwise, if the filename represents a regular file (or
-    // doesn't even exist), cd to the directory above.
-    Filename dir(get_dirname());
-
-    if (dir.empty()) {
-      // No dirname means the file is in this directory.
-      set_dirname(cwd);
-      return true;
-    }
-
-    string dirname = dir.to_os_specific();
-    if (chdir(dirname.c_str()) < 0) {
-      return false;
-    }
-    set_dirname(ExecutionEnvironment::get_cwd().get_fullpath());
-  }
-
-  // Now restore the current working directory.
-  string osdir = cwd.to_os_specific();
-  if (chdir(osdir.c_str()) < 0) {
-    cerr << "Error!  Cannot change back to " << cwd << "\n";
+  if (get_fullpath() == "/") {
+    // The root directory is a special case.
+    return true;
   }
   }
 
 
-  return true;
+  // Temporarily save the current working directory.
+  Filename cwd = ExecutionEnvironment::get_cwd();
+  return r_make_canonical(cwd);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1182,7 +1156,32 @@ find_on_searchpath(const DSearchPath &searchpath) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Filename::
 bool Filename::
 scan_directory(vector_string &contents) const {
 scan_directory(vector_string &contents) const {
-#if defined(HAVE_DIRENT_H)
+#if defined(HAVE_GLOB_H)
+  // In some cases, particularly with NFS, it seems that opendir()
+  // .. readdir() fails to properly read the entire directory ("Value
+  // too large for defined data type"), but glob() succeeds.
+  string dirname;
+  if (empty()) {
+    dirname = "*";
+  } else if (_filename[_filename.length() - 1] == '/') {
+    dirname = _filename + "*";
+  } else {
+    dirname = _filename + "/*";
+  }
+
+  glob_t globbuf;
+
+  int r = glob(dirname.c_str(), GLOB_ERR, NULL, &globbuf);
+  size_t offset = dirname.size() - 1;
+
+  for (int i = 0; globbuf.gl_pathv[i] != NULL; i++) {
+    contents.push_back(globbuf.gl_pathv[i] + offset);
+  }
+  globfree(&globbuf);
+
+  return true;
+
+#elif defined(HAVE_DIRENT_H)
   size_t orig_size = contents.size();
   size_t orig_size = contents.size();
 
 
   string dirname;
   string dirname;
@@ -1193,6 +1192,7 @@ scan_directory(vector_string &contents) const {
   }
   }
   DIR *root = opendir(dirname.c_str());
   DIR *root = opendir(dirname.c_str());
   if (root == (DIR *)NULL) {
   if (root == (DIR *)NULL) {
+    perror(dirname.c_str());
     return false;
     return false;
   }
   }
 
 
@@ -1204,6 +1204,12 @@ scan_directory(vector_string &contents) const {
     }
     }
     d = readdir(root);
     d = readdir(root);
   }
   }
+  if (errno != 0 && errno != ENOENT && errno != ENOTDIR) {
+    cerr << "Error occurred while scanning directory " << dirname << "\n";
+    perror(dirname.c_str());
+    closedir(root);
+    return false;
+  }
   closedir(root);
   closedir(root);
 
 
   sort(contents.begin() + orig_size, contents.end());
   sort(contents.begin() + orig_size, contents.end());
@@ -1379,14 +1385,20 @@ open_append(ofstream &stream) const {
 //               false otherwise.  This requires the setting of the
 //               false otherwise.  This requires the setting of the
 //               set_text()/set_binary() flags to open the file
 //               set_text()/set_binary() flags to open the file
 //               appropriately as indicated; it is an error to call
 //               appropriately as indicated; it is an error to call
-//               open_read() without first calling one of set_text()
-//               or set_binary().
+//               open_read_write() without first calling one of
+//               set_text() or set_binary().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Filename::
 bool Filename::
 open_read_write(fstream &stream) const {
 open_read_write(fstream &stream) const {
   assert(is_text() || is_binary());
   assert(is_text() || is_binary());
 
 
-  ios_openmode open_mode = ios::in | ios::out;
+  ios_openmode open_mode = ios::out | ios::in;
+
+  // Since ios::in also seems to imply ios::nocreate (!), we must
+  // guarantee the file already exists before we try to open it.
+  if (!exists()) {
+    touch();
+  }
 
 
 #ifdef HAVE_IOS_BINARY
 #ifdef HAVE_IOS_BINARY
   // For some reason, some systems (like Irix) don't define
   // For some reason, some systems (like Irix) don't define
@@ -1731,3 +1743,50 @@ count_slashes(const string &str) {
   return count;
   return count;
 }
 }
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::r_make_canonical
+//       Access: Private
+//  Description: The recursive implementation of make_canonical().
+////////////////////////////////////////////////////////////////////
+bool Filename::
+r_make_canonical(const Filename &cwd) {
+  if (get_fullpath() == "/") {
+    // If we reached the root, the whole path doesn't exist.  Report
+    // failure.
+    return false;
+  }
+
+  // First, try to cd to the filename directly.
+  string os_specific = to_os_specific();
+
+  if (chdir(os_specific.c_str()) >= 0) {
+    // That worked, save the full path string.
+    (*this) = ExecutionEnvironment::get_cwd();
+
+    // And restore the current working directory.
+    string osdir = cwd.to_os_specific();
+    if (chdir(osdir.c_str()) < 0) {
+      cerr << "Error!  Cannot change back to " << cwd << "\n";
+    }
+    return true;
+  }
+
+  // That didn't work; maybe it's not a directory.  Recursively go to
+  // the directory above.
+
+  Filename dir(get_dirname());
+  
+  if (dir.empty()) {
+    // No dirname means the file is in this directory.
+    set_dirname(cwd);
+    return true;
+  }
+  
+  if (!dir.r_make_canonical(cwd)) {
+    return false;
+  }
+  set_dirname(dir);
+  return true;
+}
+

+ 1 - 0
ppremake/filename.h

@@ -175,6 +175,7 @@ private:
   void locate_extension();
   void locate_extension();
   size_t get_common_prefix(const string &other) const;
   size_t get_common_prefix(const string &other) const;
   static int count_slashes(const string &str);
   static int count_slashes(const string &str);
+  bool r_make_canonical(const Filename &cwd);
 
 
   string _filename;
   string _filename;
   // We'll make these size_t instead of string::size_type to help out
   // We'll make these size_t instead of string::size_type to help out