This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[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                 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
109                 {
110                         this.name = name;
111                         major = minor = build = revision = -1;
112                 }
113
114                 public override void Resolve (CodeGen code_gen)
115                 {
116                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
117                         if (major != -1)
118                                 AssemblyRef.AddVersionInfo (major, minor, build, revision);
119                         if (public_key != null)
120                                 AssemblyRef.AddKey (public_key);
121                         if (public_key_token != null)
122                                 AssemblyRef.AddKeyToken (public_key_token);
123                         if (locale != null)
124                                 AssemblyRef.AddCulture (locale);
125                         if (hash != null)
126                                 AssemblyRef.AddHash (hash);
127                         class_table = new Hashtable ();
128                 }
129
130                 public override PEAPI.IExternRef GetExternRef ()
131                 {
132                         return AssemblyRef;
133                 }
134
135                 public void SetVersion (int major, int minor, int build, int revision)
136                 {
137                         this.major = major;
138                         this.minor = minor;
139                         this.build = build;
140                         this.revision = revision;
141                 }
142
143                 public void SetPublicKey (byte [] public_key)
144                 {
145                         this.public_key = public_key;
146                 }
147
148                 public void SetPublicKeyToken (byte [] public_key_token)
149                 {
150                         this.public_key_token = public_key_token;
151                 }
152
153                 public void SetLocale (string locale)
154                 {
155                         this.locale = locale;
156                 }
157
158                 public void SetHash (byte [] hash)
159                 {
160                         this.hash = hash;
161                 }
162         }
163
164         
165         public class ExternTable {
166
167                 Hashtable assembly_table;
168                 Hashtable module_table;
169                 
170                 public ExternTable ()
171                 {
172                         // Add mscorlib
173                         string mscorlib_name = "mscorlib";
174                         AssemblyName mscorlib = new AssemblyName ();
175                         mscorlib.Name = mscorlib_name;
176                         AddAssembly (mscorlib_name, mscorlib);
177
178                         // Also need to alias corlib, normally corlib and
179                         // mscorlib are used interchangably
180                         assembly_table["corlib"] = assembly_table["mscorlib"];
181                 }
182
183                 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
184                 {
185                         ExternAssembly ea = null;
186
187                         if (assembly_table == null) {
188                                 assembly_table = new Hashtable ();
189                         } else {
190                                 ea = assembly_table [name] as ExternAssembly;
191                                 if (ea != null)
192                                         return ea;
193                         }
194
195                         ea = new ExternAssembly (name, asmb_name);
196
197                         assembly_table [name] = ea;
198
199                         return ea;
200                 }
201
202                 public ExternModule AddModule (string name)
203                 {
204                         ExternModule em = null;
205
206                         if (module_table == null) {
207                                 module_table = new Hashtable ();
208                         } else {
209                                 em = module_table [name] as ExternModule;
210                                 if (em != null)
211                                         return em;
212                         }
213
214                         em = new ExternModule (name);
215
216                         module_table [name] = em;
217
218                         return em;
219                 }
220
221                 public void Resolve (CodeGen code_gen)
222                 {
223                         // Assembly table is never null because we add mscorlib
224                         foreach (ExternAssembly ext in assembly_table.Values)
225                                 ext.Resolve (code_gen);
226                         if (module_table == null)
227                                 return;
228                         foreach (ExternModule ext in module_table.Values)
229                                 ext.Resolve (code_gen);
230                 }
231
232                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
233                 {
234                         ExternAssembly ext_asmb;
235                         ext_asmb = assembly_table[asmb_name] as ExternAssembly;
236
237                         if (ext_asmb == null)
238                                 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
239
240                         return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
241                 }
242
243                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
244                 {
245                         ExternModule mod;
246                         mod = module_table [mod_name] as ExternModule;
247
248                         if (mod == null)
249                                 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
250
251                         return mod.GetTypeRef (full_name, is_valuetype, this);
252                 }
253
254                 public static void GetNameAndNamespace (string full_name,
255                         out string name_space, out string name) {
256
257                         int last_dot = full_name.LastIndexOf ('.');
258
259                         if (last_dot < 0) {
260                                 name_space = String.Empty;
261                                 name = full_name;
262                                 return;
263                         }
264
265                         name_space = full_name.Substring (0, last_dot);
266                         name = full_name.Substring (last_dot + 1);
267                 }
268
269         }
270 }
271