2005-09-13 Sureshkumar T <tsureshkumar@novell.com>
[mono.git] / mcs / ilasm / codegen / ExternTable.cs
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 //
9
10 using System;
11 using System.Collections;
12 using System.Reflection;
13
14 namespace Mono.ILASM {
15
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);
19         }
20         
21         public abstract class ExternRef : ICustomAttrTarget, IScope {
22
23                 protected string name;
24                 protected Hashtable class_table;
25                 protected Hashtable typeref_table;
26                 protected ArrayList customattr_list;
27                 protected bool is_resolved;
28
29                 public abstract void Resolve (CodeGen codegen);
30                 public abstract PEAPI.IExternRef GetExternRef ();
31
32                 public ExternRef (string name)
33                 {
34                         this.name = name;
35                         typeref_table = new Hashtable ();
36                         class_table = new Hashtable ();
37                 }
38
39                 public string Name {
40                         get { return name; }
41                 }
42
43                 public void AddCustomAttribute (CustomAttr customattr)
44                 {
45                         if (customattr_list == null)
46                                 customattr_list = new ArrayList ();
47
48                         customattr_list.Add (customattr);
49                 }
50
51                 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
52                 {
53                         string first= full_name;
54                         string rest = "";
55                         int slash = full_name.IndexOf ('/');
56                         if (slash > 0) {
57                                 first = full_name.Substring (0, slash);
58                                 rest = full_name.Substring (slash + 1);
59                         }
60                                 
61                         ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
62                         
63                         if (type_ref != null) {
64                                 if (is_valuetype && rest == "")
65                                         type_ref.MakeValueClass ();
66                         } else {
67                                 type_ref = new ExternTypeRef (this, first, is_valuetype, table);
68                                 typeref_table [first] = type_ref;
69                         }
70
71                         return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype, table));
72                 }
73
74                 public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
75                 {
76                         PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
77                         
78                         if (klass != null)
79                                 return klass;
80
81                         string name_space, name;
82                         ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
83
84                         if (is_valuetype)
85                                 klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
86                         else        
87                                 klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
88
89                         class_table [full_name] = klass;
90                         return klass;
91                 }
92
93         }
94
95         public class ExternModule : ExternRef {
96
97                 public PEAPI.ModuleRef ModuleRef;
98
99                 public ExternModule (string name) : base (name)
100                 {
101                 }
102
103                 public override void Resolve (CodeGen codegen)
104                 {
105                         if (is_resolved)
106                                 return;
107
108                         ModuleRef = codegen.PEFile.AddExternModule (name);
109                         if (customattr_list != null)
110                                 foreach (CustomAttr customattr in customattr_list)
111                                         customattr.AddTo (codegen, ModuleRef);
112
113                         is_resolved = true;
114                 }
115
116                 
117                 public override PEAPI.IExternRef GetExternRef ()
118                 {
119                         return ModuleRef;
120                 }
121         }
122
123         public class ExternAssembly : ExternRef, IDeclSecurityTarget {
124                         
125                 public PEAPI.AssemblyRef AssemblyRef;
126
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;
133
134                 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
135                 {
136                         this.name = name;
137                         major = minor = build = revision = -1;
138                 }
139
140                 public override void Resolve (CodeGen code_gen)
141                 {
142                         if (is_resolved)
143                                 return;
144
145                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
146                         if (major != -1)
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);
152                         if (locale != null)
153                                 AssemblyRef.AddCulture (locale);
154                         if (hash != null)
155                                 AssemblyRef.AddHash (hash);
156
157                         if (customattr_list != null)
158                                 foreach (CustomAttr customattr in customattr_list)
159                                         customattr.AddTo (code_gen, AssemblyRef);
160                                         
161                         if (declsec_list != null)
162                                 foreach (DeclSecurity decl_sec in declsec_list)
163                                         decl_sec.AddTo (code_gen, AssemblyRef);
164
165                         class_table = new Hashtable ();
166
167                         is_resolved = true;
168                 }
169
170                 public override PEAPI.IExternRef GetExternRef ()
171                 {
172                         return AssemblyRef;
173                 }
174                 
175                 public void AddDeclSecurity (DeclSecurity decl_sec)
176                 {
177                         if (declsec_list == null)
178                                 declsec_list = new ArrayList ();
179
180                         declsec_list.Add (decl_sec);
181                 }
182
183                 public void SetVersion (int major, int minor, int build, int revision)
184                 {
185                         this.major = major;
186                         this.minor = minor;
187                         this.build = build;
188                         this.revision = revision;
189                 }
190
191                 public void SetPublicKey (byte [] public_key)
192                 {
193                         this.public_key = public_key;
194                 }
195
196                 public void SetPublicKeyToken (byte [] public_key_token)
197                 {
198                         this.public_key_token = public_key_token;
199                 }
200
201                 public void SetLocale (string locale)
202                 {
203                         this.locale = locale;
204                 }
205
206                 public void SetHash (byte [] hash)
207                 {
208                         this.hash = hash;
209                 }
210
211         }
212
213         
214         public class ExternTable {
215
216                 Hashtable assembly_table;
217                 Hashtable module_table;
218                 bool is_resolved;
219                 
220                 public void AddCorlib ()
221                 {
222                         // Add mscorlib
223                         string mscorlib_name = "mscorlib";
224                         AssemblyName mscorlib = new AssemblyName ();
225                         mscorlib.Name = mscorlib_name;
226                         AddAssembly (mscorlib_name, mscorlib);
227
228                         // Also need to alias corlib, normally corlib and
229                         // mscorlib are used interchangably
230                         assembly_table["corlib"] = assembly_table["mscorlib"];
231                 }
232
233                 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
234                 {
235                         ExternAssembly ea = null;
236
237                         if (assembly_table == null) {
238                                 assembly_table = new Hashtable ();
239                         } else {
240                                 ea = assembly_table [name] as ExternAssembly;
241                                 if (ea != null)
242                                         return ea;
243                         }
244
245                         ea = new ExternAssembly (name, asmb_name);
246
247                         assembly_table [name] = ea;
248
249                         return ea;
250                 }
251
252                 public ExternModule AddModule (string name)
253                 {
254                         ExternModule em = null;
255
256                         if (module_table == null) {
257                                 module_table = new Hashtable ();
258                         } else {
259                                 em = module_table [name] as ExternModule;
260                                 if (em != null)
261                                         return em;
262                         }
263
264                         em = new ExternModule (name);
265
266                         module_table [name] = em;
267
268                         return em;
269                 }
270
271                 public void Resolve (CodeGen code_gen)
272                 {
273                         if (is_resolved)
274                                 return;
275
276                         if (assembly_table != null)
277                                 foreach (ExternAssembly ext in assembly_table.Values)
278                                         ext.Resolve (code_gen);
279                         if (module_table == null)
280                                 return;
281                         foreach (ExternModule ext in module_table.Values)
282                                 ext.Resolve (code_gen);
283
284                         is_resolved = true;     
285                 }
286
287                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
288                 {
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. */
293                                 AddCorlib ();
294                         if (assembly_table != null)
295                                 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
296
297                         if (ext_asmb == null)
298                                 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
299
300                         return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
301                 }
302
303                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
304                 {
305                         ExternModule mod;
306                         mod = module_table [mod_name] as ExternModule;
307
308                         if (mod == null)
309                                 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
310
311                         return mod.GetTypeRef (full_name, is_valuetype, this);
312                 }
313
314                 public static void GetNameAndNamespace (string full_name,
315                         out string name_space, out string name) {
316
317                         int last_dot = full_name.LastIndexOf ('.');
318
319                         if (last_dot < 0) {
320                                 name_space = String.Empty;
321                                 name = full_name;
322                                 return;
323                         }
324
325                         name_space = full_name.Substring (0, last_dot);
326                         name = full_name.Substring (last_dot + 1);
327                 }
328
329         }
330 }
331