**** Merged from MCS ****
[mono-project.git] / mcs / ilasm / codegen / ExternTable.cs
bloba2c9ff08d8db6054f991d8c474d6b7d4fdccf268
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;
14 namespace Mono.ILASM {
16 public abstract class ExternRef {
18 protected string name;
19 protected Hashtable class_table;
20 protected Hashtable typeref_table;
22 public abstract void Resolve (CodeGen codegen);
23 public abstract PEAPI.IExternRef GetExternRef ();
25 public ExternRef (string name)
27 this.name = name;
28 typeref_table = new Hashtable ();
29 class_table = new Hashtable ();
32 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
34 ExternTypeRef type_ref = typeref_table [full_name] as ExternTypeRef;
36 if (type_ref != null)
37 return type_ref;
39 type_ref = new ExternTypeRef (this, full_name, is_valuetype, table);
40 typeref_table [full_name] = type_ref;
42 return type_ref;
45 public PEAPI.ClassRef GetType (string full_name)
47 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
49 if (klass != null)
50 return klass;
52 string name_space, name;
53 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
55 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
56 class_table[full_name] = klass;
58 return klass;
61 public PEAPI.ClassRef GetValueType (string full_name)
63 PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
65 if (klass != null)
66 return klass;
68 string name_space, name;
69 ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
71 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
72 class_table[full_name] = klass;
74 return klass;
78 public class ExternModule : ExternRef {
80 public PEAPI.ModuleRef ModuleRef;
82 public ExternModule (string name) : base (name)
86 public override void Resolve (CodeGen codegen)
88 ModuleRef = codegen.PEFile.AddExternModule (name);
92 public override PEAPI.IExternRef GetExternRef ()
94 return ModuleRef;
98 public class ExternAssembly : ExternRef {
100 public PEAPI.AssemblyRef AssemblyRef;
102 private int major, minor, build, revision;
103 private byte [] public_key;
104 private byte [] public_key_token;
105 private string locale;
106 private byte [] hash;
108 private ArrayList cattrs_list;
110 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
112 this.name = name;
113 major = minor = build = revision = -1;
116 public override void Resolve (CodeGen code_gen)
118 AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
119 if (major != -1)
120 AssemblyRef.AddVersionInfo (major, minor, build, revision);
121 if (public_key != null)
122 AssemblyRef.AddKey (public_key);
123 if (public_key_token != null)
124 AssemblyRef.AddKeyToken (public_key_token);
125 if (locale != null)
126 AssemblyRef.AddCulture (locale);
127 if (hash != null)
128 AssemblyRef.AddHash (hash);
130 if (cattrs_list != null) {
131 foreach (CustomAttr cattr in cattrs_list)
132 cattr.AddTo (code_gen, AssemblyRef);
135 class_table = new Hashtable ();
138 public override PEAPI.IExternRef GetExternRef ()
140 return AssemblyRef;
143 public void SetVersion (int major, int minor, int build, int revision)
145 this.major = major;
146 this.minor = minor;
147 this.build = build;
148 this.revision = revision;
151 public void SetPublicKey (byte [] public_key)
153 this.public_key = public_key;
156 public void SetPublicKeyToken (byte [] public_key_token)
158 this.public_key_token = public_key_token;
161 public void SetLocale (string locale)
163 this.locale = locale;
166 public void SetHash (byte [] hash)
168 this.hash = hash;
171 public void AddCustomAttribute (CustomAttr cattr)
173 if (cattrs_list == null)
174 cattrs_list = new ArrayList ();
175 cattrs_list.Add (cattr);
180 public class ExternTable {
182 Hashtable assembly_table;
183 Hashtable module_table;
185 public ExternTable ()
187 // Add mscorlib
188 string mscorlib_name = "mscorlib";
189 AssemblyName mscorlib = new AssemblyName ();
190 mscorlib.Name = mscorlib_name;
191 AddAssembly (mscorlib_name, mscorlib);
193 // Also need to alias corlib, normally corlib and
194 // mscorlib are used interchangably
195 assembly_table["corlib"] = assembly_table["mscorlib"];
198 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
200 ExternAssembly ea = null;
202 if (assembly_table == null) {
203 assembly_table = new Hashtable ();
204 } else {
205 ea = assembly_table [name] as ExternAssembly;
206 if (ea != null)
207 return ea;
210 ea = new ExternAssembly (name, asmb_name);
212 assembly_table [name] = ea;
214 return ea;
217 public ExternModule AddModule (string name)
219 ExternModule em = null;
221 if (module_table == null) {
222 module_table = new Hashtable ();
223 } else {
224 em = module_table [name] as ExternModule;
225 if (em != null)
226 return em;
229 em = new ExternModule (name);
231 module_table [name] = em;
233 return em;
236 public void Resolve (CodeGen code_gen)
238 // Assembly table is never null because we add mscorlib
239 foreach (ExternAssembly ext in assembly_table.Values)
240 ext.Resolve (code_gen);
241 if (module_table == null)
242 return;
243 foreach (ExternModule ext in module_table.Values)
244 ext.Resolve (code_gen);
247 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
249 ExternAssembly ext_asmb;
250 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
252 if (ext_asmb == null)
253 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
255 return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
258 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
260 ExternModule mod;
261 mod = module_table [mod_name] as ExternModule;
263 if (mod == null)
264 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
266 return mod.GetTypeRef (full_name, is_valuetype, this);
269 public static void GetNameAndNamespace (string full_name,
270 out string name_space, out string name) {
272 int last_dot = full_name.LastIndexOf ('.');
274 if (last_dot < 0) {
275 name_space = String.Empty;
276 name = full_name;
277 return;
280 name_space = full_name.Substring (0, last_dot);
281 name = full_name.Substring (last_dot + 1);