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;
14 namespace Mono.ILASM {
16 public interface IScope {
17 ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table);
18 PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
21 public abstract class ExternRef : ICustomAttrTarget, IScope {
23 protected string name;
24 protected Hashtable class_table;
25 protected Hashtable typeref_table;
26 protected ArrayList customattr_list;
27 protected bool is_resolved;
29 public abstract void Resolve (CodeGen codegen);
30 public abstract PEAPI.IExternRef GetExternRef ();
32 public ExternRef (string name)
35 typeref_table = new Hashtable ();
36 class_table = new Hashtable ();
43 public void AddCustomAttribute (CustomAttr customattr)
45 if (customattr_list == null)
46 customattr_list = new ArrayList ();
48 customattr_list.Add (customattr);
51 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
53 string first= full_name;
55 int slash = full_name.IndexOf ('/');
57 first = full_name.Substring (0, slash);
58 rest = full_name.Substring (slash + 1);
61 ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
63 if (type_ref != null) {
64 if (is_valuetype && rest == "")
65 type_ref.MakeValueClass ();
67 type_ref = new ExternTypeRef (this, first, is_valuetype, table);
68 typeref_table [first] = type_ref;
71 return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype, table));
74 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
76 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
81 string name_space, name;
82 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
85 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
87 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
89 class_table [full_name] = klass;
95 public class ExternModule : ExternRef {
97 public PEAPI.ModuleRef ModuleRef;
99 public ExternModule (string name) : base (name)
103 public override void Resolve (CodeGen codegen)
108 ModuleRef = codegen.PEFile.AddExternModule (name);
109 if (customattr_list != null)
110 foreach (CustomAttr customattr in customattr_list)
111 customattr.AddTo (codegen, ModuleRef);
117 public override PEAPI.IExternRef GetExternRef ()
123 public class ExternAssembly : ExternRef, IDeclSecurityTarget {
125 public PEAPI.AssemblyRef AssemblyRef;
127 private int major, minor, build, revision;
128 private byte [] public_key;
129 private byte [] public_key_token;
130 private string locale;
131 private byte [] hash;
132 private ArrayList declsec_list;
134 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
137 major = minor = build = revision = -1;
140 public override void Resolve (CodeGen code_gen)
145 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
147 AssemblyRef.AddVersionInfo (major, minor, build, revision);
148 if (public_key != null)
149 AssemblyRef.AddKey (public_key);
150 if (public_key_token != null)
151 AssemblyRef.AddKeyToken (public_key_token);
153 AssemblyRef.AddCulture (locale);
155 AssemblyRef.AddHash (hash);
157 if (customattr_list != null)
158 foreach (CustomAttr customattr in customattr_list)
159 customattr.AddTo (code_gen, AssemblyRef);
161 if (declsec_list != null)
162 foreach (DeclSecurity decl_sec in declsec_list)
163 decl_sec.AddTo (code_gen, AssemblyRef);
165 class_table = new Hashtable ();
170 public override PEAPI.IExternRef GetExternRef ()
175 public void AddDeclSecurity (DeclSecurity decl_sec)
177 if (declsec_list == null)
178 declsec_list = new ArrayList ();
180 declsec_list.Add (decl_sec);
183 public void SetVersion (int major, int minor, int build, int revision)
188 this.revision = revision;
191 public void SetPublicKey (byte [] public_key)
193 this.public_key = public_key;
196 public void SetPublicKeyToken (byte [] public_key_token)
198 this.public_key_token = public_key_token;
201 public void SetLocale (string locale)
203 this.locale = locale;
206 public void SetHash (byte [] hash)
214 public class ExternTable {
216 Hashtable assembly_table;
217 Hashtable module_table;
220 public void AddCorlib ()
223 string mscorlib_name = "mscorlib";
224 AssemblyName mscorlib = new AssemblyName ();
225 mscorlib.Name = mscorlib_name;
226 AddAssembly (mscorlib_name, mscorlib);
228 // Also need to alias corlib, normally corlib and
229 // mscorlib are used interchangably
230 assembly_table["corlib"] = assembly_table["mscorlib"];
233 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
235 ExternAssembly ea = null;
237 if (assembly_table == null) {
238 assembly_table = new Hashtable ();
240 ea = assembly_table [name] as ExternAssembly;
245 ea = new ExternAssembly (name, asmb_name);
247 assembly_table [name] = ea;
252 public ExternModule AddModule (string name)
254 ExternModule em = null;
256 if (module_table == null) {
257 module_table = new Hashtable ();
259 em = module_table [name] as ExternModule;
264 em = new ExternModule (name);
266 module_table [name] = em;
271 public void Resolve (CodeGen code_gen)
276 if (assembly_table != null)
277 foreach (ExternAssembly ext in assembly_table.Values)
278 ext.Resolve (code_gen);
279 if (module_table == null)
281 foreach (ExternModule ext in module_table.Values)
282 ext.Resolve (code_gen);
287 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
289 ExternAssembly ext_asmb = null;
290 if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib"))
291 /* AddCorlib if mscorlib is being referenced but
292 we haven't encountered a ".assembly 'name'" as yet. */
294 if (assembly_table != null)
295 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
297 if (ext_asmb == null)
298 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
300 return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
303 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
306 mod = module_table [mod_name] as ExternModule;
309 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
311 return mod.GetTypeRef (full_name, is_valuetype, this);
314 public static void GetNameAndNamespace (string full_name,
315 out string name_space, out string name) {
317 int last_dot = full_name.LastIndexOf ('.');
320 name_space = String.Empty;
325 name_space = full_name.Substring (0, last_dot);
326 name = full_name.Substring (last_dot + 1);