Replace() bugfix #2 - forgot to insert replacement text ( yes yes I suck you can...
[reactos.git] / reactos / tools / rbuild / module.cpp
index 9820906..b114b7a 100644 (file)
@@ -1,3 +1,20 @@
+/*
+ * 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>
 
@@ -6,6 +23,26 @@
 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 )
 {
@@ -19,6 +56,19 @@ 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,
@@ -73,20 +123,41 @@ GetDirectory ( 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;
@@ -100,6 +171,8 @@ IfableData::~IfableData()
                delete libraries[i];
        for ( i = 0; i < properties.size(); i++ )
                delete properties[i];
+       for ( i = 0; i < compilerFlags.size(); i++ )
+               delete compilerFlags[i];
        for ( i = 0; i < ifs.size(); i++ )
                delete ifs[i];
 }
@@ -117,6 +190,8 @@ void IfableData::ProcessXML ()
                libraries[i]->ProcessXML ();
        for ( i = 0; i < properties.size(); i++ )
                properties[i]->ProcessXML ();
+       for ( i = 0; i < compilerFlags.size(); i++ )
+               compilerFlags[i]->ProcessXML ();
        for ( i = 0; i < ifs.size (); i++ )
                ifs[i]->ProcessXML ();
 }
@@ -137,11 +212,21 @@ Module::Module ( const Project& project,
                                                  __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;
 
@@ -230,6 +315,12 @@ Module::Module ( const Project& project,
                enableWarnings = att->value == "true";
        else
                enableWarnings = false;
+
+       att = moduleNode.GetAttribute ( "aliasof", false );
+       if ( type == Alias && att != NULL )
+               aliasedModuleName = att->value;
+       else
+               aliasedModuleName = "";
 }
 
 Module::~Module ()
@@ -252,6 +343,22 @@ 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 );
@@ -307,7 +414,8 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                }
                File* pFile = new File ( FixSeparator ( path + CSEP + e.value ),
                                         first,
-                                        switches );
+                                        switches,
+                                        false );
                if ( pIf )
                        pIf->data.files.push_back ( pFile );
                else
@@ -331,7 +439,7 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        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
@@ -388,9 +496,23 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                        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" )
        {
-               compilerFlags.push_back ( new CompilerFlag ( project, this, e ) );
+               CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
+               if ( pIf )
+                       pIf->data.compilerFlags.push_back ( pCompilerFlag );
+               else
+                       non_if_data.compilerFlags.push_back ( pCompilerFlag );
                subs_invalid = true;
        }
        else if ( e.name == "linkerflag" )
@@ -425,7 +547,7 @@ Module::ProcessXMLSubElement ( const XMLElement& 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 )
@@ -476,6 +598,8 @@ Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
                return RpcServer;
        if ( attribute.value == "rpcclient" )
                return RpcClient;
+       if ( attribute.value == "alias" )
+               return Alias;
        throw InvalidAttributeValueException ( location,
                                               attribute.name,
                                               attribute.value );
@@ -515,6 +639,8 @@ Module::GetDefaultModuleExtension () const
                        return ".o";
                case RpcClient:
                        return ".o";
+               case Alias:
+                       return "";
        }
        throw InvalidOperationException ( __FILE__,
                                          __LINE__ );
@@ -551,6 +677,7 @@ Module::GetDefaultModuleEntrypoint () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -563,7 +690,7 @@ Module::GetDefaultModuleBaseaddress () const
        switch ( type )
        {
                case Kernel:
-                       return "0xc0000000";
+                       return "0x80000000";
                case Win32DLL:
                        return "0x10000000";
                case NativeDLL:
@@ -585,6 +712,7 @@ Module::GetDefaultModuleBaseaddress () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -621,6 +749,38 @@ Module::IsDLL () const
                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__,
@@ -709,10 +869,12 @@ Module::InvokeModule () const
 
 
 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)
 {
 }
 
@@ -721,6 +883,13 @@ File::ProcessXML()
 {
 }
 
+bool
+File::IsGeneratedFile () const
+{
+       string extension = GetExtension ( name );
+       return ( extension == ".spec" || extension == ".SPEC" );
+}
+
 
 Library::Library ( const XMLElement& _node,
                    const Module& _module,
@@ -728,14 +897,14 @@ Library::Library ( const XMLElement& _node,
        : 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'",
@@ -935,8 +1104,9 @@ ImportLibrary::ImportLibrary ( const XMLElement& _node,
 
 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;
 
@@ -984,8 +1154,8 @@ Property::ProcessXML()
 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_)
 {
 }