XML.cpp -> xml.cpp, XML.h -> xml.h. Sorry Windows users, if you make sure your stuff is in the correct case the first time then you wont have problems when doing a svn update. Deleted: trunk/reactos/tools/buildno/XML.cpp Deleted: trunk/reactos/tools/buildno/XML.h Modified: trunk/reactos/tools/buildno/buildno.cpp Modified: trunk/reactos/tools/buildno/buildno.mak Added: trunk/reactos/tools/buildno/xml.cpp Added: trunk/reactos/tools/buildno/xml.h Deleted: trunk/reactos/tools/rbuild/XML.cpp Deleted: trunk/reactos/tools/rbuild/XML.h Modified: trunk/reactos/tools/rbuild/exception.h Modified: trunk/reactos/tools/rbuild/rbuild.h Modified: trunk/reactos/tools/rbuild/rbuild.mak Added: trunk/reactos/tools/rbuild/xml.cpp Added: trunk/reactos/tools/rbuild/xml.h _____
Deleted: trunk/reactos/tools/buildno/XML.cpp --- trunk/reactos/tools/buildno/XML.cpp 2005-11-27 06:34:50 UTC (rev 19674) +++ trunk/reactos/tools/buildno/XML.cpp 2005-11-27 06:48:34 UTC (rev 19675) @@ -1,733 +0,0 @@
-// XML.cpp - -#include "pch.h" - -#ifdef _MSC_VER -#define MAX_PATH _MAX_PATH -#endif - -#ifdef WIN32 -# include <direct.h> -# include <io.h> -#else -# include <sys/stat.h> -# define MAX_PATH PATH_MAX -#endif -#include <assert.h> - -#include "XML.h" -#include "exception.h" -#include "ssprintf.h" - -using std::string; -using std::vector; - -#ifdef WIN32 -#define getcwd _getcwd -#endif//WIN32 - -static const char* WS = " \t\r\n"; -static const char* WSEQ = " =\t\r\n"; - -string working_directory; - -class XMLInclude -{ -public: - XMLElement *e; - Path path; - - XMLInclude ( XMLElement* e_, const Path& path_ ) - : e(e_), path(path_) - { - } -}; - -class XMLIncludes : public vector<XMLInclude*> -{ -public: - ~XMLIncludes() - { - for ( size_t i = 0; i < this->size(); i++ ) - delete (*this)[i]; - } -}; - -void -InitWorkingDirectory() -{ - // store the current directory for path calculations - working_directory.resize ( _MAX_PATH ); - working_directory[0] = 0; - getcwd ( &working_directory[0], working_directory.size() ); - working_directory.resize ( strlen ( working_directory.c_str() ) ); -} - -#ifdef _MSC_VER -unsigned __int64 -#else -unsigned long long -#endif -filelen ( FILE* f ) -{ -#ifdef WIN32 - return _filelengthi64 ( _fileno(f) ); -#else -# ifdef __FreeBSD__ - struct stat file_stat; - if ( fstat(fileno(f), &file_stat) != 0 ) -# else - struct stat64 file_stat; - if ( fstat64(fileno(f), &file_stat) != 0 ) -# endif // __FreeBSD__ - return 0; - return file_stat.st_size; - -#endif // WIN32 -} - -Path::Path() -{ - if ( !working_directory.size() ) - InitWorkingDirectory(); - string s ( working_directory ); - const char* p = strtok ( &s[0], "/\" ); - while ( p ) - { - if ( *p ) - path.push_back ( p ); - p = strtok ( NULL, "/\" ); - } -} - -Path::Path ( const Path& cwd, const string& file ) -{ - string s ( cwd.Fixup ( file, false ) ); - const char* p = strtok ( &s[0], "/\" ); - while ( p ) - { - if ( *p ) - path.push_back ( p ); - p = strtok ( NULL, "/\" ); - } -} - -string -Path::Fixup ( const string& file, bool include_filename ) const -{ - if ( strchr ( "/\", file[0] ) -#ifdef WIN32 - // this squirreliness is b/c win32 has drive letters and *nix doesn't... - || file[1] == ':' -#endif//WIN32 - ) - { - return file; - } - vector<string> pathtmp ( path ); - string tmp ( file ); - const char* prev = strtok ( &tmp[0], "/\" ); - const char* p = strtok ( NULL, "/\" ); - while ( p ) - { - if ( !strcmp ( prev, "." ) ) - ; // do nothing - else if ( !strcmp ( prev, ".." ) ) - { - // this squirreliness is b/c win32 has drive letters and *nix doesn't... -#ifdef WIN32 - if ( pathtmp.size() > 1 ) -#else - if ( pathtmp.size() ) -#endif - pathtmp.resize ( pathtmp.size() - 1 ); - } - else - pathtmp.push_back ( prev ); - prev = p; - p = strtok ( NULL, "/\" ); - } - if ( include_filename ) - pathtmp.push_back ( prev ); - - // reuse tmp variable to return recombined path - tmp.resize(0); - for ( size_t i = 0; i < pathtmp.size(); i++ ) - { - // this squirreliness is b/c win32 has drive letters and *nix doesn't... -#ifdef WIN32 - if ( i ) tmp += "/"; -#else - tmp += "/"; -#endif - tmp += pathtmp[i]; - } - return tmp; -} - -/*static*/ string -Path::RelativeFromWorkingDirectory ( const string& path ) -{ - vector<string> vwork, vpath, vout; - Path::Split ( vwork, working_directory, true ); - Path::Split ( vpath, path, true ); -#ifdef WIN32 - // this squirreliness is b/c win32 has drive letters and *nix doesn't... - // not possible to do relative across different drive letters - if ( vwork[0] != vpath[0] ) - return path; -#endif - size_t i = 0; - while ( i < vwork.size() && i < vpath.size() && vwork[i] == vpath[i] ) - ++i; - if ( i < vwork.size() ) - { - // path goes above our working directory, we will need some ..'s - for ( size_t j = 0; j < i; j++ ) - vout.push_back ( ".." ); - } - while ( i < vpath.size() ) - vout.push_back ( vpath[i++] ); - - // now merge vout into a string again - string out = "."; - for ( i = 0; i < vout.size(); i++ ) - { - out += "/" + vout[i]; - } - return out; -} - -/*static*/ void -Path::Split ( vector<string>& out, - const string& path, - bool include_last ) -{ - string s ( path ); - const char* prev = strtok ( &s[0], "/\" ); - const char* p = strtok ( NULL, "/\" ); - out.resize ( 0 ); - while ( p ) - { - out.push_back ( prev ); - prev = p; - p = strtok ( NULL, "/\" ); - } - if ( include_last ) - out.push_back ( prev ); -} - -XMLFile::XMLFile() -{ -} - -void -XMLFile::close() -{ - _buf.resize(0); - _p = _end = NULL; -} - -bool -XMLFile::open(const string& filename_) -{ - close(); - FILE* f = fopen ( filename_.c_str(), "rb" ); - if ( !f ) - return false; - unsigned long len = (unsigned long)filelen(f); - _buf.resize ( len ); - fread ( &_buf[0], 1, len, f ); - fclose ( f ); - _p = _buf.c_str(); - _end = _p + len; - _filename = filename_; - next_token(); - return true; -} - -// next_token() moves the pointer to next token, which may be -// an xml element or a text element, basically it's a glorified -// skipspace, normally the user of this class won't need to call -// this function -void -XMLFile::next_token() -{ - _p += strspn ( _p, WS ); -} - -bool -XMLFile::next_is_text() -{ - return *_p != '<'; -} - -bool -XMLFile::more_tokens() -{ - return _p != _end; -} - -// get_token() is used to return a token, and move the pointer -// past the token -bool -XMLFile::get_token(string& token) -{ - const char* tokend; - if ( !strncmp ( _p, "<!--", 4 ) ) - { - tokend = strstr ( _p, "-->" ); - if ( !tokend ) - tokend = _end; - else - tokend += 3; - } - else if ( !strncmp ( _p, "<?", 2 ) ) - { - tokend = strstr ( _p, "?>" ); - if ( !tokend ) - tokend = _end; - else - tokend += 2; - } - else if ( *_p == '<' ) - { - tokend = strchr ( _p, '>' ); - if ( !tokend ) - tokend = _end; - else - ++tokend; - } - else - { - tokend = strchr ( _p, '<' ); - if ( !tokend ) - tokend = _end; - while ( tokend > _p && isspace(tokend[-1]) ) - --tokend; - } - if ( tokend == _p ) - return false; - token = string ( _p, tokend-_p ); - _p = tokend; - next_token(); - return true; -} - -string -XMLFile::Location() const -{ - int line = 1; - const char* p = strchr ( _buf.c_str(), '\n' ); - while ( p && p < _p ) - { - ++line; - p = strchr ( p+1, '\n' ); - } - return ssprintf ( "%s(%i)",_filename.c_str(), line ); -} - -XMLAttribute::XMLAttribute() -{ -} - -XMLAttribute::XMLAttribute(const string& name_, - const string& value_) - : name(name_), value(value_) -{ -} - -XMLAttribute::XMLAttribute ( const XMLAttribute& src ) - : name(src.name), value(src.value) -{ - -} - -XMLAttribute& XMLAttribute::operator = ( const XMLAttribute& src ) -{ - name = src.name; - value = src.value; - return *this; -} - -XMLElement::XMLElement ( const string& location_ ) - : location(location_), - parentElement(NULL) -{ -} - -XMLElement::~XMLElement() -{ - size_t i; - for ( i = 0; i < attributes.size(); i++ ) - delete attributes[i]; - for ( i = 0; i < subElements.size(); i++ ) - delete subElements[i]; -} - -void -XMLElement::AddSubElement ( XMLElement* e ) -{ - subElements.push_back ( e ); - e->parentElement = this; -} - -// Parse() -// This function takes a single xml tag ( i.e. beginning with '<' and -// ending with '>', and parses out it's tag name and constituent -// attributes. -// Return Value: returns true if you need to look for a </tag> for -// the one it just parsed... -bool -XMLElement::Parse(const string& token, - bool& end_tag) -{ - const char* p = token.c_str(); - assert ( *p == '<' ); - ++p; - p += strspn ( p, WS ); - - // check if this is a comment - if ( !strncmp ( p, "!--", 3 ) ) - { - name = "!--"; - end_tag = false; - return false; // never look for end tag to a comment - } - - end_tag = ( *p == '/' ); - if ( end_tag ) - { - ++p; - p += strspn ( p, WS ); - } - const char* end = strpbrk ( p, WS ); - if ( !end ) - { - end = strpbrk ( p, "/>" ); - assert ( end ); - } - name = string ( p, end-p ); - p = end; - p += strspn ( p, WS ); - while ( *p != '>' && *p != '/' ) - { - end = strpbrk ( p, WSEQ ); - if ( !end ) - { - end = strpbrk ( p, "/>" ); - assert ( end ); - } - string attribute ( p, end-p ), value; - p = end; - p += strspn ( p, WS ); - if ( *p == '=' ) - { - ++p; - p += strspn ( p, WS ); - char quote = 0; - if ( strchr ( ""'", *p ) ) - { - quote = *p++; - end = strchr ( p, quote ); - } - else - { - end = strpbrk ( p, WS ); - } - if ( !end ) - { - end = strchr ( p, '>' ); - assert(end); - if ( end[-1] == '/' ) - end--; - } - value = string ( p, end-p ); - p = end; - if ( quote && *p == quote ) - p++; - p += strspn ( p, WS ); - } - else if ( name[0] != '!' ) - { - throw XMLSyntaxErrorException ( location, - "attributes must have values" ); - } - attributes.push_back ( new XMLAttribute ( attribute, value ) ); - } - return !( *p == '/' ) && !end_tag; -} - -XMLAttribute* -XMLElement::GetAttribute ( const string& attribute, - bool required ) -{ - // this would be faster with a tree-based container, but our attribute - // lists are likely to stay so short as to not be an issue. - for ( size_t i = 0; i < attributes.size(); i++ ) - { - if ( attribute == attributes[i]->name ) - return attributes[i]; - } - if ( required ) - { - throw RequiredAttributeNotFoundException ( location, - attribute, - name ); - } - return NULL; -} - -const XMLAttribute* -XMLElement::GetAttribute ( const string& attribute, - bool required ) const -{ - // this would be faster with a tree-based container, but our attribute - // lists are likely to stay so short as to not be an issue. - for ( size_t i = 0; i < attributes.size(); i++ ) - { - if ( attribute == attributes[i]->name ) - return attributes[i]; - } - if ( required ) - { - throw RequiredAttributeNotFoundException ( location, - attribute, - name ); - } - return NULL; -} - -// XMLParse() -// This function reads a "token" from the file loaded in XMLFile -// if it finds a tag that is non-singular, it parses sub-elements and/or -// inner text into the XMLElement that it is building to return. -// Return Value: an XMLElement allocated via the new operator that contains -// it's parsed data. Keep calling this function until it returns NULL -// (no more data) -XMLElement* -XMLParse(XMLFile& f, - XMLIncludes* includes, - const Path& path, - bool* pend_tag = NULL ) -{ - string token; - if ( !f.get_token(token) ) - return NULL; - bool end_tag, is_include = false; - - while ( token[0] != '<' - || !strncmp ( token.c_str(), "<!--", 4 ) - || !strncmp ( token.c_str(), "<?", 2 ) ) - { - if ( token[0] != '<' ) - throw XMLSyntaxErrorException ( f.Location(), - "expecting xml tag, not '%s'", - token.c_str() ); - if ( !f.get_token(token) ) - return NULL; - } - - XMLElement* e = new XMLElement ( f.Location() ); - bool bNeedEnd = e->Parse ( token, end_tag ); - - if ( e->name == "xi:include" && includes ) - { - includes->push_back ( new XMLInclude ( e, path ) ); - is_include = true; - } - - if ( !bNeedEnd ) - { - if ( pend_tag ) - *pend_tag = end_tag; - else if ( end_tag ) - { - delete e; - throw XMLSyntaxErrorException ( f.Location(), - "end tag '%s' not expected", - token.c_str() ); - return NULL; - } - return e; - } - bool bThisMixingErrorReported = false; - while ( f.more_tokens() ) - { - if ( f.next_is_text() ) - { - if ( !f.get_token ( token ) || !token.size() ) - { - throw InvalidBuildFileException ( - f.Location(), - "internal tool error - get_token() failed when more_tokens() returned true" ); - break; - } - if ( e->subElements.size() && !bThisMixingErrorReported ) - { - throw XMLSyntaxErrorException ( f.Location(), - "mixing of inner text with sub elements" ); - bThisMixingErrorReported = true; - } - if ( strchr ( token.c_str(), '>' ) ) - { - throw XMLSyntaxErrorException ( f.Location(), - "invalid symbol '>'" ); - } - if ( e->value.size() ) - { - throw XMLSyntaxErrorException ( f.Location(), - "multiple instances of inner text" ); - e->value += " " + token; - } - else - e->value = token; - } - else - { - XMLElement* e2 = XMLParse ( f, is_include ? NULL : includes, path, &end_tag ); - if ( !e2 ) - { - throw InvalidBuildFileException ( - e->location, - "end of file found looking for end tag" ); - break; - } - if ( end_tag ) - { - if ( e->name != e2->name ) - { - delete e2; - throw XMLSyntaxErrorException ( f.Location(), - "end tag name mismatch" ); - break; - } - delete e2; - break; - } - if ( e->value.size() && !bThisMixingErrorReported ) - { - throw XMLSyntaxErrorException ( f.Location(), - "mixing of inner text with sub elements" ); - bThisMixingErrorReported = true; - } - e->AddSubElement ( e2 ); - } - } - return e; -} - -void -XMLReadFile ( XMLFile& f, XMLElement& head, XMLIncludes& includes, const Path& path ) -{ - for ( ;; ) - { - XMLElement* e = XMLParse ( f, &includes, path ); - if ( !e ) - return; - head.AddSubElement ( e ); - } -} - -XMLElement* -XMLLoadInclude ( XMLElement* e, const Path& path, XMLIncludes& includes ) -{ - XMLAttribute* att; - att = e->GetAttribute("href",true); - assert(att); - - string file ( path.Fixup(att->value,true) ); - string top_file ( Path::RelativeFromWorkingDirectory ( file ) ); - e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) ); - XMLFile fInc; - if ( !fInc.open ( file ) ) - { - // look for xi:fallback element - for ( size_t i = 0; i < e->subElements.size(); i++ ) - { - XMLElement* e2 = e->subElements[i]; - if ( e2->name == "xi:fallback" ) - { - // now look for xi:include below... - for ( i = 0; i < e2->subElements.size(); i++ ) - { - XMLElement* e3 = e2->subElements[i]; - if ( e3->name == "xi:include" ) - { - return XMLLoadInclude ( e3, path, includes ); - } - } - throw InvalidBuildFileException ( - e2->location, - "xi:fallback must have a xi:include sub-element" ); - return NULL; - } - } - return NULL; - } - else - { - XMLElement* new_e = new XMLElement ( e->location ); - new_e->name = "xi:included"; - Path path2 ( path, att->value ); - XMLReadFile ( fInc, *new_e, includes, path2 ); - return new_e; - } -} - -XMLElement* -XMLLoadFile ( const string& filename, const Path& path ) -{ - XMLIncludes includes; - XMLFile f; - - if ( !f.open ( filename ) ) - throw FileNotFoundException ( filename ); - - XMLElement* head = new XMLElement("(virtual)"); - - XMLReadFile ( f, *head, includes, path ); - - for ( size_t i = 0; i < includes.size(); i++ ) - { - XMLElement* e = includes[i]->e; - XMLElement* e2 = XMLLoadInclude ( includes[i]->e, includes[i]->path, includes ); - if ( !e2 ) - { - throw FileNotFoundException ( - ssprintf("%s (referenced from %s)", - e->GetAttribute("top_href",true)->value.c_str(), - f.Location().c_str() ) ); - } - XMLElement* parent = e->parentElement; - XMLElement** parent_container = NULL; - if ( !parent ) - { - delete e; - throw Exception ( "internal tool error: xi:include doesn't have a parent" ); - return NULL; - } - for ( size_t j = 0; j < parent->subElements.size(); j++ ) - { - if ( parent->subElements[j] == e ) - { - parent_container = &parent->subElements[j]; - break; - } - } - if ( !parent_container ) - { - delete e; - throw Exception ( "internal tool error: couldn't find xi:include in parent's sub-elements" ); - return NULL; - } - // replace inclusion tree with the imported tree - e2->parentElement = e->parentElement; - e2->name = e->name; - e2->attributes = e->attributes; - *parent_container = e2; - e->attributes.resize(0); - delete e; - } - return head; -} _____
Deleted: trunk/reactos/tools/buildno/XML.h --- trunk/reactos/tools/buildno/XML.h 2005-11-27 06:34:50 UTC (rev 19674) +++ trunk/reactos/tools/buildno/XML.h 2005-11-27 06:48:34 UTC (rev 19675) @@ -1,96 +0,0 @@
-// XML.h - -#ifndef XML_H -#define XML_H - -#include "pch.h" - -void -InitWorkingDirectory(); - -#ifdef _MSC_VER -unsigned __int64 -#else -unsigned long long -#endif -filelen ( FILE* f ); - -class Path -{ - std::vectorstd::string path; -public: - Path(); // initializes path to getcwd(); - Path ( const Path& cwd, const std::string& filename ); - std::string Fixup ( const std::string& filename, bool include_filename ) const; - - static std::string RelativeFromWorkingDirectory ( const std::string& path ); - - static void Split ( std::vectorstd::string& out, - const std::string& path, - bool include_last ); -}; - -class XMLFile -{ - friend class XMLElement; -public: - XMLFile(); - void close(); - bool open(const std::string& filename); - void next_token(); - bool next_is_text(); - bool more_tokens(); - bool get_token(std::string& token); - const std::string& filename() { return _filename; } - std::string Location() const; - -private: - std::string _buf, _filename; - - const char *_p, *_end; -}; - - -class XMLAttribute -{ -public: - std::string name; - std::string value; - - XMLAttribute(); - XMLAttribute ( const std::string& name_, const std::string& value_ ); - XMLAttribute ( const XMLAttribute& ); - XMLAttribute& operator = ( const XMLAttribute& ); -}; - - -class XMLElement -{ -public: - std::string location; - std::string name; - std::vector<XMLAttribute*> attributes; - XMLElement* parentElement; - std::vector<XMLElement*> subElements; - std::string value; - - XMLElement ( const std::string& location_ ); - ~XMLElement(); - bool Parse(const std::string& token, - bool& end_tag); - void AddSubElement ( XMLElement* e ); - XMLAttribute* GetAttribute ( const std::string& attribute, - bool required); - const XMLAttribute* GetAttribute ( const std::string& attribute, - bool required) const; -}; - -XMLElement* -XMLLoadFile ( const std::string& filename, const Path& path ); - -/*XMLElement* -XMLParse(XMLFile& f, - const Path& path, - bool* pend_tag = NULL);*/ - -#endif//XML_H _____
Modified: trunk/reactos/tools/buildno/buildno.cpp --- trunk/reactos/tools/buildno/buildno.cpp 2005-11-27 06:34:50 UTC (rev 19674) +++ trunk/reactos/tools/buildno/buildno.cpp 2005-11-27 06:48:34 UTC (rev 19675) @@ -28,7 +28,7 @@
#include <time.h> #include <string.h> #include "version.h" -#include "XML.h" +#include "xml.h" #include "exception.h"
#define FALSE 0 _____
Modified: trunk/reactos/tools/buildno/buildno.mak --- trunk/reactos/tools/buildno/buildno.mak 2005-11-27 06:34:50 UTC (rev 19674) +++ trunk/reactos/tools/buildno/buildno.mak 2005-11-27 06:48:34 UTC (rev 19675) @@ -22,7 +22,7 @@
buildno.cpp \ exception.cpp \ ssprintf.cpp \ - XML.cpp \ + xml.cpp \ )
BUILDNO_OBJECTS = \ @@ -48,7 +48,7 @@ $(ECHO_CC) ${host_gpp} $(BUILDNO_HOST_CXXFLAGS) -c $< -o $@
-$(BUILDNO_INT_)XML.o: $(BUILDNO_BASE_)XML.cpp | $(BUILDNO_INT) +$(BUILDNO_INT_)xml.o: $(BUILDNO_BASE_)xml.cpp | $(BUILDNO_INT) $(ECHO_CC) ${host_gpp} $(BUILDNO_HOST_CXXFLAGS) -c $< -o $@
_____
Copied: trunk/reactos/tools/buildno/xml.cpp (from rev 19674, trunk/reactos/tools/buildno/XML.cpp) --- trunk/reactos/tools/buildno/XML.cpp 2005-11-27 06:34:50 UTC (rev 19674) +++ trunk/reactos/tools/buildno/xml.cpp 2005-11-27 06:48:34 UTC (rev 19675) @@ -0,0 +1,733 @@
+// xml.cpp + +#include "pch.h" + +#ifdef _MSC_VER +#define MAX_PATH _MAX_PATH +#endif + +#ifdef WIN32 +# include <direct.h> +# include <io.h> +#else +# include <sys/stat.h> +# define MAX_PATH PATH_MAX +#endif +#include <assert.h> + +#include "xml.h" +#include "exception.h" +#include "ssprintf.h" + +using std::string; +using std::vector; + +#ifdef WIN32 +#define getcwd _getcwd +#endif//WIN32 + +static const char* WS = " \t\r\n"; +static const char* WSEQ = " =\t\r\n"; + +string working_directory; + +class XMLInclude +{ +public: + XMLElement *e; + Path path; + + XMLInclude ( XMLElement* e_, const Path& path_ ) + : e(e_), path(path_) + { + } +}; + +class XMLIncludes : public vector<XMLInclude*> +{ +public: + ~XMLIncludes() + { + for ( size_t i = 0; i < this->size(); i++ ) + delete (*this)[i]; + } +}; + +void +InitWorkingDirectory() +{ + // store the current directory for path calculations + working_directory.resize ( _MAX_PATH ); + working_directory[0] = 0; + getcwd ( &working_directory[0], working_directory.size() ); + working_directory.resize ( strlen ( working_directory.c_str() ) ); +} + +#ifdef _MSC_VER +unsigned __int64 +#else +unsigned long long +#endif +filelen ( FILE* f ) +{ +#ifdef WIN32 + return _filelengthi64 ( _fileno(f) ); +#else +# ifdef __FreeBSD__ + struct stat file_stat; + if ( fstat(fileno(f), &file_stat) != 0 ) +# else + struct stat64 file_stat; + if ( fstat64(fileno(f), &file_stat) != 0 ) +# endif // __FreeBSD__ + return 0; + return file_stat.st_size; + +#endif // WIN32 +} + +Path::Path() +{ + if ( !working_directory.size() ) + InitWorkingDirectory(); + string s ( working_directory ); + const char* p = strtok ( &s[0], "/\" ); + while ( p ) + { + if ( *p ) + path.push_back ( p ); + p = strtok ( NULL, "/\" ); + } +} + +Path::Path ( const Path& cwd, const string& file ) +{ + string s ( cwd.Fixup ( file, false ) ); + const char* p = strtok ( &s[0], "/\" ); + while ( p ) + { + if ( *p ) + path.push_back ( p ); + p = strtok ( NULL, "/\" ); + } +} + +string +Path::Fixup ( const string& file, bool include_filename ) const +{ + if ( strchr ( "/\", file[0] ) +#ifdef WIN32 + // this squirreliness is b/c win32 has drive letters and *nix doesn't... + || file[1] == ':' [truncated at 1000 lines; 2744 more skipped]