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