bring in latest filename code from panda

This commit is contained in:
David Rose 2004-02-02 21:27:05 +00:00
parent 9492316ed7
commit fa5f359fa3
5 changed files with 161 additions and 61 deletions

View File

@ -42,7 +42,7 @@ AC_SUBST(libm)
dnl Checks for header files.
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.

View File

@ -85,12 +85,22 @@ get_num_files() const {
// Access: Public
// Description: Returns the nth file on the result list.
////////////////////////////////////////////////////////////////////
Filename DSearchPath::Results::
const Filename &DSearchPath::Results::
get_file(int n) const {
assert(n >= 0 && n < (int)_files.size());
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
// Access: Public
@ -246,7 +256,7 @@ get_num_directories() const {
// Access: Public
// Description: Returns the nth directory on the search list.
////////////////////////////////////////////////////////////////////
Filename DSearchPath::
const Filename &DSearchPath::
get_directory(int n) const {
assert(n >= 0 && n < (int)_directories.size());
return _directories[n];
@ -262,11 +272,22 @@ get_directory(int n) const {
////////////////////////////////////////////////////////////////////
Filename DSearchPath::
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
// list with *all* of the matching filenames found, if
// 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::
find_all_files(const Filename &filename,
DSearchPath::Results &results) const {
results._files.clear();
int num_added = 0;
Directories::const_iterator di;
for (di = _directories.begin(); di != _directories.end(); ++di) {
Filename match((*di), filename);
if (match.exists()) {
results._files.push_back(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.
results.add_file(filename);
} else {
results.add_file(match);
}
num_added++;
}
}
}
return results._files.size();
return num_added;
}
////////////////////////////////////////////////////////////////////

View File

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

View File

@ -33,6 +33,10 @@
#include <fcntl.h>
#endif
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
@ -705,44 +709,14 @@ make_canonical() {
return false;
}
if (get_fullpath() == "/") {
// The root directory is a special case.
return true;
}
// 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";
}
return true;
return r_make_canonical(cwd);
}
////////////////////////////////////////////////////////////////////
@ -1182,7 +1156,32 @@ find_on_searchpath(const DSearchPath &searchpath) {
////////////////////////////////////////////////////////////////////
bool Filename::
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();
string dirname;
@ -1193,6 +1192,7 @@ scan_directory(vector_string &contents) const {
}
DIR *root = opendir(dirname.c_str());
if (root == (DIR *)NULL) {
perror(dirname.c_str());
return false;
}
@ -1204,6 +1204,12 @@ scan_directory(vector_string &contents) const {
}
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);
sort(contents.begin() + orig_size, contents.end());
@ -1379,14 +1385,20 @@ open_append(ofstream &stream) const {
// false otherwise. This requires the setting of the
// set_text()/set_binary() flags to open the file
// 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::
open_read_write(fstream &stream) const {
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
// For some reason, some systems (like Irix) don't define
@ -1731,3 +1743,50 @@ count_slashes(const string &str) {
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;
}

View File

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