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::vector<std::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::vector<std::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]