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()
: 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" )

View file

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

View file

@ -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 vector<Define*
string
MingwModuleHandler::GenerateGccDefineParameters ( const Module& module ) const
{
string parameters = GenerateGccDefineParametersFromVector ( module.project->defines );
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)

View file

@ -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()
{
}

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_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 );
}

View file

@ -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 ();
};

View file

@ -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()
{
}

View file

@ -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-<module> 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() );
}

View file

@ -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-<project> 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++ )
{

View file

@ -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<Include*> includes;
std::vector<Define*> 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