mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:23:01 +00:00
added xi:fallback support
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
This commit is contained in:
parent
51221a2b14
commit
e5130a546a
11 changed files with 310 additions and 87 deletions
|
@ -1,6 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE project SYSTEM "tools/rbuild/project.dtd">
|
||||
<project name="ReactOS" makefile="Makefile.auto" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<xi:include href="config.xml">
|
||||
<xi:fallback>
|
||||
<xi:include href="config.template.xml" />
|
||||
</xi:fallback>
|
||||
</xi:include>
|
||||
<define name="_M_IX86" />
|
||||
<include>include</include>
|
||||
<include>w32api/include</include>
|
||||
|
|
66
reactos/config.template.xml
Normal file
66
reactos/config.template.xml
Normal file
|
@ -0,0 +1,66 @@
|
|||
<!--
|
||||
Architecture to build for
|
||||
|
||||
Specify one of: i386
|
||||
Possible values in the future: alpha,i386,m68k,mips,powerpc
|
||||
-->
|
||||
|
||||
<define name="ARCH" value="i386" />
|
||||
|
||||
|
||||
<!--
|
||||
Which cpu should reactos optimze for
|
||||
example : i486, i586, pentium, pentium2, pentum3, pentium4
|
||||
athlon-xp, athlon-mp, k6-2,
|
||||
|
||||
see gcc manual for more cpu name and which cpu it can
|
||||
be optimze for.
|
||||
-->
|
||||
|
||||
<define name="OARCH" value="i486" />
|
||||
|
||||
<!--
|
||||
Whether to compile in the kernel debugger
|
||||
-->
|
||||
|
||||
<define name="KDBG" value="0" />
|
||||
|
||||
|
||||
<!--
|
||||
Whether to compile for debugging
|
||||
-->
|
||||
|
||||
<define name="DBG" value="0" />
|
||||
|
||||
|
||||
<!--
|
||||
Whether to compile with optimizations
|
||||
-->
|
||||
|
||||
<define name="OPTIMIZED" value="0" />
|
||||
|
||||
|
||||
<!--
|
||||
Whether to compile a multiprocessor or single processor version
|
||||
-->
|
||||
|
||||
<define name="MP" value="0" />
|
||||
|
||||
<!--
|
||||
Whether to compile for ACPI compliant systems
|
||||
-->
|
||||
|
||||
<define name="ACPI" value="0" />
|
||||
|
||||
|
||||
<!--
|
||||
whether to use a 3GB User, 1GB Kernel memory map
|
||||
-->
|
||||
|
||||
<define name="3GB" value="1" />
|
||||
|
||||
|
||||
<!--
|
||||
Which version of NDIS do we support up to?
|
||||
<define name="NDISVERSION" value="NDIS50" />
|
||||
-->
|
|
@ -22,6 +22,28 @@ 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()
|
||||
{
|
||||
|
@ -306,6 +328,19 @@ XMLAttribute::XMLAttribute(const string& name_,
|
|||
{
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -451,7 +486,6 @@ XMLElement::GetAttribute ( const string& attribute,
|
|||
|
||||
// XMLParse()
|
||||
// This function reads a "token" from the file loaded in XMLFile
|
||||
// REM TODO FIXME: At the moment it can't handle comments or non-xml tags.
|
||||
// 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
|
||||
|
@ -459,13 +493,14 @@ XMLElement::GetAttribute ( const string& attribute,
|
|||
// (no more data)
|
||||
XMLElement*
|
||||
XMLParse(XMLFile& f,
|
||||
XMLIncludes* includes,
|
||||
const Path& path,
|
||||
bool* pend_tag /*= NULL*/)
|
||||
bool* pend_tag = NULL )
|
||||
{
|
||||
string token;
|
||||
if ( !f.get_token(token) )
|
||||
return NULL;
|
||||
bool end_tag;
|
||||
bool end_tag, is_include = false;
|
||||
|
||||
while ( token[0] != '<'
|
||||
|| !strncmp ( token.c_str(), "<!--", 4 )
|
||||
|
@ -482,32 +517,10 @@ XMLParse(XMLFile& f,
|
|||
XMLElement* e = new XMLElement ( f.Location() );
|
||||
bool bNeedEnd = e->Parse ( token, end_tag );
|
||||
|
||||
if ( e->name == "xi:include" )
|
||||
if ( e->name == "xi:include" && 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 ) )
|
||||
throw FileNotFoundException (
|
||||
ssprintf("%s (referenced from %s)",
|
||||
file.c_str(),
|
||||
f.Location().c_str() ) );
|
||||
else
|
||||
{
|
||||
Path path2 ( path, att->value );
|
||||
for ( ;; )
|
||||
{
|
||||
XMLElement* e2 = XMLParse ( fInc, path2 );
|
||||
if ( !e2 )
|
||||
break;
|
||||
e->AddSubElement ( e2 );
|
||||
}
|
||||
}
|
||||
includes->push_back ( new XMLInclude ( e, path ) );
|
||||
is_include = true;
|
||||
}
|
||||
|
||||
if ( !bNeedEnd )
|
||||
|
@ -531,7 +544,9 @@ XMLParse(XMLFile& f,
|
|||
{
|
||||
if ( !f.get_token ( token ) || !token.size() )
|
||||
{
|
||||
throw Exception ( "internal tool error - get_token() failed when more_tokens() returned true" );
|
||||
throw InvalidBuildFileException (
|
||||
f.Location(),
|
||||
"internal tool error - get_token() failed when more_tokens() returned true" );
|
||||
break;
|
||||
}
|
||||
if ( e->subElements.size() && !bThisMixingErrorReported )
|
||||
|
@ -556,12 +571,23 @@ XMLParse(XMLFile& f,
|
|||
}
|
||||
else
|
||||
{
|
||||
XMLElement* e2 = XMLParse ( f, path, &end_tag );
|
||||
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;
|
||||
}
|
||||
|
@ -576,3 +602,118 @@ XMLParse(XMLFile& f,
|
|||
}
|
||||
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 )
|
||||
{
|
||||
// TODO FIXME
|
||||
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->name = e->name;
|
||||
e2->attributes = e->attributes;
|
||||
*parent_container = e2;
|
||||
e->attributes.resize(0);
|
||||
delete e;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
|
||||
XMLAttribute();
|
||||
XMLAttribute ( const std::string& name_, const std::string& value_ );
|
||||
XMLAttribute ( const XMLAttribute& );
|
||||
XMLAttribute& operator = ( const XMLAttribute& );
|
||||
};
|
||||
|
||||
|
||||
|
@ -77,8 +79,11 @@ public:
|
|||
};
|
||||
|
||||
XMLElement*
|
||||
XMLLoadFile ( const std::string& filename, const Path& path );
|
||||
|
||||
/*XMLElement*
|
||||
XMLParse(XMLFile& f,
|
||||
const Path& path,
|
||||
bool* pend_tag = NULL);
|
||||
bool* pend_tag = NULL);*/
|
||||
|
||||
#endif//XML_H
|
||||
|
|
|
@ -8,17 +8,29 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::map;
|
||||
|
||||
map<string,Backend::Factory*>* Backend::Factory::factories = NULL;
|
||||
map<string,Backend::Factory*>*
|
||||
Backend::Factory::factories = NULL;
|
||||
int
|
||||
Backend::Factory::ref = 0;
|
||||
|
||||
Backend::Factory::Factory ( const std::string& name_ )
|
||||
{
|
||||
string name(name_);
|
||||
strlwr ( &name[0] );
|
||||
if ( !factories )
|
||||
if ( !ref++ )
|
||||
factories = new map<string,Factory*>;
|
||||
(*factories)[name] = this;
|
||||
}
|
||||
|
||||
Backend::Factory::~Factory()
|
||||
{
|
||||
if ( !--ref )
|
||||
{
|
||||
delete factories;
|
||||
factories = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ Backend*
|
||||
Backend::Factory::Create ( const string& name,
|
||||
Project& project )
|
||||
|
|
|
@ -13,11 +13,12 @@ public:
|
|||
class Factory
|
||||
{
|
||||
static std::map<std::string,Factory*>* factories;
|
||||
static int ref;
|
||||
|
||||
protected:
|
||||
|
||||
Factory ( const std::string& name_ );
|
||||
virtual ~Factory() {}
|
||||
virtual ~Factory();
|
||||
|
||||
virtual Backend* operator() ( Project& ) = 0;
|
||||
|
||||
|
|
|
@ -12,17 +12,28 @@ using std::map;
|
|||
|
||||
map<ModuleType,MingwModuleHandler*>*
|
||||
MingwModuleHandler::handler_map = NULL;
|
||||
int
|
||||
MingwModuleHandler::ref = 0;
|
||||
|
||||
FILE*
|
||||
MingwModuleHandler::fMakefile = NULL;
|
||||
|
||||
MingwModuleHandler::MingwModuleHandler ( ModuleType moduletype )
|
||||
{
|
||||
if ( !handler_map )
|
||||
if ( !ref++ )
|
||||
handler_map = new map<ModuleType,MingwModuleHandler*>;
|
||||
(*handler_map)[moduletype] = this;
|
||||
}
|
||||
|
||||
MingwModuleHandler::~MingwModuleHandler()
|
||||
{
|
||||
if ( !--ref )
|
||||
{
|
||||
delete handler_map;
|
||||
handler_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
MingwModuleHandler::SetMakefile ( FILE* f )
|
||||
{
|
||||
|
|
|
@ -7,9 +7,10 @@ class MingwModuleHandler
|
|||
{
|
||||
public:
|
||||
static std::map<ModuleType,MingwModuleHandler*>* handler_map;
|
||||
static int ref;
|
||||
|
||||
MingwModuleHandler ( ModuleType moduletype );
|
||||
virtual ~MingwModuleHandler() {}
|
||||
virtual ~MingwModuleHandler();
|
||||
|
||||
static void SetMakefile ( FILE* f );
|
||||
static MingwModuleHandler* LookupHandler ( const std::string& location,
|
||||
|
|
|
@ -7,39 +7,48 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
Project::Project()
|
||||
/*Project::Project()
|
||||
: node(NULL), head(NULL)
|
||||
{
|
||||
}
|
||||
}*/
|
||||
|
||||
Project::Project ( const string& filename )
|
||||
: xmlfile(filename), node(NULL), head(NULL)
|
||||
{
|
||||
if ( !xmlfile.open ( filename ) )
|
||||
throw FileNotFoundException ( filename );
|
||||
ReadXml();
|
||||
}
|
||||
|
||||
Project::~Project ()
|
||||
{
|
||||
for ( size_t i = 0; i < modules.size (); i++ )
|
||||
size_t i;
|
||||
for ( i = 0; i < modules.size (); i++ )
|
||||
delete modules[i];
|
||||
delete node;
|
||||
for ( i = 0; i < includes.size(); i++ )
|
||||
delete includes[i];
|
||||
for ( i = 0; i < defines.size(); i++ )
|
||||
delete defines[i];
|
||||
delete head;
|
||||
}
|
||||
|
||||
void
|
||||
Project::ReadXml()
|
||||
{
|
||||
Path path;
|
||||
|
||||
do
|
||||
head = XMLLoadFile ( xmlfile, path );
|
||||
node = NULL;
|
||||
for ( size_t i = 0; i < head->subElements.size(); i++ )
|
||||
{
|
||||
node = XMLParse ( xmlfile, path );
|
||||
if ( !node )
|
||||
if ( head->subElements[i]->name == "project" )
|
||||
{
|
||||
node = head->subElements[i];
|
||||
this->ProcessXML ( "." );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw InvalidBuildFileException (
|
||||
node->location,
|
||||
"Document contains no 'project' tag." );
|
||||
} while ( node->name != "project" );
|
||||
|
||||
this->ProcessXML ( "." );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -32,38 +32,6 @@ main ( int argc, char** argv )
|
|||
backend->Process ();
|
||||
delete backend;
|
||||
|
||||
// REM TODO FIXME actually do something with Project object...
|
||||
#if 0
|
||||
printf ( "Found %d modules:\n", project.modules.size() );
|
||||
for ( size_t i = 0; i < project.modules.size(); i++ )
|
||||
{
|
||||
Module& m = *project.modules[i];
|
||||
printf ( "\t%s in folder: %s\n",
|
||||
m.name.c_str(),
|
||||
m.path.c_str() );
|
||||
printf ( "\txml dependencies:\n\t\t%s\n",
|
||||
projectFilename.c_str() );
|
||||
const XMLElement* e = &m.node;
|
||||
while ( e )
|
||||
{
|
||||
if ( e->name == "xi:include" )
|
||||
{
|
||||
const XMLAttribute* att = e->GetAttribute("top_href",false);
|
||||
if ( att )
|
||||
{
|
||||
printf ( "\t\t%s\n", att->value.c_str() );
|
||||
}
|
||||
}
|
||||
e = e->parentElement;
|
||||
}
|
||||
printf ( "\tfiles:\n" );
|
||||
for ( size_t j = 0; j < m.files.size(); j++ )
|
||||
{
|
||||
printf ( "\t\t%s\n", m.files[j]->name.c_str() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exception& ex)
|
||||
|
|
|
@ -33,6 +33,8 @@ class Dependency;
|
|||
|
||||
class Project
|
||||
{
|
||||
std::string xmlfile;
|
||||
XMLElement *node, *head;
|
||||
public:
|
||||
std::string name;
|
||||
std::string makefile;
|
||||
|
@ -40,7 +42,7 @@ public:
|
|||
std::vector<Include*> includes;
|
||||
std::vector<Define*> defines;
|
||||
|
||||
Project ();
|
||||
//Project ();
|
||||
Project ( const std::string& filename );
|
||||
~Project ();
|
||||
void ProcessXML ( const std::string& path );
|
||||
|
@ -48,10 +50,12 @@ public:
|
|||
const Module* LocateModule ( const std::string& name ) const;
|
||||
private:
|
||||
void ReadXml ();
|
||||
XMLFile xmlfile;
|
||||
XMLElement* node;
|
||||
void ProcessXMLSubElement ( const XMLElement& e,
|
||||
const std::string& path );
|
||||
|
||||
// disable copy semantics
|
||||
Project ( const Project& );
|
||||
Project& operator = ( const Project& );
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue