2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / ilasm / codegen / ExternTable.cs
blobff0237d8398ed474598ec644d8e61e436bfe10ac
1 //
2 // Mono.ILASM.ExternTable.cs
3 //
4 // Author(s):
5 // Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
10 using System;
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)
37 this.name = name;
38 typeref_table = new Hashtable ();
39 class_table = new Hashtable ();
42 public string Name {
43 get { return name; }
46 public virtual string FullName {
47 get { return name; }
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;
61 string rest = "";
62 int slash = full_name.IndexOf ('/');
63 if (slash > 0) {
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 ();
73 } else {
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;
85 if (klass != null)
86 return klass;
88 string name_space, name;
89 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
91 if (is_valuetype)
92 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
93 else
94 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
96 class_table [full_name] = klass;
97 return klass;
102 public class ExternModule : ExternRef {
104 public PEAPI.ModuleRef ModuleRef;
106 public ExternModule (string name) : base (name)
110 public override string FullName {
111 get {
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)
120 if (is_resolved)
121 return;
123 ModuleRef = codegen.PEFile.AddExternModule (name);
124 if (customattr_list != null)
125 foreach (CustomAttr customattr in customattr_list)
126 customattr.AddTo (codegen, ModuleRef);
128 is_resolved = true;
132 public override PEAPI.IExternRef GetExternRef ()
134 return ModuleRef;
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;
149 //flags
150 private PEAPI.AssemAttr attr;
152 public ExternAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr) : base (name)
154 this.name = name;
155 this.asmb_name = asmb_name;
156 this.attr = attr;
157 major = minor = build = revision = -1;
160 public override string FullName {
161 get {
162 //'name' field should not contain the []
163 //as its used for resolving
164 return String.Format ("[{0}]", name);
168 public AssemblyName AssemblyName {
169 get { return asmb_name; }
172 public DeclSecurity DeclSecurity {
173 get {
174 if (decl_sec == null)
175 decl_sec = new DeclSecurity ();
176 return decl_sec;
180 public override void Resolve (CodeGen code_gen)
182 if (is_resolved)
183 return;
185 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
186 AssemblyRef.AddAssemblyAttr (attr);
187 if (major != -1)
188 AssemblyRef.AddVersionInfo (major, minor, build, revision);
189 if (public_key != null)
190 AssemblyRef.AddKey (public_key);
191 if (public_key_token != null)
192 AssemblyRef.AddKeyToken (public_key_token);
193 if (locale != null)
194 AssemblyRef.AddCulture (locale);
195 if (hash != null)
196 AssemblyRef.AddHash (hash);
198 if (customattr_list != null)
199 foreach (CustomAttr customattr in customattr_list)
200 customattr.AddTo (code_gen, AssemblyRef);
202 if (decl_sec != null)
203 decl_sec.AddTo (code_gen, AssemblyRef);
205 class_table = new Hashtable ();
207 is_resolved = true;
210 public override PEAPI.IExternRef GetExternRef ()
212 return AssemblyRef;
215 public void SetVersion (int major, int minor, int build, int revision)
217 this.major = major;
218 this.minor = minor;
219 this.build = build;
220 this.revision = revision;
221 asmb_name.Version = new Version (major, minor, build, revision);
224 public void SetPublicKey (byte [] public_key)
226 this.public_key = public_key;
227 asmb_name.SetPublicKey (public_key);
230 public void SetPublicKeyToken (byte [] public_key_token)
232 this.public_key_token = public_key_token;
233 asmb_name.SetPublicKey (public_key);
236 public void SetLocale (string locale)
238 this.locale = locale;
239 //FIXME: is this correct?
240 asmb_name.CultureInfo = new CultureInfo (locale);
243 public void SetHash (byte [] hash)
245 this.hash = hash;
251 public class ExternTable {
253 Hashtable assembly_table;
254 Hashtable module_table;
255 bool is_resolved;
257 public void AddCorlib ()
259 // Add mscorlib
260 string mscorlib_name = "mscorlib";
261 AssemblyName mscorlib = new AssemblyName ();
262 mscorlib.Name = mscorlib_name;
263 AddAssembly (mscorlib_name, mscorlib, 0);
265 // Also need to alias corlib, normally corlib and
266 // mscorlib are used interchangably
267 assembly_table["corlib"] = assembly_table["mscorlib"];
270 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr)
272 ExternAssembly ea = null;
274 if (assembly_table == null) {
275 assembly_table = new Hashtable ();
276 } else {
277 ea = assembly_table [name] as ExternAssembly;
278 if (ea != null)
279 return ea;
282 ea = new ExternAssembly (name, asmb_name, attr);
284 assembly_table [name] = ea;
286 return ea;
289 public ExternModule AddModule (string name)
291 ExternModule em = null;
293 if (module_table == null) {
294 module_table = new Hashtable ();
295 } else {
296 em = module_table [name] as ExternModule;
297 if (em != null)
298 return em;
301 em = new ExternModule (name);
303 module_table [name] = em;
305 return em;
308 public void Resolve (CodeGen code_gen)
310 if (is_resolved)
311 return;
313 if (assembly_table != null)
314 foreach (ExternAssembly ext in assembly_table.Values)
315 ext.Resolve (code_gen);
316 if (module_table == null)
317 return;
318 foreach (ExternModule ext in module_table.Values)
319 ext.Resolve (code_gen);
321 is_resolved = true;
324 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
326 ExternAssembly ext_asmb = null;
327 if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
328 /* AddCorlib if mscorlib is being referenced but
329 we haven't encountered a ".assembly 'name'" as yet. */
330 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
331 AddCorlib ();
333 if (assembly_table != null)
334 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
336 if (ext_asmb == null) {
337 System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
338 asmname.Name = asmb_name;
340 Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
341 ext_asmb = AddAssembly (asmb_name, asmname, 0);
344 return ext_asmb.GetTypeRef (full_name, is_valuetype);
347 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
349 ExternModule mod = null;
350 if (module_table != null)
351 mod = module_table [mod_name] as ExternModule;
353 if (mod == null)
354 Report.Error ("Module " + mod_name + " not defined.");
356 return mod.GetTypeRef (full_name, is_valuetype);
359 public static void GetNameAndNamespace (string full_name,
360 out string name_space, out string name) {
362 int last_dot = full_name.LastIndexOf ('.');
364 if (last_dot < 0) {
365 name_space = String.Empty;
366 name = full_name;
367 return;
370 name_space = full_name.Substring (0, last_dot);
371 name = full_name.Substring (last_dot + 1);