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.Collections.Generic;
13 using System.Reflection;
14 using System.Security;
15 using System.Globalization;
18 namespace Mono.ILASM {
20 public interface IScope {
21 ExternTypeRef GetTypeRef (string full_name, bool is_valuetype);
22 PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
23 string FullName { get; }
26 public abstract class ExternRef : ICustomAttrTarget, IScope {
28 protected string name;
29 protected Hashtable class_table;
30 protected Hashtable typeref_table;
31 protected ArrayList customattr_list;
32 protected bool is_resolved;
34 public abstract void Resolve (CodeGen codegen);
35 public abstract PEAPI.IExternRef GetExternRef ();
37 public ExternRef (string name)
40 typeref_table = new Hashtable ();
41 class_table = new Hashtable ();
48 public virtual string FullName {
52 public void AddCustomAttribute (CustomAttr customattr)
54 if (customattr_list == null)
55 customattr_list = new ArrayList ();
57 customattr_list.Add (customattr);
60 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype)
62 string first= full_name;
64 int slash = full_name.IndexOf ('/');
66 first = full_name.Substring (0, slash);
67 rest = full_name.Substring (slash + 1);
70 ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
72 if (type_ref != null) {
73 if (is_valuetype && rest == "")
74 type_ref.MakeValueClass ();
76 type_ref = new ExternTypeRef (this, first, is_valuetype);
77 typeref_table [first] = type_ref;
80 return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype));
83 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
85 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
90 string name_space, name;
91 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
94 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
96 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
98 class_table [full_name] = klass;
104 public class ExternModule : ExternRef {
106 public PEAPI.ModuleRef ModuleRef;
108 public ExternModule (string name) : base (name)
112 public override string FullName {
114 //'name' field should not contain the [.module ]
115 //as its used for resolving
116 return String.Format ("[.module {0}]", name);
120 public override void Resolve (CodeGen codegen)
125 ModuleRef = codegen.PEFile.AddExternModule (name);
126 if (customattr_list != null)
127 foreach (CustomAttr customattr in customattr_list)
128 customattr.AddTo (codegen, ModuleRef);
134 public override PEAPI.IExternRef GetExternRef ()
140 public class ExternAssembly : ExternRef, IDeclSecurityTarget {
142 public PEAPI.AssemblyRef AssemblyRef;
144 private int major, minor, build, revision;
145 private byte [] public_key;
146 private byte [] public_key_token;
147 private string locale;
148 private byte [] hash;
149 private DeclSecurity decl_sec;
150 private AssemblyName asmb_name;
152 private PEAPI.AssemAttr attr;
154 public ExternAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr) : base (name)
157 this.asmb_name = asmb_name;
159 major = minor = build = revision = -1;
162 public override string FullName {
164 //'name' field should not contain the []
165 //as its used for resolving
166 return String.Format ("[{0}]", name);
170 public AssemblyName AssemblyName {
171 get { return asmb_name; }
174 public DeclSecurity DeclSecurity {
176 if (decl_sec == null)
177 decl_sec = new DeclSecurity ();
182 public override void Resolve (CodeGen code_gen)
187 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
188 AssemblyRef.AddAssemblyAttr (attr);
190 AssemblyRef.AddVersionInfo (major, minor, build, revision);
191 if (public_key != null)
192 AssemblyRef.AddKey (public_key);
193 if (public_key_token != null)
194 AssemblyRef.AddKeyToken (public_key_token);
196 AssemblyRef.AddCulture (locale);
198 AssemblyRef.AddHash (hash);
200 if (customattr_list != null)
201 foreach (CustomAttr customattr in customattr_list)
202 customattr.AddTo (code_gen, AssemblyRef);
204 if (decl_sec != null)
205 decl_sec.AddTo (code_gen, AssemblyRef);
207 class_table = new Hashtable ();
212 public override PEAPI.IExternRef GetExternRef ()
217 public void SetVersion (int major, int minor, int build, int revision)
222 this.revision = revision;
223 asmb_name.Version = new Version (major, minor, build, revision);
226 public void SetPublicKey (byte [] public_key)
228 this.public_key = public_key;
229 asmb_name.SetPublicKey (public_key);
232 public void SetPublicKeyToken (byte [] public_key_token)
234 this.public_key_token = public_key_token;
235 asmb_name.SetPublicKey (public_key);
238 public void SetLocale (string locale)
240 this.locale = locale;
241 //FIXME: is this correct?
242 asmb_name.CultureInfo = new CultureInfo (locale);
245 public void SetHash (byte [] hash)
252 public class ExternClass
256 string assemblyReference;
258 public ExternClass (string fullName, TypeAttr ta, string assemblyReference)
260 this.fullName = fullName;
262 this.assemblyReference = assemblyReference;
265 public void Resolve (CodeGen code_gen, ExternTable table)
267 var ar = table.GetAssemblyRef (assemblyReference);
270 string name = fullName;
272 int pos = name.LastIndexOf ('.');
274 ns = name.Substring (0, pos);
275 name = name.Substring (pos + 1);
278 code_gen.PEFile.AddExternClass (ns, name, ta, ar.AssemblyRef);
284 public class ExternTable {
286 Hashtable assembly_table;
287 Hashtable module_table;
288 List<ExternClass> class_table;
292 public void AddCorlib ()
295 string mscorlib_name = "mscorlib";
296 AssemblyName mscorlib = new AssemblyName ();
297 mscorlib.Name = mscorlib_name;
298 AddAssembly (mscorlib_name, mscorlib, 0);
300 // Also need to alias corlib, normally corlib and
301 // mscorlib are used interchangably
302 assembly_table["corlib"] = assembly_table["mscorlib"];
305 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr)
307 ExternAssembly ea = null;
309 if (assembly_table == null) {
310 assembly_table = new Hashtable ();
312 ea = assembly_table [name] as ExternAssembly;
317 ea = new ExternAssembly (name, asmb_name, attr);
319 assembly_table [name] = ea;
324 public ExternModule AddModule (string name)
326 ExternModule em = null;
328 if (module_table == null) {
329 module_table = new Hashtable ();
331 em = module_table [name] as ExternModule;
336 em = new ExternModule (name);
338 module_table [name] = em;
343 public void AddClass (string name, TypeAttr ta, string assemblyReference)
345 if (class_table == null)
346 class_table = new List<ExternClass> ();
348 class_table.Add (new ExternClass (name, ta, assemblyReference));
351 public void Resolve (CodeGen code_gen)
356 if (assembly_table != null)
357 foreach (ExternAssembly ext in assembly_table.Values)
358 ext.Resolve (code_gen);
360 if (module_table != null)
361 foreach (ExternModule ext in module_table.Values)
362 ext.Resolve (code_gen);
364 if (class_table != null)
365 foreach (var entry in class_table)
366 entry.Resolve (code_gen, this);
371 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
373 ExternAssembly ext_asmb = null;
374 if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
375 /* AddCorlib if mscorlib is being referenced but
376 we haven't encountered a ".assembly 'name'" as yet. */
377 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
380 if (assembly_table != null)
381 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
383 if (ext_asmb == null) {
384 System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
385 asmname.Name = asmb_name;
387 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
388 ext_asmb = AddAssembly (asmb_name, asmname, 0);
391 return ext_asmb.GetTypeRef (full_name, is_valuetype);
394 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
396 ExternModule mod = null;
397 if (module_table != null)
398 mod = module_table [mod_name] as ExternModule;
401 Report.Error ("Module " + mod_name + " not defined.");
403 return mod.GetTypeRef (full_name, is_valuetype);
406 public ExternAssembly GetAssemblyRef (string assembly_name)
408 ExternAssembly ass = null;
409 if (assembly_table != null)
410 ass = assembly_table [assembly_name] as ExternAssembly;
413 Report.Error ("Assembly " + assembly_name + " is not defined.");
418 public static void GetNameAndNamespace (string full_name,
419 out string name_space, out string name) {
421 int last_dot = full_name.LastIndexOf ('.');
424 name_space = String.Empty;
429 name_space = full_name.Substring (0, last_dot);
430 name = full_name.Substring (last_dot + 1);