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