* Implement <autoregister>
[reactos.git] / reactos / tools / rbuild / module.cpp
index 0eb61ab..3bd1a5e 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>
 
 using std::string;
 using std::vector;
 
+string
+Right ( const string& s, size_t n )
+{
+       if ( n > s.size() )
+               return s;
+       return string ( &s[s.size()-n] );
+}
+
+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
+ChangeSeparator ( const string& s,
+                  const char fromSeparator,
+                  const char toSeparator )
+{
+       string s2(s);
+       char* p = strchr ( &s2[0], fromSeparator );
+       while ( p )
+       {
+               *p++ = toSeparator;
+               p = strchr ( p, fromSeparator );
+       }
+       return s2;
+}
+
 string
 FixSeparator ( const string& s )
+{
+       return ChangeSeparator ( s, cBadSep, cSep );
+}
+
+string
+FixSeparatorForSystemCommand ( const string& s )
 {
        string s2(s);
-       char* p = strchr ( &s2[0], CBAD_SEP );
+       char* p = strchr ( &s2[0], DEF_CBAD_SEP );
        while ( p )
        {
-               *p++ = CSEP;
-               p = strchr ( p, CBAD_SEP );
+               *p++ = DEF_CSEP;
+               p = strchr ( p, DEF_CBAD_SEP );
+       }
+       return s2;
+}
+
+string
+DosSeparator ( const string& s )
+{
+       string s2(s);
+       char* p = strchr ( &s2[0], '/' );
+       while ( p )
+       {
+               *p++ = '\\';
+               p = strchr ( p, '/' );
        }
        return s2;
 }
@@ -53,7 +132,7 @@ GetSubPath (
                        "<directory> tag has invalid characters in 'name' attribute" );
        if ( !path.size() )
                return att_value;
-       return FixSeparator(path + CSEP + att_value);
+       return FixSeparator(path + cSep + att_value);
 }
 
 string
@@ -71,7 +150,7 @@ GetExtension ( const string& filename )
 string
 GetDirectory ( const string& filename )
 {
-       size_t index = filename.find_last_of ( CSEP );
+       size_t index = filename.find_last_of ( cSep );
        if ( index == string::npos )
                return "";
        else
@@ -81,7 +160,7 @@ GetDirectory ( const string& filename )
 string
 GetFilename ( const string& filename )
 {
-       size_t index = filename.find_last_of ( CSEP );
+       size_t index = filename.find_last_of ( cSep );
        if ( index == string::npos )
                return filename;
        else
@@ -99,30 +178,45 @@ NormalizeFilename ( const string& filename )
        return FixSeparator ( relativeNormalizedPath );
 }
 
+bool
+GetBooleanValue ( const string& value )
+{
+       if ( value == "1" )
+               return true;
+       else
+               return false;
+}
+
+string
+ToLower ( string filename )
+{
+       for ( size_t i = 1; i < filename.length (); i++ )
+               filename[i] = tolower ( filename[i] );
+       return filename;
+}
+
 IfableData::~IfableData()
 {
        size_t i;
-       for ( i = 0; i < files.size(); i++ )
-               delete files[i];
-       for ( i = 0; i < includes.size(); i++ )
+       for ( i = 0; i < includes.size (); i++ )
                delete includes[i];
-       for ( i = 0; i < defines.size(); i++ )
+       for ( i = 0; i < defines.size (); i++ )
                delete defines[i];
-       for ( i = 0; i < libraries.size(); i++ )
+       for ( i = 0; i < libraries.size (); i++ )
                delete libraries[i];
-       for ( i = 0; i < properties.size(); i++ )
+       for ( i = 0; i < properties.size (); i++ )
                delete properties[i];
-       for ( i = 0; i < compilerFlags.size(); i++ )
+       for ( i = 0; i < compilerFlags.size (); i++ )
                delete compilerFlags[i];
-       for ( i = 0; i < ifs.size(); i++ )
+       for ( i = 0; i < ifs.size (); i++ )
                delete ifs[i];
+       for ( i = 0; i < compilationUnits.size (); i++ )
+               delete compilationUnits[i];
 }
 
 void IfableData::ProcessXML ()
 {
        size_t i;
-       for ( i = 0; i < files.size (); i++ )
-               files[i]->ProcessXML ();
        for ( i = 0; i < includes.size (); i++ )
                includes[i]->ProcessXML ();
        for ( i = 0; i < defines.size (); i++ )
@@ -135,6 +229,8 @@ void IfableData::ProcessXML ()
                compilerFlags[i]->ProcessXML ();
        for ( i = 0; i < ifs.size (); i++ )
                ifs[i]->ProcessXML ();
+       for ( i = 0; i < compilationUnits.size (); i++ )
+               compilationUnits[i]->ProcessXML ();
 }
 
 Module::Module ( const Project& project,
@@ -144,6 +240,8 @@ Module::Module ( const Project& project,
          node (moduleNode),
          importLibrary (NULL),
          bootstrap (NULL),
+         autoRegister(NULL),
+         linkerScript (NULL),
          pch (NULL),
          cplusplus (false),
          host (HostDefault)
@@ -153,11 +251,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;
 
@@ -171,6 +279,25 @@ Module::Module ( const Project& project,
        else
                extension = GetDefaultModuleExtension ();
 
+       att = moduleNode.GetAttribute ( "unicode", false );
+       if ( att != NULL )
+       {
+               const char* p = att->value.c_str();
+               if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
+                       isUnicode = true;
+               else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
+                       isUnicode = false;
+               else
+               {
+                       throw InvalidAttributeValueException (
+                               moduleNode.location,
+                               "unicode",
+                               att->value );
+               }
+       }
+       else
+               isUnicode = false;
+
        att = moduleNode.GetAttribute ( "entrypoint", false );
        if ( att != NULL )
                entrypoint = att->value;
@@ -241,11 +368,26 @@ Module::Module ( const Project& project,
        else
                useWRC = true;
 
-       att = moduleNode.GetAttribute ( "warnings", false );
+       att = moduleNode.GetAttribute ( "allowwarnings", false );
+       if ( att == NULL )
+       {
+               att = moduleNode.GetAttribute ( "warnings", false );
+               if ( att != NULL )
+               {
+                       printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
+                               moduleNode.location.c_str() );
+               }
+       }
        if ( att != NULL )
-               enableWarnings = att->value == "true";
+               allowWarnings = att->value == "true";
+       else
+               allowWarnings = false;
+
+       att = moduleNode.GetAttribute ( "aliasof", false );
+       if ( type == Alias && att != NULL )
+               aliasedModuleName = att->value;
        else
-               enableWarnings = false;
+               aliasedModuleName = "";
 }
 
 Module::~Module ()
@@ -261,6 +403,8 @@ Module::~Module ()
                delete linkerFlags[i];
        for ( i = 0; i < stubbedComponents.size(); i++ )
                delete stubbedComponents[i];
+       if ( linkerScript )
+               delete linkerScript;
        if ( pch )
                delete pch;
 }
@@ -268,9 +412,28 @@ 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 );
+       {
+               ParseContext parseContext;
+               ProcessXMLSubElement ( *node.subElements[i], path, parseContext );
+       }
        for ( i = 0; i < invocations.size(); i++ )
                invocations[i]->ProcessXML ();
        for ( i = 0; i < dependencies.size(); i++ )
@@ -282,15 +445,21 @@ Module::ProcessXML()
        for ( i = 0; i < stubbedComponents.size(); i++ )
                stubbedComponents[i]->ProcessXML();
        non_if_data.ProcessXML();
+       if ( linkerScript )
+               linkerScript->ProcessXML();
        if ( pch )
                pch->ProcessXML();
+       if ( autoRegister )
+               autoRegister->ProcessXML();
 }
 
 void
 Module::ProcessXMLSubElement ( const XMLElement& e,
                                const string& path,
-                               If* pIf /*= NULL*/ )
+                               ParseContext& parseContext )
 {
+       If* pOldIf = parseContext.ifData;
+       CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
        bool subs_invalid = false;
        string subpath ( path );
        if ( e.name == "file" && e.value.size () > 0 )
@@ -321,12 +490,22 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                        else if ( !stricmp ( ext.c_str(), ".cxx" ) )
                                cplusplus = true;
                }
-               File* pFile = new File ( FixSeparator ( path + CSEP + e.value ),
+               File* pFile = new File ( FixSeparator ( path + cSep + e.value ),
                                         first,
                                         switches,
                                         false );
-               if ( pIf )
-                       pIf->data.files.push_back ( pFile );
+               if ( parseContext.compilationUnit )
+                       parseContext.compilationUnit->files.push_back ( pFile );
+               else
+               {
+                       CompilationUnit* pCompilationUnit = new CompilationUnit ( pFile );
+                       if ( parseContext.ifData )
+                               parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
+                       else
+                               non_if_data.compilationUnits.push_back ( pCompilationUnit );
+               }
+               if ( parseContext.ifData )
+                       parseContext.ifData->data.files.push_back ( pFile );
                else
                        non_if_data.files.push_back ( pFile );
                subs_invalid = true;
@@ -334,8 +513,8 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        else if ( e.name == "library" && e.value.size () )
        {
                Library* pLibrary = new Library ( e, *this, e.value );
-               if ( pIf )
-                       pIf->data.libraries.push_back ( pLibrary );
+               if ( parseContext.ifData )
+                       parseContext.ifData->data.libraries.push_back ( pLibrary );
                else
                        non_if_data.libraries.push_back ( pLibrary );
                subs_invalid = true;
@@ -348,9 +527,9 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        else if ( e.name == "include" )
        {
-               Include* include = new Include ( project, this, e );
-               if ( pIf )
-                       pIf->data.includes.push_back ( include );
+               Include* include = new Include ( project, this, &e );
+               if ( parseContext.ifData )
+                       parseContext.ifData->data.includes.push_back ( include );
                else
                        non_if_data.includes.push_back ( include );
                subs_invalid = true;
@@ -358,15 +537,15 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        else if ( e.name == "define" )
        {
                Define* pDefine = new Define ( project, this, e );
-               if ( pIf )
-                       pIf->data.defines.push_back ( pDefine );
+               if ( parseContext.ifData )
+                       parseContext.ifData->data.defines.push_back ( pDefine );
                else
                        non_if_data.defines.push_back ( pDefine );
                subs_invalid = true;
        }
        else if ( e.name == "invoke" )
        {
-               if ( pIf )
+               if ( parseContext.ifData )
                        throw InvalidBuildFileException (
                                e.location,
                                "<invoke> is not a valid sub-element of <if>" );
@@ -375,7 +554,7 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        else if ( e.name == "dependency" )
        {
-               if ( pIf )
+               if ( parseContext.ifData )
                        throw InvalidBuildFileException (
                                e.location,
                                "<dependency> is not a valid sub-element of <if>" );
@@ -384,7 +563,7 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        else if ( e.name == "importlibrary" )
        {
-               if ( pIf )
+               if ( parseContext.ifData )
                        throw InvalidBuildFileException (
                                e.location,
                                "<importlibrary> is not a valid sub-element of <if>" );
@@ -397,19 +576,27 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        else if ( e.name == "if" )
        {
-               If* pOldIf = pIf;
-               pIf = new If ( e, project, this );
+               parseContext.ifData = new If ( e, project, this );
+               if ( pOldIf )
+                       pOldIf->data.ifs.push_back ( parseContext.ifData );
+               else
+                       non_if_data.ifs.push_back ( parseContext.ifData );
+               subs_invalid = false;
+       }
+       else if ( e.name == "ifnot" )
+       {
+               parseContext.ifData = new If ( e, project, this, true );
                if ( pOldIf )
-                       pOldIf->data.ifs.push_back ( pIf );
+                       pOldIf->data.ifs.push_back ( parseContext.ifData );
                else
-                       non_if_data.ifs.push_back ( pIf );
+                       non_if_data.ifs.push_back ( parseContext.ifData );
                subs_invalid = false;
        }
        else if ( e.name == "compilerflag" )
        {
                CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
-               if ( pIf )
-                       pIf->data.compilerFlags.push_back ( pCompilerFlag );
+               if ( parseContext.ifData )
+                       parseContext.ifData->data.compilerFlags.push_back ( pCompilerFlag );
                else
                        non_if_data.compilerFlags.push_back ( pCompilerFlag );
                subs_invalid = true;
@@ -419,6 +606,15 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
                subs_invalid = true;
        }
+       else if ( e.name == "linkerscript" )
+       {
+               if ( linkerScript )
+                       throw InvalidBuildFileException (
+                               e.location,
+                               "Only one <linkerscript> is valid per module" );
+               linkerScript = new LinkerScript ( project, this, e );
+               subs_invalid = true;
+       }
        else if ( e.name == "component" )
        {
                stubbedComponents.push_back ( new StubbedComponent ( this, e ) );
@@ -437,7 +633,7 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
        }
        else if ( e.name == "pch" )
        {
-               if ( pIf )
+               if ( parseContext.ifData )
                        throw InvalidBuildFileException (
                                e.location,
                                "<pch> is not a valid sub-element of <if>" );
@@ -446,7 +642,31 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                                e.location,
                                "Only one <pch> is valid per module" );
                pch = new PchFile (
-                       e, *this, File ( FixSeparator ( path + CSEP + e.value ), false, "", true ) );
+                       e, *this, File ( FixSeparator ( path + cSep + e.value ), false, "", true ) );
+               subs_invalid = true;
+       }
+       else if ( e.name == "compilationunit" )
+       {
+               if ( project.configuration.CompilationUnitsEnabled )
+               {
+                       CompilationUnit* pCompilationUnit = new CompilationUnit ( &project, this, &e );
+                       if ( parseContext.ifData )
+                               parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
+                       else
+                               non_if_data.compilationUnits.push_back ( pCompilationUnit );
+                       parseContext.compilationUnit = pCompilationUnit;
+               }
+               subs_invalid = false;
+       }
+       else if ( e.name == "autoregister" )
+       {
+               if ( autoRegister != NULL)
+               {
+                       throw InvalidBuildFileException ( e.location,
+                                                         "there can be only one <%s> element for a module",
+                                                         e.name.c_str() );
+               }
+               autoRegister = new AutoRegister ( project, this, e );
                subs_invalid = true;
        }
        if ( subs_invalid && e.subElements.size() > 0 )
@@ -455,7 +675,9 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
                        "<%s> cannot have sub-elements",
                        e.name.c_str() );
        for ( size_t i = 0; i < e.subElements.size (); i++ )
-               ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
+               ProcessXMLSubElement ( *e.subElements[i], subpath, parseContext );
+       parseContext.ifData = pOldIf;
+       parseContext.compilationUnit = pOldCompilationUnit;
 }
 
 ModuleType
@@ -497,6 +719,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 );
@@ -508,7 +732,7 @@ Module::GetDefaultModuleExtension () const
        switch (type)
        {
                case BuildTool:
-                       return EXEPOSTFIX;
+                       return ExePostfix;
                case StaticLibrary:
                        return ".a";
                case ObjectLibrary:
@@ -536,6 +760,8 @@ Module::GetDefaultModuleExtension () const
                        return ".o";
                case RpcClient:
                        return ".o";
+               case Alias:
+                       return "";
        }
        throw InvalidOperationException ( __FILE__,
                                          __LINE__ );
@@ -558,9 +784,15 @@ Module::GetDefaultModuleEntrypoint () const
                        return "_DllMain@12";
                case Win32CUI:
                case Test:
-                       return "_mainCRTStartup";
+                       if ( isUnicode )
+                               return "_wmainCRTStartup";
+                       else
+                               return "_mainCRTStartup";
                case Win32GUI:
-                       return "_WinMainCRTStartup";
+                       if ( isUnicode )
+                               return "_wWinMainCRTStartup";
+                       else
+                               return "_WinMainCRTStartup";
                case KernelModeDriver:
                        return "_DriverEntry@8";
                case BuildTool:
@@ -572,6 +804,7 @@ Module::GetDefaultModuleEntrypoint () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -584,7 +817,7 @@ Module::GetDefaultModuleBaseaddress () const
        switch ( type )
        {
                case Kernel:
-                       return "0xc0000000";
+                       return "0x80000000";
                case Win32DLL:
                        return "0x10000000";
                case NativeDLL:
@@ -606,6 +839,7 @@ Module::GetDefaultModuleBaseaddress () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -642,6 +876,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__,
@@ -673,7 +939,7 @@ string
 Module::GetPath () const
 {
        if ( path.length() > 0 )
-               return path + CSEP + GetTargetName ();
+               return path + cSep + GetTargetName ();
        else
                return GetTargetName ();
 }
@@ -681,7 +947,7 @@ Module::GetPath () const
 string
 Module::GetPathWithPrefix ( const string& prefix ) const
 {
-       return path + CSEP + prefix + GetTargetName ();
+       return path + cSep + prefix + GetTargetName ();
 }
 
 string
@@ -698,11 +964,10 @@ Module::HasFileWithExtension (
        const std::string& extension ) const
 {
        size_t i;
-       for ( i = 0; i < data.files.size (); i++ )
+       for ( i = 0; i < data.compilationUnits.size (); i++ )
        {
-               File& file = *data.files[i];
-               string file_ext = GetExtension ( file.name );
-               if ( !stricmp ( file_ext.c_str (), extension.c_str () ) )
+               CompilationUnit* compilationUnit = data.compilationUnits[i];
+               if ( compilationUnit->HasFileWithExtension ( extension ) )
                        return true;
        }
        for ( i = 0; i < data.ifs.size (); i++ )
@@ -719,7 +984,7 @@ Module::InvokeModule () const
        for ( size_t i = 0; i < invocations.size (); i++ )
        {
                Invoke& invoke = *invocations[i];
-               string command = invoke.invokeModule->GetPath () + " " + invoke.GetParameters ();
+               string command = FixSeparatorForSystemCommand(invoke.invokeModule->GetPath ()) + " " + invoke.GetParameters ();
                printf ( "Executing '%s'\n\n", command.c_str () );
                int exitcode = system ( command.c_str () );
                if ( exitcode != 0 )
@@ -744,13 +1009,6 @@ File::ProcessXML()
 {
 }
 
-bool
-File::IsGeneratedFile () const
-{
-       string extension = GetExtension ( name );
-       return ( extension == ".spec" || extension == ".SPEC" );
-}
-
 
 Library::Library ( const XMLElement& _node,
                    const Module& _module,
@@ -758,14 +1016,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'",
@@ -839,7 +1097,7 @@ Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
        bool subs_invalid = false;
        if ( e.name == "inputfile" && e.value.size () > 0 )
        {
-               input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
+               input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + cSep + e.value ) ) );
                subs_invalid = true;
        }
        if ( subs_invalid && e.subElements.size() > 0 )
@@ -854,7 +1112,7 @@ Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
        bool subs_invalid = false;
        if ( e.name == "outputfile" && e.value.size () > 0 )
        {
-               output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
+               output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + cSep + e.value ) ) );
                subs_invalid = true;
        }
        if ( subs_invalid && e.subElements.size() > 0 )
@@ -965,8 +1223,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;
 
@@ -1023,3 +1282,85 @@ void
 PchFile::ProcessXML()
 {
 }
+
+
+AutoRegister::AutoRegister ( const Project& project_,
+                             const Module* module_,
+                             const XMLElement& node_ )
+       : project(project_),
+         module(module_),
+         node(node_)
+{
+       Initialize();
+}
+
+AutoRegister::~AutoRegister ()
+{
+}
+
+bool
+AutoRegister::IsSupportedModuleType ( ModuleType type )
+{
+       switch ( type )
+       {
+               case Win32DLL:
+                       return true;
+               case Kernel:
+               case KernelModeDLL:
+               case NativeDLL:
+               case NativeCUI:
+               case Win32CUI:
+               case Win32GUI:
+               case KernelModeDriver:
+               case BootSector:
+               case BootLoader:
+               case BuildTool:
+               case StaticLibrary:
+               case ObjectLibrary:
+               case Iso:
+               case LiveIso:
+               case Test:
+               case RpcServer:
+               case RpcClient:
+               case Alias:
+                       return false;
+       }
+       throw InvalidOperationException ( __FILE__,
+                                         __LINE__ );
+}
+
+AutoRegisterType
+AutoRegister::GetAutoRegisterType( string type )
+{
+       if ( type == "DllRegisterServer" )
+               return DllRegisterServer;
+       if ( type == "DllInstall" )
+               return DllInstall;
+       if ( type == "Both" )
+               return Both;
+       throw InvalidBuildFileException (
+               node.location,
+               "<autoregister> type attribute must be DllRegisterServer, DllInstall or Both." );
+}
+
+void
+AutoRegister::Initialize ()
+{
+       if ( !IsSupportedModuleType ( module->type ) )
+       {
+               throw InvalidBuildFileException (
+                       node.location,
+                       "<autoregister> is not applicable for this module type." );
+       }
+
+       const XMLAttribute* att = node.GetAttribute ( "infsection", true );
+       infSection = att->value;
+
+       att = node.GetAttribute ( "type", true );
+       type = GetAutoRegisterType ( att->value );
+}
+
+void
+AutoRegister::ProcessXML()
+{
+}