Display error messages instead of stack traces.
[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 override void Resolve (CodeGen code_gen)
163                 {
164                         if (is_resolved)
165                                 return;
166
167                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
168                         if (major != -1)
169                                 AssemblyRef.AddVersionInfo (major, minor, build, revision);
170                         if (public_key != null)
171                                 AssemblyRef.AddKey (public_key);
172                         if (public_key_token != null)
173                                 AssemblyRef.AddKeyToken (public_key_token);
174                         if (locale != null)
175                                 AssemblyRef.AddCulture (locale);
176                         if (hash != null)
177                                 AssemblyRef.AddHash (hash);
178
179                         if (customattr_list != null)
180                                 foreach (CustomAttr customattr in customattr_list)
181                                         customattr.AddTo (code_gen, AssemblyRef);
182                                         
183                         if (decl_sec != null)
184                                 decl_sec.AddTo (code_gen, AssemblyRef);
185
186                         class_table = new Hashtable ();
187
188                         is_resolved = true;
189                 }
190
191                 public override PEAPI.IExternRef GetExternRef ()
192                 {
193                         return AssemblyRef;
194                 }
195                 
196                 public void AddPermissionSet (PEAPI.SecurityAction sec_action, PermissionSet ps)
197                 {
198                         if (decl_sec == null)
199                                 decl_sec = new DeclSecurity ();
200
201                         decl_sec.AddPermissionSet (sec_action, ps);        
202                 }
203                 
204                 public void AddPermission (PEAPI.SecurityAction sec_action, IPermission iper)
205                 {
206                         if (decl_sec == null)
207                                 decl_sec = new DeclSecurity ();
208
209                         decl_sec.AddPermission (sec_action, iper);
210                 }
211
212                 public void SetVersion (int major, int minor, int build, int revision)
213                 {
214                         this.major = major;
215                         this.minor = minor;
216                         this.build = build;
217                         this.revision = revision;
218                 }
219
220                 public void SetPublicKey (byte [] public_key)
221                 {
222                         this.public_key = public_key;
223                 }
224
225                 public void SetPublicKeyToken (byte [] public_key_token)
226                 {
227                         this.public_key_token = public_key_token;
228                 }
229
230                 public void SetLocale (string locale)
231                 {
232                         this.locale = locale;
233                 }
234
235                 public void SetHash (byte [] hash)
236                 {
237                         this.hash = hash;
238                 }
239
240         }
241
242         
243         public class ExternTable {
244
245                 Hashtable assembly_table;
246                 Hashtable module_table;
247                 bool is_resolved;
248                 
249                 public void AddCorlib ()
250                 {
251                         // Add mscorlib
252                         string mscorlib_name = "mscorlib";
253                         AssemblyName mscorlib = new AssemblyName ();
254                         mscorlib.Name = mscorlib_name;
255                         AddAssembly (mscorlib_name, mscorlib);
256
257                         // Also need to alias corlib, normally corlib and
258                         // mscorlib are used interchangably
259                         assembly_table["corlib"] = assembly_table["mscorlib"];
260                 }
261
262                 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
263                 {
264                         ExternAssembly ea = null;
265
266                         if (assembly_table == null) {
267                                 assembly_table = new Hashtable ();
268                         } else {
269                                 ea = assembly_table [name] as ExternAssembly;
270                                 if (ea != null)
271                                         return ea;
272                         }
273
274                         ea = new ExternAssembly (name, asmb_name);
275
276                         assembly_table [name] = ea;
277
278                         return ea;
279                 }
280
281                 public ExternModule AddModule (string name)
282                 {
283                         ExternModule em = null;
284
285                         if (module_table == null) {
286                                 module_table = new Hashtable ();
287                         } else {
288                                 em = module_table [name] as ExternModule;
289                                 if (em != null)
290                                         return em;
291                         }
292
293                         em = new ExternModule (name);
294
295                         module_table [name] = em;
296
297                         return em;
298                 }
299
300                 public void Resolve (CodeGen code_gen)
301                 {
302                         if (is_resolved)
303                                 return;
304
305                         if (assembly_table != null)
306                                 foreach (ExternAssembly ext in assembly_table.Values)
307                                         ext.Resolve (code_gen);
308                         if (module_table == null)
309                                 return;
310                         foreach (ExternModule ext in module_table.Values)
311                                 ext.Resolve (code_gen);
312
313                         is_resolved = true;     
314                 }
315
316                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
317                 {
318                         ExternAssembly ext_asmb = null;
319                         if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib"))
320                                 /* AddCorlib if mscorlib is being referenced but
321                                    we haven't encountered a ".assembly 'name'" as yet. */
322                                 AddCorlib ();
323                         if (assembly_table != null)
324                                 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
325
326                         if (ext_asmb == null) {
327                                 System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
328                                 asmname.Name = asmb_name;
329
330                                 Console.Error.WriteLine ("Warning -- Reference to undeclared extern assembly '{0}', adding.", asmb_name);
331                                 ext_asmb = AddAssembly (asmb_name, asmname);
332                         }
333
334                         return ext_asmb.GetTypeRef (full_name, is_valuetype);
335                 }
336
337                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
338                 {
339                         ExternModule mod = null;
340                         if (module_table != null)
341                                 mod = module_table [mod_name] as ExternModule;
342
343                         if (mod == null)
344                                 Report.Error ("Module " + mod_name + " not defined.");
345
346                         return mod.GetTypeRef (full_name, is_valuetype);
347                 }
348
349                 public static void GetNameAndNamespace (string full_name,
350                         out string name_space, out string name) {
351
352                         int last_dot = full_name.LastIndexOf ('.');
353
354                         if (last_dot < 0) {
355                                 name_space = String.Empty;
356                                 name = full_name;
357                                 return;
358                         }
359
360                         name_space = full_name.Substring (0, last_dot);
361                         name = full_name.Substring (last_dot + 1);
362                 }
363
364         }
365 }
366