updating to the latest module.
[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 abstract class ExternRef : ICustomAttrTarget {
17
18                 protected string name;
19                 protected Hashtable class_table;
20                 protected Hashtable typeref_table;
21                 protected ArrayList customattr_list;
22
23                 public abstract void Resolve (CodeGen codegen);
24                 public abstract PEAPI.IExternRef GetExternRef ();
25
26                 public ExternRef (string name)
27                 {
28                         this.name = name;
29                         typeref_table = new Hashtable ();
30                         class_table = new Hashtable ();
31                 }
32
33                 public void AddCustomAttribute (CustomAttr customattr)
34                 {
35                         if (customattr_list == null)
36                                 customattr_list = new ArrayList ();
37
38                         customattr_list.Add (customattr);
39                 }
40
41                 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
42                 {
43                         ExternTypeRef type_ref = typeref_table [full_name] as ExternTypeRef;
44                         
45                         if (type_ref != null)
46                                 return type_ref;
47                         
48                         type_ref = new ExternTypeRef (this, full_name, is_valuetype, table);
49                         typeref_table [full_name] = type_ref;
50                         
51                         return type_ref;
52                 }
53
54                 public PEAPI.ClassRef GetType (string full_name)
55                 {
56                         PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
57                         
58                         if (klass != null)
59                                 return klass;
60
61                         string name_space, name;
62                         ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
63
64                         klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
65                         class_table[full_name] = klass;
66
67                         return klass;
68                 }
69
70                 public PEAPI.ClassRef GetValueType (string full_name)
71                 {
72                         PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
73
74                         if (klass != null) 
75                                 return klass;
76
77                         string name_space, name;
78                         ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
79
80                         klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
81                         class_table[full_name] = klass;
82
83                         return klass;
84                 }
85         }
86
87         public class ExternModule : ExternRef {
88
89                 public PEAPI.ModuleRef ModuleRef;
90
91                 public ExternModule (string name) : base (name)
92                 {
93                 }
94
95                 public override void Resolve (CodeGen codegen)
96                 {
97                         ModuleRef = codegen.PEFile.AddExternModule (name);
98                         if (customattr_list != null)
99                                 foreach (CustomAttr customattr in customattr_list)
100                                         customattr.AddTo (codegen, ModuleRef);
101                 }
102
103                 
104                 public override PEAPI.IExternRef GetExternRef ()
105                 {
106                         return ModuleRef;
107                 }
108         }
109
110         public class ExternAssembly : ExternRef {
111                         
112                 public PEAPI.AssemblyRef AssemblyRef;
113
114                 private int major, minor, build, revision;
115                 private byte [] public_key;
116                 private byte [] public_key_token;
117                 private string locale;
118                 private byte [] hash;
119
120                 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
121                 {
122                         this.name = name;
123                         major = minor = build = revision = -1;
124                 }
125
126                 public override void Resolve (CodeGen code_gen)
127                 {
128                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
129                         if (major != -1)
130                                 AssemblyRef.AddVersionInfo (major, minor, build, revision);
131                         if (public_key != null)
132                                 AssemblyRef.AddKey (public_key);
133                         if (public_key_token != null)
134                                 AssemblyRef.AddKeyToken (public_key_token);
135                         if (locale != null)
136                                 AssemblyRef.AddCulture (locale);
137                         if (hash != null)
138                                 AssemblyRef.AddHash (hash);
139
140                         if (customattr_list != null)
141                                 foreach (CustomAttr customattr in customattr_list)
142                                         customattr.AddTo (code_gen, AssemblyRef);
143
144                         class_table = new Hashtable ();
145                 }
146
147                 public override PEAPI.IExternRef GetExternRef ()
148                 {
149                         return AssemblyRef;
150                 }
151
152                 public void SetVersion (int major, int minor, int build, int revision)
153                 {
154                         this.major = major;
155                         this.minor = minor;
156                         this.build = build;
157                         this.revision = revision;
158                 }
159
160                 public void SetPublicKey (byte [] public_key)
161                 {
162                         this.public_key = public_key;
163                 }
164
165                 public void SetPublicKeyToken (byte [] public_key_token)
166                 {
167                         this.public_key_token = public_key_token;
168                 }
169
170                 public void SetLocale (string locale)
171                 {
172                         this.locale = locale;
173                 }
174
175                 public void SetHash (byte [] hash)
176                 {
177                         this.hash = hash;
178                 }
179
180         }
181
182         
183         public class ExternTable {
184
185                 Hashtable assembly_table;
186                 Hashtable module_table;
187                 
188                 public ExternTable ()
189                 {
190                         // Add mscorlib
191                         string mscorlib_name = "mscorlib";
192                         AssemblyName mscorlib = new AssemblyName ();
193                         mscorlib.Name = mscorlib_name;
194                         AddAssembly (mscorlib_name, mscorlib);
195
196                         // Also need to alias corlib, normally corlib and
197                         // mscorlib are used interchangably
198                         assembly_table["corlib"] = assembly_table["mscorlib"];
199                 }
200
201                 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
202                 {
203                         ExternAssembly ea = null;
204
205                         if (assembly_table == null) {
206                                 assembly_table = new Hashtable ();
207                         } else {
208                                 ea = assembly_table [name] as ExternAssembly;
209                                 if (ea != null)
210                                         return ea;
211                         }
212
213                         ea = new ExternAssembly (name, asmb_name);
214
215                         assembly_table [name] = ea;
216
217                         return ea;
218                 }
219
220                 public ExternModule AddModule (string name)
221                 {
222                         ExternModule em = null;
223
224                         if (module_table == null) {
225                                 module_table = new Hashtable ();
226                         } else {
227                                 em = module_table [name] as ExternModule;
228                                 if (em != null)
229                                         return em;
230                         }
231
232                         em = new ExternModule (name);
233
234                         module_table [name] = em;
235
236                         return em;
237                 }
238
239                 public void Resolve (CodeGen code_gen)
240                 {
241                         // Assembly table is never null because we add mscorlib
242                         foreach (ExternAssembly ext in assembly_table.Values)
243                                 ext.Resolve (code_gen);
244                         if (module_table == null)
245                                 return;
246                         foreach (ExternModule ext in module_table.Values)
247                                 ext.Resolve (code_gen);
248                 }
249
250                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
251                 {
252                         ExternAssembly ext_asmb;
253                         ext_asmb = assembly_table[asmb_name] as ExternAssembly;
254
255                         if (ext_asmb == null)
256                                 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
257
258                         return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
259                 }
260
261                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
262                 {
263                         ExternModule mod;
264                         mod = module_table [mod_name] as ExternModule;
265
266                         if (mod == null)
267                                 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
268
269                         return mod.GetTypeRef (full_name, is_valuetype, this);
270                 }
271
272                 public static void GetNameAndNamespace (string full_name,
273                         out string name_space, out string name) {
274
275                         int last_dot = full_name.LastIndexOf ('.');
276
277                         if (last_dot < 0) {
278                                 name_space = String.Empty;
279                                 name = full_name;
280                                 return;
281                         }
282
283                         name_space = full_name.Substring (0, last_dot);
284                         name = full_name.Substring (last_dot + 1);
285                 }
286
287         }
288 }
289