added xi:fallback support
authorRoyce Mitchell III <royce3@ev1.net>
Sun, 9 Jan 2005 19:16:35 +0000 (19:16 +0000)
committerRoyce Mitchell III <royce3@ev1.net>
Sun, 9 Jan 2005 19:16:35 +0000 (19:16 +0000)
fixed some memory leaks in Project
detect and report "end of file looking for end tag" instead of just crashing

svn path=/branches/xmlbuildsystem/; revision=12911

reactos/ReactOS.xml
reactos/config.template.xml [new file with mode: 0644]
reactos/tools/rbuild/XML.cpp
reactos/tools/rbuild/XML.h
reactos/tools/rbuild/backend/backend.cpp
reactos/tools/rbuild/backend/backend.h
reactos/tools/rbuild/backend/mingw/modulehandler.cpp
reactos/tools/rbuild/backend/mingw/modulehandler.h
reactos/tools/rbuild/project.cpp
reactos/tools/rbuild/rbuild.cpp
reactos/tools/rbuild/rbuild.h

index 63f491c..957e717 100644 (file)
@@ -1,6 +1,11 @@
 <?xml version="1.0"?>\r
 <!DOCTYPE project SYSTEM "tools/rbuild/project.dtd">\r
 <project name="ReactOS" makefile="Makefile.auto" xmlns:xi="http://www.w3.org/2001/XInclude">\r
+       <xi:include href="config.xml">\r
+               <xi:fallback>\r
+                       <xi:include href="config.template.xml" />\r
+               </xi:fallback>\r
+       </xi:include>\r
        <define name="_M_IX86" />\r
        <include>include</include>\r
        <include>w32api/include</include>\r
diff --git a/reactos/config.template.xml b/reactos/config.template.xml
new file mode 100644 (file)
index 0000000..341c548
--- /dev/null
@@ -0,0 +1,66 @@
+<!--\r
+ Architecture to build for\r
+\r
+ Specify one of: i386\r
+ Possible values in the future: alpha,i386,m68k,mips,powerpc\r
+-->\r
+\r
+<define name="ARCH" value="i386" />\r
+\r
+\r
+<!--\r
+ Which cpu should reactos optimze for\r
+ example : i486, i586, pentium, pentium2, pentum3, pentium4\r
+           athlon-xp, athlon-mp, k6-2, \r
+\r
+ see gcc manual for more cpu name and which cpu it can \r
+ be optimze for. \r
+-->\r
+\r
+<define name="OARCH" value="i486" />\r
+\r
+<!--\r
+ Whether to compile in the kernel debugger\r
+-->\r
+\r
+<define name="KDBG" value="0" />\r
+\r
+\r
+<!--\r
+ Whether to compile for debugging\r
+-->\r
+\r
+<define name="DBG" value="0" />\r
+\r
+\r
+<!--\r
+ Whether to compile with optimizations\r
+-->\r
+\r
+<define name="OPTIMIZED" value="0" />\r
+\r
+\r
+<!--\r
+ Whether to compile a multiprocessor or single processor version\r
+-->\r
+\r
+<define name="MP" value="0" />\r
+\r
+<!--\r
+ Whether to compile for ACPI compliant systems\r
+-->\r
+\r
+<define name="ACPI" value="0" />\r
+\r
+\r
+<!--\r
+ whether to use a 3GB User, 1GB Kernel memory map\r
+-->\r
+\r
+<define name="3GB" value="1" />\r
+\r
+\r
+<!--\r
+ Which version of NDIS do we support up to?\r
+<define name="NDISVERSION" value="NDIS50" />\r
+-->\r
index 16767a5..b936df7 100644 (file)
@@ -22,6 +22,28 @@ static const char* WSEQ = " =\t\r\n";
 \r
 string working_directory;\r
 \r
+class XMLInclude\r
+{\r
+public:\r
+       XMLElement *e;\r
+       Path path;\r
+\r
+       XMLInclude ( XMLElement* e_, const Path& path_ )\r
+               : e(e_), path(path_)\r
+       {\r
+       }\r
+};\r
+\r
+class XMLIncludes : public vector<XMLInclude*>\r
+{\r
+public:\r
+       ~XMLIncludes()\r
+       {\r
+               for ( size_t i = 0; i < this->size(); i++ )\r
+                       delete (*this)[i];\r
+       }\r
+};\r
+\r
 void\r
 InitWorkingDirectory()\r
 {\r
@@ -306,6 +328,19 @@ XMLAttribute::XMLAttribute(const string& name_,
 {\r
 }\r
 \r
+XMLAttribute::XMLAttribute ( const XMLAttribute& src )\r
+       : name(src.name), value(src.value)\r
+{\r
+\r
+}\r
+\r
+XMLAttribute& XMLAttribute::operator = ( const XMLAttribute& src )\r
+{\r
+       name = src.name;\r
+       value = src.value;\r
+       return *this;\r
+}\r
+\r
 XMLElement::XMLElement ( const string& location_ )\r
        : location(location_),\r
          parentElement(NULL)\r
@@ -451,7 +486,6 @@ XMLElement::GetAttribute ( const string& attribute,
 \r
 // XMLParse()\r
 // This function reads a "token" from the file loaded in XMLFile\r
-// REM TODO FIXME: At the moment it can't handle comments or non-xml tags.\r
 // if it finds a tag that is non-singular, it parses sub-elements and/or\r
 // inner text into the XMLElement that it is building to return.\r
 // Return Value: an XMLElement allocated via the new operator that contains\r
@@ -459,13 +493,14 @@ XMLElement::GetAttribute ( const string& attribute,
 // (no more data)\r
 XMLElement*\r
 XMLParse(XMLFile& f,\r
+         XMLIncludes* includes,\r
          const Path& path,\r
-         bool* pend_tag /*= NULL*/)\r
+         bool* pend_tag = NULL )\r
 {\r
        string token;\r
        if ( !f.get_token(token) )\r
                return NULL;\r
-       bool end_tag;\r
+       bool end_tag, is_include = false;\r
 \r
        while ( token[0] != '<'\r
                || !strncmp ( token.c_str(), "<!--", 4 )\r
@@ -482,32 +517,10 @@ XMLParse(XMLFile& f,
        XMLElement* e = new XMLElement ( f.Location() );\r
        bool bNeedEnd = e->Parse ( token, end_tag );\r
 \r
-       if ( e->name == "xi:include" )\r
+       if ( e->name == "xi:include" && includes )\r
        {\r
-               XMLAttribute* att;\r
-               att = e->GetAttribute("href",true);\r
-               assert(att);\r
-\r
-               string file ( path.Fixup(att->value,true) );\r
-               string top_file ( Path::RelativeFromWorkingDirectory ( file ) );\r
-               e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) );\r
-               XMLFile fInc;\r
-               if ( !fInc.open ( file ) )\r
-                       throw FileNotFoundException (\r
-                               ssprintf("%s (referenced from %s)",\r
-                                       file.c_str(),\r
-                                       f.Location().c_str() ) );\r
-               else\r
-               {\r
-                       Path path2 ( path, att->value );\r
-                       for ( ;; )\r
-                       {\r
-                               XMLElement* e2 = XMLParse ( fInc, path2 );\r
-                               if ( !e2 )\r
-                                       break;\r
-                               e->AddSubElement ( e2 );\r
-                       }\r
-               }\r
+               includes->push_back ( new XMLInclude ( e, path ) );\r
+               is_include = true;\r
        }\r
 \r
        if ( !bNeedEnd )\r
@@ -531,7 +544,9 @@ XMLParse(XMLFile& f,
                {\r
                        if ( !f.get_token ( token ) || !token.size() )\r
                        {\r
-                               throw Exception ( "internal tool error - get_token() failed when more_tokens() returned true" );\r
+                               throw InvalidBuildFileException (\r
+                                       f.Location(),\r
+                                       "internal tool error - get_token() failed when more_tokens() returned true" );\r
                                break;\r
                        }\r
                        if ( e->subElements.size() && !bThisMixingErrorReported )\r
@@ -556,12 +571,23 @@ XMLParse(XMLFile& f,
                }\r
                else\r
                {\r
-                       XMLElement* e2 = XMLParse ( f, path, &end_tag );\r
+                       XMLElement* e2 = XMLParse ( f, is_include ? NULL : includes, path, &end_tag );\r
+                       if ( !e2 )\r
+                       {\r
+                               throw InvalidBuildFileException (\r
+                                       e->location,\r
+                                       "end of file found looking for end tag" );\r
+                               break;\r
+                       }\r
                        if ( end_tag )\r
                        {\r
                                if ( e->name != e2->name )\r
+                               {\r
+                                       delete e2;\r
                                        throw XMLSyntaxErrorException ( f.Location(),\r
                                                                        "end tag name mismatch" );\r
+                                       break;\r
+                               }\r
                                delete e2;\r
                                break;\r
                        }\r
@@ -576,3 +602,118 @@ XMLParse(XMLFile& f,
        }\r
        return e;\r
 }\r
+\r
+void\r
+XMLReadFile ( XMLFile& f, XMLElement& head, XMLIncludes& includes, const Path& path )\r
+{\r
+       for ( ;; )\r
+       {\r
+               XMLElement* e = XMLParse ( f, &includes, path );\r
+               if ( !e )\r
+                       return;\r
+               head.AddSubElement ( e );\r
+       }\r
+}\r
+\r
+XMLElement*\r
+XMLLoadInclude ( XMLElement* e, const Path& path, XMLIncludes& includes )\r
+{\r
+       // TODO FIXME\r
+       XMLAttribute* att;\r
+       att = e->GetAttribute("href",true);\r
+       assert(att);\r
+\r
+       string file ( path.Fixup(att->value,true) );\r
+       string top_file ( Path::RelativeFromWorkingDirectory ( file ) );\r
+       e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) );\r
+       XMLFile fInc;\r
+       if ( !fInc.open ( file ) )\r
+       {\r
+               // look for xi:fallback element\r
+               for ( size_t i = 0; i < e->subElements.size(); i++ )\r
+               {\r
+                       XMLElement* e2 = e->subElements[i];\r
+                       if ( e2->name == "xi:fallback" )\r
+                       {\r
+                               // now look for xi:include below...\r
+                               for ( i = 0; i < e2->subElements.size(); i++ )\r
+                               {\r
+                                       XMLElement* e3 = e2->subElements[i];\r
+                                       if ( e3->name == "xi:include" )\r
+                                       {\r
+                                               return XMLLoadInclude ( e3, path, includes );\r
+                                       }\r
+                               }\r
+                               throw InvalidBuildFileException (\r
+                                       e2->location,\r
+                                       "<xi:fallback> must have a <xi:include> sub-element" );\r
+                               return NULL;\r
+                       }\r
+               }\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               XMLElement* new_e = new XMLElement ( e->location );\r
+               new_e->name = "xi:included";\r
+               Path path2 ( path, att->value );\r
+               XMLReadFile ( fInc, *new_e, includes, path2 );\r
+               return new_e;\r
+       }\r
+}\r
+\r
+XMLElement*\r
+XMLLoadFile ( const string& filename, const Path& path )\r
+{\r
+       XMLIncludes includes;\r
+       XMLFile f;\r
+\r
+       if ( !f.open ( filename ) )\r
+               throw FileNotFoundException ( filename );\r
+\r
+       XMLElement* head = new XMLElement("(virtual)");\r
+\r
+       XMLReadFile ( f, *head, includes, path );\r
+\r
+       for ( size_t i = 0; i < includes.size(); i++ )\r
+       {\r
+               XMLElement* e = includes[i]->e;\r
+               XMLElement* e2 = XMLLoadInclude ( includes[i]->e, includes[i]->path, includes );\r
+               if ( !e2 )\r
+               {\r
+                       throw FileNotFoundException (\r
+                               ssprintf("%s (referenced from %s)",\r
+                                       e->GetAttribute("top_href",true)->value.c_str(),\r
+                                       f.Location().c_str() ) );\r
+               }\r
+               XMLElement* parent = e->parentElement;\r
+               XMLElement** parent_container = NULL;\r
+               if ( !parent )\r
+               {\r
+                       delete e;\r
+                       throw Exception ( "internal tool error: xi:include doesn't have a parent" );\r
+                       return NULL;\r
+               }\r
+               for ( size_t j = 0; j < parent->subElements.size(); j++ )\r
+               {\r
+                       if ( parent->subElements[j] == e )\r
+                       {\r
+                               parent_container = &parent->subElements[j];\r
+                               break;\r
+                       }\r
+               }\r
+               if ( !parent_container )\r
+               {\r
+                       delete e;\r
+                       throw Exception ( "internal tool error: couldn't find xi:include in parent's sub-elements" );\r
+                       return NULL;\r
+               }\r
+               // replace inclusion tree with the imported tree\r
+               e2->name = e->name;\r
+               e2->attributes = e->attributes;\r
+               *parent_container = e2;\r
+               e->attributes.resize(0);\r
+               delete e;\r
+       }\r
+       return head;\r
+}\r
index ba55e26..37b8684 100644 (file)
@@ -52,6 +52,8 @@ public:
 \r
        XMLAttribute();\r
        XMLAttribute ( const std::string& name_, const std::string& value_ );\r
+       XMLAttribute ( const XMLAttribute& );\r
+       XMLAttribute& operator = ( const XMLAttribute& );\r
 };\r
 \r
 \r
@@ -77,8 +79,11 @@ public:
 };\r
 \r
 XMLElement*\r
+XMLLoadFile ( const std::string& filename, const Path& path );\r
+\r
+/*XMLElement*\r
 XMLParse(XMLFile& f,\r
          const Path& path,\r
-         bool* pend_tag = NULL);\r
+         bool* pend_tag = NULL);*/\r
 \r
 #endif//XML_H\r
index a54558c..02da1dc 100644 (file)
@@ -8,17 +8,29 @@ using std::string;
 using std::vector;\r
 using std::map;\r
 \r
-map<string,Backend::Factory*>* Backend::Factory::factories = NULL;\r
+map<string,Backend::Factory*>*\r
+Backend::Factory::factories = NULL;\r
+int\r
+Backend::Factory::ref = 0;\r
 \r
 Backend::Factory::Factory ( const std::string& name_ )\r
 {\r
        string name(name_);\r
        strlwr ( &name[0] );\r
-       if ( !factories )\r
+       if ( !ref++ )\r
                factories = new map<string,Factory*>;\r
        (*factories)[name] = this;\r
 }\r
 \r
+Backend::Factory::~Factory()\r
+{\r
+       if ( !--ref )\r
+       {\r
+               delete factories;\r
+               factories = NULL;\r
+       }\r
+}\r
+\r
 /*static*/ Backend*\r
 Backend::Factory::Create ( const string& name,\r
                            Project& project )\r
index 2c7497a..c265682 100644 (file)
@@ -13,11 +13,12 @@ public:
        class Factory\r
        {\r
                static std::map<std::string,Factory*>* factories;\r
+               static int ref;\r
 \r
        protected:\r
 \r
                Factory ( const std::string& name_ );\r
-               virtual ~Factory() {}\r
+               virtual ~Factory();\r
 \r
                virtual Backend* operator() ( Project& ) = 0;\r
 \r
index 4c6e34a..23fbfba 100644 (file)
@@ -12,17 +12,28 @@ using std::map;
 \r
 map<ModuleType,MingwModuleHandler*>*\r
 MingwModuleHandler::handler_map = NULL;\r
+int\r
+MingwModuleHandler::ref = 0;\r
 \r
 FILE*\r
 MingwModuleHandler::fMakefile = NULL;\r
 \r
 MingwModuleHandler::MingwModuleHandler ( ModuleType moduletype )\r
 {\r
-       if ( !handler_map )\r
+       if ( !ref++ )\r
                handler_map = new map<ModuleType,MingwModuleHandler*>;\r
        (*handler_map)[moduletype] = this;\r
 }\r
 \r
+MingwModuleHandler::~MingwModuleHandler()\r
+{\r
+       if ( !--ref )\r
+       {\r
+               delete handler_map;\r
+               handler_map = NULL;\r
+       }\r
+}\r
+\r
 /*static*/ void\r
 MingwModuleHandler::SetMakefile ( FILE* f )\r
 {\r
index c0173e7..cfa1912 100644 (file)
@@ -7,9 +7,10 @@ class MingwModuleHandler
 {\r
 public:\r
        static std::map<ModuleType,MingwModuleHandler*>* handler_map;\r
+       static int ref;\r
 \r
        MingwModuleHandler ( ModuleType moduletype );\r
-       virtual ~MingwModuleHandler() {}\r
+       virtual ~MingwModuleHandler();\r
 \r
        static void SetMakefile ( FILE* f );\r
        static MingwModuleHandler* LookupHandler ( const std::string& location,\r
index c46c25f..69ffeda 100644 (file)
@@ -7,39 +7,48 @@
 using std::string;\r
 using std::vector;\r
 \r
-Project::Project()\r
+/*Project::Project()\r
+       : node(NULL), head(NULL)\r
 {\r
-}\r
+}*/\r
 \r
 Project::Project ( const string& filename )\r
+       : xmlfile(filename), node(NULL), head(NULL)\r
 {\r
-       if ( !xmlfile.open ( filename ) )\r
-               throw FileNotFoundException ( filename );\r
        ReadXml();\r
 }\r
 \r
 Project::~Project ()\r
 {\r
-       for ( size_t i = 0; i < modules.size (); i++ )\r
+       size_t i;\r
+       for ( i = 0; i < modules.size (); i++ )\r
                delete modules[i];\r
-       delete node;\r
+       for ( i = 0; i < includes.size(); i++ )\r
+               delete includes[i];\r
+       for ( i = 0; i < defines.size(); i++ )\r
+               delete defines[i];\r
+       delete head;\r
 }\r
 \r
 void\r
-Project::ReadXml ()\r
+Project::ReadXml()\r
 {\r
        Path path;\r
-\r
-       do\r
+       head = XMLLoadFile ( xmlfile, path );\r
+       node = NULL;\r
+       for ( size_t i = 0; i < head->subElements.size(); i++ )\r
        {\r
-               node = XMLParse ( xmlfile, path );\r
-               if ( !node )\r
-                       throw InvalidBuildFileException (\r
-                               node->location,\r
-                               "Document contains no 'project' tag." );\r
-       } while ( node->name != "project" );\r
+               if ( head->subElements[i]->name == "project" )\r
+               {\r
+                       node = head->subElements[i];\r
+                       this->ProcessXML ( "." );\r
+                       return;\r
+               }\r
+       }\r
 \r
-       this->ProcessXML ( "." );\r
+       throw InvalidBuildFileException (\r
+               node->location,\r
+               "Document contains no 'project' tag." );\r
 }\r
 \r
 void\r
index 58d6ac1..d0e24bf 100644 (file)
@@ -31,38 +31,6 @@ main ( int argc, char** argv )
                Backend* backend = Backend::Factory::Create ( buildtarget, project );\r
                backend->Process ();\r
                delete backend;\r
-               \r
-               // REM TODO FIXME actually do something with Project object...\r
-#if 0\r
-               printf ( "Found %d modules:\n", project.modules.size() );\r
-               for ( size_t i = 0; i < project.modules.size(); i++ )\r
-               {\r
-                       Module& m = *project.modules[i];\r
-                       printf ( "\t%s in folder: %s\n",\r
-                                m.name.c_str(),\r
-                                m.path.c_str() );\r
-                       printf ( "\txml dependencies:\n\t\t%s\n",\r
-                                projectFilename.c_str() );\r
-                       const XMLElement* e = &m.node;\r
-                       while ( e )\r
-                       {\r
-                               if ( e->name == "xi:include" )\r
-                               {\r
-                                       const XMLAttribute* att = e->GetAttribute("top_href",false);\r
-                                       if ( att )\r
-                                       {\r
-                                               printf ( "\t\t%s\n", att->value.c_str() );\r
-                                       }\r
-                               }\r
-                               e = e->parentElement;\r
-                       }\r
-                       printf ( "\tfiles:\n" );\r
-                       for ( size_t j = 0; j < m.files.size(); j++ )\r
-                       {\r
-                               printf ( "\t\t%s\n", m.files[j]->name.c_str() );\r
-                       }\r
-               }\r
-#endif\r
 \r
                return 0;\r
        }\r
index 1407a84..8de0735 100644 (file)
@@ -33,6 +33,8 @@ class Dependency;
 \r
 class Project\r
 {\r
+       std::string xmlfile;\r
+       XMLElement *node, *head;\r
 public:\r
        std::string name;\r
        std::string makefile;\r
@@ -40,7 +42,7 @@ public:
        std::vector<Include*> includes;\r
        std::vector<Define*> defines;\r
 \r
-       Project ();\r
+       //Project ();\r
        Project ( const std::string& filename );\r
        ~Project ();\r
        void ProcessXML ( const std::string& path );\r
@@ -48,10 +50,12 @@ public:
        const Module* LocateModule ( const std::string& name ) const;\r
 private:\r
        void ReadXml ();\r
-       XMLFile xmlfile;\r
-       XMLElement* node;\r
        void ProcessXMLSubElement ( const XMLElement& e,\r
                                    const std::string& path );\r
+\r
+       // disable copy semantics\r
+       Project ( const Project& );\r
+       Project& operator = ( const Project& );\r
 };\r
 \r
 \r