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