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;
14 using System.Globalization;
16 namespace Mono.ILASM {
18 public interface IScope {
19 ExternTypeRef GetTypeRef (string full_name, bool is_valuetype);
20 PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
21 string FullName { get; }
24 public abstract class ExternRef : ICustomAttrTarget, IScope {
26 protected string name;
27 protected Hashtable class_table;
28 protected Hashtable typeref_table;
29 protected ArrayList customattr_list;
30 protected bool is_resolved;
32 public abstract void Resolve (CodeGen codegen);
33 public abstract PEAPI.IExternRef GetExternRef ();
35 public ExternRef (string name)
38 typeref_table = new Hashtable ();
39 class_table = new Hashtable ();
46 public virtual string FullName {
50 public void AddCustomAttribute (CustomAttr customattr)
52 if (customattr_list == null)
53 customattr_list = new ArrayList ();
55 customattr_list.Add (customattr);
58 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype)
60 string first= full_name;
62 int slash = full_name.IndexOf ('/');
64 first = full_name.Substring (0, slash);
65 rest = full_name.Substring (slash + 1);
68 ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
70 if (type_ref != null) {
71 if (is_valuetype && rest == "")
72 type_ref.MakeValueClass ();
74 type_ref = new ExternTypeRef (this, first, is_valuetype);
75 typeref_table [first] = type_ref;
78 return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype));
81 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
83 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
88 string name_space, name;
89 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
92 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
94 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
96 class_table [full_name] = klass;
102 public class ExternModule : ExternRef {
104 public PEAPI.ModuleRef ModuleRef;
106 public ExternModule (string name) : base (name)
110 public override string FullName {
112 //'name' field should not contain the [.module ]
113 //as its used for resolving
114 return String.Format ("[.module {0}]", name);
118 public override void Resolve (CodeGen codegen)
123 ModuleRef = codegen.PEFile.AddExternModule (name);
124 if (customattr_list != null)
125 foreach (CustomAttr customattr in customattr_list)
126 customattr.AddTo (codegen, ModuleRef);
132 public override PEAPI.IExternRef GetExternRef ()
138 public class ExternAssembly : ExternRef, IDeclSecurityTarget {
140 public PEAPI.AssemblyRef AssemblyRef;
142 private int major, minor, build, revision;
143 private byte [] public_key;
144 private byte [] public_key_token;
145 private string locale;
146 private byte [] hash;
147 private DeclSecurity decl_sec;
148 private AssemblyName asmb_name;
150 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
153 this.asmb_name = asmb_name;
154 major = minor = build = revision = -1;
157 public override string FullName {
159 //'name' field should not contain the []
160 //as its used for resolving
161 return String.Format ("[{0}]", name);
165 public AssemblyName AssemblyName {
166 get { return asmb_name; }
169 public DeclSecurity DeclSecurity {
171 if (decl_sec == null)
172 decl_sec = new DeclSecurity ();
177 public override void Resolve (CodeGen code_gen)
182 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
184 AssemblyRef.AddVersionInfo (major, minor, build, revision);
185 if (public_key != null)
186 AssemblyRef.AddKey (public_key);
187 if (public_key_token != null)
188 AssemblyRef.AddKeyToken (public_key_token);
190 AssemblyRef.AddCulture (locale);
192 AssemblyRef.AddHash (hash);
194 if (customattr_list != null)
195 foreach (CustomAttr customattr in customattr_list)
196 customattr.AddTo (code_gen, AssemblyRef);
198 if (decl_sec != null)
199 decl_sec.AddTo (code_gen, AssemblyRef);
201 class_table = new Hashtable ();
206 public override PEAPI.IExternRef GetExternRef ()
211 public void SetVersion (int major, int minor, int build, int revision)
216 this.revision = revision;
217 asmb_name.Version = new Version (major, minor, build, revision);
220 public void SetPublicKey (byte [] public_key)
222 this.public_key = public_key;
223 asmb_name.SetPublicKey (public_key);
226 public void SetPublicKeyToken (byte [] public_key_token)
228 this.public_key_token = public_key_token;
229 asmb_name.SetPublicKey (public_key);
232 public void SetLocale (string locale)
234 this.locale = locale;
235 //FIXME: is this correct?
236 asmb_name.CultureInfo = new CultureInfo (locale);
239 public void SetHash (byte [] hash)
247 public class ExternTable {
249 Hashtable assembly_table;
250 Hashtable module_table;
253 public void AddCorlib ()
256 string mscorlib_name = "mscorlib";
257 AssemblyName mscorlib = new AssemblyName ();
258 mscorlib.Name = mscorlib_name;
259 AddAssembly (mscorlib_name, mscorlib);
261 // Also need to alias corlib, normally corlib and
262 // mscorlib are used interchangably
263 assembly_table["corlib"] = assembly_table["mscorlib"];
266 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
268 ExternAssembly ea = null;
270 if (assembly_table == null) {
271 assembly_table = new Hashtable ();
273 ea = assembly_table [name] as ExternAssembly;
278 ea = new ExternAssembly (name, asmb_name);
280 assembly_table [name] = ea;
285 public ExternModule AddModule (string name)
287 ExternModule em = null;
289 if (module_table == null) {
290 module_table = new Hashtable ();
292 em = module_table [name] as ExternModule;
297 em = new ExternModule (name);
299 module_table [name] = em;
304 public void Resolve (CodeGen code_gen)
309 if (assembly_table != null)
310 foreach (ExternAssembly ext in assembly_table.Values)
311 ext.Resolve (code_gen);
312 if (module_table == null)
314 foreach (ExternModule ext in module_table.Values)
315 ext.Resolve (code_gen);
320 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
322 ExternAssembly ext_asmb = null;
323 if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
324 /* AddCorlib if mscorlib is being referenced but
325 we haven't encountered a ".assembly 'name'" as yet. */
326 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
329 if (assembly_table != null)
330 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
332 if (ext_asmb == null) {
333 System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
334 asmname.Name = asmb_name;
336 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
337 ext_asmb = AddAssembly (asmb_name, asmname);
340 return ext_asmb.GetTypeRef (full_name, is_valuetype);
343 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
345 ExternModule mod = null;
346 if (module_table != null)
347 mod = module_table [mod_name] as ExternModule;
350 Report.Error ("Module " + mod_name + " not defined.");
352 return mod.GetTypeRef (full_name, is_valuetype);
355 public static void GetNameAndNamespace (string full_name,
356 out string name_space, out string name) {
358 int last_dot = full_name.LastIndexOf ('.');
361 name_space = String.Empty;
366 name_space = full_name.Substring (0, last_dot);
367 name = full_name.Substring (last_dot + 1);