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