xml nodes now store the location they were parsed from; invalidbuildexceptions now required a location of the error; don't allow modules to process xml until all modules are created; don't allow libraries, defines, includes, etc to process xml until all modules have processed; don't allow module to link against itself or a non-existant module; don't allow library to specify non-existant module;

svn path=/branches/xmlbuildsystem/; revision=12879
This commit is contained in:
Royce Mitchell III 2005-01-08 03:37:32 +00:00
parent de7c566b05
commit 774f167e5e
10 changed files with 196 additions and 102 deletions

View file

@ -306,8 +306,9 @@ XMLAttribute::XMLAttribute(const string& name_,
{ {
} }
XMLElement::XMLElement() XMLElement::XMLElement ( const string& location_ )
: parentElement(NULL) : location(location_),
parentElement(NULL)
{ {
} }
@ -476,7 +477,7 @@ XMLParse(XMLFile& f,
return NULL; return NULL;
} }
XMLElement* e = new XMLElement; XMLElement* e = new XMLElement ( f.Location() );
bool bNeedEnd = e->Parse ( token, end_tag ); bool bNeedEnd = e->Parse ( token, end_tag );
if ( e->name == "xi:include" ) if ( e->name == "xi:include" )

View file

@ -58,13 +58,14 @@ public:
class XMLElement class XMLElement
{ {
public: public:
std::string location;
std::string name; std::string name;
std::vector<XMLAttribute*> attributes; std::vector<XMLAttribute*> attributes;
XMLElement* parentElement; XMLElement* parentElement;
std::vector<XMLElement*> subElements; std::vector<XMLElement*> subElements;
std::string value; std::string value;
XMLElement(); XMLElement ( const std::string& location_ );
~XMLElement(); ~XMLElement();
bool Parse(const std::string& token, bool Parse(const std::string& token,
bool& end_tag); bool& end_tag);

View file

@ -48,7 +48,7 @@ MingwModuleHandler::GetImportLibraryDependencies ( const Module& module ) const
{ {
if ( dependencies.size () > 0 ) if ( dependencies.size () > 0 )
dependencies += " "; dependencies += " ";
Module* importedModule = module.project->LocateModule ( module.libraries[i]->name ); const Module* importedModule = module.project.LocateModule ( module.libraries[i]->name );
assert ( importedModule != NULL ); assert ( importedModule != NULL );
dependencies += importedModule->GetPath ().c_str (); dependencies += importedModule->GetPath ().c_str ();
} }
@ -117,7 +117,7 @@ MingwModuleHandler::GenerateGccDefineParametersFromVector ( const vector<Define*
string string
MingwModuleHandler::GenerateGccDefineParameters ( const Module& module ) const MingwModuleHandler::GenerateGccDefineParameters ( const Module& module ) const
{ {
string parameters = GenerateGccDefineParametersFromVector ( module.project->defines ); string parameters = GenerateGccDefineParametersFromVector ( module.project.defines );
string s = GenerateGccDefineParametersFromVector ( module.defines ); string s = GenerateGccDefineParametersFromVector ( module.defines );
if (s.length () > 0) if (s.length () > 0)
{ {
@ -160,7 +160,7 @@ string
MingwModuleHandler::GenerateGccIncludeParameters ( const Module& module ) const MingwModuleHandler::GenerateGccIncludeParameters ( const Module& module ) const
{ {
string parameters = GenerateGccIncludeParametersFromVector ( ".", string parameters = GenerateGccIncludeParametersFromVector ( ".",
module.project->includes ); module.project.includes );
string s = GenerateGccIncludeParametersFromVector ( module.path, string s = GenerateGccIncludeParametersFromVector ( module.path,
module.includes ); module.includes );
if (s.length () > 0) if (s.length () > 0)

View file

@ -6,23 +6,23 @@
using std::string; using std::string;
using std::vector; using std::vector;
Define::Define ( Project* project, Define::Define ( const Project& project,
const XMLElement& defineNode ) const XMLElement& defineNode )
: project(project), : project(project),
module(NULL), module(NULL),
node(defineNode) node(defineNode)
{ {
Initialize (defineNode); Initialize();
} }
Define::Define ( Project* project, Define::Define ( const Project& project,
Module* module, const Module* module,
const XMLElement& defineNode ) const XMLElement& defineNode )
: project(project), : project(project),
module(module), module(module),
node(defineNode) node(defineNode)
{ {
Initialize (defineNode); Initialize();
} }
Define::~Define () Define::~Define ()
@ -30,15 +30,15 @@ Define::~Define ()
} }
void void
Define::Initialize ( const XMLElement& defineNode ) Define::Initialize()
{ {
const XMLAttribute* att = defineNode.GetAttribute ( "name", true ); const XMLAttribute* att = node.GetAttribute ( "name", true );
assert(att); assert(att);
name = att->value; name = att->value;
value = defineNode.value; value = node.value;
} }
void void
Define::ProcessXML ( const XMLElement& e ) Define::ProcessXML()
{ {
} }

View file

@ -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_list args;
va_start ( args, va_start ( args,
message ); message );
SetMessage ( message, SetLocationMessage ( location, message, args );
args );
va_end ( 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, XMLSyntaxErrorException::XMLSyntaxErrorException ( const string& location,
const char* message, const char* message,
@ -81,7 +88,7 @@ XMLSyntaxErrorException::XMLSyntaxErrorException ( const string& location,
va_list args; va_list args;
va_start ( args, va_start ( args,
message ); message );
Message = location + ": " + ssvprintf ( message, args ); SetLocationMessage ( location, message, args );
va_end ( args ); va_end ( args );
} }

View file

@ -40,12 +40,15 @@ public:
std::string Filename; std::string Filename;
}; };
class InvalidBuildFileException : public Exception class InvalidBuildFileException : public Exception
{ {
public: 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: protected:
InvalidBuildFileException (); InvalidBuildFileException ();
}; };

View file

@ -6,21 +6,23 @@
using std::string; using std::string;
using std::vector; using std::vector;
Include::Include ( Project* project, Include::Include ( const Project& project_,
const XMLElement& includeNode ) const XMLElement& includeNode )
: project(project), : project(project_),
module(NULL),
node(includeNode) node(includeNode)
{ {
Initialize ( includeNode ); Initialize();
} }
Include::Include ( Project* project, Include::Include ( const Project& project_,
Module* module, const Module* module_,
const XMLElement& includeNode ) const XMLElement& includeNode )
: project(project), : project(project_),
module(module_),
node(includeNode) node(includeNode)
{ {
Initialize ( includeNode ); Initialize();
} }
Include::~Include () Include::~Include ()
@ -28,12 +30,12 @@ Include::~Include ()
} }
void void
Include::Initialize ( const XMLElement& includeNode ) Include::Initialize()
{ {
directory = FixSeparator ( includeNode.value ); directory = FixSeparator ( node.value );
} }
void void
Include::ProcessXML ( const XMLElement& e ) Include::ProcessXML()
{ {
} }

View file

@ -21,13 +21,16 @@ FixSeparator ( const string& s )
return s2; return s2;
} }
Module::Module ( Project* project, Module::Module ( const Project& project,
const XMLElement& moduleNode, const XMLElement& moduleNode,
const string& modulePath ) const string& modulePath )
: project(project), : project(project),
node(moduleNode) node(moduleNode)
{ {
path = FixSeparator ( modulePath ); if ( node.name != "module" )
throw Exception ( "internal tool error: Module created with non-<module> node" );
path = FixSeparator ( modulePath );
const XMLAttribute* att = moduleNode.GetAttribute ( "name", true ); const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
assert(att); assert(att);
@ -54,17 +57,30 @@ Module::~Module ()
} }
void void
Module::ProcessXML ( const XMLElement& e, Module::ProcessXML()
const string& path )
{ {
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 ); string subpath ( path );
if ( e.name == "file" && e.value.size () ) if ( e.name == "file" && e.value.size () )
{ {
files.push_back ( new File ( FixSeparator ( path + CSEP + e.value ) ) ); files.push_back ( new File ( FixSeparator ( path + CSEP + e.value ) ) );
subs_invalid = true;
} }
else if ( e.name == "library" && e.value.size () ) 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" ) else if ( e.name == "directory" )
{ {
@ -74,18 +90,21 @@ Module::ProcessXML ( const XMLElement& e,
} }
else if ( e.name == "include" ) else if ( e.name == "include" )
{ {
Include* include = new Include ( project, this, e ); includes.push_back ( new Include ( project, this, e ) );
includes.push_back ( include ); subs_invalid = true;
include->ProcessXML ( e );
} }
else if ( e.name == "define" ) else if ( e.name == "define" )
{ {
Define* define = new Define ( project, this, e ); defines.push_back ( new Define ( project, this, e ) );
defines.push_back ( define ); subs_invalid = true;
define->ProcessXML ( e );
} }
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++ ) for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXML ( *e.subElements[i], subpath ); ProcessXMLSubElement ( *e.subElements[i], subpath );
} }
ModuleType ModuleType
@ -102,7 +121,7 @@ Module::GetModuleType ( const XMLAttribute& attribute )
} }
string string
Module::GetDefaultModuleExtension () Module::GetDefaultModuleExtension () const
{ {
switch (type) switch (type)
{ {
@ -130,7 +149,27 @@ File::File ( const string& _name )
} }
Library::Library ( const string& _name ) Library::Library ( const XMLElement& _node,
: name(_name) 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() );
} }

View file

@ -22,7 +22,7 @@ Project::~Project ()
{ {
for ( size_t i = 0; i < modules.size (); i++ ) for ( size_t i = 0; i < modules.size (); i++ )
delete modules[i]; delete modules[i];
delete head; delete node;
} }
void void
@ -32,37 +32,53 @@ Project::ReadXml ()
do do
{ {
head = XMLParse ( xmlfile, path ); node = XMLParse ( xmlfile, path );
if ( !head ) if ( !node )
throw InvalidBuildFileException ( "Document contains no 'project' tag." ); throw InvalidBuildFileException (
} while ( head->name != "project" ); node->location,
"Document contains no 'project' tag." );
} while ( node->name != "project" );
this->ProcessXML ( *head, "." ); this->ProcessXML ( "." );
} }
void void
Project::ProcessXML ( const XMLElement& e, const string& path ) Project::ProcessXML ( const string& path )
{ {
const XMLAttribute *att; const XMLAttribute *att;
string subpath(path); if ( node->name != "project" )
if ( e.name == "project" ) throw Exception ( "internal tool error: Project::ProcessXML() called with non-<project> node" );
{
att = e.GetAttribute ( "name", false );
if ( !att )
name = "Unnamed";
else
name = att->value;
att = e.GetAttribute ( "makefile", true ); att = node->GetAttribute ( "name", false );
assert(att); if ( !att )
makefile = att->value; name = "Unnamed";
} else
else if ( e.name == "module" ) 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 ( new Module ( *this, e, path ) );
modules.push_back ( module ); return; // defer processing until later
module->ProcessXML ( e, path );
return;
} }
else if ( e.name == "directory" ) else if ( e.name == "directory" )
{ {
@ -72,22 +88,37 @@ Project::ProcessXML ( const XMLElement& e, const string& path )
} }
else if ( e.name == "include" ) else if ( e.name == "include" )
{ {
Include* include = new Include ( this, e ); includes.push_back ( new Include ( *this, e ) );
includes.push_back ( include ); subs_invalid = true;
include->ProcessXML ( e );
} }
else if ( e.name == "define" ) else if ( e.name == "define" )
{ {
Define* define = new Define ( this, e ); defines.push_back ( new Define ( *this, e ) );
defines.push_back ( define ); subs_invalid = true;
define->ProcessXML ( e );
} }
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++ ) for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXML ( *e.subElements[i], subpath ); ProcessXMLSubElement ( *e.subElements[i], subpath );
} }
Module* 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++ ) for ( size_t i = 0; i < modules.size (); i++ )
{ {

View file

@ -40,13 +40,15 @@ public:
Project (); Project ();
Project ( const std::string& filename ); Project ( const std::string& filename );
~Project (); ~Project ();
void ProcessXML ( const XMLElement& e, void ProcessXML ( const std::string& path );
const std::string& path ); Module* LocateModule ( const std::string& name );
Module* LocateModule ( std::string name ); const Module* LocateModule ( const std::string& name ) const;
private: private:
void ReadXml (); void ReadXml ();
XMLFile xmlfile; XMLFile xmlfile;
XMLElement* head; XMLElement* node;
void ProcessXMLSubElement ( const XMLElement& e,
const std::string& path );
}; };
@ -61,7 +63,7 @@ enum ModuleType
class Module class Module
{ {
public: public:
Project* project; const Project& project;
const XMLElement& node; const XMLElement& node;
std::string name; std::string name;
std::string extension; std::string extension;
@ -72,56 +74,58 @@ public:
std::vector<Include*> includes; std::vector<Include*> includes;
std::vector<Define*> defines; std::vector<Define*> defines;
Module ( Project* project, Module ( const Project& project,
const XMLElement& moduleNode, const XMLElement& moduleNode,
const std::string& modulePath ); const std::string& modulePath );
~Module (); ~Module ();
ModuleType GetModuleType (const XMLAttribute& attribute ); ModuleType GetModuleType (const XMLAttribute& attribute );
std::string GetPath () const; std::string GetPath () const;
void ProcessXML ( const XMLElement& e, const std::string& path ); void ProcessXML();
private: private:
std::string GetDefaultModuleExtension (); std::string GetDefaultModuleExtension () const;
void ProcessXMLSubElement ( const XMLElement& e,
const std::string& path );
}; };
class Include class Include
{ {
public: public:
Project* project; const Project& project;
Module* module; const Module* module;
const XMLElement& node; const XMLElement& node;
std::string directory; std::string directory;
Include ( Project* project, Include ( const Project& project,
const XMLElement& includeNode ); const XMLElement& includeNode );
Include ( Project* project, Include ( const Project& project,
Module* module, const Module* module,
const XMLElement& includeNode ); const XMLElement& includeNode );
~Include (); ~Include ();
void ProcessXML ( const XMLElement& e ); void ProcessXML();
private: private:
void Initialize ( const XMLElement& includeNode ); void Initialize();
}; };
class Define class Define
{ {
public: public:
Project* project; const Project& project;
Module* module; const Module* module;
const XMLElement& node; const XMLElement& node;
std::string name; std::string name;
std::string value; std::string value;
Define ( Project* project, Define ( const Project& project,
const XMLElement& defineNode ); const XMLElement& defineNode );
Define ( Project* project, Define ( const Project& project,
Module* module, const Module* module,
const XMLElement& defineNode ); const XMLElement& defineNode );
~Define(); ~Define();
void ProcessXML ( const XMLElement& e ); void ProcessXML();
private: private:
void Initialize ( const XMLElement& defineNode ); void Initialize();
}; };
@ -137,9 +141,15 @@ public:
class Library class Library
{ {
public: public:
const XMLElement& node;
const Module& module;
std::string name; std::string name;
Library ( const std::string& _name ); Library ( const XMLElement& _node,
const Module& _module,
const std::string& _name );
void ProcessXML();
}; };
extern std::string extern std::string