+/*
+ * Copyright (C) 2005 Casper S. Hornstrup
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include "pch.h"
#include <assert.h>
using std::string;
using std::vector;
+string
+Replace ( const string& s, const string& find, const string& with )
+{
+ string ret;
+ const char* p = s.c_str();
+ while ( p )
+ {
+ const char* p2 = strstr ( p, find.c_str() );
+ if ( !p2 )
+ break;
+ if ( p2 > p )
+ ret += string ( p, p2-p );
+ ret += with;
+ p = p2 + find.size();
+ }
+ if ( *p )
+ ret += p;
+ return ret;
+}
+
string
FixSeparator ( const string& s )
{
return s2;
}
+string
+DosSeparator ( const string& s )
+{
+ string s2(s);
+ char* p = strchr ( &s2[0], '/' );
+ while ( p )
+ {
+ *p++ = '\\';
+ p = strchr ( p, '/' );
+ }
+ return s2;
+}
+
string
ReplaceExtension (
const string& filename,
{
size_t index = filename.find_last_of ( CSEP );
if ( index == string::npos )
- return filename;
+ return "";
else
return filename.substr ( 0, index );
}
+string
+GetFilename ( const string& filename )
+{
+ size_t index = filename.find_last_of ( CSEP );
+ if ( index == string::npos )
+ return filename;
+ else
+ return filename.substr ( index + 1, filename.length () - index );
+}
+
string
NormalizeFilename ( const string& filename )
{
+ if ( filename == "" )
+ return "";
Path path;
string normalizedPath = path.Fixup ( filename, true );
string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );
return FixSeparator ( relativeNormalizedPath );
}
+bool
+GetBooleanValue ( const string& value )
+{
+ if ( value == "1" )
+ return true;
+ else
+ return false;
+}
+
IfableData::~IfableData()
{
size_t i;
__LINE__,
"Module created with non-<module> node" );
- xmlbuildFile = Path::RelativeFromWorkingDirectory ( moduleNode.xmlFile->filename() );
+ xmlbuildFile = Path::RelativeFromWorkingDirectory ( moduleNode.xmlFile->filename () );
path = FixSeparator ( modulePath );
- const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
+ enabled = true;
+
+ const XMLAttribute* att = moduleNode.GetAttribute ( "if", false );
+ if ( att != NULL )
+ enabled = GetBooleanValue ( project.ResolveProperties ( att->value ) );
+
+ att = moduleNode.GetAttribute ( "ifnot", false );
+ if ( att != NULL )
+ enabled = !GetBooleanValue ( project.ResolveProperties ( att->value ) );
+
+ att = moduleNode.GetAttribute ( "name", true );
assert(att);
name = att->value;
enableWarnings = att->value == "true";
else
enableWarnings = false;
+
+ att = moduleNode.GetAttribute ( "aliasof", false );
+ if ( type == Alias && att != NULL )
+ aliasedModuleName = att->value;
+ else
+ aliasedModuleName = "";
}
Module::~Module ()
void
Module::ProcessXML()
{
+ if ( type == Alias )
+ {
+ if ( aliasedModuleName == name )
+ throw InvalidBuildFileException (
+ node.location,
+ "module '%s' cannot link against itself",
+ name.c_str() );
+ const Module* m = project.LocateModule ( aliasedModuleName );
+ if ( !m )
+ throw InvalidBuildFileException (
+ node.location,
+ "module '%s' trying to alias non-existant module '%s'",
+ name.c_str(),
+ aliasedModuleName.c_str() );
+ }
+
size_t i;
for ( i = 0; i < node.subElements.size(); i++ )
ProcessXMLSubElement ( *node.subElements[i], path );
}
File* pFile = new File ( FixSeparator ( path + CSEP + e.value ),
first,
- switches );
+ switches,
+ false );
if ( pIf )
pIf->data.files.push_back ( pFile );
else
}
else if ( e.name == "include" )
{
- Include* include = new Include ( project, this, e );
+ Include* include = new Include ( project, this, &e );
if ( pIf )
pIf->data.includes.push_back ( include );
else
non_if_data.ifs.push_back ( pIf );
subs_invalid = false;
}
+ else if ( e.name == "ifnot" )
+ {
+ If* pOldIf = pIf;
+ pIf = new If ( e, project, this, true );
+ if ( pOldIf )
+ pOldIf->data.ifs.push_back ( pIf );
+ else
+ non_if_data.ifs.push_back ( pIf );
+ subs_invalid = false;
+ }
else if ( e.name == "compilerflag" )
{
CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
e.location,
"Only one <pch> is valid per module" );
pch = new PchFile (
- e, *this, FixSeparator ( path + CSEP + e.value ) );
+ e, *this, File ( FixSeparator ( path + CSEP + e.value ), false, "", true ) );
subs_invalid = true;
}
if ( subs_invalid && e.subElements.size() > 0 )
return RpcServer;
if ( attribute.value == "rpcclient" )
return RpcClient;
+ if ( attribute.value == "alias" )
+ return Alias;
throw InvalidAttributeValueException ( location,
attribute.name,
attribute.value );
return ".o";
case RpcClient:
return ".o";
+ case Alias:
+ return "";
}
throw InvalidOperationException ( __FILE__,
__LINE__ );
case LiveIso:
case RpcServer:
case RpcClient:
+ case Alias:
return "";
}
throw InvalidOperationException ( __FILE__,
switch ( type )
{
case Kernel:
- return "0xc0000000";
+ return "0x80000000";
case Win32DLL:
return "0x10000000";
case NativeDLL:
case LiveIso:
case RpcServer:
case RpcClient:
+ case Alias:
return "";
}
throw InvalidOperationException ( __FILE__,
case LiveIso:
case RpcServer:
case RpcClient:
+ case Alias:
+ return false;
+ }
+ throw InvalidOperationException ( __FILE__,
+ __LINE__ );
+}
+
+bool
+Module::GenerateInOutputTree () const
+{
+ switch ( type )
+ {
+ case Kernel:
+ case KernelModeDLL:
+ case NativeDLL:
+ case Win32DLL:
+ case KernelModeDriver:
+ case NativeCUI:
+ case Win32CUI:
+ case Test:
+ case Win32GUI:
+ case BuildTool:
+ case BootLoader:
+ case BootSector:
+ case Iso:
+ case LiveIso:
+ return true;
+ case StaticLibrary:
+ case ObjectLibrary:
+ case RpcServer:
+ case RpcClient:
+ case Alias:
return false;
}
throw InvalidOperationException ( __FILE__,
File::File ( const string& _name, bool _first,
- std::string _switches )
+ std::string _switches,
+ bool _isPreCompiledHeader )
: name(_name),
first(_first),
- switches(_switches)
+ switches(_switches),
+ isPreCompiledHeader(_isPreCompiledHeader)
{
}
{
}
+bool
+File::IsGeneratedFile () const
+{
+ string extension = GetExtension ( name );
+ return ( extension == ".spec" || extension == ".SPEC" );
+}
+
Library::Library ( const XMLElement& _node,
const Module& _module,
: node(_node),
module(_module),
name(_name),
- imported_module(_module.project.LocateModule(_name))
+ importedModule(_module.project.LocateModule(_name))
{
if ( module.name == name )
throw InvalidBuildFileException (
node.location,
"module '%s' cannot link against itself",
name.c_str() );
- if ( !imported_module )
+ if ( !importedModule )
throw InvalidBuildFileException (
node.location,
"module '%s' trying to import non-existant module '%s'",
If::If ( const XMLElement& node_,
const Project& project_,
- const Module* module_ )
- : node(node_), project(project_), module(module_)
+ const Module* module_,
+ const bool negated_ )
+ : node(node_), project(project_), module(module_), negated(negated_)
{
const XMLAttribute* att;
PchFile::PchFile (
const XMLElement& node_,
const Module& module_,
- const string& header_ )
- : node(node_), module(module_), header(header_)
+ const File file_ )
+ : node(node_), module(module_), file(file_)
{
}