support for <xi:include href="foo/foo.xml">, including the "relative path-mucking" necessary Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h _____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp 2005-01-04 06:24:17 UTC (rev 12781) +++ branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.cpp 2005-01-04 07:03:59 UTC (rev 12782) @@ -7,11 +7,16 @@
#include <stdio.h> #include <io.h> #include <assert.h> +#include <direct.h> #include "rbuild.h"
using std::string; using std::vector;
+#ifdef WIN32 +#define getcwd _getcwd +#endif//WIN32 + #ifdef _MSC_VER unsigned __int64 #else @@ -32,6 +37,86 @@ static const char* WS = " \t\r\n"; static const char* WSEQ = " =\t\r\n";
+Path::Path() +{ + string s; + s.resize ( _MAX_PATH ); + s[0] = 0; + getcwd ( &s[0], s.size() ); + s.resize ( strlen ( s.c_str() ) ); + 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; +} + XMLFile::XMLFile() { } @@ -47,10 +132,10 @@ _p = _end = NULL; }
-bool XMLFile::open(const char* filename) +bool XMLFile::open(const string& filename) { close(); - FILE* f = fopen ( filename, "r" ); + FILE* f = fopen ( filename.c_str(), "rb" ); if ( !f ) return false; unsigned long len = (unsigned long)filelen(f); @@ -205,7 +290,8 @@ return !( *p == '/' ) && !end_tag; }
-const XMLAttribute* XMLElement::GetAttribute ( const string& attribute ) const +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. @@ -214,6 +300,11 @@ if ( attribute == attributes[i]->name ) return attributes[i]; } + if ( required ) + { + printf ( "syntax error: attribute '%s' required for <%s>\n", + attribute.c_str(), name.c_str() ); + } return NULL; }
@@ -226,6 +317,7 @@ // it's parsed data. Keep calling this function until it returns NULL // (no more data) XMLElement* XMLParse(XMLFile& f, + const Path& path, bool* pend_tag = NULL) { string token; @@ -233,8 +325,35 @@ return NULL; XMLElement* e = new XMLElement; bool end_tag; - if ( !e->Parse ( token, end_tag ) ) + + bool bNeedEnd = e->Parse ( token, end_tag ); + + if ( e->name == "xi:include" ) { + const XMLAttribute* att; + att = e->GetAttribute("href",true); + if ( att ) + { + string file ( path.Fixup(att->value,true) ); + XMLFile fInc; + if ( !fInc.open ( file ) ) + printf ( "xi:include error, couldn't find file '%s'\n", file.c_str() ); + else + { + Path path2 ( path, att->value ); + for ( ;; ) + { + XMLElement* e2 = XMLParse ( fInc, path2 ); + if ( !e2 ) + break; + e->subElements.push_back ( e2 ); + } + } + } + } + + if ( !bNeedEnd ) + { if ( pend_tag ) *pend_tag = end_tag; else if ( end_tag ) @@ -249,7 +368,7 @@ { if ( f.next_is_text() ) { - if ( !f.get_token ( token ) ) + if ( !f.get_token ( token ) || !token.size() ) { printf ( "internal tool error - get_token() failed when more_tokens() returned true\n" ); break; @@ -266,7 +385,7 @@ } else { - XMLElement* e2 = XMLParse ( f, &end_tag ); + XMLElement* e2 = XMLParse ( f, path, &end_tag ); if ( end_tag ) { if ( e->name != e2->name ) @@ -292,7 +411,7 @@ string subpath(path); if ( e.name == "project" ) { - att = e.GetAttribute ( "name" ); + att = e.GetAttribute ( "name", false ); if ( !att ) name = "Unnamed"; else @@ -300,24 +419,18 @@ } else if ( e.name == "module" ) { - att = e.GetAttribute ( "name" ); + att = e.GetAttribute ( "name", true ); if ( !att ) - { - printf ( "syntax error: 'name' attribute required for <module>\n" ); return; - } Module* module = new Module ( e, att->value, path ); modules.push_back ( module ); return; // REM TODO FIXME no processing of modules... yet } else if ( e.name == "directory" ) { - const XMLAttribute* att = e.GetAttribute("name"); + const XMLAttribute* att = e.GetAttribute ( "name", true ); if ( !att ) - { - printf ( "syntax error: 'name' attribute required for <directory>\n" ); return; - } subpath = path + "/" + att->value; } for ( size_t i = 0; i < e.subElements.size(); i++ ) @@ -327,6 +440,7 @@ int main ( int argc, char** argv ) { XMLFile f; + Path path; if ( !f.open ( "ReactOS.xml" ) ) { printf ( "couldn't open ReactOS.xml!\n" ); @@ -335,7 +449,7 @@
for ( ;; ) { - XMLElement* head = XMLParse ( f ); + XMLElement* head = XMLParse ( f, path ); if ( !head ) break; // end of file
_____
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h --- branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h 2005-01-04 06:24:17 UTC (rev 12781) +++ branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h 2005-01-04 07:03:59 UTC (rev 12782) @@ -4,13 +4,22 @@
#include <string> #include <vector>
+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; +}; + class XMLFile { friend class XMLElement; public: XMLFile(); void close(); - bool open(const char* filename); + bool open(const std::string& filename); void next_token(); bool next_is_text(); bool more_tokens(); @@ -47,7 +56,8 @@ ~XMLElement(); bool Parse(const std::string& token, bool& end_tag); - const XMLAttribute* GetAttribute ( const std::string& attribute ) const; + const XMLAttribute* GetAttribute ( const std::string& attribute, + bool required) const; };
class Project;