Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / ilasm / codegen / ExternTable.cs
index 9339658a5731385741d5b3617e4d73cd3074d59a..25a46efbf3180a5898d536eb0b2224a4bc0132f8 100644 (file)
@@ -9,14 +9,18 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Security;
+using System.Globalization;
+using PEAPI;
 
 namespace Mono.ILASM {
 
         public interface IScope {
-                ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table);
+                ExternTypeRef GetTypeRef (string full_name, bool is_valuetype);
                 PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
+                string FullName { get; }
         }
        
         public abstract class ExternRef : ICustomAttrTarget, IScope {
@@ -41,6 +45,10 @@ namespace Mono.ILASM {
                        get { return name; }
                }
 
+                public virtual string FullName {
+                        get { return name; }
+                }
+
                 public void AddCustomAttribute (CustomAttr customattr)
                 {
                         if (customattr_list == null)
@@ -49,7 +57,7 @@ namespace Mono.ILASM {
                         customattr_list.Add (customattr);
                 }
 
-                public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
+                public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype)
                 {
                         string first= full_name;
                         string rest = "";
@@ -65,11 +73,11 @@ namespace Mono.ILASM {
                                 if (is_valuetype && rest == "")
                                         type_ref.MakeValueClass ();
                         } else {
-                                type_ref = new ExternTypeRef (this, first, is_valuetype, table);
+                                type_ref = new ExternTypeRef (this, first, is_valuetype);
                                 typeref_table [first] = type_ref;
                         }
 
-                        return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype, table));
+                        return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype));
                 }
 
                 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
@@ -101,6 +109,14 @@ namespace Mono.ILASM {
                 {
                 }
 
+                public override string FullName {
+                        get { 
+                                //'name' field should not contain the [.module ]
+                                //as its used for resolving
+                                return String.Format ("[.module {0}]", name); 
+                        }
+                }
+
                 public override void Resolve (CodeGen codegen)
                 {
                         if (is_resolved)
@@ -131,19 +147,45 @@ namespace Mono.ILASM {
                 private string locale;
                 private byte [] hash;
                 private DeclSecurity decl_sec;
+                private AssemblyName asmb_name;
+                //flags
+                private PEAPI.AssemAttr attr;
 
-                public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
+                public ExternAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr) : base (name)
                 {
                         this.name = name;
+                        this.asmb_name = asmb_name;
+                        this.attr = attr;
                         major = minor = build = revision = -1;
                 }
 
+                public override string FullName {
+                        get { 
+                                //'name' field should not contain the []
+                                //as its used for resolving
+                                return String.Format ("[{0}]", name); 
+                        }
+                }
+
+                public AssemblyName AssemblyName {
+                        get { return asmb_name; }
+                }
+
+                public DeclSecurity DeclSecurity {
+                        get {
+                                if (decl_sec == null)
+                                        decl_sec = new DeclSecurity ();
+                                return decl_sec;
+                        }
+                }
+
                 public override void Resolve (CodeGen code_gen)
                 {
                         if (is_resolved)
                                 return;
 
                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
+                        AssemblyRef.AddAssemblyAttr (attr);
                         if (major != -1)
                                 AssemblyRef.AddVersionInfo (major, minor, build, revision);
                         if (public_key != null)
@@ -172,43 +214,32 @@ namespace Mono.ILASM {
                         return AssemblyRef;
                 }
                 
-                public void AddPermissionSet (PEAPI.SecurityAction sec_action, PermissionSet ps)
-                {
-                        if (decl_sec == null)
-                                decl_sec = new DeclSecurity ();
-
-                        decl_sec.AddPermissionSet (sec_action, ps);        
-                }
-                
-                public void AddPermission (PEAPI.SecurityAction sec_action, IPermission iper)
-                {
-                        if (decl_sec == null)
-                                decl_sec = new DeclSecurity ();
-
-                        decl_sec.AddPermission (sec_action, iper);
-                }
-
                 public void SetVersion (int major, int minor, int build, int revision)
                 {
                         this.major = major;
                         this.minor = minor;
                         this.build = build;
                         this.revision = revision;
+                        asmb_name.Version = new Version (major, minor, build, revision);
                 }
 
                 public void SetPublicKey (byte [] public_key)
                 {
                         this.public_key = public_key;
+                        asmb_name.SetPublicKey (public_key);
                 }
 
                 public void SetPublicKeyToken (byte [] public_key_token)
                 {
                         this.public_key_token = public_key_token;
+                        asmb_name.SetPublicKey (public_key);
                 }
 
                 public void SetLocale (string locale)
                 {
                         this.locale = locale;
+                        //FIXME: is this correct?
+                        asmb_name.CultureInfo = new CultureInfo (locale);
                 }
 
                 public void SetHash (byte [] hash)
@@ -218,11 +249,34 @@ namespace Mono.ILASM {
 
         }
 
+        public class ExternClass
+        {
+            string name;
+            TypeAttr ta;
+            string assemblyReference;
+
+            public ExternClass (string name, TypeAttr ta, string assemblyReference)
+            {
+                this.name = name;
+                this.ta = ta;
+                this.assemblyReference = assemblyReference;
+            }
+
+            public void Resolve (CodeGen code_gen, ExternTable table)
+            {
+                var ar = table.GetAssemblyRef (assemblyReference);
+                if (ar != null)
+                    code_gen.PEFile.AddExternClass (name, ta, ar.AssemblyRef);
+            }
+        }
+
         
         public class ExternTable {
 
                 Hashtable assembly_table;
                 Hashtable module_table;
+                List<ExternClass> class_table;
+
                 bool is_resolved;
                 
                 public void AddCorlib ()
@@ -231,14 +285,14 @@ namespace Mono.ILASM {
                         string mscorlib_name = "mscorlib";
                         AssemblyName mscorlib = new AssemblyName ();
                         mscorlib.Name = mscorlib_name;
-                        AddAssembly (mscorlib_name, mscorlib);
+                        AddAssembly (mscorlib_name, mscorlib, 0);
 
                         // Also need to alias corlib, normally corlib and
                         // mscorlib are used interchangably
                         assembly_table["corlib"] = assembly_table["mscorlib"];
                 }
 
-                public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
+                public ExternAssembly AddAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr)
                 {
                         ExternAssembly ea = null;
 
@@ -250,7 +304,7 @@ namespace Mono.ILASM {
                                         return ea;
                         }
 
-                        ea = new ExternAssembly (name, asmb_name);
+                        ea = new ExternAssembly (name, asmb_name, attr);
 
                         assembly_table [name] = ea;
 
@@ -276,6 +330,14 @@ namespace Mono.ILASM {
                         return em;
                 }
 
+                public void AddClass (string name, TypeAttr ta, string assemblyReference)
+                {
+                    if (class_table == null)
+                        class_table = new List<ExternClass> ();
+
+                    class_table.Add (new ExternClass (name, ta, assemblyReference));
+                }
+
                 public void Resolve (CodeGen code_gen)
                 {
                         if (is_resolved)
@@ -284,39 +346,63 @@ namespace Mono.ILASM {
                         if (assembly_table != null)
                                 foreach (ExternAssembly ext in assembly_table.Values)
                                         ext.Resolve (code_gen);
-                        if (module_table == null)
-                                return;
-                        foreach (ExternModule ext in module_table.Values)
-                                ext.Resolve (code_gen);
 
-                       is_resolved = true;     
+                        if (module_table != null)
+                            foreach (ExternModule ext in module_table.Values)
+                                    ext.Resolve (code_gen);
+
+                        if (class_table != null)
+                            foreach (var entry in class_table)
+                                entry.Resolve (code_gen, this);
+
+                        is_resolved = true;    
                 }
 
                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
                 {
                         ExternAssembly ext_asmb = null;
-                        if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib"))
+                        if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
                                 /* AddCorlib if mscorlib is being referenced but
                                    we haven't encountered a ".assembly 'name'" as yet. */
+                                Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
                                 AddCorlib ();
+                        }
                         if (assembly_table != null)
                                 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
 
-                        if (ext_asmb == null)
-                                throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
+                        if (ext_asmb == null) {
+                                System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
+                                asmname.Name = asmb_name;
 
-                        return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
+                                Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
+                                ext_asmb = AddAssembly (asmb_name, asmname, 0);
+                        }
+
+                        return ext_asmb.GetTypeRef (full_name, is_valuetype);
                 }
 
                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
                 {
-                        ExternModule mod;
-                        mod = module_table [mod_name] as ExternModule;
+                        ExternModule mod = null;
+                        if (module_table != null)
+                                mod = module_table [mod_name] as ExternModule;
 
                         if (mod == null)
-                                throw new Exception (String.Format ("Module {0} not defined.", mod_name));
+                                Report.Error ("Module " + mod_name + " not defined.");
+
+                        return mod.GetTypeRef (full_name, is_valuetype);
+                }
+
+                public ExternAssembly GetAssemblyRef (string assembly_name)
+                {
+                        ExternAssembly ass = null;
+                        if (assembly_table != null)
+                                ass = assembly_table [assembly_name] as ExternAssembly;
+
+                        if (ass == null)
+                                Report.Error ("Assembly " + assembly_name + " is not defined.");
 
-                        return mod.GetTypeRef (full_name, is_valuetype, this);
+                        return ass;
                 }
 
                 public static void GetNameAndNamespace (string full_name,