get latest filename code, build on Irix

This commit is contained in:
David Rose 2003-03-05 21:06:24 +00:00
parent 7588017984
commit adda410582
6 changed files with 307 additions and 44 deletions

View File

@ -31,6 +31,81 @@
#define getcwd _getcwd
#endif
////////////////////////////////////////////////////////////////////
// Function: ExecutionEnvironment::get_environment_variable
// Access: Public, Static
// Description: Returns the definition of the indicated environment
// variable, or the empty string if the variable is
// undefined. The nonstatic implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
get_environment_variable(const string &var) {
const char *def = getenv(var.c_str());
if (def != (char *)NULL) {
return def;
}
return string();
}
////////////////////////////////////////////////////////////////////
// Function: ExecutionEnviroment::expand_string
// Access: Public, Static
// Description: Reads the string, looking for environment variable
// names marked by a $. Expands all such variable
// names. A repeated dollar sign ($$) is mapped to a
// single dollar sign.
//
// Returns the expanded string.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
expand_string(const string &str) {
string result;
size_t last = 0;
size_t dollar = str.find('$');
while (dollar != string::npos && dollar + 1 < str.length()) {
size_t start = dollar + 1;
if (str[start] == '$') {
// A double dollar sign maps to a single dollar sign.
result += str.substr(last, start - last);
last = start + 1;
} else {
string varname;
size_t end = start;
if (str[start] == '{') {
// Curly braces delimit the variable name explicitly.
end = str.find('}', start + 1);
if (end != string::npos) {
varname = str.substr(start + 1, end - (start + 1));
end++;
}
}
if (end == start) {
// Scan for the end of the variable name.
while (end < str.length() && (isalnum(str[end]) || str[end] == '_')) {
end++;
}
varname = str.substr(start, end - start);
}
string subst =
result += str.substr(last, dollar - last);
result += get_environment_variable(varname);
last = end;
}
dollar = str.find('$', last);
}
result += str.substr(last);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: ExecutionEnviroment::get_cwd
// Access: Public, Static

View File

@ -30,6 +30,8 @@
////////////////////////////////////////////////////////////////////
class ExecutionEnvironment {
public:
static string get_environment_variable(const string &var);
static string expand_string(const string &str);
static Filename get_cwd();
};

View File

@ -52,6 +52,12 @@
#include <windows.h>
#endif
// The MSVC 6.0 Win32 SDK lacks the following definitions, so we define them
// here for compatibility.
#ifndef FILE_ATTRIBUTE_DEVICE
#define FILE_ATTRIBUTE_DEVICE 0x00000040
#endif
// We might have been linked with the Cygwin dll. This is ideal if it
// is available, because it allows Panda to access all the Cygwin
// mount definitions if they are in use. If the Cygwin dll is not
@ -99,7 +105,7 @@ get_panda_root() {
panda_root = front_to_back_slash(envvar);
}
if (!panda_root.empty() && panda_root[panda_root.length() - 1] != '\\') {
if (panda_root.empty() || panda_root[panda_root.length() - 1] != '\\') {
panda_root += '\\';
}
@ -110,7 +116,7 @@ get_panda_root() {
}
static string
convert_pathname(const string &unix_style_pathname) {
convert_pathname(const string &unix_style_pathname, bool use_backslash) {
if (unix_style_pathname.empty()) {
return string();
}
@ -133,7 +139,11 @@ convert_pathname(const string &unix_style_pathname) {
// It doesn't even start from the root, so we don't have to do
// anything fancy--relative pathnames are the same in Windows as
// in Unix, except for the direction of the slashes.
windows_pathname = front_to_back_slash(unix_style_pathname);
if (use_backslash) {
windows_pathname = front_to_back_slash(unix_style_pathname);
} else {
windows_pathname = unix_style_pathname;
}
} else if (unix_style_pathname.length() > 3 &&
isalpha(unix_style_pathname[1]) &&
@ -145,9 +155,15 @@ convert_pathname(const string &unix_style_pathname) {
// compilers (e.g. Cygwin's gcc 2.95.3) happy; so that they do not
// confuse this string constructor with one that takes two
// iterators.
windows_pathname =
string(1, (char)toupper(unix_style_pathname[1])) + ":" +
front_to_back_slash(unix_style_pathname.substr(2));
if (use_backslash) {
windows_pathname =
string(1, (char)toupper(unix_style_pathname[1])) + ":" +
front_to_back_slash(unix_style_pathname.substr(2));
} else {
windows_pathname =
string(1, (char)toupper(unix_style_pathname[1])) + ":" +
unix_style_pathname.substr(2);
}
} else {
// It starts with a slash, but the first part is not a single
@ -157,29 +173,37 @@ convert_pathname(const string &unix_style_pathname) {
// Use Cygwin to convert it if possible.
char result[4096] = "";
cygwin_conv_to_win32_path(unix_style_pathname.c_str(), result);
windows_pathname = result;
if (use_backslash) {
windows_pathname = result;
} else {
windows_pathname = back_to_front_slash(result);
}
#else // HAVE_CYGWIN
// Without Cygwin, just prefix $PANDA_ROOT.
windows_pathname =
get_panda_root() + front_to_back_slash(unix_style_pathname.substr(1));
windows_pathname = get_panda_root();
if (use_backslash) {
windows_pathname += front_to_back_slash(unix_style_pathname.substr(1));
} else {
windows_pathname += unix_style_pathname.substr(1);
}
#endif // HAVE_CYGWIN
}
return windows_pathname;
}
string
convert_dso_pathname(const string &unix_style_pathname) {
static string
convert_dso_pathname(const string &unix_style_pathname, bool use_backslash) {
// If the extension is .so, change it to .dll.
size_t dot = unix_style_pathname.rfind('.');
if (dot == string::npos ||
unix_style_pathname.find('/', dot) != string::npos) {
// No filename extension.
return convert_pathname(unix_style_pathname);
return convert_pathname(unix_style_pathname, use_backslash);
}
if (unix_style_pathname.substr(dot) != ".so") {
// Some other extension.
return convert_pathname(unix_style_pathname);
return convert_pathname(unix_style_pathname, use_backslash);
}
string dll_basename = unix_style_pathname.substr(0, dot);
@ -196,27 +220,27 @@ convert_dso_pathname(const string &unix_style_pathname) {
// somewhere on the LD_LIBRARY_PATH, or on PATH, or any of a number
// of nutty places.
return convert_pathname(dll_basename + "_d.dll");
return convert_pathname(dll_basename + "_d.dll", use_backslash);
#else
return convert_pathname(dll_basename + ".dll");
return convert_pathname(dll_basename + ".dll", use_backslash);
#endif
}
string
convert_executable_pathname(const string &unix_style_pathname) {
static string
convert_executable_pathname(const string &unix_style_pathname, bool use_backslash) {
// If the extension is not .exe, append .exe.
size_t dot = unix_style_pathname.rfind('.');
if (dot == string::npos ||
unix_style_pathname.find('/', dot) != string::npos) {
// No filename extension.
return convert_pathname(unix_style_pathname + ".exe");
return convert_pathname(unix_style_pathname + ".exe", use_backslash);
}
if (unix_style_pathname.substr(dot) != ".exe") {
// Some other extension.
return convert_pathname(unix_style_pathname + ".exe");
return convert_pathname(unix_style_pathname + ".exe", use_backslash);
}
return convert_pathname(unix_style_pathname);
return convert_pathname(unix_style_pathname, use_backslash);
}
#endif //WIN32
@ -313,6 +337,19 @@ from_os_specific(const string &os_specific, Filename::Type type) {
#endif // WIN32
}
////////////////////////////////////////////////////////////////////
// Function: Filename::expand_from
// Access: Public, Static
// Description: Returns the same thing as from_os_specific(), but
// embedded environment variable references
// (e.g. "$DMODELS/foo.txt") are expanded out.
////////////////////////////////////////////////////////////////////
Filename Filename::
expand_from(const string &os_specific, Filename::Type type) {
return from_os_specific(ExecutionEnvironment::expand_string(os_specific),
type);
}
////////////////////////////////////////////////////////////////////
// Function: Filename::temporary
// Access: Public
@ -505,6 +542,39 @@ set_extension(const string &s) {
}
}
////////////////////////////////////////////////////////////////////
// Function: Filename::extract_components
// Access: Public
// Description: Extracts out the individual directory components of
// the path into a series of strings. get_basename()
// will be the last component stored in the vector.
// Note that no distinction is made by this method
// between a leading slash and no leading slash, but you
// can call is_local() to differentiate the two cases.
////////////////////////////////////////////////////////////////////
void Filename::
extract_components(vector_string &components) const {
components.clear();
size_t p = 0;
if (!_filename.empty() && _filename[0] == '/') {
// Skip the leading slash.
p = 1;
}
while (p < _filename.length()) {
size_t q = _filename.find('/', p);
if (q == string::npos) {
components.push_back(_filename.substr(p));
return;
}
components.push_back(_filename.substr(p, q - p));
p = q + 1;
}
// A trailing slash means we have an empty get_basename().
components.push_back(string());
}
////////////////////////////////////////////////////////////////////
// Function: Filename::standardize
// Access: Public
@ -700,11 +770,48 @@ to_os_specific() const {
#ifdef WIN32
switch (get_type()) {
case T_dso:
return convert_dso_pathname(standard.get_fullpath());
return convert_dso_pathname(standard.get_fullpath(), true);
case T_executable:
return convert_executable_pathname(standard.get_fullpath());
return convert_executable_pathname(standard.get_fullpath(), true);
default:
return convert_pathname(standard.get_fullpath());
return convert_pathname(standard.get_fullpath(), true);
}
#else // WIN32
return standard;
#endif // WIN32
}
////////////////////////////////////////////////////////////////////
// Function: Filename::to_os_generic
// Access: Public
// Description: This is similar to to_os_specific(), but it is
// designed to generate a filename that can be
// understood on as many platforms as possible. Since
// Windows can usually understand a
// forward-slash-delimited filename, this means it does
// the same thing as to_os_specific(), but it uses
// forward slashes instead of backslashes.
//
// This method has a pretty limited use; it should
// generally be used for writing file references to a
// file that might be read on any operating system.
////////////////////////////////////////////////////////////////////
string Filename::
to_os_generic() const {
if (empty()) {
return string();
}
Filename standard(*this);
standard.standardize();
#ifdef WIN32
switch (get_type()) {
case T_dso:
return convert_dso_pathname(standard.get_fullpath(), false);
case T_executable:
return convert_executable_pathname(standard.get_fullpath(), false);
default:
return convert_pathname(standard.get_fullpath(), false);
}
#else // WIN32
return standard;
@ -1158,7 +1265,7 @@ bool Filename::
open_read(ifstream &stream) const {
assert(is_text() || is_binary());
ios::openmode open_mode = ios::in;
ios_openmode open_mode = ios::in;
#ifdef HAVE_IOS_BINARY
// For some reason, some systems (like Irix) don't define
@ -1184,12 +1291,30 @@ open_read(ifstream &stream) const {
// appropriately as indicated; it is an error to call
// open_read() without first calling one of set_text()
// or set_binary().
//
// If truncate is true, the file is truncated to zero
// length upon opening it, if it already exists.
// Otherwise, the file is kept at its original length.
////////////////////////////////////////////////////////////////////
bool Filename::
open_write(ofstream &stream) const {
open_write(ofstream &stream, bool truncate) const {
assert(is_text() || is_binary());
ios::openmode open_mode = ios::out;
ios_openmode open_mode = ios::out;
if (truncate) {
open_mode |= ios::trunc;
} else {
// Some systems insist on having ios::in set to prevent the file
// from being truncated when we open it. Makes ios::trunc kind of
// pointless, doesn't it? On the other hand, setting ios::in also
// seems to imply ios::nocreate (!), so we should only set this if
// the file already exists.
if (exists()) {
open_mode |= ios::in;
}
}
#ifdef HAVE_IOS_BINARY
// For some reason, some systems (like Irix) don't define
@ -1225,7 +1350,7 @@ bool Filename::
open_append(ofstream &stream) const {
assert(is_text() || is_binary());
ios::openmode open_mode = ios::app;
ios_openmode open_mode = ios::app;
#ifdef HAVE_IOS_BINARY
// For some reason, some systems (like Irix) don't define
@ -1261,7 +1386,7 @@ 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::in | ios::out;
#ifdef HAVE_IOS_BINARY
// For some reason, some systems (like Irix) don't define
@ -1292,7 +1417,36 @@ open_read_write(fstream &stream) const {
////////////////////////////////////////////////////////////////////
bool Filename::
touch() const {
#ifdef HAVE_UTIME_H
#ifdef WIN32_VC
// In Windows, we have to use the Windows API to do this reliably.
// First, guarantee the file exists (and also get its handle).
string os_specific = to_os_specific();
HANDLE fhandle;
fhandle = CreateFile(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fhandle == INVALID_HANDLE_VALUE) {
return false;
}
// Now update the file time and date.
SYSTEMTIME sysnow;
FILETIME ftnow;
GetSystemTime(&sysnow);
if (!SystemTimeToFileTime(&sysnow, &ftnow)) {
CloseHandle(fhandle);
return false;
}
if (!SetFileTime(fhandle, NULL, NULL, &ftnow)) {
CloseHandle(fhandle);
return false;
}
CloseHandle(fhandle);
return true;
#elif defined(HAVE_UTIME_H)
// Most Unix systems can do this explicitly.
string os_specific = to_os_specific();
@ -1325,14 +1479,14 @@ touch() const {
return false;
}
return true;
#else // HAVE_UTIME_H
#else // WIN32, HAVE_UTIME_H
// Other systems may not have an explicit control over the
// modification time. For these systems, we'll just temporarily
// open the file in append mode, then close it again (it gets closed
// when the ofstream goes out of scope).
ofstream file;
return open_append(file);
#endif // HAVE_UTIME_H
#endif // WIN32, HAVE_UTIME_H
}
////////////////////////////////////////////////////////////////////
@ -1374,12 +1528,27 @@ rename_to(const Filename &other) const {
// itself. This assumes that the Filename contains the
// name of a file, not a directory name; it ensures that
// the directory containing the file exists.
//
// However, if the filename ends in a slash, it assumes
// the Filename represents the name of a directory, and
// creates all the paths.
////////////////////////////////////////////////////////////////////
bool Filename::
make_dir() const {
if (empty()) {
return false;
}
Filename path = *this;
path.standardize();
string dirname = path.get_dirname();
string dirname;
if (_filename[_filename.length() - 1] == '/') {
// The Filename ends in a slash; it represents a directory.
dirname = path.get_fullpath();
} else {
// The Filename does not end in a slash; it represents a file.
dirname = path.get_dirname();
}
// First, make sure everything up to the last path is known. We
// don't care too much if any of these fail; maybe they failed

View File

@ -77,6 +77,8 @@ PUBLISHED:
static Filename from_os_specific(const string &os_specific,
Type type = T_general);
static Filename expand_from(const string &user_string,
Type type = T_general);
static Filename temporary(const string &dirname, const string &prefix,
Type type = T_general);
@ -120,6 +122,7 @@ PUBLISHED:
INLINE void set_type(Type type);
INLINE Type get_type() const;
void extract_components(vector_string &components) const;
void standardize();
// The following functions deal with the outside world.
@ -132,6 +135,7 @@ PUBLISHED:
bool make_canonical();
string to_os_specific() const;
string to_os_generic() const;
bool exists() const;
bool is_regular_file() const;
@ -148,7 +152,7 @@ PUBLISHED:
bool scan_directory(vector_string &contents) const;
bool open_read(ifstream &stream) const;
bool open_write(ofstream &stream) const;
bool open_write(ofstream &stream, bool truncate = true) const;
bool open_append(ofstream &stream) const;
bool open_read_write(fstream &stream) const;

View File

@ -1911,34 +1911,34 @@ expand_makeguid(const string &params) {
MD5Final(digest, &context);
string guid;
int i = 0;
char hex[2];
int i;
for (int i = 0; i < 4; i++) {
for (i = 0; i < 4; i++) {
sprintf(hex, "%02x", digest[i]);
guid.append(hex);
}
guid += "-";
for (int i = 4; i < 6; i++) {
for (i = 4; i < 6; i++) {
sprintf(hex, "%02x", digest[i]);
guid.append(hex);
}
guid += "-";
for (int i = 6; i < 8; i++) {
for (i = 6; i < 8; i++) {
sprintf(hex, "%02x", digest[i]);
guid.append(hex);
}
guid += "-";
for (int i = 8; i < 10; i++) {
for (i = 8; i < 10; i++) {
sprintf(hex, "%02x", digest[i]);
guid.append(hex);
}
guid += "-";
for (int i = 10; i < 16; i++) {
for (i = 10; i < 16; i++) {
sprintf(hex, "%02x", digest[i]);
guid.append(hex);
}

View File

@ -22,17 +22,30 @@
#include <fstream>
#ifdef HAVE_SSTREAM
#include <sstream>
#else // HAVE_SSTREAM
#else /* HAVE_SSTREAM */
#include <strstream>
#endif // HAVE_SSTREAM
#else // HAVE_IOSTREAM
#endif /* HAVE_SSTREAM */
typedef std::ios::openmode ios_openmode;
typedef std::ios::fmtflags ios_fmtflags;
typedef std::ios::iostate ios_iostate;
typedef std::ios::seekdir ios_seekdir;
#else /* HAVE_IOSTREAM */
#include <iostream.h>
#include <fstream.h>
#include <strstream.h>
#endif // HAVE_IOSTREAM
typedef int ios_openmode;
typedef int ios_fmtflags;
typedef int ios_iostate;
/* Old iostream libraries used ios::seek_dir instead of ios::seekdir. */
typedef ios::seek_dir ios_seekdir;
#endif /* HAVE_IOSTREAM */
#if defined(HAVE_CYGWIN) || defined(WIN32_VC)
// Either Cygwin or Visual C++ is a Win32 environment.
/* Either Cygwin or Visual C++ is a Win32 environment. */
#define WIN32
#endif