2 // Mono.ILASM.ExternTable.cs
5 // Jackson Harper (Jackson@LatitudeGeo.com)
7 // (C) 2003 Jackson Harper, All rights reserved
11 using System.Collections;
12 using System.Reflection;
13 using System.Security;
15 namespace Mono.ILASM {
17 public interface IScope {
18 ExternTypeRef GetTypeRef (string full_name, bool is_valuetype);
19 PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
20 string FullName { get; }
23 public abstract class ExternRef : ICustomAttrTarget, IScope {
25 protected string name;
26 protected Hashtable class_table;
27 protected Hashtable typeref_table;
28 protected ArrayList customattr_list;
29 protected bool is_resolved;
31 public abstract void Resolve (CodeGen codegen);
32 public abstract PEAPI.IExternRef GetExternRef ();
34 public ExternRef (string name)
37 typeref_table = new Hashtable ();
38 class_table = new Hashtable ();
45 public virtual string FullName {
49 public void AddCustomAttribute (CustomAttr customattr)
51 if (customattr_list == null)
52 customattr_list = new ArrayList ();
54 customattr_list.Add (customattr);
57 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype)
59 string first= full_name;
61 int slash = full_name.IndexOf ('/');
63 first = full_name.Substring (0, slash);
64 rest = full_name.Substring (slash + 1);
67 ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
69 if (type_ref != null) {
70 if (is_valuetype && rest == "")
71 type_ref.MakeValueClass ();
73 type_ref = new ExternTypeRef (this, first, is_valuetype);
74 typeref_table [first] = type_ref;
77 return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype));
80 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
82 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
87 string name_space, name;
88 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
91 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
93 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
95 class_table [full_name] = klass;
101 public class ExternModule : ExternRef {
103 public PEAPI.ModuleRef ModuleRef;
105 public ExternModule (string name) : base (name)
109 public override string FullName {
111 //'name' field should not contain the [.module ]
112 //as its used for resolving
113 return String.Format ("[.module {0}]", name);
117 public override void Resolve (CodeGen codegen)
122 ModuleRef = codegen.PEFile.AddExternModule (name);
123 if (customattr_list != null)
124 foreach (CustomAttr customattr in customattr_list)
125 customattr.AddTo (codegen, ModuleRef);
131 public override PEAPI.IExternRef GetExternRef ()
137 public class ExternAssembly : ExternRef, IDeclSecurityTarget {
139 public PEAPI.AssemblyRef AssemblyRef;
141 private int major, minor, build, revision;
142 private byte [] public_key;
143 private byte [] public_key_token;
144 private string locale;
145 private byte [] hash;
146 private DeclSecurity decl_sec;
148 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
151 major = minor = build = revision = -1;
154 public override string FullName {
156 //'name' field should not contain the []
157 //as its used for resolving
158 return String.Format ("[{0}]", name);
162 public DeclSecurity DeclSecurity {
164 if (decl_sec == null)
165 decl_sec = new DeclSecurity ();
170 public override void Resolve (CodeGen code_gen)
175 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
177 AssemblyRef.AddVersionInfo (major, minor, build, revision);
178 if (public_key != null)
179 AssemblyRef.AddKey (public_key);
180 if (public_key_token != null)
181 AssemblyRef.AddKeyToken (public_key_token);
183 AssemblyRef.AddCulture (locale);
185 AssemblyRef.AddHash (hash);
187 if (customattr_list != null)
188 foreach (CustomAttr customattr in customattr_list)
189 customattr.AddTo (code_gen, AssemblyRef);
191 if (decl_sec != null)
192 decl_sec.AddTo (code_gen, AssemblyRef);
194 class_table = new Hashtable ();
199 public override PEAPI.IExternRef GetExternRef ()
204 public void SetVersion (int major, int minor, int build, int revision)
209 this.revision = revision;
212 public void SetPublicKey (byte [] public_key)
214 this.public_key = public_key;
217 public void SetPublicKeyToken (byte [] public_key_token)
219 this.public_key_token = public_key_token;
222 public void SetLocale (string locale)
224 this.locale = locale;
227 public void SetHash (byte [] hash)
235 public class ExternTable {
237 Hashtable assembly_table;
238 Hashtable module_table;
241 public void AddCorlib ()
244 string mscorlib_name = "mscorlib";
245 AssemblyName mscorlib = new AssemblyName ();
246 mscorlib.Name = mscorlib_name;
247 AddAssembly (mscorlib_name, mscorlib);
249 // Also need to alias corlib, normally corlib and
250 // mscorlib are used interchangably
251 assembly_table["corlib"] = assembly_table["mscorlib"];
254 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
256 ExternAssembly ea = null;
258 if (assembly_table == null) {
259 assembly_table = new Hashtable ();
261 ea = assembly_table [name] as ExternAssembly;
266 ea = new ExternAssembly (name, asmb_name);
268 assembly_table [name] = ea;
273 public ExternModule AddModule (string name)
275 ExternModule em = null;
277 if (module_table == null) {
278 module_table = new Hashtable ();
280 em = module_table [name] as ExternModule;
285 em = new ExternModule (name);
287 module_table [name] = em;
292 public void Resolve (CodeGen code_gen)
297 if (assembly_table != null)
298 foreach (ExternAssembly ext in assembly_table.Values)
299 ext.Resolve (code_gen);
300 if (module_table == null)
302 foreach (ExternModule ext in module_table.Values)
303 ext.Resolve (code_gen);
308 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
310 ExternAssembly ext_asmb = null;
311 if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
312 /* AddCorlib if mscorlib is being referenced but
313 we haven't encountered a ".assembly 'name'" as yet. */
314 Console.Error.WriteLine ("Warning -- Reference to undeclared extern assembly '{0}', adding.", asmb_name);
317 if (assembly_table != null)
318 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
320 if (ext_asmb == null) {
321 System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
322 asmname.Name = asmb_name;
324 Console.Error.WriteLine ("Warning -- Reference to undeclared extern assembly '{0}', adding.", asmb_name);
325 ext_asmb = AddAssembly (asmb_name, asmname);
328 return ext_asmb.GetTypeRef (full_name, is_valuetype);
331 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
333 ExternModule mod = null;
334 if (module_table != null)
335 mod = module_table [mod_name] as ExternModule;
338 Report.Error ("Module " + mod_name + " not defined.");
340 return mod.GetTypeRef (full_name, is_valuetype);
343 public static void GetNameAndNamespace (string full_name,
344 out string name_space, out string name) {
346 int last_dot = full_name.LastIndexOf ('.');
349 name_space = String.Empty;
354 name_space = full_name.Substring (0, last_dot);
355 name = full_name.Substring (last_dot + 1);