add a 'unicode' property to modules (not yet supported by mingw, need to add a librar...
[reactos.git] / reactos / tools / rbuild / module.cpp
index 93ebc62..004fe92 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,34 @@
 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
 FixSeparator ( const string& s )
 {
@@ -19,6 +64,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,
@@ -190,6 +248,23 @@ 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 );
+               }
+       }
+
        att = moduleNode.GetAttribute ( "entrypoint", false );
        if ( att != NULL )
                entrypoint = att->value;
@@ -260,11 +335,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 ()
@@ -287,6 +377,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 );
@@ -526,6 +632,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 );
@@ -565,6 +673,8 @@ Module::GetDefaultModuleExtension () const
                        return ".o";
                case RpcClient:
                        return ".o";
+               case Alias:
+                       return "";
        }
        throw InvalidOperationException ( __FILE__,
                                          __LINE__ );
@@ -587,9 +697,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:
@@ -601,6 +717,7 @@ Module::GetDefaultModuleEntrypoint () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -635,6 +752,7 @@ Module::GetDefaultModuleBaseaddress () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return "";
        }
        throw InvalidOperationException ( __FILE__,
@@ -671,6 +789,7 @@ Module::IsDLL () const
                case LiveIso:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return false;
        }
        throw InvalidOperationException ( __FILE__,
@@ -701,6 +820,7 @@ Module::GenerateInOutputTree () const
                case ObjectLibrary:
                case RpcServer:
                case RpcClient:
+               case Alias:
                        return false;
        }
        throw InvalidOperationException ( __FILE__,
@@ -817,14 +937,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'",