diff --git a/reactos/tools/rbuild/XML.cpp b/reactos/tools/rbuild/XML.cpp index df2aa72ce77..833a0336af7 100644 --- a/reactos/tools/rbuild/XML.cpp +++ b/reactos/tools/rbuild/XML.cpp @@ -306,8 +306,9 @@ XMLAttribute::XMLAttribute(const string& name_, { } -XMLElement::XMLElement() - : parentElement(NULL) +XMLElement::XMLElement ( const string& location_ ) + : location(location_), + parentElement(NULL) { } @@ -476,7 +477,7 @@ XMLParse(XMLFile& f, return NULL; } - XMLElement* e = new XMLElement; + XMLElement* e = new XMLElement ( f.Location() ); bool bNeedEnd = e->Parse ( token, end_tag ); if ( e->name == "xi:include" ) diff --git a/reactos/tools/rbuild/XML.h b/reactos/tools/rbuild/XML.h index d255456d43a..ba55e267d79 100644 --- a/reactos/tools/rbuild/XML.h +++ b/reactos/tools/rbuild/XML.h @@ -58,13 +58,14 @@ public: class XMLElement { public: + std::string location; std::string name; std::vector attributes; XMLElement* parentElement; std::vector subElements; std::string value; - XMLElement(); + XMLElement ( const std::string& location_ ); ~XMLElement(); bool Parse(const std::string& token, bool& end_tag); diff --git a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp index c7a999fe8fa..e3fadcaa82a 100644 --- a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp +++ b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp @@ -48,7 +48,7 @@ MingwModuleHandler::GetImportLibraryDependencies ( const Module& module ) const { if ( dependencies.size () > 0 ) dependencies += " "; - Module* importedModule = module.project->LocateModule ( module.libraries[i]->name ); + const Module* importedModule = module.project.LocateModule ( module.libraries[i]->name ); assert ( importedModule != NULL ); dependencies += importedModule->GetPath ().c_str (); } @@ -117,7 +117,7 @@ MingwModuleHandler::GenerateGccDefineParametersFromVector ( const vectordefines ); + string parameters = GenerateGccDefineParametersFromVector ( module.project.defines ); string s = GenerateGccDefineParametersFromVector ( module.defines ); if (s.length () > 0) { @@ -160,7 +160,7 @@ string MingwModuleHandler::GenerateGccIncludeParameters ( const Module& module ) const { string parameters = GenerateGccIncludeParametersFromVector ( ".", - module.project->includes ); + module.project.includes ); string s = GenerateGccIncludeParametersFromVector ( module.path, module.includes ); if (s.length () > 0) diff --git a/reactos/tools/rbuild/define.cpp b/reactos/tools/rbuild/define.cpp index c443d446198..2530249ece1 100644 --- a/reactos/tools/rbuild/define.cpp +++ b/reactos/tools/rbuild/define.cpp @@ -6,23 +6,23 @@ using std::string; using std::vector; -Define::Define ( Project* project, +Define::Define ( const Project& project, const XMLElement& defineNode ) : project(project), module(NULL), node(defineNode) { - Initialize (defineNode); + Initialize(); } -Define::Define ( Project* project, - Module* module, +Define::Define ( const Project& project, + const Module* module, const XMLElement& defineNode ) : project(project), module(module), node(defineNode) { - Initialize (defineNode); + Initialize(); } Define::~Define () @@ -30,15 +30,15 @@ Define::~Define () } void -Define::Initialize ( const XMLElement& defineNode ) +Define::Initialize() { - const XMLAttribute* att = defineNode.GetAttribute ( "name", true ); + const XMLAttribute* att = node.GetAttribute ( "name", true ); assert(att); name = att->value; - value = defineNode.value; + value = node.value; } void -Define::ProcessXML ( const XMLElement& e ) +Define::ProcessXML() { } diff --git a/reactos/tools/rbuild/exception.cpp b/reactos/tools/rbuild/exception.cpp index d04014ced66..f3b3d5bc586 100644 --- a/reactos/tools/rbuild/exception.cpp +++ b/reactos/tools/rbuild/exception.cpp @@ -58,14 +58,14 @@ AccessDeniedException::AccessDeniedException ( const string& filename) } -InvalidBuildFileException::InvalidBuildFileException ( const char* message, +InvalidBuildFileException::InvalidBuildFileException ( const string& location, + const char* message, ...) { va_list args; va_start ( args, message ); - SetMessage ( message, - args ); + SetLocationMessage ( location, message, args ); va_end ( args ); } @@ -73,6 +73,13 @@ InvalidBuildFileException::InvalidBuildFileException () { } +void +InvalidBuildFileException::SetLocationMessage ( const std::string& location, + const char* message, + va_list args ) +{ + Message = location + ": " + ssvprintf ( message, args ); +} XMLSyntaxErrorException::XMLSyntaxErrorException ( const string& location, const char* message, @@ -81,7 +88,7 @@ XMLSyntaxErrorException::XMLSyntaxErrorException ( const string& location, va_list args; va_start ( args, message ); - Message = location + ": " + ssvprintf ( message, args ); + SetLocationMessage ( location, message, args ); va_end ( args ); } diff --git a/reactos/tools/rbuild/exception.h b/reactos/tools/rbuild/exception.h index 1653a0c2909..50a95100762 100644 --- a/reactos/tools/rbuild/exception.h +++ b/reactos/tools/rbuild/exception.h @@ -40,12 +40,15 @@ public: std::string Filename; }; - class InvalidBuildFileException : public Exception { public: - InvalidBuildFileException ( const char* message, + InvalidBuildFileException ( const std::string& location, + const char* message, ...); + void SetLocationMessage ( const std::string& location, + const char* message, + va_list args ); protected: InvalidBuildFileException (); }; diff --git a/reactos/tools/rbuild/include.cpp b/reactos/tools/rbuild/include.cpp index 01412031382..b8d71341918 100644 --- a/reactos/tools/rbuild/include.cpp +++ b/reactos/tools/rbuild/include.cpp @@ -6,21 +6,23 @@ using std::string; using std::vector; -Include::Include ( Project* project, +Include::Include ( const Project& project_, const XMLElement& includeNode ) - : project(project), + : project(project_), + module(NULL), node(includeNode) { - Initialize ( includeNode ); + Initialize(); } -Include::Include ( Project* project, - Module* module, +Include::Include ( const Project& project_, + const Module* module_, const XMLElement& includeNode ) - : project(project), + : project(project_), + module(module_), node(includeNode) { - Initialize ( includeNode ); + Initialize(); } Include::~Include () @@ -28,12 +30,12 @@ Include::~Include () } void -Include::Initialize ( const XMLElement& includeNode ) +Include::Initialize() { - directory = FixSeparator ( includeNode.value ); + directory = FixSeparator ( node.value ); } void -Include::ProcessXML ( const XMLElement& e ) +Include::ProcessXML() { } diff --git a/reactos/tools/rbuild/module.cpp b/reactos/tools/rbuild/module.cpp index de767b353ba..0ca1a6555c4 100644 --- a/reactos/tools/rbuild/module.cpp +++ b/reactos/tools/rbuild/module.cpp @@ -21,13 +21,16 @@ FixSeparator ( const string& s ) return s2; } -Module::Module ( Project* project, +Module::Module ( const Project& project, const XMLElement& moduleNode, const string& modulePath ) : project(project), node(moduleNode) { - path = FixSeparator ( modulePath ); + if ( node.name != "module" ) + throw Exception ( "internal tool error: Module created with non- node" ); + + path = FixSeparator ( modulePath ); const XMLAttribute* att = moduleNode.GetAttribute ( "name", true ); assert(att); @@ -54,17 +57,30 @@ Module::~Module () } void -Module::ProcessXML ( const XMLElement& e, - const string& path ) +Module::ProcessXML() { + size_t i; + for ( i = 0; i < node.subElements.size(); i++ ) + ProcessXMLSubElement ( *node.subElements[i], path ); + for ( i = 0; i < libraries.size(); i++ ) + libraries[i]->ProcessXML(); +} + +void +Module::ProcessXMLSubElement ( const XMLElement& e, + const string& path ) +{ + bool subs_invalid = false; string subpath ( path ); if ( e.name == "file" && e.value.size () ) { files.push_back ( new File ( FixSeparator ( path + CSEP + e.value ) ) ); + subs_invalid = true; } else if ( e.name == "library" && e.value.size () ) { - libraries.push_back ( new Library ( e.value ) ); + libraries.push_back ( new Library ( e, *this, e.value ) ); + subs_invalid = true; } else if ( e.name == "directory" ) { @@ -74,18 +90,21 @@ Module::ProcessXML ( const XMLElement& e, } else if ( e.name == "include" ) { - Include* include = new Include ( project, this, e ); - includes.push_back ( include ); - include->ProcessXML ( e ); + includes.push_back ( new Include ( project, this, e ) ); + subs_invalid = true; } else if ( e.name == "define" ) { - Define* define = new Define ( project, this, e ); - defines.push_back ( define ); - define->ProcessXML ( e ); + defines.push_back ( new Define ( project, this, e ) ); + subs_invalid = true; } + if ( subs_invalid && e.subElements.size() ) + throw InvalidBuildFileException ( + e.location, + "<%s> cannot have sub-elements", + e.name.c_str() ); for ( size_t i = 0; i < e.subElements.size (); i++ ) - ProcessXML ( *e.subElements[i], subpath ); + ProcessXMLSubElement ( *e.subElements[i], subpath ); } ModuleType @@ -102,7 +121,7 @@ Module::GetModuleType ( const XMLAttribute& attribute ) } string -Module::GetDefaultModuleExtension () +Module::GetDefaultModuleExtension () const { switch (type) { @@ -130,7 +149,27 @@ File::File ( const string& _name ) } -Library::Library ( const string& _name ) - : name(_name) +Library::Library ( const XMLElement& _node, + const Module& _module, + const string& _name ) + : node(_node), + module(_module), + name(_name) { + if ( module.name == name ) + throw InvalidBuildFileException ( + node.location, + "module '%s' cannot link against itself", + name.c_str() ); +} + +void +Library::ProcessXML() +{ + if ( !module.project.LocateModule ( name ) ) + throw InvalidBuildFileException ( + node.location, + "module '%s' trying to link against non-existant module '%s'", + module.name.c_str(), + name.c_str() ); } diff --git a/reactos/tools/rbuild/project.cpp b/reactos/tools/rbuild/project.cpp index fcd3f5f0768..ec5a6929da5 100644 --- a/reactos/tools/rbuild/project.cpp +++ b/reactos/tools/rbuild/project.cpp @@ -22,7 +22,7 @@ Project::~Project () { for ( size_t i = 0; i < modules.size (); i++ ) delete modules[i]; - delete head; + delete node; } void @@ -32,37 +32,53 @@ Project::ReadXml () do { - head = XMLParse ( xmlfile, path ); - if ( !head ) - throw InvalidBuildFileException ( "Document contains no 'project' tag." ); - } while ( head->name != "project" ); + node = XMLParse ( xmlfile, path ); + if ( !node ) + throw InvalidBuildFileException ( + node->location, + "Document contains no 'project' tag." ); + } while ( node->name != "project" ); - this->ProcessXML ( *head, "." ); + this->ProcessXML ( "." ); } void -Project::ProcessXML ( const XMLElement& e, const string& path ) +Project::ProcessXML ( const string& path ) { const XMLAttribute *att; - string subpath(path); - if ( e.name == "project" ) - { - att = e.GetAttribute ( "name", false ); - if ( !att ) - name = "Unnamed"; - else - name = att->value; + if ( node->name != "project" ) + throw Exception ( "internal tool error: Project::ProcessXML() called with non- node" ); - att = e.GetAttribute ( "makefile", true ); - assert(att); - makefile = att->value; - } - else if ( e.name == "module" ) + att = node->GetAttribute ( "name", false ); + if ( !att ) + name = "Unnamed"; + else + name = att->value; + + att = node->GetAttribute ( "makefile", true ); + assert(att); + makefile = att->value; + + size_t i; + for ( i = 0; i < node->subElements.size(); i++ ) + ProcessXMLSubElement ( *node->subElements[i], path ); + for ( i = 0; i < modules.size(); i++ ) + modules[i]->ProcessXML(); + for ( i = 0; i < includes.size(); i++ ) + includes[i]->ProcessXML(); + for ( i = 0; i < defines.size(); i++ ) + defines[i]->ProcessXML(); +} + +void +Project::ProcessXMLSubElement ( const XMLElement& e, const string& path ) +{ + bool subs_invalid = false; + string subpath(path); + if ( e.name == "module" ) { - Module* module = new Module ( this, e, path ); - modules.push_back ( module ); - module->ProcessXML ( e, path ); - return; + modules.push_back ( new Module ( *this, e, path ) ); + return; // defer processing until later } else if ( e.name == "directory" ) { @@ -72,22 +88,37 @@ Project::ProcessXML ( const XMLElement& e, const string& path ) } else if ( e.name == "include" ) { - Include* include = new Include ( this, e ); - includes.push_back ( include ); - include->ProcessXML ( e ); + includes.push_back ( new Include ( *this, e ) ); + subs_invalid = true; } else if ( e.name == "define" ) { - Define* define = new Define ( this, e ); - defines.push_back ( define ); - define->ProcessXML ( e ); + defines.push_back ( new Define ( *this, e ) ); + subs_invalid = true; } + if ( subs_invalid && e.subElements.size() ) + throw InvalidBuildFileException ( + e.location, + "<%s> cannot have sub-elements", + e.name.c_str() ); for ( size_t i = 0; i < e.subElements.size (); i++ ) - ProcessXML ( *e.subElements[i], subpath ); + ProcessXMLSubElement ( *e.subElements[i], subpath ); } Module* -Project::LocateModule ( string name ) +Project::LocateModule ( const string& name ) +{ + for ( size_t i = 0; i < modules.size (); i++ ) + { + if (modules[i]->name == name) + return modules[i]; + } + + return NULL; +} + +const Module* +Project::LocateModule ( const string& name ) const { for ( size_t i = 0; i < modules.size (); i++ ) { diff --git a/reactos/tools/rbuild/rbuild.h b/reactos/tools/rbuild/rbuild.h index 22285b08bcf..7844a1e1762 100644 --- a/reactos/tools/rbuild/rbuild.h +++ b/reactos/tools/rbuild/rbuild.h @@ -40,13 +40,15 @@ public: Project (); Project ( const std::string& filename ); ~Project (); - void ProcessXML ( const XMLElement& e, - const std::string& path ); - Module* LocateModule ( std::string name ); + void ProcessXML ( const std::string& path ); + Module* LocateModule ( const std::string& name ); + const Module* LocateModule ( const std::string& name ) const; private: void ReadXml (); XMLFile xmlfile; - XMLElement* head; + XMLElement* node; + void ProcessXMLSubElement ( const XMLElement& e, + const std::string& path ); }; @@ -61,7 +63,7 @@ enum ModuleType class Module { public: - Project* project; + const Project& project; const XMLElement& node; std::string name; std::string extension; @@ -72,56 +74,58 @@ public: std::vector includes; std::vector defines; - Module ( Project* project, + Module ( const Project& project, const XMLElement& moduleNode, const std::string& modulePath ); ~Module (); ModuleType GetModuleType (const XMLAttribute& attribute ); std::string GetPath () const; - void ProcessXML ( const XMLElement& e, const std::string& path ); + void ProcessXML(); private: - std::string GetDefaultModuleExtension (); + std::string GetDefaultModuleExtension () const; + void ProcessXMLSubElement ( const XMLElement& e, + const std::string& path ); }; class Include { public: - Project* project; - Module* module; + const Project& project; + const Module* module; const XMLElement& node; std::string directory; - Include ( Project* project, + Include ( const Project& project, const XMLElement& includeNode ); - Include ( Project* project, - Module* module, + Include ( const Project& project, + const Module* module, const XMLElement& includeNode ); ~Include (); - void ProcessXML ( const XMLElement& e ); + void ProcessXML(); private: - void Initialize ( const XMLElement& includeNode ); + void Initialize(); }; class Define { public: - Project* project; - Module* module; + const Project& project; + const Module* module; const XMLElement& node; std::string name; std::string value; - Define ( Project* project, + Define ( const Project& project, const XMLElement& defineNode ); - Define ( Project* project, - Module* module, + Define ( const Project& project, + const Module* module, const XMLElement& defineNode ); ~Define(); - void ProcessXML ( const XMLElement& e ); + void ProcessXML(); private: - void Initialize ( const XMLElement& defineNode ); + void Initialize(); }; @@ -137,9 +141,15 @@ public: class Library { public: + const XMLElement& node; + const Module& module; std::string name; - Library ( const std::string& _name ); + Library ( const XMLElement& _node, + const Module& _module, + const std::string& _name ); + + void ProcessXML(); }; extern std::string