2 // Mono.ILASM.ExternTable.cs
5 // Jackson Harper (Jackson@LatitudeGeo.com)
7 // (C) 2003 Jackson Harper, All rights reserved
11 using System
.Collections
;
12 using System
.Reflection
;
13 using System
.Security
;
14 using System
.Globalization
;
16 namespace Mono
.ILASM
{
18 public interface IScope
{
19 ExternTypeRef
GetTypeRef (string full_name
, bool is_valuetype
);
20 PEAPI
.ClassRef
GetType (string full_name
, bool is_valuetype
);
21 string FullName { get; }
24 public abstract class ExternRef
: ICustomAttrTarget
, IScope
{
26 protected string name
;
27 protected Hashtable class_table
;
28 protected Hashtable typeref_table
;
29 protected ArrayList customattr_list
;
30 protected bool is_resolved
;
32 public abstract void Resolve (CodeGen codegen
);
33 public abstract PEAPI
.IExternRef
GetExternRef ();
35 public ExternRef (string name
)
38 typeref_table
= new Hashtable ();
39 class_table
= new Hashtable ();
46 public virtual string FullName
{
50 public void AddCustomAttribute (CustomAttr customattr
)
52 if (customattr_list
== null)
53 customattr_list
= new ArrayList ();
55 customattr_list
.Add (customattr
);
58 public ExternTypeRef
GetTypeRef (string full_name
, bool is_valuetype
)
60 string first
= full_name
;
62 int slash
= full_name
.IndexOf ('/');
64 first
= full_name
.Substring (0, slash
);
65 rest
= full_name
.Substring (slash
+ 1);
68 ExternTypeRef type_ref
= typeref_table
[first
] as ExternTypeRef
;
70 if (type_ref
!= null) {
71 if (is_valuetype
&& rest
== "")
72 type_ref
.MakeValueClass ();
74 type_ref
= new ExternTypeRef (this, first
, is_valuetype
);
75 typeref_table
[first
] = type_ref
;
78 return (rest
== "" ? type_ref
: type_ref
.GetTypeRef (rest
, is_valuetype
));
81 public PEAPI
.ClassRef
GetType (string full_name
, bool is_valuetype
)
83 PEAPI
.ClassRef klass
= class_table
[full_name
] as PEAPI
.ClassRef
;
88 string name_space
, name
;
89 ExternTable
.GetNameAndNamespace (full_name
, out name_space
, out name
);
92 klass
= (PEAPI
.ClassRef
) GetExternRef ().AddValueClass (name_space
, name
);
94 klass
= (PEAPI
.ClassRef
) GetExternRef ().AddClass (name_space
, name
);
96 class_table
[full_name
] = klass
;
102 public class ExternModule
: ExternRef
{
104 public PEAPI
.ModuleRef ModuleRef
;
106 public ExternModule (string name
) : base (name
)
110 public override string FullName
{
112 //'name' field should not contain the [.module ]
113 //as its used for resolving
114 return String
.Format ("[.module {0}]", name
);
118 public override void Resolve (CodeGen codegen
)
123 ModuleRef
= codegen
.PEFile
.AddExternModule (name
);
124 if (customattr_list
!= null)
125 foreach (CustomAttr customattr
in customattr_list
)
126 customattr
.AddTo (codegen
, ModuleRef
);
132 public override PEAPI
.IExternRef
GetExternRef ()
138 public class ExternAssembly
: ExternRef
, IDeclSecurityTarget
{
140 public PEAPI
.AssemblyRef AssemblyRef
;
142 private int major
, minor
, build
, revision
;
143 private byte [] public_key
;
144 private byte [] public_key_token
;
145 private string locale
;
146 private byte [] hash
;
147 private DeclSecurity decl_sec
;
148 private AssemblyName asmb_name
;
150 private PEAPI
.AssemAttr attr
;
152 public ExternAssembly (string name
, AssemblyName asmb_name
, PEAPI
.AssemAttr attr
) : base (name
)
155 this.asmb_name
= asmb_name
;
157 major
= minor
= build
= revision
= -1;
160 public override string FullName
{
162 //'name' field should not contain the []
163 //as its used for resolving
164 return String
.Format ("[{0}]", name
);
168 public AssemblyName AssemblyName
{
169 get { return asmb_name; }
172 public DeclSecurity DeclSecurity
{
174 if (decl_sec
== null)
175 decl_sec
= new DeclSecurity ();
180 public override void Resolve (CodeGen code_gen
)
185 AssemblyRef
= code_gen
.PEFile
.AddExternAssembly (name
);
186 AssemblyRef
.AddAssemblyAttr (attr
);
188 AssemblyRef
.AddVersionInfo (major
, minor
, build
, revision
);
189 if (public_key
!= null)
190 AssemblyRef
.AddKey (public_key
);
191 if (public_key_token
!= null)
192 AssemblyRef
.AddKeyToken (public_key_token
);
194 AssemblyRef
.AddCulture (locale
);
196 AssemblyRef
.AddHash (hash
);
198 if (customattr_list
!= null)
199 foreach (CustomAttr customattr
in customattr_list
)
200 customattr
.AddTo (code_gen
, AssemblyRef
);
202 if (decl_sec
!= null)
203 decl_sec
.AddTo (code_gen
, AssemblyRef
);
205 class_table
= new Hashtable ();
210 public override PEAPI
.IExternRef
GetExternRef ()
215 public void SetVersion (int major
, int minor
, int build
, int revision
)
220 this.revision
= revision
;
221 asmb_name
.Version
= new Version (major
, minor
, build
, revision
);
224 public void SetPublicKey (byte [] public_key
)
226 this.public_key
= public_key
;
227 asmb_name
.SetPublicKey (public_key
);
230 public void SetPublicKeyToken (byte [] public_key_token
)
232 this.public_key_token
= public_key_token
;
233 asmb_name
.SetPublicKey (public_key
);
236 public void SetLocale (string locale
)
238 this.locale
= locale
;
239 //FIXME: is this correct?
240 asmb_name
.CultureInfo
= new CultureInfo (locale
);
243 public void SetHash (byte [] hash
)
251 public class ExternTable
{
253 Hashtable assembly_table
;
254 Hashtable module_table
;
257 public void AddCorlib ()
260 string mscorlib_name
= "mscorlib";
261 AssemblyName mscorlib
= new AssemblyName ();
262 mscorlib
.Name
= mscorlib_name
;
263 AddAssembly (mscorlib_name
, mscorlib
, 0);
265 // Also need to alias corlib, normally corlib and
266 // mscorlib are used interchangably
267 assembly_table
["corlib"] = assembly_table
["mscorlib"];
270 public ExternAssembly
AddAssembly (string name
, AssemblyName asmb_name
, PEAPI
.AssemAttr attr
)
272 ExternAssembly ea
= null;
274 if (assembly_table
== null) {
275 assembly_table
= new Hashtable ();
277 ea
= assembly_table
[name
] as ExternAssembly
;
282 ea
= new ExternAssembly (name
, asmb_name
, attr
);
284 assembly_table
[name
] = ea
;
289 public ExternModule
AddModule (string name
)
291 ExternModule em
= null;
293 if (module_table
== null) {
294 module_table
= new Hashtable ();
296 em
= module_table
[name
] as ExternModule
;
301 em
= new ExternModule (name
);
303 module_table
[name
] = em
;
308 public void Resolve (CodeGen code_gen
)
313 if (assembly_table
!= null)
314 foreach (ExternAssembly ext
in assembly_table
.Values
)
315 ext
.Resolve (code_gen
);
316 if (module_table
== null)
318 foreach (ExternModule ext
in module_table
.Values
)
319 ext
.Resolve (code_gen
);
324 public ExternTypeRef
GetTypeRef (string asmb_name
, string full_name
, bool is_valuetype
)
326 ExternAssembly ext_asmb
= null;
327 if (assembly_table
== null && (asmb_name
== "mscorlib" || asmb_name
== "corlib")) {
328 /* AddCorlib if mscorlib is being referenced but
329 we haven't encountered a ".assembly 'name'" as yet. */
330 Report
.Warning (String
.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name
));
333 if (assembly_table
!= null)
334 ext_asmb
= assembly_table
[asmb_name
] as ExternAssembly
;
336 if (ext_asmb
== null) {
337 System
.Reflection
.AssemblyName asmname
= new System
.Reflection
.AssemblyName ();
338 asmname
.Name
= asmb_name
;
340 Report
.Warning (String
.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name
));
341 ext_asmb
= AddAssembly (asmb_name
, asmname
, 0);
344 return ext_asmb
.GetTypeRef (full_name
, is_valuetype
);
347 public ExternTypeRef
GetModuleTypeRef (string mod_name
, string full_name
, bool is_valuetype
)
349 ExternModule mod
= null;
350 if (module_table
!= null)
351 mod
= module_table
[mod_name
] as ExternModule
;
354 Report
.Error ("Module " + mod_name
+ " not defined.");
356 return mod
.GetTypeRef (full_name
, is_valuetype
);
359 public static void GetNameAndNamespace (string full_name
,
360 out string name_space
, out string name
) {
362 int last_dot
= full_name
.LastIndexOf ('.');
365 name_space
= String
.Empty
;
370 name_space
= full_name
.Substring (0, last_dot
);
371 name
= full_name
.Substring (last_dot
+ 1);