Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / PEAPI / Metadata.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5 using System.Reflection;
6
7 namespace PEAPI {
8
9         #region Enums
10
11         /// <summary>
12         /// flags for the assembly (.corflags)
13         /// </summary>
14         public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15                 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
16
17         /// <summary>
18         /// subsystem for the assembly (.subsystem)
19         /// </summary>
20         public enum SubSystem { Native = 1, Windows_GUI = 2, 
21                 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8, 
22                 Windows_CE_GUI = 9}
23
24         /// <summary>
25         /// Hash algorithms for the assembly
26         /// </summary>
27         public enum HashAlgorithm { None, SHA1 }
28
29         /// <summary>
30         /// Attributes for this assembly
31         /// </summary>
32         public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000, 
33                 DisableJITCompileOptimizer = 0x4000}
34
35         /// <summary>
36         /// Method call conventions
37         /// </summary>
38         [Flags]
39         public enum CallConv { Default, Cdecl, Stdcall, Thiscall, 
40                 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
41
42         /// <summary>
43         /// Type custom modifier
44         /// </summary>
45         public enum CustomModifier { modreq = 0x1F, modopt };
46
47         /// <summary>
48         /// Attibutes for a class
49         /// </summary>
50         [Flags]
51         public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, 
52                 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, 
53                 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, 
54                 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, 
55                 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, 
56                 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57                 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
58                 Forwarder = 0x200000,
59                 VisibilityMask = 0x07 }
60
61         /// <summary>
62         /// Attributes for a field
63         /// </summary>
64         public enum FieldAttr {Default, Private, FamAndAssem, Assembly, 
65                 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16, 
66                 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80, 
67                 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
68
69         /// <summary>
70         /// Attributes for a method
71         /// </summary>
72         public enum MethAttr { Default, Private, FamAndAssem, Assembly,
73                 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, 
74                 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, 
75                 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, 
76                 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
77                 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, 
78                 HasSecurity = 0x4000, RequireSecObject = 0x8000}
79
80         /// <summary>
81         /// Attributes for .pinvokeimpl method declarations
82         /// </summary>
83         public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
84                 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
85                 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
86                 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
87                 charmaperror_on = 0x1000, charmaperror_off = 0x2000
88         }
89
90         /// <summary>
91         /// Implementation attributes for a method
92         /// </summary>
93         public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
94                 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000, 
95                 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
96
97         /// <summary>
98         /// Modes for a parameter
99         /// </summary>
100         public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
101
102         /// <summary>
103         /// CIL instructions
104         /// </summary>
105         public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
106                 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3, 
107                 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3, 
108                 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop, 
109                 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4, 
110                 ldind_u4, ldind_i8, ldind_i,  ldind_r4, ldind_r8, ldind_ref, stind_ref, 
111                 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
112                 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not, 
113                 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8, 
114                 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
115                 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un, 
116                 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un, 
117                 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2, 
118                 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8, 
119                 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
120                 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2, 
121                 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3, 
122                 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf, 
123                 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, 
124                 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, 
125                 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, 
126                 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
127
128         /// <summary>
129         /// CIL instructions requiring an integer parameter
130         /// </summary>
131         public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s, 
132                 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
133                 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
134
135         /// <summary>
136         /// CIL instructions requiring a field parameter
137         /// </summary>
138         public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
139                 stsfld, ldtoken = 0xD0 }
140
141         /// <summary>
142         /// CIL instructions requiring a method parameter
143         /// </summary>
144         public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73, 
145                 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
146
147         /// <summary>
148         /// CIL instructions requiring a type parameter
149         /// </summary>
150         public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, 
151                 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, 
152                 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, 
153                 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16, 
154                 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
155
156         /// <summary>
157         /// CIL branch instructions
158         /// </summary>
159         public enum BranchOp {
160                 // short branches
161                 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
162                 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
163                 // long branches
164                 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
165                 bne_un, bge_un, bgt_un, ble_un, blt_un,
166
167                 leave = 0xDD, leave_s }
168
169         /// <summary>
170         /// Index for all the tables in the meta data
171         /// </summary>
172         public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
173                 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute, 
174                 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig, 
175                 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics, 
176                 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20, 
177                 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor, 
178                 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
179                 GenericParam, MethodSpec, GenericParamConstraint  }
180
181         public enum SafeArrayType { int16 = 2, int32, float32, float64,
182                 currency, date, bstr, dispatch, error, boolean, variant, unknown,
183                 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
184
185         internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
186                 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, 
187                 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
188                 TypeOrMethodDef, MaxCIx }
189
190         internal enum MapType { eventMap, propertyMap, nestedClass }
191
192         public enum ValueClass { ValueType, Enum }
193
194         public enum GenParamType : byte { 
195                 Var = 0x13, MVar = 0x1E 
196         }
197
198         [Flags]
199         public enum GenericParamAttributes : ushort {
200                 VarianceMask  = 0x0003,
201                 NonVariant    = 0x0000,
202                 Covariant     = 0x0001,
203                 Contravariant = 0x0002,
204
205                 SpecialConstraintMask = 0x001c,
206                 ReferenceTypeConstraint = 0x0004,
207                 NotNullableValueTypeConstraint = 0x0008,
208                 DefaultConstructorConstrait = 0x0010
209         }
210
211         /* Taken from Mono.Cecil */
212         public enum SecurityAction : short {
213                 Request = 1,
214                 Demand = 2,
215                 Assert = 3,
216                 Deny = 4,
217                 PermitOnly = 5,
218                 LinkDemand = 6,
219                 InheritDemand = 7,
220                 RequestMinimum = 8,
221                 RequestOptional = 9,
222                 RequestRefuse = 10,
223                 PreJitGrant = 11,
224                 PreJitDeny = 12,
225                 NonCasDemand = 13,
226                 NonCasLinkDemand = 14,
227                 NonCasInheritance = 15,
228                 LinkDemandChoice = 16,
229                 InheritDemandChoice = 17,
230                 DemandChoice = 18
231         }
232
233         #endregion
234
235         /**************************************************************************/  
236         /// <summary>
237         /// Base class for all Meta Data table elements
238         /// </summary>
239
240         public abstract class MetaDataElement: IComparable {
241                 protected ArrayList customAttributes;
242                 private uint row = 0;
243                 protected bool done = false;
244                 protected MDTable tabIx;
245                 protected bool sortTable = false;
246                 //Temporary hack.. 
247                 private bool has_custom_attrs = false;
248
249                 internal MetaDataElement() { }
250
251                 public uint Row {
252                         get {
253                                 return row;
254                         }
255                         set {
256                                 row = value;
257                         }
258                 }
259
260                 public bool HasCustomAttr {
261                         get { return has_custom_attrs; }
262                         set { has_custom_attrs = value; }
263                 }
264
265                 internal virtual uint GetCodedIx(CIx code) { return 0; }
266
267                 /// <summary>
268                 /// Add a custom attribute to this item
269                 /// </summary>
270                 /// <param name="ctorMeth">the constructor method for this attribute</param>
271                 /// <param name="val">the byte value of the parameters</param>
272                 public void AddCustomAttribute(Method ctorMeth, byte[] val) 
273                 {
274                         if (customAttributes == null) {
275                                 customAttributes = new ArrayList();
276                         } 
277                         customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
278                 }
279
280                 /// <summary>
281                 /// Add a custom attribute to this item
282                 /// </summary>
283                 /// <param name="ctorMeth">the constructor method for this attribute</param>
284                 /// <param name="val">the constant values of the parameters</param>
285                 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) 
286                 {
287                         if (customAttributes == null) {
288                                 customAttributes = new ArrayList();
289                         } 
290                         //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
291                 }
292
293                 internal uint Token() 
294                 {
295                         return (((uint)tabIx << 24) | row);
296                 }
297
298                 internal virtual void BuildTables(MetaData md) 
299                 {
300                         done = true;
301                 }
302
303                 internal virtual uint Size(MetaData md) 
304                 {
305                         return 0;
306                 }
307
308                 internal virtual void Write(FileImage output) {   }
309
310                 internal virtual uint SortKey() 
311                 { 
312                         throw new PEFileException("Trying to sort table of " + this);
313                         //return 0; 
314                 }
315
316                 internal virtual uint SortKey2()
317                 {
318                         return 0;
319                 }
320
321                 public int CompareTo(object obj) 
322                 {
323                         uint otherKey = ((MetaDataElement)obj).SortKey();
324                         uint thisKey = SortKey();
325
326                         if (thisKey == otherKey)  {
327
328                                 otherKey = ((MetaDataElement)obj).SortKey2();
329                                 thisKey = SortKey2();
330                                 if (thisKey == otherKey)
331                                         return 0;
332                                 if (thisKey < otherKey)
333                                         return -1;
334                                 return 1;
335                         }
336                         if (thisKey < otherKey) return -1;
337
338                         return 1;
339                 }
340
341         }
342
343         /**************************************************************************/  
344         /// <summary>
345         /// Layout information for a class (.class [sequential | explicit])
346         /// </summary>
347         internal class ClassLayout : MetaDataElement {
348
349                 ClassDef parent;
350                 ushort packSize = 0;
351                 uint classSize = 0;
352
353                 internal ClassLayout(int pack, int cSize, ClassDef par) 
354                 {
355                         packSize = (ushort)pack;
356                         classSize = (uint)cSize;
357                         parent = par;
358                         tabIx = MDTable.ClassLayout;
359                 }
360
361                 internal sealed override uint Size(MetaData md) 
362                 {
363                         return 6 + md.TableIndexSize(MDTable.TypeDef);
364                 }
365
366                 internal sealed override void Write(FileImage output) 
367                 {
368                         output.Write(packSize);
369                         output.Write(classSize);
370                         output.WriteIndex(MDTable.TypeDef,parent.Row);
371                 }
372
373         }
374
375         /**************************************************************************/  
376         /// <summary>
377         /// Summary description for ConstantElem.
378         /// </summary>
379         internal class ConstantElem : MetaDataElement {
380
381                 MetaDataElement parent;
382                 Constant cValue;
383                 uint valIx = 0;
384
385                 internal ConstantElem(MetaDataElement parent, Constant val) 
386                 {
387                         this.parent = parent;
388                         cValue = val;
389                         tabIx = MDTable.Constant;
390                         sortTable = true;
391                 }
392
393                 internal override uint SortKey() 
394                 {  
395                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst]) 
396                                 | parent.GetCodedIx(CIx.HasConst);
397                 }
398
399                 internal sealed override void BuildTables(MetaData md) 
400                 {
401                         if (done) return;
402                         valIx = cValue.GetBlobIndex(md);
403                         done = true;
404                 }
405
406                 internal void AddToBlob(BinaryWriter bw) 
407                 {
408                         cValue.Write(bw);
409                 }
410
411                 internal sealed override uint Size(MetaData md) 
412                 {
413                         return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
414                 }
415
416                 internal sealed override void Write(FileImage output) 
417                 {
418                         output.Write(cValue.GetTypeIndex());
419                         output.Write((byte)0);
420                         output.WriteCodedIndex(CIx.HasConst,parent);
421                         output.BlobIndex(valIx);
422                 }
423
424         }
425         /**************************************************************************/  
426         /// <summary>
427         /// Descriptor for a Custom Attribute (.custom) 
428         /// </summary>
429
430         public class CustomAttribute : MetaDataElement {
431
432                 MetaDataElement parent;
433                 Method type;
434                 uint valIx;
435                 Constant cVal;
436                 byte[] byteVal;
437                 ushort numNamed = 0;
438                 ArrayList names, vals;
439
440                 internal CustomAttribute(MetaDataElement paren, Method constrType, 
441                                 Constant val) {
442                         parent = paren;
443                         type = constrType;
444                         cVal = val;
445                         tabIx = MDTable.CustomAttribute;
446
447                         var bac = val as ByteArrConst;
448                         if (bac != null)
449                                 byteVal = bac.val;
450                 }
451
452                 internal CustomAttribute(MetaDataElement paren, Method constrType,
453                                 byte[] val) {
454                         parent = paren;
455                         type = constrType;
456                         tabIx = MDTable.CustomAttribute;
457                         byteVal = val;
458                 }
459
460                 internal override uint SortKey() 
461                 {
462                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
463                                 | parent.GetCodedIx(CIx.HasCustomAttr);
464                 }
465
466                 public void AddFieldOrProp(string name, Constant val) 
467                 {
468                         if (numNamed == 0) {
469                                 names = new ArrayList();
470                                 vals = new ArrayList();
471                         }
472                         names.Add(name);
473                         vals.Add(val);
474                 }
475
476                 internal sealed override void BuildTables(MetaData md) 
477                 {
478                         md.AddToTable(MDTable.CustomAttribute, this);
479                         if (byteVal == null) {
480                                 valIx = 0;
481                                 return;
482                         }
483
484                         BinaryWriter bw = new BinaryWriter(new MemoryStream());
485                         bw.Write(byteVal);
486                         MemoryStream str = (MemoryStream)bw.BaseStream;
487                         valIx = md.AddToBlobHeap(str.ToArray());
488                 }
489
490                 internal sealed override uint Size(MetaData md) 
491                 {
492                         return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
493                 }
494
495                 internal sealed override void Write(FileImage output) 
496                 {
497                         output.WriteCodedIndex(CIx.HasCustomAttr,parent);
498                         output.WriteCodedIndex(CIx.CustomAttributeType,type);
499                         output.BlobIndex(valIx);
500                 }
501
502         }
503
504         /**************************************************************************/  
505         /// <summary>
506         /// Descriptor for security permissions for a class or a method
507         /// </summary>
508
509         public abstract class BaseDeclSecurity : MetaDataElement {
510
511                 ushort action;
512                 MetaDataElement parent;
513                 uint permissionIx;
514
515                 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
516                 {
517                         parent = paren;
518                         action = act;
519                         tabIx = MDTable.DeclSecurity;
520                 }
521
522                 internal override uint SortKey() 
523                 {
524                         return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
525                                 | parent.GetCodedIx(CIx.HasDeclSecurity);
526                 }
527
528                 internal sealed override uint Size(MetaData md) 
529                 {
530                         return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
531                 }
532
533                 internal sealed override void BuildTables(MetaData md) 
534                 {
535                         if (done) return;
536
537                         BinaryWriter bw = new BinaryWriter (new MemoryStream ());
538                         md.AddToTable (MDTable.DeclSecurity, this);
539                         MemoryStream str = (MemoryStream)bw.BaseStream;
540                         WriteSig (bw);
541                         permissionIx = md.AddToBlobHeap(str.ToArray());
542
543                         done = true;
544                 }
545
546                 internal abstract void WriteSig (BinaryWriter bw);
547
548                 internal sealed override void Write(FileImage output) 
549                 {
550                         output.Write(action);
551                         output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
552                         output.BlobIndex(permissionIx);
553                 }
554
555         }
556
557         public class DeclSecurity : BaseDeclSecurity {
558
559                 byte [] byteVal;
560
561                 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)        
562                         : base (paren, act)
563                 {
564                         byteVal = val;
565                 }
566
567                 internal override void WriteSig (BinaryWriter bw)
568                 {
569                         bw.Write (byteVal);
570                 }
571
572         }
573
574         public class DeclSecurity_20 : BaseDeclSecurity {
575
576                 PermissionSet ps;
577
578                 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
579                         : base (paren, act)
580                 {
581                         this.ps = ps;
582                 }
583
584                 internal override void WriteSig (BinaryWriter bw)
585                 {
586                         ps.Write (bw);
587                 }
588         }
589
590         public class PermissionMember {
591
592                 MemberTypes member_type;
593                 PEAPI.Type type;
594                 string name;
595                 object value;
596
597                 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
598                 {
599                         this.member_type = member_type;
600                         this.type = type;
601                         this.name = name;
602                         this.value = value;
603                 }
604
605                 public void Write (BinaryWriter bw)
606                 {
607                         byte [] b;
608
609                         if (member_type == MemberTypes.Field)
610                                 bw.Write ((byte) 0x53);
611                         else
612                                 //Property
613                                 bw.Write ((byte) 0x54);
614
615                         if (type is PrimitiveType) {
616                                 bw.Write (type.GetTypeIndex ());
617                         } else {
618                                 //must be enum
619                                 bw.Write ((byte) 0x55); //ENUM
620
621                                 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
622                                 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
623                                 bw.Write (b);
624                         }
625                         
626                         b = Encoding.UTF8.GetBytes (name);
627                         MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
628                         bw.Write (b);
629
630                         ((Constant) value).Write (bw);
631                 }
632
633         }
634
635         public class Permission
636         {
637                 PEAPI.Type type;
638
639                 //PermissionMembers
640                 ArrayList members;
641                 string name;
642
643                 public Permission (PEAPI.Type type, string name)
644                 {
645                         this.type = type;
646                         this.name = name;
647                 }
648
649                 public void AddMember (PEAPI.PermissionMember member)
650                 {
651                         if (members == null)
652                                 members = new ArrayList ();
653
654                         members.Add (member);
655                 }
656
657                 public void Write (BinaryWriter bw)
658                 {
659                         byte [] b = Encoding.UTF8.GetBytes (name);
660                         MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
661                         bw.Write (b);
662
663                         BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
664                         MemoryStream str = (MemoryStream) perm_writer.BaseStream;
665
666                         MetaData.CompressNum ((uint) members.Count, str);//number of params
667                         foreach (PermissionMember member in members)
668                                 member.Write (perm_writer);
669
670                         bw.Write ((byte) str.Length); //(optional) parameters length
671                         bw.Write (str.ToArray ());
672                 }
673         }
674
675         public class PermissionSet 
676         {
677                 PEAPI.SecurityAction sec_action;
678                 ArrayList permissions;
679
680                 public PermissionSet (PEAPI.SecurityAction sec_action)
681                 {
682                         this.sec_action = sec_action;
683                 }
684
685                 public void AddPermission (PEAPI.Permission perm)
686                 {
687                         if (permissions == null)
688                                 permissions = new ArrayList ();
689
690                         permissions.Add (perm);
691                 }
692
693                 public void Write (BinaryWriter bw)
694                 {
695                         bw.Write ((byte) 0x2e);
696                         MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
697
698                         foreach (Permission perm in permissions)
699                                 perm.Write (bw);
700                 }
701
702         }
703
704         /**************************************************************************/  
705         /// <summary>
706         /// Descriptor for layout information for a field
707         /// </summary>
708
709         public class FieldLayout : MetaDataElement {
710
711                 Field field;
712                 uint offset;
713
714                 internal FieldLayout(Field field, uint offset)      
715                 {
716                         this.field = field;
717                         this.offset = offset;
718                         tabIx = MDTable.FieldLayout;
719                 }
720
721                 internal sealed override uint Size(MetaData md) 
722                 {
723                         return 4 + md.TableIndexSize(MDTable.Field);
724                 }
725
726                 internal sealed override void Write(FileImage output) 
727                 {
728                         output.Write(offset);
729                         output.WriteIndex(MDTable.Field,field.Row);
730                 }
731
732         }
733
734         /*****************************************************************************/  
735         /// <summary>
736         /// Marshalling information for a field or param
737         /// </summary>
738         public class FieldMarshal : MetaDataElement {
739
740                 MetaDataElement field;
741                 NativeType nt;
742                 uint ntIx;
743
744                 internal FieldMarshal(MetaDataElement field, NativeType nType)      
745                 {
746                         this.field = field;
747                         this.nt = nType;
748                         tabIx = MDTable.FieldMarshal;
749                 }
750
751                 internal override uint SortKey() 
752                 {
753                         return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
754                                 | field.GetCodedIx(CIx.HasFieldMarshal);
755                 }
756
757                 internal sealed override void BuildTables(MetaData md) 
758                 {
759                         if (done) return;
760                         ntIx = md.AddToBlobHeap(nt.ToBlob());
761                         done = true;
762                 }
763
764                 internal sealed override uint Size(MetaData md) 
765                 {
766                         return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
767                 }
768
769                 internal sealed override void Write(FileImage output) 
770                 {
771                         output.WriteCodedIndex(CIx.HasFieldMarshal,field);
772                         output.BlobIndex(ntIx);
773                 }
774
775         }
776
777         /**************************************************************************/  
778         /// <summary>
779         /// Descriptor for the address of a field's value in the PE file
780         /// </summary>
781         public class FieldRVA : MetaDataElement {
782
783                 Field field;
784                 DataConstant data;
785
786                 internal FieldRVA(Field field, DataConstant data)   
787                 {
788                         this.field = field;
789                         this.data = data;
790                         tabIx = MDTable.FieldRVA;
791                 }
792
793                 internal sealed override void BuildTables(MetaData md) 
794                 {
795                         if (done) return;
796                         md.AddData(data);
797                         done = true;
798                 }
799
800                 internal sealed override uint Size(MetaData md) 
801                 {
802                         return 4 + md.TableIndexSize(MDTable.Field);
803                 }
804
805                 internal sealed override void Write(FileImage output) 
806                 {
807                         output.WriteDataRVA(data.DataOffset);
808                         output.WriteIndex(MDTable.Field,field.Row);
809                 }
810
811         }
812
813         /**************************************************************************/  
814         /// <summary>
815         /// Descriptor for a file referenced in THIS assembly/module (.file)
816         /// </summary>
817         public class FileRef : MetaDataElement {
818
819                 private static readonly uint NoMetaData = 0x1;
820                 uint nameIx = 0, hashIx = 0;
821                 uint flags = 0;
822                 protected string name;
823
824                 internal FileRef(string name, byte[] hashBytes, bool metaData,
825                                 bool entryPoint, MetaData md) {
826                         if (!metaData) flags = NoMetaData;
827                         if (entryPoint) md.SetEntryPoint(this);
828                         this.name = name;
829                         nameIx = md.AddToStringsHeap(name);
830                         hashIx = md.AddToBlobHeap(hashBytes);
831                         tabIx = MDTable.File;
832                 }
833
834                 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
835                                 bool entryPoint, MetaData md) {
836                         if (!metaData) flags = NoMetaData;
837                         if (entryPoint) md.SetEntryPoint(this);
838                         this.nameIx = nameIx;
839                         hashIx = md.AddToBlobHeap(hashBytes);
840                         tabIx = MDTable.File;
841                 }
842
843                 internal sealed override uint Size(MetaData md) 
844                 {
845                         return 4 + md.StringsIndexSize() + md.BlobIndexSize();
846                 }
847
848                 internal sealed override void BuildTables(MetaData md) 
849                 {
850                         md.AddToTable(MDTable.File,this);
851                 }
852
853                 internal sealed override void Write(FileImage output) 
854                 {
855                         output.Write(flags);
856                         output.StringsIndex(nameIx);
857                         output.BlobIndex(hashIx);
858                 }
859
860                 internal sealed override uint GetCodedIx(CIx code) 
861                 {
862                         switch (code) {
863                                 case (CIx.HasCustomAttr) : return 16; 
864                                 case (CIx.Implementation) : return 0;
865                         }
866                         return 0;
867                 }
868
869         }
870         /**************************************************************************/  
871         /// <summary>
872         /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
873         /// </summary>
874         public class ImplMap : MetaDataElement {
875
876                 private static readonly ushort NoMangle = 0x01;
877                 ushort flags;
878                 Method meth;
879                 string importName;
880                 uint iNameIx;
881                 ModuleRef importScope;
882
883                 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) 
884                 {
885                         flags = flag;
886                         meth = implMeth;
887                         importName = iName;
888                         importScope = mScope;
889                         tabIx = MDTable.ImplMap;
890                         if (iName == null) flags |= NoMangle;
891                         //throw(new NotYetImplementedException("PInvoke "));
892                 }
893
894                 internal override uint SortKey() 
895                 {
896                         return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded]) 
897                                 | meth.GetCodedIx(CIx.MemberForwarded);
898                 }
899
900                 internal sealed override void BuildTables(MetaData md) 
901                 {
902                         if (done) return;
903                         iNameIx = md.AddToStringsHeap(importName);
904                         done = true;
905                 }
906
907                 internal sealed override uint Size(MetaData md) 
908                 {
909                         return 2+ md.CodedIndexSize(CIx.MemberForwarded) + 
910                                 md.StringsIndexSize() +  md.TableIndexSize(MDTable.ModuleRef);
911                 }
912
913                 internal sealed override void Write(FileImage output) 
914                 {
915                         output.Write(flags);
916                         output.WriteCodedIndex(CIx.MemberForwarded,meth);
917                         output.StringsIndex(iNameIx);
918                         output.WriteIndex(MDTable.ModuleRef,importScope.Row);
919                 }
920
921         }
922
923         /**************************************************************************/  
924
925         public class GenericParameter : MetaDataElement {
926
927                 MetaDataElement owner;
928                 MetaData metadata;
929                 public string name;
930                 uint nameIx;
931                 short index;
932                 GenericParamAttributes attr;
933
934                 internal GenericParameter (ClassDef owner, MetaData metadata,
935                                 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
936                 {
937                 }
938
939                 internal GenericParameter (MethodDef owner, MetaData metadata,
940                                 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
941                 {
942                 }
943
944                 private GenericParameter (MetaDataElement owner, MetaData metadata,
945                                 short index, string name, GenericParamAttributes attr, bool nadda) {
946                         this.owner = owner;
947                         this.metadata = metadata;
948                         this.index = index;
949                         tabIx = MDTable.GenericParam;
950                         this.name = name;
951                         this.attr = attr;
952                 }
953
954                 internal override uint SortKey() 
955                 {
956                         return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
957                                 | owner.GetCodedIx(CIx.TypeOrMethodDef);
958                 }
959
960                 internal override uint SortKey2 ()
961                 {
962                         return (uint) index;
963                 }
964
965                 public void AddConstraint  (Type constraint) 
966                 {
967                         metadata.AddToTable (MDTable.GenericParamConstraint,
968                                         new GenericParamConstraint (this, constraint));
969                 }
970
971                 internal sealed override uint Size(MetaData md) 
972                 {
973                         return (uint) (4 +
974                                         md.CodedIndexSize(CIx.TypeOrMethodDef) + 
975                                         md.StringsIndexSize ());
976                 }
977
978                 internal sealed override void BuildTables(MetaData md) 
979                 {
980                         if (done) return;
981                         nameIx = md.AddToStringsHeap(name);
982                         done = true;
983                 }
984
985                 internal sealed override void Write(FileImage output) 
986                 {
987                         output.Write ((short) index);
988                         output.Write ((short) attr);
989                         output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
990                         output.StringsIndex (nameIx);
991                 }
992
993                 internal sealed override uint GetCodedIx(CIx code) 
994                 {
995                         switch (code) {
996                                 case (CIx.HasCustomAttr) : return 19; 
997                         }
998                         return 0;
999                 }
1000
1001         }
1002
1003         internal class GenericParamConstraint : MetaDataElement {
1004
1005                 GenericParameter param;
1006                 Type type;
1007
1008                 public GenericParamConstraint (GenericParameter param, Type type) 
1009                 {
1010                         this.param = param;
1011                         this.type = type;
1012                         tabIx = MDTable.GenericParamConstraint;
1013                 }
1014
1015                 internal override uint SortKey() 
1016                 {
1017                         return param.Row;
1018                 }
1019
1020                 internal sealed override uint Size(MetaData md) 
1021                 {
1022                         return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1023                                         md.CodedIndexSize(CIx.TypeDefOrRef));
1024                 }
1025
1026                 internal sealed override void Write(FileImage output) 
1027                 {
1028                         output.WriteIndex(MDTable.GenericParam, param.Row);
1029                         output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1030                 }
1031
1032         }
1033
1034         internal class MethodSpec : Method {
1035
1036                 Method meth;
1037                 GenericMethodSig g_sig;
1038                 uint sidx;
1039
1040                 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1041                 {
1042                         this.meth = meth;
1043                         this.g_sig = g_sig;
1044                         tabIx = MDTable.MethodSpec;
1045                 }
1046
1047                 internal override uint GetSigIx (MetaData md)
1048                 {
1049                         throw new Exception ("Should not be used.");
1050                 }
1051
1052                 public override void AddCallConv (CallConv cconv)
1053                 {
1054                         throw new Exception ("Should not be used.");
1055                 }
1056                 
1057                 internal sealed override void BuildTables (MetaData md) 
1058                 {
1059                         if (done) return;
1060                         sidx = g_sig.GetSigIx (md);
1061                         done = true;
1062                 }
1063
1064                 internal sealed override uint Size (MetaData md) 
1065                 {
1066                         return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1067                                         md.BlobIndexSize ());
1068                 }
1069
1070                 internal sealed override void Write (FileImage output) 
1071                 {
1072                         output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1073                         output.BlobIndex (sidx);
1074                 }
1075
1076                 internal sealed override void TypeSig (MemoryStream sig)
1077                 {
1078                         throw new Exception ("Should not be used.");
1079                 }
1080         }
1081
1082         /**************************************************************************/
1083         /// <summary>
1084         /// Descriptor for interface implemented by a class
1085         /// </summary>
1086         public class InterfaceImpl: MetaDataElement {
1087
1088                 ClassDef theClass;
1089                 Class theInterface;
1090
1091                 internal InterfaceImpl(ClassDef theClass, Class theInterface) 
1092                 {
1093                         this.theClass = theClass;
1094                         this.theInterface = theInterface;
1095                         tabIx = MDTable.InterfaceImpl;
1096                 }
1097
1098                 internal sealed override uint Size(MetaData md) 
1099                 {
1100                         return md.TableIndexSize(MDTable.TypeDef) + 
1101                                 md.CodedIndexSize(CIx.TypeDefOrRef);
1102                 }
1103
1104                 internal sealed override void Write(FileImage output) 
1105                 {
1106                         output.WriteIndex(MDTable.TypeDef,theClass.Row);
1107                         output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1108                 }
1109
1110                 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1111
1112                 internal override uint SortKey ()
1113                 {
1114                         return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1115                                 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1116                 }
1117
1118         }
1119
1120         /**************************************************************************/  
1121         /// <summary>
1122         /// Descriptor for resources used in this PE file 
1123         /// </summary>
1124
1125         public class ManifestResource : MetaDataElement {
1126
1127                 public static readonly uint PublicResource = 0x1;
1128                 public static readonly uint PrivateResource = 0x2;
1129
1130                 string mrName;
1131                 MetaDataElement rRef;
1132                 uint fileOffset;
1133                 uint nameIx = 0;
1134                 uint flags = 0;
1135                 byte [] resourceBytes;
1136
1137                 public ManifestResource (string name, byte[] resBytes, uint flags) 
1138                 {
1139                         InitResource (name, flags);
1140                         this.resourceBytes = resBytes;
1141                 }
1142
1143                 public ManifestResource(string name, uint flags, FileRef fileRef) 
1144                 {
1145                         InitResource (name, flags);
1146                         rRef = fileRef;
1147                 }
1148
1149                 public ManifestResource(string name, uint flags, FileRef fileRef, 
1150                                 uint fileIx) {
1151                         InitResource (name, flags);
1152                         rRef = fileRef;
1153                         fileOffset = fileIx;
1154                 }
1155
1156                 public ManifestResource(string name, uint flags, AssemblyRef assemRef) 
1157                 {
1158                         InitResource (name, flags);
1159                         rRef = assemRef;
1160                 }
1161
1162                 internal ManifestResource (ManifestResource mres) 
1163                 {
1164                         mrName = mres.mrName;
1165                         flags = mres.flags;
1166                         rRef = mres.rRef;
1167                         fileOffset = mres.fileOffset;
1168                         resourceBytes = mres.resourceBytes;
1169                 }
1170
1171                 private void InitResource (string name, uint flags) 
1172                 {
1173                         mrName = name;
1174                         this.flags = flags;
1175                         tabIx = MDTable.ManifestResource;
1176                 }
1177
1178                 internal sealed override void BuildTables(MetaData md) 
1179                 {
1180                         if (done) return;
1181                         md.AddToTable (MDTable.ManifestResource, this);
1182                         nameIx = md.AddToStringsHeap(mrName);
1183                         if (resourceBytes != null) {
1184                                 if (rRef != null)
1185                                         throw new PEFileException ("Manifest Resource has byte value and file reference");
1186                                 fileOffset = md.AddResource(resourceBytes);
1187                         } else {
1188                                 if (rRef == null)
1189                                         throw new PEFileException ("Manifest Resource has no implementation or value");
1190                                 rRef.BuildTables (md);
1191                         }
1192
1193                         done = true;
1194                 }
1195
1196                 internal sealed override uint Size(MetaData md) 
1197                 {
1198                         return 8 + md.StringsIndexSize() + 
1199                                 md.CodedIndexSize(CIx.Implementation);
1200                 }
1201
1202                 internal sealed override void Write(FileImage output) 
1203                 {
1204                         output.Write(fileOffset);
1205                         output.Write(flags);
1206                         output.StringsIndex(nameIx);
1207                         output.WriteCodedIndex(CIx.Implementation,rRef);
1208                 }
1209
1210                 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1211
1212                 public string Name {
1213                         get { return mrName; }
1214                         set { mrName = value; }
1215                 }
1216
1217         }
1218         /**************************************************************************/  
1219         /// <summary>
1220         /// Base class for elements in the PropertyMap, EventMap and 
1221         /// NestedClass MetaData tables
1222         /// </summary>
1223         public class MapElem : MetaDataElement {
1224
1225                 ClassDef parent;
1226                 uint elemIx;
1227                 MDTable elemTable;
1228
1229                 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) 
1230                 {
1231                         parent = par;
1232                         elemIx = elIx;
1233                         elemTable = elemTab;
1234                 }
1235
1236                 internal sealed override uint Size(MetaData md) 
1237                 {
1238                         return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1239                 }
1240
1241                 internal sealed override void Write(FileImage output) 
1242                 {
1243                         output.WriteIndex(MDTable.TypeDef,parent.Row);
1244                         output.WriteIndex(elemTable,elemIx);
1245                 }
1246         }
1247
1248         /**************************************************************************/  
1249         /// <summary>
1250         /// Descriptor for an overriding method (.override)
1251         /// </summary>
1252         public class MethodImpl : MetaDataElement {
1253
1254                 ClassDef parent;
1255                 Method header, body;
1256
1257                 internal MethodImpl(ClassDef par, Method decl, Method bod)      
1258                 {
1259                         parent = par;
1260                         header = decl;
1261                         body = bod;
1262                         tabIx = MDTable.MethodImpl;
1263                 }
1264
1265                 internal sealed override uint Size(MetaData md) 
1266                 {
1267                         return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1268                 }
1269
1270                 internal sealed override void Write(FileImage output) 
1271                 {
1272                         output.WriteIndex(MDTable.TypeDef,parent.Row);
1273                         output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1274                         output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1275                 }
1276
1277         }
1278
1279         /**************************************************************************/  
1280         /// <summary>
1281         /// Descriptor for Property and Event methods
1282         /// </summary>
1283         public class MethodSemantics : MetaDataElement {
1284
1285                 Feature.MethodType type;
1286                 MethodDef meth;
1287                 Feature eventOrProp;
1288
1289                 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) 
1290                 {
1291                         type = mType;
1292                         meth = method;
1293                         eventOrProp = feature;
1294                         tabIx = MDTable.MethodSemantics;
1295                 }
1296
1297                 internal override uint SortKey() 
1298                 {
1299                         return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1300                                 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1301                 }
1302
1303                 internal sealed override uint Size(MetaData md) 
1304                 {
1305                         return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1306                 }
1307
1308                 internal sealed override void Write(FileImage output) 
1309                 {
1310                         output.Write((ushort)type);
1311                         output.WriteIndex(MDTable.Method,meth.Row);
1312                         output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1313                 }
1314
1315         }
1316
1317         /**************************************************************************/  
1318         /// <summary>
1319         /// Descriptor for a parameter of a method defined in this assembly/module
1320         /// </summary>
1321         public class Param : MetaDataElement {
1322
1323
1324                 Type pType;
1325                 string pName;
1326                 internal ushort seqNo = 0;
1327                 ushort parMode;
1328                 ConstantElem defaultVal;
1329                 uint nameIx = 0;
1330                 FieldMarshal marshalInfo;
1331
1332                 /// <summary>
1333                 /// Create a new parameter for a method
1334                 /// </summary>
1335                 /// <param name="mode">param mode (in, out, opt)</param>
1336                 /// <param name="parName">parameter name</param>
1337                 /// <param name="parType">parameter type</param>
1338                 public Param(ParamAttr mode, string parName, Type parType) 
1339                 {
1340                         pName = parName;
1341                         pType = parType;
1342                         parMode = (ushort)mode;
1343                         tabIx = MDTable.Param;
1344                 }
1345
1346                 public bool HasMarshalInfo {
1347                         get { return marshalInfo != null; }
1348                 }
1349
1350                 /// <summary>
1351                 /// Add a default value to this parameter
1352                 /// </summary>
1353                 /// <param name="c">the default value for the parameter</param>
1354                 public void AddDefaultValue(Constant cVal) 
1355                 {
1356                         defaultVal = new ConstantElem(this,cVal);
1357                         parMode |= (ushort) ParamAttr.HasDefault;
1358                 }
1359
1360                 /// <summary>
1361                 /// Add marshalling information about this parameter
1362                 /// </summary>
1363                 public void AddMarshallInfo(NativeType marshallType) 
1364                 {
1365                         parMode |= (ushort) ParamAttr.HasFieldMarshal;
1366                         marshalInfo = new FieldMarshal(this,marshallType);
1367                 }
1368
1369                 internal Type GetParType() { return pType; }
1370
1371                 internal sealed override void BuildTables(MetaData md) 
1372                 {
1373                         if (done) return;
1374                         nameIx = md.AddToStringsHeap(pName);
1375                         if (defaultVal != null) {
1376                                 md.AddToTable(MDTable.Constant,defaultVal);
1377                                 defaultVal.BuildTables(md);
1378                         }
1379                         if (marshalInfo != null) {
1380                                 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1381                                 marshalInfo.BuildTables(md);
1382                         }
1383                         done = true;
1384                 }
1385
1386                 internal void TypeSig(MemoryStream str) 
1387                 {
1388                         pType.TypeSig(str);
1389                 }
1390
1391                 internal sealed override uint Size(MetaData md) 
1392                 {
1393                         return 4 + md.StringsIndexSize();
1394                 }
1395
1396                 internal sealed override void Write(FileImage output) 
1397                 {
1398                         output.Write(parMode);
1399                         output.Write(seqNo);
1400                         output.StringsIndex(nameIx);
1401                 }
1402
1403                 internal sealed override uint GetCodedIx(CIx code) 
1404                 {
1405                         switch (code) {
1406                                 case (CIx.HasCustomAttr) : return 4; 
1407                                 case (CIx.HasConst) : return 1; 
1408                                 case (CIx.HasFieldMarshal) : return 1; 
1409                         }
1410                         return 0;
1411                 }
1412
1413         }
1414
1415         /**************************************************************************/  
1416         public abstract class Signature : MetaDataElement  {
1417
1418                 protected uint sigIx;
1419
1420                 internal Signature() 
1421                 {
1422                         tabIx = MDTable.StandAloneSig;
1423                 }
1424
1425                 internal sealed override uint Size(MetaData md) 
1426                 {
1427                         return md.BlobIndexSize();
1428                 }
1429
1430                 internal sealed override void Write(FileImage output) 
1431                 {
1432                         output.BlobIndex(sigIx);
1433                 }
1434
1435                 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1436
1437         }
1438
1439         /**************************************************************************/  
1440         public class TypeSpec : MetaDataElement {
1441                 uint sigIx = 0;
1442
1443                 internal TypeSpec(Type aType, MetaData md) 
1444                 {
1445                         MemoryStream sig = new MemoryStream();
1446                         aType.TypeSig(sig);
1447                         sigIx = md.AddToBlobHeap(sig.ToArray());
1448                         tabIx = MDTable.TypeSpec;
1449                 }
1450
1451                 internal sealed override uint GetCodedIx(CIx code) 
1452                 {
1453                         switch (code) {
1454                                 case (CIx.TypeDefOrRef) : return 2; 
1455                                 case (CIx.HasCustomAttr) : return 13; 
1456                                 case (CIx.MemberRefParent) : return 4; 
1457                         }
1458                         return 0;
1459                 }
1460
1461                 internal override uint Size(MetaData md) 
1462                 {
1463                         return md.BlobIndexSize();
1464                 }
1465
1466                 internal sealed override void Write(FileImage output) 
1467                 {
1468                         //Console.WriteLine("Writing the blob index for a TypeSpec");
1469                         output.BlobIndex(sigIx);
1470                 }
1471         }
1472
1473
1474         /**************************************************************************/  
1475         /// <summary>
1476         /// Base class for all IL types
1477         /// </summary>
1478         public abstract class Type : MetaDataElement {
1479                 protected byte typeIndex;
1480                 protected TypeSpec typeSpec;
1481
1482                 internal Type(byte tyIx) { typeIndex = tyIx; }
1483
1484                 internal byte GetTypeIndex() { return typeIndex; }
1485                 internal void SetTypeIndex (byte b) { typeIndex = b; }
1486
1487                 internal virtual MetaDataElement GetTypeSpec(MetaData md) 
1488                 {
1489                         if (typeSpec == null) {
1490                                 typeSpec = new TypeSpec(this,md);
1491                                 md.AddToTable(MDTable.TypeSpec,typeSpec);
1492                         }
1493                         return typeSpec;
1494                 }
1495
1496                 internal virtual void TypeSig(MemoryStream str) 
1497                 {
1498                         throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1499                                                 " doesn't have a type signature!!"));   
1500                 }
1501         }
1502
1503         public class ClassRefInst : Type {
1504
1505                 private Type type;
1506                 private bool is_value;
1507
1508                 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ()) 
1509                 {
1510                         this.type = type;
1511                         this.is_value = is_value;
1512                         if (is_value)
1513                                 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1514                         tabIx = MDTable.TypeSpec;
1515                 }
1516
1517                 internal sealed override void TypeSig(MemoryStream str) 
1518                 {
1519                         type.TypeSig (str);
1520                 }
1521         }
1522
1523         /**************************************************************************/  
1524         /// <summary>
1525         /// The base descriptor for a class 
1526         /// </summary>
1527         public abstract class Class : Type {
1528
1529                 protected int row = 0;
1530                 public string name, nameSpace;
1531                 protected uint nameIx, nameSpaceIx;
1532                 protected MetaData _metaData;
1533                 internal Class(string nameSpaceName, string className, MetaData md)
1534                         : base(PrimitiveType.Class.GetTypeIndex ()) 
1535                 {
1536                                 nameSpace = nameSpaceName;
1537                                 name = className;
1538                                 nameIx = md.AddToStringsHeap(name);
1539                                 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1540                                 _metaData = md;
1541                 }
1542
1543                 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ()) 
1544                 {
1545                         nameSpaceIx = nsIx;
1546                         nameIx = nIx;
1547                 }
1548
1549                 internal Class (byte typeIndex) : base (typeIndex)
1550                 {
1551                         nameSpace = "Should not be used";
1552                         name = "Should not be used";
1553                 }
1554
1555                 internal virtual uint TypeDefOrRefToken() { return 0; }
1556
1557                 internal virtual void MakeValueClass(ValueClass vClass) 
1558                 {
1559                         typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1560                 }
1561
1562                 internal virtual string TypeName() 
1563                 {
1564                         return (nameSpace + "." + name);
1565                 }
1566
1567                 internal override MetaDataElement GetTypeSpec(MetaData md) 
1568                 {
1569                         return this;
1570                 }
1571         }
1572
1573         /**************************************************************************/  
1574         // This Class produces entries in the TypeDef table of the MetaData 
1575         // in the PE meta data.
1576
1577         // NOTE:  Entry 0 in TypeDef table is always the pseudo class <module> 
1578         // which is the parent for functions and variables declared a module level
1579
1580         /// <summary>
1581         /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1582         /// </summary>
1583         /// 
1584         public class ClassDef : Class {
1585
1586                 Class superType;
1587                 ArrayList fields = new ArrayList();
1588                 ArrayList methods = new ArrayList();
1589                 ArrayList events;
1590                 ArrayList properties;
1591                 bool typeIndexChecked = true;
1592                 uint fieldIx = 0, methodIx = 0;
1593                 uint flags;
1594                 ClassLayout layout;
1595                 ClassDef parentClass;
1596                 MetaData metaData;
1597
1598                 internal ClassDef(TypeAttr attrSet, string nsName, string name, 
1599                                 MetaData md) : base(nsName, name, md) 
1600                 {
1601                         metaData = md;
1602                         if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1603                                 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1604                         }
1605                         flags = (uint)attrSet;
1606                         tabIx = MDTable.TypeDef;
1607                 }
1608
1609                 internal void SetSuper(Class sClass) 
1610                 {
1611                         superType = sClass;
1612                         if (! (sClass is GenericTypeInst))
1613                                 typeIndexChecked = false;
1614                 }
1615
1616                 internal override void MakeValueClass(ValueClass vClass) 
1617                 {
1618                         if (vClass == ValueClass.Enum)  
1619                                 superType = metaData.mscorlib.EnumType();
1620                         else  
1621                                 superType = metaData.mscorlib.ValueType();
1622
1623                         typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1624                 }
1625
1626                 public void SpecialNoSuper() 
1627                 {
1628                         superType = null;
1629                 }
1630
1631                 /// <summary>
1632                 /// Add an attribute to this class
1633                 /// </summary>
1634                 /// <param name="ta">the attribute to be added</param>
1635                 public void AddAttribute(TypeAttr ta) 
1636                 {
1637                         flags |= (uint)ta;
1638                 }
1639
1640                 /// <summary>
1641                 /// Add an interface that is implemented by this class
1642                 /// </summary>
1643                 /// <param name="iFace">the interface that is implemented</param>
1644                 public void AddImplementedInterface(Class iFace) 
1645                 {
1646                         metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1647                 }
1648
1649                 /// <summary>
1650                 ///  Add a named generic type parameter
1651                 /// </summary>
1652                 public GenericParameter AddGenericParameter (short index, string name) 
1653                 {
1654                         return AddGenericParameter (index, name, 0);
1655                 }
1656
1657                 /// <summary>
1658                 ///  Add a named generic type parameter with attributes
1659                 /// </summary>
1660                 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1661                 {
1662                         GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1663                         metaData.AddToTable (MDTable.GenericParam, gp);
1664                         return gp;
1665                 }
1666
1667                 /// <summary>
1668                 /// Add a field to this class
1669                 /// </summary>
1670                 /// <param name="name">field name</param>
1671                 /// <param name="fType">field type</param>
1672                 /// <returns>a descriptor for this new field</returns>
1673                 public FieldDef AddField(string name, Type fType) 
1674                 {
1675                         FieldDef field = new FieldDef(name,fType);
1676                         fields.Add(field);
1677                         return field;
1678                 }
1679
1680                 /// <summary>
1681                 /// Add a field to this class
1682                 /// </summary>
1683                 /// <param name="fAtts">attributes for this field</param>
1684                 /// <param name="name">field name</param>
1685                 /// <param name="fType">field type</param>
1686                 /// <returns>a descriptor for this new field</returns>
1687                 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) 
1688                 {
1689                         FieldDef field = new FieldDef(fAtts,name,fType);
1690                         fields.Add(field);
1691                         return field;
1692                 }
1693
1694                 public void SetFieldOrder (ArrayList fields)
1695                 {
1696                         this.fields = fields;
1697                 }
1698
1699                 /// <summary>
1700                 /// Add a method to this class
1701                 /// </summary>
1702                 /// <param name="name">method name</param>
1703                 /// <param name="retType">return type</param>
1704                 /// <param name="pars">parameters</param>
1705                 /// <returns>a descriptor for this new method</returns>
1706                 public MethodDef AddMethod(string name, Type retType, Param[] pars) 
1707                 {
1708                         return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1709                 }
1710
1711                 public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 
1712                 {
1713                         // Console.WriteLine("Adding method " + name + " to class " + this.name);
1714                         MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1715                         methods.Add(meth);
1716                         return meth;
1717                 }
1718
1719                 /// <summary>
1720                 /// Add a method to this class
1721                 /// </summary>
1722                 /// <param name="mAtts">attributes for this method</param>
1723                 /// <param name="iAtts">implementation attributes for this method</param>
1724                 /// <param name="name">method name</param>
1725                 /// <param name="retType">return type</param>
1726                 /// <param name="pars">parameters</param>
1727                 /// <returns>a descriptor for this new method</returns>
1728                 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, 
1729                                 Param ret_param, Param [] pars) {
1730                         // Console.WriteLine("Adding method " + name + " to class " + this.name);
1731                         MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1732                         methods.Add(meth);
1733                         return meth;
1734                 }
1735
1736                 /// <summary>
1737                 /// Add an event to this class
1738                 /// </summary>
1739                 /// <param name="name">event name</param>
1740                 /// <param name="eType">event type</param>
1741                 /// <returns>a descriptor for this new event</returns>
1742                 public Event AddEvent(string name, Type eType) 
1743                 {
1744                         Event e = new Event(name,eType,this);
1745                         if (events == null) events = new ArrayList();
1746                         events.Add(e);
1747                         return e;
1748                 }
1749
1750                 /// <summary>
1751                 /// Add a property to this class
1752                 /// </summary>
1753                 /// <param name="name">property name</param>
1754                 /// <param name="propType">property type</param>
1755                 /// <returns>a descriptor for this new property</returns>
1756                 public Property AddProperty(string name, Type retType, Type[] pars) 
1757                 {
1758                         Property p = new Property(name, retType, pars, this);
1759                         if (properties == null) properties = new ArrayList();
1760                         properties.Add(p);
1761                         return p;
1762                 }
1763
1764                 /// <summary>
1765                 /// Add a nested class to this class
1766                 /// </summary>
1767                 /// <param name="attrSet">attributes for this nested class</param>
1768                 /// <param name="nsName">nested name space name</param>
1769                 /// <param name="name">nested class name</param>
1770                 /// <returns>a descriptor for this new nested class</returns>
1771                 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1772                                 string name) {
1773                         ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1774                         metaData.AddToTable(MDTable.TypeDef,nClass);
1775                         metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1776                         nClass.parentClass = this;
1777                         return (nClass);
1778                 }
1779
1780                 public static bool IsValueType (Class type)
1781                 {
1782                         return IsValueType (type.nameSpace, type.name);
1783                 }
1784
1785                 public static bool IsEnum (Class type)
1786                 {
1787                         return IsEnum (type.nameSpace, type.name);
1788                 }
1789
1790                 public static bool IsValueType (string nsName, string name)
1791                 {
1792                         return (nsName == "System" && name == "ValueType");
1793                 }
1794
1795                 public static bool IsEnum (string nsName, string name)
1796                 {
1797                         return (nsName == "System" && name == "Enum");
1798                 }
1799
1800                 /// <summary>
1801                 /// Add a nested class to this class
1802                 /// </summary>
1803                 /// <param name="attrSet">attributes for this nested class</param>
1804                 /// <param name="nsName">nested name space name</param>
1805                 /// <param name="name">nested class name</param>
1806                 /// <param name="sType">super type of this nested class</param>
1807                 /// <returns>a descriptor for this new nested class</returns>
1808                 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1809                                 string name, Class sType) {
1810                         ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1811                         nClass.SetSuper(sType);
1812                         if (ClassDef.IsValueType (sType))
1813                                 nClass.MakeValueClass (ValueClass.ValueType);
1814                         else
1815                                 if (ClassDef.IsEnum (sType))
1816                                         nClass.MakeValueClass (ValueClass.Enum);
1817
1818                         if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1819                                 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1820
1821                         nClass.typeIndexChecked = true;
1822                         return (nClass);
1823                 }
1824
1825                 /// <summary>
1826                 /// Add layout information for this class.  This class must have the
1827                 /// sequential or explicit attribute.
1828                 /// </summary>
1829                 /// <param name="packSize">packing size (.pack)</param>
1830                 /// <param name="classSize">class size (.size)</param>
1831                 public void AddLayoutInfo (int packSize, int classSize) 
1832                 {
1833                         layout = new ClassLayout(packSize,classSize,this);
1834                 }
1835
1836                 /// <summary>
1837                 /// Use a method as the implementation for another method (.override)
1838                 /// </summary>
1839                 /// <param name="decl">the method to be overridden</param>
1840                 /// <param name="body">the implementation to be used</param>
1841                 public void AddMethodOverride(Method decl, Method body) 
1842                 {
1843                         metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1844                 }
1845
1846                 /// <summary>
1847                 /// Add security to this class NOT YET IMPLEMENTED
1848                 /// </summary>
1849                 /// <param name="permissionSet"></param>
1850                 public void AddSecurity(byte[] permissionSet) 
1851                 {
1852                         throw(new NotYetImplementedException("Class security "));
1853                         //flags |= HasSecurity;
1854                         // securityActions = permissionSet;
1855                 }
1856
1857                 //public void AddLineInfo(int row, int col) { }
1858
1859                 internal void CheckTypeIndex() 
1860                 {
1861                         if (typeIndexChecked) return;
1862                         if (superType is ClassDef) 
1863                                 ((ClassDef)superType).CheckTypeIndex();
1864                         typeIndex = superType.GetTypeIndex();
1865                         typeIndexChecked = true;
1866                 }
1867
1868                 internal sealed override void BuildTables(MetaData md) 
1869                 {
1870                         if (done) return;
1871                         if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1872                         // Console.WriteLine("Building tables for " + name);
1873                         if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1874                         // Console.WriteLine("adding methods " + methods.Count);
1875                         methodIx = md.TableIndex(MDTable.Method);
1876                         for (int i=0; i < methods.Count; i++) {
1877                                 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1878                                 ((MethodDef)methods[i]).BuildTables(md);
1879                         }
1880                         // Console.WriteLine("adding fields");
1881                         fieldIx = md.TableIndex(MDTable.Field);
1882                         for (int i=0; i < fields.Count; i++) {
1883                                 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1884                                 ((FieldDef)fields[i]).BuildTables(md);
1885                         }
1886                         // Console.WriteLine("adding events and properties");
1887                         if (events != null) { 
1888                                 for (int i=0; i < events.Count; i++) {
1889                                         md.AddToTable(MDTable.Event,(Event)events[i]);
1890                                         ((Event)events[i]).BuildTables(md);
1891                                 }
1892                                 md.AddToTable(MDTable.EventMap,
1893                                                 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1894                         }
1895                         if (properties != null) { 
1896                                 for (int i=0; i < properties.Count; i++) {
1897                                         md.AddToTable(MDTable.Property,(Property)properties[i]);
1898                                         ((Property)properties[i]).BuildTables(md);
1899                                 }
1900                                 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1901                                                         ((Property)properties[0]).Row,MDTable.Property));
1902                         }
1903                         // Console.WriteLine("End of building tables");
1904                         done = true;
1905                 }
1906
1907                 internal sealed override uint Size(MetaData md) 
1908                 {
1909                         return 4 + 2 * md.StringsIndexSize() + 
1910                                 md.CodedIndexSize(CIx.TypeDefOrRef) +
1911                                 md.TableIndexSize(MDTable.Field) + 
1912                                 md.TableIndexSize(MDTable.Method);
1913                 }
1914
1915                 internal sealed override void Write(FileImage output) 
1916                 {
1917                         output.Write(flags);
1918                         output.StringsIndex(nameIx);
1919                         output.StringsIndex(nameSpaceIx);
1920                         //if (superType != null) 
1921                         // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1922                         output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1923                         output.WriteIndex(MDTable.Field,fieldIx);
1924                         output.WriteIndex(MDTable.Method,methodIx);
1925                 }
1926
1927                 internal sealed override uint TypeDefOrRefToken() 
1928                 {
1929                         uint cIx = Row;
1930                         cIx = cIx << 2;
1931                         return cIx;
1932                 }
1933
1934                 internal sealed override void TypeSig(MemoryStream sig) 
1935                 {
1936                         if (!typeIndexChecked) CheckTypeIndex();
1937                         sig.WriteByte(GetTypeIndex());
1938                         MetaData.CompressNum(TypeDefOrRefToken(),sig);
1939                 }
1940
1941                 internal sealed override uint GetCodedIx(CIx code) 
1942                 {
1943                         switch (code) {
1944                                 case (CIx.TypeDefOrRef) : return 0; 
1945                                 case (CIx.HasCustomAttr) : return 3; 
1946                                 case (CIx.HasDeclSecurity) : return 0; 
1947                                 case (CIx.TypeOrMethodDef) : return 0; 
1948                         }
1949                         return 0;
1950                 }
1951
1952         }
1953
1954         /**************************************************************************/  
1955         /// <summary>
1956         /// Descriptor for a class/interface declared in another module of THIS 
1957         /// assembly, or in another assembly.
1958         /// </summary>
1959         public class ClassRef : Class, IExternRef, IResolutionScope {
1960
1961                 protected IResolutionScope parent;
1962                 protected MetaData metaData;
1963
1964                 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) 
1965                 {
1966                         metaData = md;
1967                         tabIx = MDTable.TypeRef;
1968                 }
1969
1970                 /// <summary>
1971                 /// Add a method to this class
1972                 /// </summary>
1973                 /// <param name="name">method name</param>
1974                 /// <param name="retType">return type</param>
1975                 /// <param name="pars">parameter types</param>
1976                 /// <returns>a descriptor for this method</returns>
1977                 public MethodRef AddMethod(string name, Type retType, Type[] pars) 
1978                 {
1979                         return AddMethod (name, retType, pars, 0);
1980                 }
1981                 
1982                 /// <summary>
1983                 /// Add a method to this class
1984                 /// </summary>
1985                 /// <param name="name">method name</param>
1986                 /// <param name="retType">return type</param>
1987                 /// <param name="pars">parameter types</param>
1988                 /// <param name="gen_param_count">num of generic parameters</param>
1989                 /// <returns>a descriptor for this method</returns>
1990                 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count) 
1991                 {
1992                         MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1993                         metaData.AddToTable(MDTable.MemberRef,meth);
1994                         return meth;
1995                 }
1996
1997                 /// <summary>
1998                 /// Add a method to this class
1999                 /// </summary>
2000                 /// <param name="name">method name</param>
2001                 /// <param name="retType">return type</param>
2002                 /// <param name="pars">parameter types</param>
2003                 /// <returns>a descriptor for this method</returns>
2004                 public MethodRef AddVarArgMethod(string name, Type retType, 
2005                                 Type[] pars, Type[] optPars) 
2006                 {
2007                         MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2008                         metaData.AddToTable(MDTable.MemberRef,meth);
2009                         return meth;
2010                 }
2011
2012                 /// <summary>
2013                 /// Add a field to this class
2014                 /// </summary>
2015                 /// <param name="name">field name</param>
2016                 /// <param name="fType">field type</param>
2017                 /// <returns>a descriptor for this field</returns>
2018                 public FieldRef AddField(string name, Type fType) 
2019                 {
2020                         FieldRef field = new FieldRef(this,name,fType);
2021                         metaData.AddToTable(MDTable.MemberRef,field);
2022                         return field;
2023                 }
2024
2025                 public ClassRef AddClass (string nsName, string name)
2026                 {
2027                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2028                         metaData.AddToTable(MDTable.TypeRef,aClass);
2029                         aClass.SetParent(this);
2030                         return aClass;
2031                 }
2032
2033                 public ClassRef AddValueClass (string nsName, string name)
2034                 {
2035                         ClassRef aClass = AddClass (nsName, name);
2036                         aClass.MakeValueClass (ValueClass.ValueType);
2037                         return aClass;
2038                 }
2039
2040                 internal void SetParent(IResolutionScope par) 
2041                 {
2042                         parent = par;
2043                 }
2044
2045                 internal override string TypeName() 
2046                 {
2047                         if ((parent != null) && (parent is AssemblyRef))
2048                                 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2049                         else 
2050                                 return (nameSpace + name);
2051                 }
2052
2053                 internal sealed override uint Size(MetaData md) 
2054                 {
2055                         return md.CodedIndexSize(CIx.ResolutionScope) + 2 * 
2056                                 md.StringsIndexSize();
2057                 }
2058
2059                 internal sealed override void Write(FileImage output) 
2060                 {
2061                         output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2062                         output.StringsIndex(nameIx);
2063                         output.StringsIndex(nameSpaceIx);
2064                 }
2065
2066                 internal override sealed uint TypeDefOrRefToken() 
2067                 {
2068                         uint cIx = Row;
2069                         cIx = (cIx << 2) | 0x1;
2070                         return cIx;
2071                 }
2072
2073                 internal override void TypeSig(MemoryStream sig) 
2074                 {
2075                         sig.WriteByte(GetTypeIndex());
2076                         MetaData.CompressNum(TypeDefOrRefToken(),sig);
2077                 }
2078
2079                 internal sealed override uint GetCodedIx(CIx code) 
2080                 {
2081                         switch (code) {
2082                                 case (CIx.TypeDefOrRef) : return 1; 
2083                                 case (CIx.HasCustomAttr) : return 2; 
2084                                 case (CIx.MemberRefParent) : return 1; 
2085                                 case (CIx.ResolutionScope) : return 3; 
2086                         }
2087                         return 0;
2088                 }
2089
2090         }
2091
2092         /**************************************************************************/  
2093         public class ExternClassRef : ClassRef {
2094
2095                 ExternClass externClass;
2096
2097                 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2098                                 MetaDataElement declRef, MetaData md) : base(nsName,name,md) 
2099                 {
2100                         externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2101                         metaData.AddToTable(MDTable.ExportedType,externClass);
2102                 }
2103
2104                 internal ExternClassRef(string name, MetaData md) : base(null,name,md) 
2105                 {
2106                 }
2107
2108                 public ClassRef AddNestedClass(TypeAttr attrs, string name) 
2109                 {
2110                         ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2111                         externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2112                         metaData.AddToTable(MDTable.ExportedType,externClass);
2113                         return nestedClass;
2114                 }
2115
2116         }
2117
2118         /**************************************************************************/  
2119         /// <summary>
2120         /// Descriptor for a class defined in another module of THIS assembly 
2121         /// and exported (.class extern)
2122         /// </summary>
2123
2124         internal class ExternClass : Class {
2125
2126                 MetaDataElement parent;
2127                 uint flags;
2128
2129                 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx, 
2130                                 MetaDataElement paren) : base(nsIx,nIx) 
2131                 {
2132                         flags = (uint)attr;
2133                         parent = paren;
2134                         tabIx = MDTable.ExportedType;
2135                 }
2136
2137                 internal sealed override uint Size(MetaData md) 
2138                 {
2139                         return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2140                 }
2141
2142                 internal sealed override void Write(FileImage output) 
2143                 {
2144                         output.Write(flags);
2145                         output.Write(0);
2146                         output.StringsIndex(nameIx);
2147                         output.StringsIndex(nameSpaceIx);
2148                         output.WriteCodedIndex(CIx.Implementation,parent);
2149                 }
2150
2151                 internal sealed override uint GetCodedIx(CIx code) 
2152                 {
2153                         switch (code) {
2154                                 case (CIx.HasCustomAttr) : return 17; 
2155                                 case (CIx.Implementation) : return 2; 
2156                         }
2157                         return 0;
2158                 }
2159
2160         }
2161
2162         public class GenParam : Class {
2163
2164                 private int index;
2165                 private string param_name;
2166                 private uint sigIx = 0;
2167
2168                 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype) 
2169                 {
2170                         this.index = index;
2171                         this.param_name = name;
2172                         tabIx = MDTable.TypeSpec;
2173                 }
2174
2175                 public int Index {
2176                         get { return index; }
2177                         set { index = value; }
2178                 }
2179
2180                 public string Name {
2181                         get { return param_name; }
2182                         set { param_name = value; }
2183                 }
2184
2185                 public GenParamType Type {
2186                         get { return (GenParamType) GetTypeIndex (); }
2187                 }
2188                 
2189                 internal sealed override void BuildTables (MetaData md)
2190                 {
2191                         if (done)
2192                                 return;
2193                         MemoryStream str = new MemoryStream ();
2194                         TypeSig (str);
2195                         sigIx = md.AddToBlobHeap (str.ToArray ());
2196
2197                         done = true;
2198                 }
2199
2200                 internal sealed override void TypeSig(MemoryStream str) 
2201                 {
2202                         if (index < 0)
2203                                 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2204                         str.WriteByte(typeIndex);
2205                         MetaData.CompressNum ((uint) index, str);
2206                 }
2207                 
2208                 internal override uint Size(MetaData md) 
2209                 {
2210                         return md.BlobIndexSize();
2211                 }
2212
2213                 internal sealed override void Write (FileImage output)
2214                 {
2215                         output.BlobIndex (sigIx);       
2216                 }
2217
2218                 internal sealed override uint GetCodedIx(CIx code) 
2219                 {
2220                         switch (code) {
2221                                 case (CIx.TypeDefOrRef) : return 2; 
2222                                 case (CIx.HasCustomAttr) : return 13; 
2223                                 case (CIx.MemberRefParent) : return 4; 
2224                         }
2225                         return 0;
2226                 }
2227         }
2228
2229         public class GenericTypeInst : Class {
2230
2231                 private Type gen_type;
2232                 private Type[] gen_param;
2233                 bool inTable = false;
2234                 uint sigIx = 0;
2235
2236                 public GenericTypeInst (Type gen_type, Type[] gen_param) 
2237                         : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2238                 {
2239                         this.gen_type = gen_type;
2240                         this.gen_param = gen_param;
2241                         tabIx = MDTable.TypeSpec;
2242                 }
2243
2244                 internal override MetaDataElement GetTypeSpec (MetaData md)
2245                 {
2246                         if (!inTable) {
2247                                 md.AddToTable (MDTable.TypeSpec, this);
2248                                 inTable = true;
2249                         }
2250
2251                         return this;
2252                 }
2253
2254                 internal sealed override void TypeSig(MemoryStream str) 
2255                 {
2256                         str.WriteByte(typeIndex);
2257                         gen_type.TypeSig (str);
2258                         MetaData.CompressNum ((uint) gen_param.Length, str);
2259                         foreach (Type param in gen_param)
2260                                 param.TypeSig (str);
2261                 }
2262
2263                 internal sealed override void BuildTables (MetaData md)
2264                 {
2265                         if (done)
2266                                 return;
2267                         MemoryStream str = new MemoryStream ();
2268                         TypeSig (str);
2269                         sigIx = md.AddToBlobHeap (str.ToArray ());
2270
2271                         done = true;
2272                 }
2273
2274                 internal sealed override uint Size (MetaData md)
2275                 {
2276                         return md.BlobIndexSize ();
2277                 }
2278
2279                 internal sealed override void Write (FileImage output)
2280                 {
2281                         output.BlobIndex (sigIx);       
2282                 }
2283
2284                 internal sealed override uint GetCodedIx (CIx code)
2285                 {
2286                         switch (code) {
2287                                 case (CIx.TypeDefOrRef): return 2;
2288                                 case (CIx.MemberRefParent): return 4;
2289                                 case (CIx.HasCustomAttr): return 13;
2290                         }
2291                         return 0;
2292                 }
2293         }
2294
2295         public class GenericMethodSig {
2296
2297                 private Type[] gen_param;
2298                 private bool done;
2299                 private uint sigIx = 0;
2300
2301                 public GenericMethodSig (Type[] gen_param)
2302                 {
2303                         this.gen_param = gen_param;
2304                         done = false;
2305                 }
2306
2307                 internal void TypeSig (MemoryStream str)
2308                 {
2309                         str.WriteByte (0x0A); /* GENERIC_INST */
2310                         MetaData.CompressNum ((uint) gen_param.Length, str);
2311                         foreach (Type param in gen_param)
2312                                 param.TypeSig (str);
2313                 }
2314
2315                 internal uint GetSigIx (MetaData md)
2316                 {
2317                         if (done)
2318                                 return sigIx;
2319
2320                         MemoryStream sig = new MemoryStream();
2321                         TypeSig (sig);
2322                         sigIx = md.AddToBlobHeap (sig.ToArray());
2323                         done = true;
2324                         return sigIx;
2325                 }
2326         }
2327
2328         public class Sentinel : Type {
2329
2330                 public Sentinel () : base (0x41) { }
2331
2332                 internal sealed override void TypeSig(MemoryStream str) 
2333                 {
2334                         str.WriteByte(typeIndex);
2335                 }
2336         }
2337
2338         /**************************************************************************/  
2339         /// <summary>
2340         /// Descriptor for a FunctionPointer type
2341         /// </summary>
2342         /// 
2343         public class MethPtrType : Type {
2344
2345                 bool varArgMeth;
2346                 Type retType;
2347                 Type [] parList;
2348                 Type [] optParList;
2349                 CallConv callConv;
2350                 uint numPars;
2351                 uint numOptPars;
2352                 uint sigIx = 0;
2353
2354                 /// <summary>
2355                 /// Create a new function pointer type
2356                 /// </summary>
2357                 /// <param name="meth">the function to be referenced</param>
2358                 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2359                                 bool varArgMeth, Type[] optPars) : base(0x1B) 
2360                 {
2361                         this.retType = retType;
2362                         callConv = callconv;
2363                         parList = pars;
2364                         this.varArgMeth = varArgMeth;
2365                         if (parList != null) numPars = (uint)parList.Length;
2366                         if (varArgMeth) {
2367                                 optParList = optPars;
2368                                 if (optParList != null) numOptPars = (uint)optParList.Length;
2369                                 callConv |= CallConv.Vararg;
2370                         }
2371                         tabIx = MDTable.TypeSpec;
2372                 }
2373
2374                 internal sealed override void TypeSig(MemoryStream sig) 
2375                 {
2376                         sig.WriteByte(typeIndex);
2377                         // Bootlegged from method ref
2378                         sig.WriteByte((byte)callConv);
2379                         MetaData.CompressNum (numPars + numOptPars, sig);
2380                         retType.TypeSig (sig);
2381                         for (int i=0; i < numPars; i++) {
2382                                 parList[i].TypeSig (sig);
2383                         }
2384                         if (varArgMeth) {
2385                                 sig.WriteByte (0x41); // Write the sentinel
2386                                 for (int i=0; i < numOptPars; i++) {
2387                                         optParList[i].TypeSig (sig);
2388                                 }
2389                         }
2390                 }
2391
2392                 internal sealed override void BuildTables(MetaData md) 
2393                 {
2394                         if (done) return;
2395                         MemoryStream sig = new MemoryStream();
2396                         TypeSig(sig);
2397                         sigIx = md.AddToBlobHeap(sig.ToArray());
2398                         done = true;
2399                 }
2400
2401                 internal sealed override uint Size(MetaData md) 
2402                 {
2403                         return md.BlobIndexSize();
2404                 }
2405
2406                 internal sealed override void Write(FileImage output) 
2407                 {
2408                         output.BlobIndex(sigIx);
2409                 }
2410
2411                 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2412
2413         }
2414
2415         #region Array Types
2416         /* Classes for Arrays */
2417
2418         /// <summary>
2419         /// The IL Array type
2420         /// </summary>
2421         public abstract class Array : Type {
2422
2423                 protected Type elemType;
2424                 protected MetaData metaData;
2425                 protected string cnameSpace, cname;
2426
2427                 internal Array(Type eType, byte TypeId) : base(TypeId) 
2428                 {
2429                         elemType = eType;
2430                         tabIx = MDTable.TypeSpec;
2431                 }
2432         }
2433
2434         /// <summary>
2435         /// Single dimensional array with zero lower bound
2436         /// </summary>
2437         public class ZeroBasedArray : Array {
2438
2439                 /// <summary>
2440                 /// Create a new array  -   elementType[]
2441                 /// </summary>
2442                 /// <param name="elementType">the type of the array elements</param>
2443                 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2444
2445                 internal sealed override void TypeSig(MemoryStream str) 
2446                 {
2447                         str.WriteByte(typeIndex);
2448                         elemType.TypeSig(str); 
2449                 }
2450
2451         }
2452
2453         /// <summary>
2454         /// Multi dimensional array with explicit bounds
2455         /// </summary>
2456         public class BoundArray : Array {
2457                 int[] lowerBounds;
2458                 int[] sizes;
2459                 uint numDims;
2460
2461                 /// <summary>
2462                 /// Create a new multi dimensional array type 
2463                 /// eg. elemType[1..5,3..10,5,,] would be 
2464                 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2465                 /// </summary>
2466                 /// <param name="elementType">the type of the elements</param>
2467                 /// <param name="dimensions">the number of dimensions</param>
2468                 /// <param name="loBounds">lower bounds of dimensions</param>
2469                 /// <param name="sizes">sizes for the dimensions</param>
2470                 public BoundArray(Type elementType, uint dimensions, int[] loBounds, 
2471                                 int[] sizes) : base (elementType,0x14) 
2472                 {
2473                         numDims = dimensions;
2474                         lowerBounds = loBounds;
2475                         this.sizes = sizes;
2476                 }
2477
2478                 /// <summary>
2479                 /// Create a new multi dimensional array type 
2480                 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2481                 /// </summary>
2482                 /// <param name="elementType">the type of the elements</param>
2483                 /// <param name="dimensions">the number of dimensions</param>
2484                 /// <param name="size">the sizes of the dimensions</param>
2485                 public BoundArray(Type elementType, uint dimensions, int[] size) 
2486                         : base (elementType,0x14) 
2487                 {
2488                         numDims = dimensions;
2489                         sizes = size;
2490                 }
2491
2492                 /// <summary>
2493                 /// Create a new multi dimensional array type 
2494                 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2495                 /// </summary>
2496                 /// <param name="elementType">the type of the elements</param>
2497                 /// <param name="dimensions">the number of dimensions</param>
2498                 public BoundArray(Type elementType, uint dimensions)
2499                         : base (elementType,0x14) 
2500                 {
2501                         numDims = dimensions;
2502                 }
2503
2504                 internal sealed override void TypeSig(MemoryStream str) 
2505                 {
2506                         str.WriteByte(typeIndex);
2507                         elemType.TypeSig(str);
2508                         MetaData.CompressNum(numDims,str);
2509                         if ((sizes != null) && (sizes.Length > 0))  {
2510
2511                                 MetaData.CompressNum((uint)sizes.Length,str);
2512                                 for (int i=0; i < sizes.Length; i++) {
2513                                         MetaData.CompressNum((uint)sizes[i],str);
2514                                 }
2515                         } else str.WriteByte(0);
2516                         if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2517                                 MetaData.CompressNum((uint)lowerBounds.Length,str);
2518                                 for (int i=0; i < lowerBounds.Length; i++) {
2519                                         CompressSignedNum (lowerBounds[i],str);
2520                                 }
2521                         } else str.WriteByte(0);
2522                 }
2523                 private void CompressSignedNum (int val, MemoryStream str)
2524                 {
2525                         uint uval = (uint) val;
2526                         byte sign = 0;
2527                         if (val < 0) {
2528                                 val = -val;
2529                                 sign = 1;
2530                         }
2531
2532                         /* Map the signed number to an unsigned number in two ways.
2533
2534                              fval: left-rotated 2's complement representation
2535                              sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2536                                    the mapping is: x -> 2*|x| - signbit(x)
2537                         */
2538                         uint fval = (uval << 1) | sign;
2539                         int sval = (val  << 1) - sign;
2540
2541                         /* An overly clever transformation: 
2542
2543                            a. sval is used to determine the number of bytes in the compressed representation.
2544                            b. fval is truncated to the appropriate number of bits and output using the 
2545                               normal unsigned-int compressor.
2546
2547                            However, or certain values, the truncated fval doesn't carry enough information to round trip.
2548
2549                                 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2550
2551                            So, we use full 4 bytes to encode such values.
2552
2553                            LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2554                                      e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2555                         */
2556                         if (sval <= 0x7F)
2557                                 MetaData.CompressNum (fval & 0x7F, str);
2558                         else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2559                                 MetaData.CompressNum (fval & 0x3FFF, str);
2560                         else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2561                                 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2562                         else
2563                                 /* FIXME: number cannot be represented.  Report a warning.  */
2564                                 // throw new Exception ("cannot represent signed value" + -val);
2565                                 MetaData.CompressNum (fval, str);
2566                 }
2567         }
2568
2569         #endregion
2570
2571
2572         /* Empty interface for grouping TypeRef's possible ResolutionScope
2573            namely : Module, ModuleRef, AssemblyRef and TypeRef */
2574         public interface IResolutionScope  {
2575         }
2576
2577         /**************************************************************************/  
2578         /// <summary>
2579         /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2580         /// </summary>
2581         public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2582
2583                 protected uint nameIx = 0;
2584                 protected MetaData metaData;
2585                 protected string name;
2586
2587                 internal ResolutionScope(string name, MetaData md)
2588                 {
2589                         metaData = md;
2590                         this.name = name;
2591                         nameIx = md.AddToStringsHeap(name);
2592                 }
2593
2594                 internal string GetName() { return name; }
2595
2596         }
2597
2598         /**************************************************************************/  
2599         /// <summary>
2600         /// Descriptor for THIS assembly (.assembly)
2601         /// </summary>
2602         public class Assembly : ResolutionScope  {
2603
2604                 ushort majorVer, minorVer, buildNo, revisionNo;
2605                 uint flags;
2606                 uint hashAlgId;
2607                 uint keyIx = 0, cultIx = 0;
2608                 bool hasPublicKey = false;
2609
2610                 internal Assembly(string name, MetaData md) : base(name,md) 
2611                 {
2612                         tabIx = MDTable.Assembly;
2613                 }
2614
2615                 /// <summary>
2616                 /// Add details about THIS assembly
2617                 /// </summary>
2618                 /// <param name="majVer">Major Version</param>
2619                 /// <param name="minVer">Minor Version</param>
2620                 /// <param name="bldNo">Build Number</param>
2621                 /// <param name="revNo">Revision Number</param>
2622                 /// <param name="key">Hash Key</param>
2623                 /// <param name="hash">Hash Algorithm</param>
2624                 /// <param name="cult">Culture</param>
2625                 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, 
2626                                 byte[] key, uint hash, string cult) 
2627                 {
2628                         majorVer = (ushort)majVer;
2629                         minorVer = (ushort)minVer;
2630                         buildNo = (ushort)bldNo;
2631                         revisionNo = (ushort)revNo;
2632                         hashAlgId = hash;
2633                         hasPublicKey = (key != null);
2634                         keyIx = metaData.AddToBlobHeap(key);
2635                         cultIx = metaData.AddToStringsHeap(cult);
2636                 }
2637
2638                 /// <summary>
2639                 /// Add an attribute to THIS assembly
2640                 /// </summary>
2641                 /// <param name="aa">assembly attribute</param>
2642                 public void AddAssemblyAttr(AssemAttr aa) 
2643                 {
2644                         flags |= (uint)aa;
2645                 }
2646
2647                 internal sealed override uint Size(MetaData md) 
2648                 {
2649                         return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2650                 }
2651
2652                 internal sealed override void Write(FileImage output) 
2653                 {
2654                         //      Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2655                         output.Write((uint)hashAlgId);
2656                         output.Write(majorVer);
2657                         output.Write(minorVer);
2658                         output.Write(buildNo);
2659                         output.Write(revisionNo);
2660                         output.Write(flags);
2661                         output.BlobIndex(keyIx);
2662                         output.StringsIndex(nameIx);
2663                         output.StringsIndex(cultIx);
2664                 }
2665
2666                 internal sealed override uint GetCodedIx(CIx code) 
2667                 {
2668                         switch (code) {
2669                                 case (CIx.HasCustomAttr) : return 14; 
2670                                 case (CIx.HasDeclSecurity) : return 2; 
2671                         }
2672                         return 0;
2673                 }
2674
2675                 internal bool HasPublicKey {
2676                         get { return hasPublicKey; }
2677                 }
2678         }
2679
2680         /**************************************************************************/  
2681         /// <summary>
2682         /// Descriptor for THIS module
2683         /// </summary>
2684         public class Module : ResolutionScope, IExternRef {
2685
2686                 Guid mvid;
2687                 uint mvidIx = 0;
2688
2689                 internal Module(string name, MetaData md) : base(name,md)       
2690                 {
2691                         mvid = Guid.NewGuid();
2692                         mvidIx = md.AddToGUIDHeap(mvid);
2693                         tabIx = MDTable.Module;
2694                 }
2695
2696                 public Guid Guid {
2697                         get { return mvid; }
2698                 }
2699
2700                 public ClassRef AddClass(string nsName, string name) 
2701                 {
2702                         ClassRef aClass = new ClassRef (nsName, name, metaData);
2703                         metaData.AddToTable (MDTable.TypeRef, aClass);
2704                         aClass.SetParent (this);
2705                         return aClass;
2706                 }
2707
2708                 public ClassRef AddValueClass(string nsName, string name) 
2709                 {
2710                         ClassRef aClass = AddClass (nsName, name);
2711                         aClass.MakeValueClass (ValueClass.ValueType);
2712                         return aClass;
2713                 }
2714
2715                 internal sealed override uint Size(MetaData md) 
2716                 {
2717                         return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2718                 }
2719
2720                 internal sealed override void Write(FileImage output) 
2721                 {
2722                         output.Write((short)0);
2723                         output.StringsIndex(nameIx);
2724                         output.GUIDIndex(mvidIx);
2725                         output.GUIDIndex(0);
2726                         output.GUIDIndex(0);
2727                 }
2728
2729                 internal sealed override uint GetCodedIx(CIx code) 
2730                 {
2731                         switch (code) {
2732                                 case (CIx.HasCustomAttr) : return 7; 
2733                                 case (CIx.ResolutionScope) : return 0;
2734                         }
2735                         return 0;
2736                 }
2737         }
2738         /**************************************************************************/  
2739         /// <summary>
2740         /// Descriptor for another module in THIS assembly
2741         /// </summary>
2742         public class ModuleRef : ResolutionScope, IExternRef {
2743
2744                 internal ModuleRef(MetaData md, string name) : base(name,md) 
2745                 {
2746                         tabIx = MDTable.ModuleRef;
2747                 }
2748
2749                 /// <summary>
2750                 /// Add a class to this external module.  This is a class declared in
2751                 /// another module of THIS assembly.
2752                 /// </summary>
2753                 /// <param name="nsName">name space name</param>
2754                 /// <param name="name">class name</param>
2755                 /// <returns>a descriptor for this class in another module</returns>
2756                 public ClassRef AddClass(string nsName, string name) 
2757                 {
2758                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2759                         metaData.AddToTable(MDTable.TypeRef,aClass);
2760                         aClass.SetParent(this);
2761                         return aClass;
2762                 }
2763
2764                 /// <summary>
2765                 /// Make a file descriptor to correspond to this module.  The file
2766                 /// descriptor will have the same name as the module descriptor
2767                 /// </summary>
2768                 /// <param name="hashBytes">the hash of the file</param>
2769                 /// <param name="hasMetaData">the file contains metadata</param>
2770                 /// <param name="entryPoint">the program entry point is in this file</param>
2771                 /// <returns>a descriptor for the file which contains this module</returns>
2772                 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) 
2773                 {
2774                         FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2775                         metaData.AddToTable(MDTable.File,file);
2776                         return file;
2777                 }
2778
2779                 /// <summary>
2780                 /// Add a value class to this module.  This is a class declared in
2781                 /// another module of THIS assembly.
2782                 /// </summary>
2783                 /// <param name="nsName">name space name</param>
2784                 /// <param name="name">class name</param>
2785                 /// <returns></returns>
2786                 public ClassRef AddValueClass(string nsName, string name) 
2787                 {
2788                         ClassRef aClass = new ClassRef(nsName,name,metaData);
2789                         metaData.AddToTable(MDTable.TypeRef,aClass);
2790                         aClass.SetParent(this);
2791                         aClass.MakeValueClass(ValueClass.ValueType);
2792                         return aClass;
2793                 }
2794
2795                 /// <summary>
2796                 /// Add a class which is declared public in this external module of
2797                 /// THIS assembly.  This class will be exported from this assembly.
2798                 /// The ilasm syntax for this is .extern class
2799                 /// </summary>
2800                 /// <param name="attrSet">attributes of the class to be exported</param>
2801                 /// <param name="nsName">name space name</param>
2802                 /// <param name="name">external class name</param>
2803                 /// <param name="declFile">the file where the class is declared</param>
2804                 /// <param name="isValueClass">is this class a value type?</param>
2805                 /// <returns>a descriptor for this external class</returns>
2806                 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName, 
2807                                 string name, FileRef declFile, 
2808                                 bool isValueClass) {
2809                         ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2810                         metaData.AddToTable(MDTable.TypeRef,cRef);
2811                         cRef.SetParent(this);
2812                         if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2813                         return cRef;
2814                 }
2815
2816                 /// <summary>
2817                 /// Add a "global" method in another module
2818                 /// </summary>
2819                 /// <param name="name">method name</param>
2820                 /// <param name="retType">return type</param>
2821                 /// <param name="pars">method parameter types</param>
2822                 /// <returns>a descriptor for this method in anther module</returns>
2823                 public MethodRef AddMethod(string name, Type retType, Type[] pars) 
2824                 {
2825                         MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2826                         metaData.AddToTable(MDTable.MemberRef,meth);
2827                         return meth;
2828                 }
2829
2830                 /// <summary>
2831                 /// Add a vararg method to this class
2832                 /// </summary>
2833                 /// <param name="name">method name</param>
2834                 /// <param name="retType">return type</param>
2835                 /// <param name="pars">parameter types</param>
2836                 /// <param name="optPars">optional param types for this vararg method</param>
2837                 /// <returns>a descriptor for this method</returns>
2838                 public MethodRef AddVarArgMethod(string name, Type retType, 
2839                                 Type[] pars, Type[] optPars) {
2840                         MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2841                         metaData.AddToTable(MDTable.MemberRef,meth);
2842                         return meth;
2843                 }
2844
2845                 /// <summary>
2846                 /// Add a field in another module
2847                 /// </summary>
2848                 /// <param name="name">field name</param>
2849                 /// <param name="fType">field type</param>
2850                 /// <returns>a descriptor for this field in another module</returns>
2851                 public FieldRef AddField(string name, Type fType) 
2852                 {
2853                         FieldRef field = new FieldRef(this,name,fType);
2854                         metaData.AddToTable(MDTable.MemberRef,field);
2855                         return field;
2856                 }
2857
2858                 internal sealed override uint Size(MetaData md) 
2859                 {
2860                         return md.StringsIndexSize();
2861                 }
2862
2863                 internal sealed override void Write(FileImage output) 
2864                 {
2865                         output.StringsIndex(nameIx);
2866                 }
2867
2868                 internal sealed override uint GetCodedIx(CIx code) 
2869                 {
2870                         switch (code) {
2871                                 case (CIx.HasCustomAttr) : return 12; 
2872                                 case (CIx.MemberRefParent) : return 2; 
2873                                 case (CIx.ResolutionScope) : return 1; 
2874                         }
2875                         return 0;
2876                 }
2877
2878         }
2879
2880         #region Classes for Constants
2881         /// <summary>
2882         /// Descriptor for a constant value
2883         /// </summary>
2884         public abstract class Constant {
2885                 protected uint size = 0;
2886                 protected Type type;
2887                 protected uint blobIndex;
2888                 protected bool addedToBlobHeap = false;
2889
2890                 internal Constant() { }
2891
2892                 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2893
2894                 internal uint GetSize() { return size; }
2895
2896                 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2897
2898                 internal virtual void Write(BinaryWriter bw) {  }
2899
2900         }
2901         /// <summary>
2902         /// Descriptor for a constant value
2903         /// </summary>
2904         public abstract class DataConstant : Constant {
2905                 private uint dataOffset = 0;
2906
2907                 internal DataConstant() { }
2908
2909                 public uint DataOffset {
2910                         get { return dataOffset; }
2911                         set { dataOffset = value; }
2912                 }
2913
2914         }
2915
2916         /// <summary>
2917         /// Boolean constant
2918         /// </summary>
2919         public class BoolConst : Constant {
2920                 bool val;
2921
2922                 /// <summary>
2923                 /// Create a new boolean constant with the value "val"
2924                 /// </summary>
2925                 /// <param name="val">value of this boolean constant</param>
2926                 public BoolConst(bool val) 
2927                 {
2928                         this.val = val;
2929                         size = 1;
2930                         type = PrimitiveType.Boolean;
2931                 }
2932
2933                 internal sealed override uint GetBlobIndex(MetaData md) 
2934                 {
2935                         if (!addedToBlobHeap) {
2936                                 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2937                                 else blobIndex = md.AddToBlobHeap((sbyte)0);
2938                                 addedToBlobHeap = true;
2939                         }
2940                         return blobIndex;
2941                 }
2942
2943                 internal sealed override void Write(BinaryWriter bw) 
2944                 {
2945                         if (val) bw.Write((sbyte)1);
2946                         else bw.Write((sbyte)0);
2947                 }
2948
2949         }
2950
2951         public class ByteArrConst : DataConstant {
2952                 internal byte[] val;
2953
2954                 public ByteArrConst(byte[] val) 
2955                 {
2956                         type = PrimitiveType.String;
2957                         this.val = val;
2958                         size = (uint)val.Length;
2959                 }
2960
2961                 public Type Type {
2962                         get { return type; }
2963                         set { type = value; }
2964                 }
2965
2966                 internal sealed override uint GetBlobIndex(MetaData md) 
2967                 {
2968                         if (!addedToBlobHeap) {
2969                                 blobIndex = md.AddToBlobHeap(val);
2970                                 addedToBlobHeap = true;
2971                         }
2972                         return blobIndex;
2973                 }
2974
2975                 internal sealed override void Write(BinaryWriter bw) 
2976                 {
2977                         bw.Write(val);
2978                 }
2979
2980         }
2981
2982         public class CharConst : Constant {
2983                 char val;
2984
2985                 public CharConst(char val) 
2986                 {
2987                         this.val = val;
2988                         size = 2;
2989                         type = PrimitiveType.Char;
2990                 }
2991
2992                 internal sealed override uint GetBlobIndex(MetaData md) 
2993                 {
2994                         if (!addedToBlobHeap) {
2995                                 blobIndex = md.AddToBlobHeap(val);
2996                                 addedToBlobHeap = true;
2997                         }
2998                         return blobIndex;
2999                 }
3000
3001                 internal sealed override void Write(BinaryWriter bw) 
3002                 {
3003                         bw.Write(val);
3004                 }
3005
3006         }
3007
3008         public class FloatConst : DataConstant {
3009                 float val;
3010
3011                 public FloatConst(float val) 
3012                 {
3013                         this.val = val;
3014                         size = 4;
3015                         type = PrimitiveType.Float32;
3016                 }
3017
3018                 internal sealed override uint GetBlobIndex(MetaData md) 
3019                 {
3020                         if (!addedToBlobHeap) {
3021                                 blobIndex = md.AddToBlobHeap(val);
3022                                 addedToBlobHeap = true;
3023                         }
3024                         return blobIndex;
3025                 }
3026
3027                 internal sealed override void Write(BinaryWriter bw) 
3028                 {
3029                         bw.Write(val);
3030                 }
3031
3032         }
3033
3034         public class DoubleConst : DataConstant {
3035                 double val;
3036
3037                 public DoubleConst(double val) 
3038                 {
3039                         this.val = val;
3040                         size = 8;
3041                         type = PrimitiveType.Float64;
3042                 }
3043
3044                 internal sealed override uint GetBlobIndex(MetaData md) 
3045                 {
3046                         if (!addedToBlobHeap) {
3047                                 blobIndex = md.AddToBlobHeap(val);
3048                                 addedToBlobHeap = true;
3049                         }
3050                         return blobIndex;
3051                 }
3052
3053                 internal sealed override void Write(BinaryWriter bw) 
3054                 {
3055                         bw.Write(val);
3056                 }
3057
3058         }
3059
3060         public class IntConst : DataConstant {
3061                 long val;
3062
3063                 public IntConst(sbyte val) 
3064                 {
3065                         this.val = val;
3066                         size = 1;
3067                         type = PrimitiveType.Int8;
3068                 }
3069
3070                 public IntConst(short val) 
3071                 {
3072                         this.val = val;
3073                         size = 2;
3074                         type = PrimitiveType.Int16;
3075                 }
3076
3077                 public IntConst(int val) 
3078                 {
3079                         this.val = val;
3080                         size = 4;
3081                         type = PrimitiveType.Int32;
3082                 }
3083
3084                 public IntConst(long val) 
3085                 {
3086                         this.val = val;
3087                         size = 8;
3088                         type = PrimitiveType.Int64;
3089                 }
3090
3091                 internal sealed override uint GetBlobIndex(MetaData md) 
3092                 {
3093                         if (!addedToBlobHeap) {
3094                                 switch (size) {
3095                                         case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3096                                         case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3097                                         case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3098                                         default : blobIndex = md.AddToBlobHeap(val); break; 
3099                                 }
3100                                 addedToBlobHeap = true;
3101                         }
3102                         return blobIndex;
3103                 }
3104
3105                 internal sealed override void Write(BinaryWriter bw) 
3106                 {
3107                         switch (size) {
3108                                 case (1) : bw.Write((sbyte)val); break;
3109                                 case (2) : bw.Write((short)val); break;
3110                                 case (4) : bw.Write((int)val); break;
3111                                 default : bw.Write(val); break; 
3112                         }
3113                 }
3114
3115         }
3116
3117         public class UIntConst : Constant {
3118                 ulong val;
3119
3120                 public UIntConst(byte val) 
3121                 {
3122                         this.val = val;
3123                         size = 1;
3124                         type = PrimitiveType.UInt8;
3125                 }
3126                 public UIntConst(ushort val) 
3127                 {
3128                         this.val = val;
3129                         size = 2;
3130                         type = PrimitiveType.UInt16;
3131                 }
3132                 public UIntConst(uint val) 
3133                 {
3134                         this.val = val;
3135                         size = 4;
3136                         type = PrimitiveType.UInt32;
3137                 }
3138                 public UIntConst(ulong val) 
3139                 {
3140                         this.val = val;
3141                         size = 8;
3142                         type = PrimitiveType.UInt64;
3143                 }
3144
3145                 internal sealed override uint GetBlobIndex(MetaData md) 
3146                 {
3147                         if (!addedToBlobHeap) {
3148                                 switch (size) {
3149                                         case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3150                                         case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3151                                         case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3152                                         default : blobIndex = md.AddToBlobHeap(val); break;
3153                                 }
3154                                 addedToBlobHeap = true;
3155                         }
3156                         return blobIndex;
3157                 }
3158
3159                 internal sealed override void Write(BinaryWriter bw) 
3160                 {
3161                         switch (size) {
3162                                 case (1) : bw.Write((byte)val); break;
3163                                 case (2) : bw.Write((ushort)val); break;
3164                                 case (4) : bw.Write((uint)val); break;
3165                                 default : bw.Write(val); break;
3166                         }
3167                 }
3168
3169         }
3170
3171         public class StringConst : DataConstant {
3172                 string val;
3173
3174                 public StringConst(string val) 
3175                 {
3176                         this.val = val;
3177                         size = (uint)val.Length;  // need to add null ??
3178                         type = PrimitiveType.String;
3179                 }
3180
3181                 internal sealed override uint GetBlobIndex(MetaData md) 
3182                 {
3183                         if (!addedToBlobHeap) {
3184                                 byte [] b = Encoding.Unicode.GetBytes (val);
3185                                 blobIndex = md.AddToBlobHeap(b);
3186                                 addedToBlobHeap = true;
3187                         }
3188                         return blobIndex;
3189                 }
3190
3191                 internal sealed override void Write(BinaryWriter bw) 
3192                 {
3193                         bw.Write(val);
3194                 }
3195
3196         }
3197
3198         public class NullConst : Constant {
3199
3200                 public NullConst() 
3201                 {
3202                         size = 4;
3203                         type = PrimitiveType.Class;
3204                 }
3205
3206                 internal sealed override uint GetBlobIndex(MetaData md) 
3207                 {
3208                         if (!addedToBlobHeap) {
3209                                 blobIndex = md.AddToBlobHeap((int)0);
3210                                 addedToBlobHeap = true;
3211                         }
3212                         return blobIndex;
3213                 }
3214
3215                 internal sealed override void Write(BinaryWriter bw) 
3216                 {
3217                         bw.Write((int)0); 
3218                 }
3219
3220         }
3221
3222         public class AddressConstant : DataConstant {
3223                 DataConstant data;
3224
3225                 public AddressConstant(DataConstant dConst) 
3226                 {
3227                         data = dConst;
3228                         size = 4;
3229                         type = PrimitiveType.TypedRef;
3230                 }
3231
3232                 internal sealed override void Write(BinaryWriter bw) 
3233                 {
3234                         ((FileImage)bw).WriteDataRVA(data.DataOffset);
3235                 }
3236
3237         }
3238
3239         public class RepeatedConstant : DataConstant {
3240                 DataConstant data;
3241                 uint repCount;
3242
3243                 public RepeatedConstant(DataConstant dConst, int repeatCount) 
3244                 {
3245                         data = dConst;
3246                         repCount = (uint)repeatCount;
3247                         int[] sizes = new int[1];
3248                         sizes[0] = repeatCount;
3249                         type = new BoundArray(type,1,sizes);
3250                         size = data.GetSize() * repCount;
3251                 }
3252
3253                 internal sealed override void Write(BinaryWriter bw) 
3254                 {
3255                         for (int i=0; i < repCount; i++) {
3256                                 data.Write(bw);
3257                         }
3258                 }
3259
3260         }
3261
3262         public class ArrayConstant : DataConstant {
3263                 DataConstant[] dataVals;
3264
3265                 public ArrayConstant(DataConstant[] dVals) 
3266                 {
3267                         dataVals = dVals;
3268                         for (int i=0; i < dataVals.Length; i++) {
3269                                 size += dataVals[i].GetSize();
3270                         }
3271                 }
3272
3273                 internal sealed override void Write(BinaryWriter bw) 
3274                 {
3275                         for (int i=0; i < dataVals.Length; i++) {
3276                                 dataVals[i].Write(bw);
3277                         }
3278                 }
3279
3280         }
3281
3282         public class ClassType : Constant {
3283                 string name;
3284                 Class desc;
3285
3286                 public ClassType(string className) 
3287                 {
3288                         name = className;
3289                         type = PrimitiveType.ClassType;
3290                 }
3291
3292                 public ClassType(Class classDesc) 
3293                 {
3294                         desc = classDesc;
3295                         type = PrimitiveType.ClassType;
3296                 }
3297
3298                 internal override void Write(BinaryWriter bw) 
3299                 {
3300                         if (name == null)  name = desc.TypeName();
3301                         bw.Write(name);
3302                 }
3303
3304         }
3305
3306         #endregion
3307
3308         /**************************************************************************/  
3309         /// <summary>
3310         /// Descriptor for a custom modifier of a type (modopt or modreq)
3311         /// </summary>
3312
3313         public class CustomModifiedType : Type {
3314
3315                 Type type;
3316                 Class cmodType;
3317                 PrimitiveTypeRef cmodPrimType;
3318
3319                 /// <summary>
3320                 /// Create a new custom modifier for a type
3321                 /// </summary>
3322                 /// <param name="type">the type to be modified</param>
3323                 /// <param name="cmod">the modifier</param>
3324                 /// <param name="cmodType">the type reference to be associated with the type</param>
3325                 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3326                         : base((byte)cmod) 
3327                 {
3328                         this.type = type;
3329                         this.cmodType = cmodType;
3330                 }
3331
3332                 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3333                         : base((byte)cmod)
3334                 {
3335                         this.type = type;
3336                         this.cmodPrimType = cmodType;
3337                 }
3338
3339                 internal sealed override void TypeSig(MemoryStream str) 
3340                 {
3341                         str.WriteByte(typeIndex);
3342
3343                         if (cmodType != null) {
3344                                 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3345                         } else {
3346                                 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3347                         }
3348
3349                         type.TypeSig(str);
3350                 }
3351
3352         }
3353
3354         /**************************************************************************/  
3355         /// <summary>
3356         /// Base class for Event and Property descriptors
3357         /// </summary>
3358
3359         public class Feature : MetaDataElement {
3360
3361                 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08, 
3362                         RemoveOn = 0x10, Fire = 0x20 }
3363
3364                 private static readonly int INITSIZE = 5;
3365                 private static readonly ushort specialName = 0x200;
3366                 private static readonly ushort rtSpecialName = 0x400;
3367
3368                 protected ClassDef parent;
3369                 protected ushort flags = 0;
3370                 protected string name;
3371                 protected int tide = 0;
3372                 protected uint nameIx;
3373                 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3374
3375                 internal Feature(string name, ClassDef par) 
3376                 {
3377                         parent = par;
3378                         this.name = name;
3379                 }
3380
3381                 internal void AddMethod(MethodDef meth, MethodType mType) 
3382                 {
3383                         if (tide >= methods.Length) { 
3384                                 int len = methods.Length;
3385                                 MethodSemantics[] mTmp = methods;
3386                                 methods = new MethodSemantics[len * 2];
3387                                 for (int i=0; i < len; i++) {
3388                                         methods[i] = mTmp[i];
3389                                 }
3390                         }
3391                         methods[tide++] = new MethodSemantics(mType,meth,this);
3392                 }
3393
3394                 /// <summary>
3395                 /// Set the specialName attribute for this Event or Property
3396                 /// </summary>
3397                 public void SetSpecialName() 
3398                 {
3399                         flags |= specialName;
3400                 }
3401
3402                 /// <summary>
3403                 /// Set the RTSpecialName attribute for this Event or Property
3404                 /// </summary>
3405                 public void SetRTSpecialName() 
3406                 {
3407                         flags |= rtSpecialName;
3408                 }
3409
3410         }
3411
3412         /**************************************************************************/  
3413         /// <summary>
3414         /// Descriptor for an event
3415         /// </summary>
3416         public class Event : Feature {
3417
3418                 Type eventType;
3419
3420                 internal Event(string name, Type eType, ClassDef parent) 
3421                         : base(name, parent) 
3422                 {
3423                         eventType = eType;
3424                         tabIx = MDTable.Event;
3425                 }
3426
3427                 /// <summary>
3428                 /// Add the addon method to this event
3429                 /// </summary>
3430                 /// <param name="addon">the addon method</param>
3431                 public void AddAddon(MethodDef addon) 
3432                 {
3433                         AddMethod(addon,MethodType.AddOn);
3434                 }
3435
3436                 /// <summary>
3437                 /// Add the removeon method to this event
3438                 /// </summary>
3439                 /// <param name="removeOn">the removeon method</param>
3440                 public void AddRemoveOn(MethodDef removeOn) 
3441                 {
3442                         AddMethod(removeOn,MethodType.RemoveOn);
3443                 }
3444
3445                 /// <summary>
3446                 /// Add the fire method to this event
3447                 /// </summary>
3448                 /// <param name="fire">the fire method</param>
3449                 public void AddFire(MethodDef fire) 
3450                 {
3451                         AddMethod(fire,MethodType.Fire);
3452                 }
3453
3454                 /// <summary>
3455                 /// Add another method to this event
3456                 /// </summary>
3457                 /// <param name="other">the method to be added</param>
3458                 public void AddOther(MethodDef other) 
3459                 {
3460                         AddMethod(other,MethodType.Other);
3461                 }
3462
3463                 internal sealed override void BuildTables(MetaData md) 
3464                 {
3465                         if (done) return;
3466                         nameIx = md.AddToStringsHeap(name);
3467                         for (int i=0; i < tide; i++) {
3468                                 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3469                         }
3470                         done = true;
3471                 }
3472
3473                 internal sealed override uint Size(MetaData md) 
3474                 {
3475                         return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3476                 }
3477
3478                 internal sealed override void Write(FileImage output) 
3479                 {
3480                         output.Write(flags);
3481                         output.StringsIndex(nameIx);
3482                         output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3483                 }
3484
3485                 internal sealed override uint GetCodedIx(CIx code) 
3486                 {
3487                         switch (code) {
3488                                 case (CIx.HasCustomAttr) : return 10; 
3489                                 case (CIx.HasSemantics) : return 0; 
3490                         }
3491                         return 0;
3492                 }
3493
3494         }
3495
3496         /**************************************************************************/  
3497         /// <summary>
3498         /// Descriptor for the Property of a class
3499         /// </summary>
3500         public class Property : Feature {
3501
3502                 private static readonly byte PropertyTag = 0x8;
3503                 private bool instance;
3504                 MethodDef getterMeth;
3505                 ConstantElem constVal;
3506                 uint typeBlobIx = 0;
3507                 Type[] parList;
3508                 Type returnType;
3509                 uint numPars = 0;
3510
3511                 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) 
3512                 {
3513                         returnType = retType;
3514                         parList = pars;
3515                         if (pars != null) numPars = (uint)pars.Length;
3516                         tabIx = MDTable.Property;
3517                 }
3518
3519                 /// <summary>
3520                 /// Add a set method to this property
3521                 /// </summary>
3522                 /// <param name="setter">the set method</param>
3523                 public void AddSetter(MethodDef setter) 
3524                 {
3525                         AddMethod(setter,MethodType.Setter);
3526                 }
3527
3528                 /// <summary>
3529                 /// Add a get method to this property
3530                 /// </summary>
3531                 /// <param name="getter">the get method</param>
3532                 public void AddGetter(MethodDef getter) 
3533                 {
3534                         AddMethod(getter,MethodType.Getter);
3535                         getterMeth = getter;
3536                 }
3537
3538                 /// <summary>
3539                 /// Add another method to this property
3540                 /// </summary>
3541                 /// <param name="other">the method</param>
3542                 public void AddOther(MethodDef other) 
3543                 {
3544                         AddMethod(other,MethodType.Other);
3545                 }
3546
3547                 /// <summary>
3548                 /// Add an initial value for this property
3549                 /// </summary>
3550                 /// <param name="constVal">the initial value for this property</param>
3551                 public void AddInitValue(Constant constVal) 
3552                 {
3553                         this.constVal = new ConstantElem(this,constVal);
3554                 }
3555
3556                 public void SetInstance (bool isInstance)
3557                 {
3558                         this.instance = isInstance;
3559                 }
3560
3561                 internal sealed override void BuildTables(MetaData md) 
3562                 {
3563                         if (done) return;
3564                         nameIx = md.AddToStringsHeap(name);
3565                         MemoryStream sig = new MemoryStream();
3566                         byte tag = PropertyTag;
3567                         if (instance)
3568                                 tag |= 0x20;
3569                         sig.WriteByte(tag);
3570                         MetaData.CompressNum(numPars,sig);
3571                         returnType.TypeSig(sig);
3572                         for (int i=0; i < numPars; i++) {
3573                                 parList[i].TypeSig(sig);
3574                         }
3575                         typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3576                         for (int i=0; i < tide; i++) {
3577                                 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3578                         }
3579                         if (constVal != null) {
3580                                 md.AddToTable(MDTable.Constant,constVal);
3581                                 constVal.BuildTables(md);
3582                         }
3583                         done = true;
3584                 }
3585
3586                 internal sealed override uint Size(MetaData md) 
3587                 {
3588                         return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3589                 }
3590
3591                 internal sealed override void Write(FileImage output) 
3592                 {
3593                         output.Write(flags);
3594                         output.StringsIndex(nameIx);
3595                         output.BlobIndex(typeBlobIx);
3596                 }
3597
3598                 internal sealed override uint GetCodedIx(CIx code) 
3599                 {
3600                         switch (code) {
3601                                 case (CIx.HasCustomAttr) : return 9; 
3602                                 case (CIx.HasConst) : return 2; 
3603                                 case (CIx.HasSemantics) : return 1; 
3604                         }
3605                         return 0;
3606                 }
3607
3608         }
3609
3610         /**************************************************************************/  
3611         /// <summary>
3612         /// Base class for field/methods (member of a class)
3613         /// </summary>
3614         public abstract class Member : MetaDataElement {
3615
3616                 protected string name;
3617                 protected uint nameIx = 0, sigIx = 0;
3618
3619                 internal Member(string memName)
3620                 {
3621                         name = memName;
3622                         tabIx = MDTable.MemberRef;
3623                 }
3624
3625         }
3626
3627         /*****************************************************************************/  
3628         /// <summary>
3629         /// Descriptor for a field of a class
3630         /// </summary>
3631
3632         public abstract class Field : Member {
3633
3634                 protected static readonly byte FieldSig = 0x6;
3635
3636                 protected Type type;
3637
3638                 internal Field(string pfName, Type pfType) : base(pfName)
3639                 {
3640                         type = pfType;
3641                 }
3642
3643         }
3644         /**************************************************************************/  
3645         /// <summary>
3646         /// Descriptor for a field defined in a class of THIS assembly/module
3647         /// </summary>
3648         public class FieldDef : Field {
3649
3650                 //private static readonly uint PInvokeImpl = 0x2000;
3651                 private static readonly ushort HasFieldRVA = 0x100;
3652                 private static readonly ushort HasDefault = 0x8000;
3653
3654                 FieldRVA rva;
3655                 ConstantElem constVal;
3656                 FieldLayout layout;
3657                 FieldMarshal marshalInfo;
3658                 ushort flags;
3659
3660                 internal FieldDef(string name, Type fType) : base(name,fType) 
3661                 {
3662                         tabIx = MDTable.Field;
3663                 }
3664
3665                 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) 
3666                 {
3667                         flags = (ushort)attrSet;
3668                         tabIx = MDTable.Field;
3669                 }
3670
3671                 /// <summary>
3672                 /// Add an attribute(s) to this field
3673                 /// </summary>
3674                 /// <param name="fa">the attribute(s) to be added</param>
3675                 public void AddFieldAttr(FieldAttr fa) 
3676                 {
3677                         flags |= (ushort)fa;
3678                 }
3679
3680                 /// <summary>
3681                 /// Add a value for this field
3682                 /// </summary>
3683                 /// <param name="val">the value for the field</param>
3684                 public void AddValue(Constant val) 
3685                 {
3686                         constVal = new ConstantElem(this,val);
3687                         flags |= HasDefault;
3688                 }
3689
3690                 /// <summary>
3691                 /// Add an initial value for this field (at dataLabel) (.data)
3692                 /// </summary>
3693                 /// <param name="val">the value for the field</param>
3694                 /// <param name="repeatVal">the number of repetitions of this value</param>
3695                 public void AddDataValue(DataConstant val) 
3696                 {
3697                         flags |= HasFieldRVA;
3698                         rva = new FieldRVA(this,val);
3699                 }
3700
3701                 /// <summary>
3702                 /// Set the offset of the field.  Used for sequential or explicit classes.
3703                 /// (.field [offs])
3704                 /// </summary>
3705                 /// <param name="offs">field offset</param>
3706                 public void SetOffset(uint offs) 
3707                 {
3708                         layout = new FieldLayout(this,offs);
3709                 }
3710
3711                 /// <summary>
3712                 /// Set the marshalling info for a field
3713                 /// </summary>
3714                 /// <param name="mInf"></param>
3715                 public void SetMarshalInfo(NativeType marshallType) 
3716                 {
3717                         flags |= (ushort) FieldAttr.HasFieldMarshal;
3718                         marshalInfo = new FieldMarshal(this,marshallType);
3719                 }
3720
3721                 internal sealed override void BuildTables(MetaData md) 
3722                 {
3723                         if (done) return;
3724                         nameIx = md.AddToStringsHeap(name);
3725                         MemoryStream sig = new MemoryStream();
3726                         sig.WriteByte(FieldSig);
3727                         type.TypeSig(sig);
3728                         sigIx = md.AddToBlobHeap(sig.ToArray());
3729                         if (rva != null) {
3730                                 md.AddToTable(MDTable.FieldRVA,rva);
3731                                 rva.BuildTables(md);
3732                         } else if (constVal != null) {
3733                                 md.AddToTable(MDTable.Constant,constVal);
3734                                 constVal.BuildTables(md);
3735                         }
3736                         if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3737                         if (marshalInfo != null) {
3738                                 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3739                                 marshalInfo.BuildTables(md);
3740                         }
3741                         done = true;
3742                 }
3743
3744                 internal sealed override uint Size(MetaData md) 
3745                 {
3746                         return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3747                 }
3748
3749                 internal sealed override void Write(FileImage output) 
3750                 {
3751                         output.Write(flags);
3752                         output.StringsIndex(nameIx);
3753                         output.BlobIndex(sigIx);
3754                 }
3755
3756                 internal sealed override uint GetCodedIx(CIx code) 
3757                 {
3758                         switch (code) {
3759                                 case (CIx.HasConst) : return 0; 
3760                                 case (CIx.HasCustomAttr) : return 1; 
3761                                 case (CIx.HasFieldMarshal) : return 0; 
3762                                 case (CIx.MemberForwarded) : return 0; 
3763                         }
3764                         return 0;
3765                 }
3766
3767         }
3768
3769         /**************************************************************************/  
3770         /// <summary>
3771         /// Descriptor for a field of a class defined in another assembly/module
3772         /// </summary>
3773         public class FieldRef : Field {
3774
3775                 MetaDataElement parent;
3776
3777                 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)   
3778                 {
3779                         parent = paren;
3780                 }
3781
3782                 internal sealed override void BuildTables(MetaData md) 
3783                 {
3784                         if (done) return;
3785                         nameIx = md.AddToStringsHeap(name);
3786                         MemoryStream sig = new MemoryStream();
3787                         sig.WriteByte(FieldSig);
3788                         type.TypeSig(sig);
3789                         sigIx = md.AddToBlobHeap(sig.ToArray());
3790                         done = true;
3791                 }
3792
3793                 internal sealed override uint Size(MetaData md) 
3794                 {
3795                         return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3796                 }
3797
3798                 internal sealed override void Write(FileImage output) 
3799                 {
3800                         output.WriteCodedIndex(CIx.MemberRefParent,parent);
3801                         output.StringsIndex(nameIx);
3802                         output.BlobIndex(sigIx);
3803                 }
3804
3805                 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3806
3807         }
3808
3809         /**************************************************************************/  
3810         /// <summary>
3811         /// Base class for Method Descriptors
3812         /// </summary>
3813
3814         public abstract class Method : Member {
3815
3816                 internal Method (string methName) : base (methName)
3817                 {}
3818
3819                 public abstract void AddCallConv(CallConv cconv);
3820                 internal abstract void TypeSig(MemoryStream sig);
3821                 internal abstract uint GetSigIx(MetaData md);
3822         }
3823
3824         /**************************************************************************/  
3825         /// <summary>
3826         /// Descriptor for a method defined in THIS assembly/module
3827         /// IL     .method
3828         /// </summary>
3829
3830         public class MethodDef : Method {
3831
3832                 private static readonly ushort PInvokeImpl = 0x2000;
3833                 //private static readonly uint UnmanagedExport = 0x0008;
3834                 // private static readonly byte LocalSigByte = 0x7;
3835                 uint parIx = 0, textOffset = 0;
3836                 private CallConv callConv = CallConv.Default;
3837                 private int gen_param_count;
3838
3839                 MetaData metaData;
3840                 CILInstructions code;
3841                 Param[] parList;
3842                 Local[] locals;
3843                 bool initLocals;
3844                 ushort methFlags = 0, implFlags = 0;
3845                 int maxStack = 0, numPars = 0;
3846                 bool entryPoint = false;
3847                 LocalSig localSig;
3848                 ArrayList varArgSigList;
3849                 ImplMap pinvokeImpl;
3850                 Param ret_param;
3851
3852                 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3853                         : this (md, 0, 0, name, ret_param, pars)
3854                 {
3855                 }
3856
3857                 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, 
3858                                 Param ret_param, Param [] pars) 
3859                         : base (name)
3860                 {
3861                         methFlags = (ushort)mAttrSet;
3862                         implFlags = (ushort)iAttrSet;
3863                         this.ret_param = ret_param;
3864                         metaData = md;
3865                         parList = pars;
3866                         if (parList != null) 
3867                                 numPars = parList.Length;
3868                         tabIx = MDTable.Method;
3869                 }
3870
3871                 internal Param[] GetPars() 
3872                 {
3873                         return parList;
3874                 }
3875
3876                 internal override uint GetSigIx(MetaData md)
3877                 {
3878                         MemoryStream sig = new MemoryStream();
3879                         TypeSig(sig);
3880                         return md.AddToBlobHeap(sig.ToArray());
3881                 }
3882
3883                 public override void AddCallConv(CallConv cconv)
3884                 {
3885                         callConv |= cconv;
3886                 }
3887                 
3888                 /// <summary>
3889                 /// Add some attributes to this method descriptor
3890                 /// </summary>
3891                 /// <param name="ma">the attributes to be added</param>
3892                 public void AddMethAttribute(MethAttr ma) 
3893                 {
3894                         methFlags |= (ushort)ma;
3895                 }
3896
3897                 /// <summary>
3898                 /// Add some implementation attributes to this method descriptor
3899                 /// </summary>
3900                 /// <param name="ia">the attributes to be added</param>
3901                 public void AddImplAttribute(ImplAttr ia) 
3902                 {
3903                         implFlags |= (ushort)ia;
3904                 }
3905
3906                 public void AddPInvokeInfo(ModuleRef scope, string methName,
3907                                 PInvokeAttr callAttr) {
3908                         pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3909                         methFlags |= PInvokeImpl;
3910                 }
3911
3912                 /// <summary>
3913                 ///  Add a named generic type parameter
3914                 /// </summary>
3915                 public GenericParameter AddGenericParameter (short index, string name) 
3916                 {
3917                         return AddGenericParameter (index, name, 0);
3918                 }
3919
3920                 /// <summary>
3921                 ///  Add a named generic type parameter with attributes
3922                 /// </summary>
3923                 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr) 
3924                 {
3925                         GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3926                         metaData.AddToTable (MDTable.GenericParam, gp);
3927                         gen_param_count ++;
3928                         return gp;
3929                 }
3930
3931                 /// <summary>
3932                 /// Set the maximum stack height for this method
3933                 /// </summary>
3934                 /// <param name="maxStack">the maximum height of the stack</param>
3935                 public void SetMaxStack(int maxStack) 
3936                 {
3937                         this.maxStack = maxStack; 
3938                 }
3939
3940                 /// <summary>
3941                 /// Add local variables to this method
3942                 /// </summary>
3943                 /// <param name="locals">the locals to be added</param>
3944                 /// <param name="initLocals">are locals initialised to default values</param>
3945                 public void AddLocals(Local[] locals, bool initLocals) 
3946                 {
3947                         this.locals = locals;
3948                         this.initLocals = initLocals;
3949                 }
3950
3951                 /* Add Marshal info for return type */
3952                 public void AddRetTypeMarshallInfo (NativeType marshallType) 
3953                 {
3954                         ret_param.AddMarshallInfo (marshallType);
3955                 }
3956
3957                 /// <summary>
3958                 /// Mark this method as having an entry point
3959                 /// </summary>
3960                 public void DeclareEntryPoint() 
3961                 {
3962                         entryPoint = true;
3963                 }
3964
3965                 /// <summary>
3966                 /// Create a code buffer for this method to add the IL instructions to
3967                 /// </summary>
3968                 /// <returns>a buffer for this method's IL instructions</returns>
3969                 public CILInstructions CreateCodeBuffer() 
3970                 {
3971                         code = new CILInstructions(metaData);
3972                         return code;
3973                 }
3974
3975                 /// <summary>
3976                 /// Make a method reference descriptor for this method to be used 
3977                 /// as a callsite signature for this vararg method
3978                 /// </summary>
3979                 /// <param name="optPars">the optional pars for the vararg method call</param>
3980                 /// <returns></returns>
3981                 public MethodRef MakeVarArgSignature(Type[] optPars) 
3982                 {
3983                         Type[] pars = new Type[numPars];
3984                         MethodRef varArgSig;
3985                         for (int i=0; i < numPars; i++) {
3986                                 pars[i] = parList[i].GetParType();
3987                         }
3988                         varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3989
3990                         if (varArgSigList == null)
3991                                 varArgSigList = new ArrayList ();
3992                         varArgSigList.Add (varArgSig);
3993                         return varArgSig;
3994                 }
3995
3996                 internal sealed override void TypeSig(MemoryStream sig) 
3997                 {
3998                         sig.WriteByte((byte)callConv);
3999                         if ((callConv & CallConv.Generic) == CallConv.Generic)
4000                                 MetaData.CompressNum ((uint) gen_param_count, sig);
4001                         MetaData.CompressNum((uint)numPars,sig);
4002
4003                         ret_param.seqNo = 0;
4004                         ret_param.TypeSig (sig);
4005                         for (ushort i=0; i < numPars; i++) {
4006                                 parList[i].seqNo = (ushort)(i+1);
4007                                 parList[i].TypeSig(sig);
4008                         }
4009                 }
4010
4011                 internal sealed override void BuildTables(MetaData md) 
4012                 {
4013                         if (done) return;
4014                         if (pinvokeImpl != null) {
4015                                 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4016                                 pinvokeImpl.BuildTables(md);
4017                         }
4018                         if (entryPoint) md.SetEntryPoint(this);
4019                         uint locToken = 0;
4020                         if (locals != null) {
4021                                 localSig = new LocalSig(locals);
4022                                 md.AddToTable(MDTable.StandAloneSig,localSig);
4023                                 localSig.BuildTables(md);
4024                                 locToken = localSig.Token();
4025                         }
4026                         if (code != null) {
4027                                 code.CheckCode(locToken,initLocals,maxStack);
4028                                 textOffset = md.AddCode(code);
4029                         }
4030                         nameIx = md.AddToStringsHeap(name);
4031                         sigIx = GetSigIx(md);
4032                         parIx = md.TableIndex(MDTable.Param);
4033                         if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4034                                 md.AddToTable(MDTable.Param, ret_param);
4035                                 ret_param.BuildTables(md);
4036                         }
4037                         for (int i=0; i < numPars; i++) {
4038                                 md.AddToTable(MDTable.Param,parList[i]);
4039                                 parList[i].BuildTables(md);
4040                         }
4041                         if (varArgSigList != null) {
4042                                 foreach (MethodRef varArgSig in varArgSigList) {
4043                                         md.AddToTable(MDTable.MemberRef,varArgSig);
4044                                         varArgSig.BuildTables(md);
4045                                 }
4046                         }
4047                         // Console.WriteLine("method has " + numPars + " parameters");
4048                         done = true;
4049                 }
4050
4051                 internal sealed override uint Size(MetaData md) 
4052                 {
4053                         return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4054                 }
4055
4056                 internal sealed override void Write(FileImage output) 
4057                 {
4058                         if (ZeroRva ()) output.Write(0);
4059                         else output.WriteCodeRVA(textOffset);
4060                         output.Write(implFlags);
4061                         output.Write(methFlags);
4062                         output.StringsIndex(nameIx);
4063                         output.BlobIndex(sigIx);
4064                         output.WriteIndex(MDTable.Param,parIx);
4065                 }
4066
4067                 internal bool ZeroRva () 
4068                 {
4069                         return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4070                                         ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4071                                         ((implFlags & (ushort)ImplAttr.InternalCall) != 0) || 
4072                                         (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4073                 }
4074
4075                 internal sealed override uint GetCodedIx(CIx code) 
4076                 {
4077                         switch (code) {
4078                                 case (CIx.HasCustomAttr) : return 0; 
4079                                 case (CIx.HasDeclSecurity) : return 1; 
4080                                 case (CIx.MemberRefParent) : return 3; 
4081                                 case (CIx.MethodDefOrRef) : return 0; 
4082                                 case (CIx.MemberForwarded) : return 1; 
4083                                 case (CIx.CustomAttributeType) : return 2; 
4084                                 case (CIx.TypeOrMethodDef) : return 1; 
4085                         }
4086                         return 0;
4087                 }
4088
4089         }
4090         /**************************************************************************/  
4091         /// <summary>
4092         /// Descriptor for a method defined in another assembly/module
4093         /// </summary>
4094         public class MethodRef : Method {
4095
4096                 private static readonly byte Sentinel = 0x41;
4097                 Type[] parList, optParList;
4098                 MetaDataElement parent;
4099                 uint numPars = 0, numOptPars = 0;
4100                 CallConv callConv = CallConv.Default;
4101                 Type retType;
4102                 int gen_param_count;
4103
4104                 internal MethodRef(MetaDataElement paren, string name, Type retType,
4105                                 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4106                 {
4107                         parent = paren;
4108                         parList = pars;
4109                         this.retType = retType;
4110                         if (parList != null) numPars = (uint)parList.Length;
4111                         if (varArgMeth) {
4112                                 optParList = optPars;
4113                                 if (optParList != null) numOptPars = (uint)optParList.Length;
4114                                 callConv = CallConv.Vararg;
4115                         }
4116                         this.gen_param_count = gen_param_count;
4117                 }
4118
4119                 internal override uint GetSigIx(MetaData md)
4120                 {
4121                         MemoryStream sig = new MemoryStream();
4122                         TypeSig(sig);
4123                         return md.AddToBlobHeap(sig.ToArray());
4124                 }
4125
4126                 public override void AddCallConv(CallConv cconv)
4127                 {
4128                         callConv |= cconv;
4129                 }
4130                 
4131                 internal sealed override void TypeSig(MemoryStream sig) 
4132                 {
4133                         sig.WriteByte((byte)callConv);
4134                         if ((callConv & CallConv.Generic) == CallConv.Generic)
4135                                 MetaData.CompressNum ((uint) gen_param_count, sig);
4136                         MetaData.CompressNum(numPars+numOptPars,sig);
4137                         retType.TypeSig(sig);
4138                         for (int i=0; i < numPars; i++) {
4139                                 parList[i].TypeSig(sig);
4140                         }
4141                         if (numOptPars > 0) {
4142                                 sig.WriteByte(Sentinel);
4143                                 for (int i=0; i < numOptPars; i++) {
4144                                         optParList[i].TypeSig(sig);
4145                                 }
4146                         }
4147                 }
4148
4149                 internal sealed override void BuildTables(MetaData md) 
4150                 {
4151                         if (done) return;
4152                         nameIx = md.AddToStringsHeap(name);
4153                         sigIx = GetSigIx(md);
4154                         done = true;
4155                 }
4156
4157                 internal sealed override uint Size(MetaData md) 
4158                 {
4159                         return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4160                 }
4161
4162                 internal sealed override void Write(FileImage output) 
4163                 {
4164                         output.WriteCodedIndex(CIx.MemberRefParent,parent);
4165                         output.StringsIndex(nameIx);
4166                         output.BlobIndex(sigIx);
4167                 }
4168
4169                 internal sealed override uint GetCodedIx(CIx code) 
4170                 {
4171                         switch (code) {
4172                                 case (CIx.HasCustomAttr) : return 6; 
4173                                 case (CIx.MethodDefOrRef) : return 1; 
4174                                 case (CIx.CustomAttributeType) : return 3; 
4175                         }
4176                         return 0;
4177                 }
4178
4179         }
4180
4181
4182         /**************************************************************************/  
4183         /// <summary>
4184         /// Descriptors for native types used for marshalling
4185         /// </summary>
4186         public class NativeType {
4187                 public static readonly NativeType Void = new NativeType(0x01);
4188                 public static readonly NativeType Boolean = new NativeType(0x02);
4189                 public static readonly NativeType Int8 = new NativeType(0x03);
4190                 public static readonly NativeType UInt8 = new NativeType(0x04);
4191                 public static readonly NativeType Int16 = new NativeType(0x05);
4192                 public static readonly NativeType UInt16 = new NativeType(0x06);
4193                 public static readonly NativeType Int32 = new NativeType(0x07);
4194                 public static readonly NativeType UInt32 = new NativeType(0x08);
4195                 public static readonly NativeType Int64 = new NativeType(0x09);
4196                 public static readonly NativeType UInt64 = new NativeType(0x0A);
4197                 public static readonly NativeType Float32 = new NativeType(0x0B);
4198                 public static readonly NativeType Float64 = new NativeType(0x0C);
4199                 public static readonly NativeType Currency = new NativeType(0x0F);
4200                 public static readonly NativeType BStr = new NativeType(0x13);
4201                 public static readonly NativeType LPStr = new NativeType(0x14);
4202                 public static readonly NativeType LPWStr = new NativeType(0x15);
4203                 public static readonly NativeType LPTStr = new NativeType(0x16);
4204                 public static readonly NativeType FixedSysString = new NativeType(0x17);
4205                 public static readonly NativeType IUnknown = new NativeType(0x19);
4206                 public static readonly NativeType IDispatch = new NativeType(0x1A);
4207                 public static readonly NativeType Struct = new NativeType(0x1B);
4208                 public static readonly NativeType Interface = new NativeType(0x1C);
4209                 public static readonly NativeType Int = new NativeType(0x1F);
4210                 public static readonly NativeType UInt = new NativeType(0x20);
4211                 public static readonly NativeType ByValStr = new NativeType(0x22);
4212                 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4213                 public static readonly NativeType TBstr = new NativeType(0x24);
4214                 public static readonly NativeType VariantBool = new NativeType(0x25);
4215                 public static readonly NativeType FuncPtr = new NativeType(0x26);
4216                 public static readonly NativeType AsAny = new NativeType(0x28);
4217                 public static readonly NativeType LPStruct = new NativeType(0x2b);
4218                 public static readonly NativeType Error = new NativeType(0x2d);
4219
4220                 protected byte typeIndex;
4221
4222                 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4223                 internal byte GetTypeIndex() { return typeIndex; }
4224
4225                 internal virtual byte[] ToBlob() 
4226                 {
4227                         byte[] bytes = new byte[1];
4228                         bytes[0] = GetTypeIndex();
4229                         return bytes;
4230                 }
4231
4232         }
4233
4234         public class FixedSysString : NativeType  {
4235
4236                 uint size;
4237
4238                 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4239                 {
4240                         this.size = size;
4241                 }
4242
4243                 internal override byte [] ToBlob () 
4244                 {
4245                         MemoryStream str = new MemoryStream ();
4246                         str.WriteByte (GetTypeIndex ());
4247                         MetaData.CompressNum (size, str);
4248                         return str.ToArray ();
4249                 }
4250
4251         }  
4252
4253         public class NativeArray : NativeType  {
4254
4255                 NativeType elemType;
4256                 int numElem = -1, parNum = -1, elemMult = -1;
4257
4258                 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1) 
4259                 {
4260                         this.elemType = elemType;
4261                 }
4262
4263                 /*    public NativeArray(NativeType elemType, int len) : base(0x2A) {
4264                       this.elemType = elemType;
4265                       this.len = len;
4266                       }
4267                  */
4268
4269                 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A) 
4270                 {
4271                         this.elemType = elemType;
4272                         this.numElem = numElem;
4273                         parNum = parNumForLen;
4274                         this.elemMult = elemMult;
4275                 }
4276
4277                 public NativeArray(NativeType elemType, int numElem, int parNumForLen) 
4278                         : this (elemType, numElem, parNumForLen, -1) 
4279                 {
4280                 }
4281
4282                 internal override byte[] ToBlob() 
4283                 {
4284                         MemoryStream str = new MemoryStream();
4285                         str.WriteByte(GetTypeIndex());
4286                         if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
4287                         else str.WriteByte(elemType.GetTypeIndex());
4288
4289                         /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4290                          * LAMESPEC: Older spec versions say elemMult comes before
4291                          * len. Newer spec versions don't talk about elemMult at
4292                          * all, but csc still emits it, and it is used to distinguish
4293                          * between parNum being 0, and parNum being omitted.
4294                          */
4295
4296                         if (parNum == -1)
4297                                 // <native_type> []
4298                                 return str.ToArray ();
4299
4300                         MetaData.CompressNum((uint) parNum,str);
4301                         if (numElem != -1) {
4302                                 MetaData.CompressNum ((uint) numElem, str);
4303                                 if (elemMult != -1)
4304                                         // <native_type> [ int32 ]
4305                                         MetaData.CompressNum((uint) elemMult,str);
4306                                 //else <native_type> [ int32 + int32 ]
4307                         } else if (elemMult != -1) {
4308                                 // When can this occur ?
4309                                 MetaData.CompressNum (0, str);
4310                                 MetaData.CompressNum((uint) elemMult,str);
4311                         }
4312                         //else <native_type> [ + int32 ]
4313
4314                         return str.ToArray();
4315                 }
4316
4317         }
4318
4319         public class SafeArray : NativeType  {
4320
4321                 SafeArrayType elemType;
4322                 bool hasElemType;
4323
4324                 public SafeArray() : base(0x1D) 
4325                 {
4326                 }
4327
4328                 public SafeArray(SafeArrayType elemType) : base(0x1D) 
4329                 {
4330                         this.elemType = elemType;
4331                         hasElemType = true;
4332                 }
4333
4334                 internal override byte[] ToBlob() 
4335                 {
4336                         byte[] bytes = new byte[hasElemType ? 2 : 1];
4337                         bytes[0] = GetTypeIndex();
4338                         if (hasElemType)
4339                                 bytes[1] = (byte)elemType;
4340                         return bytes;
4341                 }
4342
4343         }
4344
4345         public class FixedArray : NativeType  {
4346
4347                 uint numElem;
4348
4349                 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4350                 public FixedArray(int numElems) : base(0x1E) 
4351                 {
4352                         //this.elemType = elemType;
4353                         numElem = (uint)numElems;
4354                 }
4355
4356                 internal override byte[] ToBlob() 
4357                 {
4358                         MemoryStream str = new MemoryStream();
4359                         str.WriteByte(GetTypeIndex());
4360                         MetaData.CompressNum(numElem,str);
4361                         /* FIXME: 
4362                            fixed array [5] lpstr [2]
4363                            This format is not supported by ilasm 1.1.4322.2032, 
4364                            but is supported by 2.0.5125..
4365                            ilasm 1.1 only supports "fixed array [5]" 
4366                            if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
4367                            else str.WriteByte(elemType.GetTypeIndex());*/
4368
4369                         return str.ToArray();
4370                 }
4371
4372         }
4373
4374         public class CustomMarshaller : NativeType  {
4375
4376                 string typeName;
4377                 string marshallerName;
4378                 string cookie;
4379
4380                 public CustomMarshaller(string typeNameOrGUID, string marshallerName, 
4381                                 string optCookie) : base(0x2C) 
4382                 {
4383                         typeName = typeNameOrGUID;
4384                         this.marshallerName = marshallerName;
4385                         cookie = optCookie;
4386                 }
4387
4388                 public CustomMarshaller(string marshallerName, string optCookie)
4389                         :this (null, marshallerName, optCookie) 
4390                 {
4391                 }
4392
4393                 internal override byte[] ToBlob() 
4394                 {
4395                         MemoryStream str = new MemoryStream();
4396                         BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4397                         bw.Write(GetTypeIndex());
4398                         //Native type name & unmanaged type - unused
4399                         //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4400                         bw.Write ((byte) 0); // Native Type name, unused 
4401                         bw.Write ((byte) 0); // Unmanaged type, unused 
4402                         if (marshallerName != null) {
4403                                 MetaData.CompressNum ((uint)marshallerName.Length, str);
4404                                 bw.Write(marshallerName.ToCharArray());
4405                         } else { 
4406                                 bw.Write ((byte) 0);
4407                         }
4408                         if (cookie != null) {
4409                                 MetaData.CompressNum ((uint)cookie.Length, str);
4410                                 bw.Write(cookie.ToCharArray());
4411                         } else {
4412                                 bw.Write ((byte) 0);
4413                         }
4414                         bw.Flush();
4415                         return str.ToArray();
4416                 }
4417         }
4418
4419         /**************************************************************************/  
4420         /// <summary>
4421         /// Descriptor for the Primitive types defined in IL
4422         /// </summary>
4423         public class PrimitiveType : Type {
4424
4425                 private string name;
4426                 private int systemTypeIndex;
4427                 public static int NumSystemTypes = 18;
4428
4429                 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4430                 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4431                 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4432                 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4433                 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4434                 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4435                 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4436                 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4437                 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4438                 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4439                 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4440                 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4441                 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4442                 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4443                 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4444                 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4445                 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4446                 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4447                 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4448                 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4449                 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4450                 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4451                 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4452                 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4453                 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4454                 public static readonly PrimitiveType NativeInt = IntPtr;
4455                 public static readonly PrimitiveType NativeUInt = UIntPtr;
4456
4457                 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4458
4459                 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) 
4460                 {
4461                         this.name = name;
4462                         this.systemTypeIndex = STIx;
4463                 }
4464
4465                 internal string GetName() { return name; }
4466
4467                 internal int GetSystemTypeIx() { return systemTypeIndex; }
4468
4469                 internal sealed override void TypeSig(MemoryStream str) 
4470                 {
4471                         str.WriteByte(typeIndex);
4472                 }
4473
4474                 internal override MetaDataElement GetTypeSpec(MetaData md) 
4475                 {
4476                         TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4477                         if (tS == null) {
4478                                 tS = new TypeSpec(this,md);
4479                                 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4480                                 md.AddToTable(MDTable.TypeSpec,tS);
4481                         }
4482                         return tS;
4483                 }
4484
4485         }
4486
4487         public class PrimitiveTypeRef : Type
4488         {
4489                 PrimitiveType type;
4490                 MetaData metaData;
4491
4492                 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4493                         : base (0)
4494                 {
4495                         this.type = type;
4496                         this.metaData = md;
4497                 }
4498
4499                 internal uint TypeDefOrRefToken()
4500                 {
4501                         uint cIx = type.GetTypeSpec (metaData).Row;
4502                         cIx = (cIx << 2) | 0x2;
4503                         return cIx;
4504                 }
4505         }
4506
4507         /**************************************************************************/  
4508         /// <summary>
4509         /// Descriptor for an pointer (type * or type &)
4510         /// </summary>
4511         public abstract class PtrType : Type {
4512
4513                 Type baseType;
4514
4515                 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4516                 {
4517                         baseType = bType;
4518                         tabIx = MDTable.TypeSpec;
4519                 }
4520
4521                 internal sealed override void TypeSig(MemoryStream str) 
4522                 {
4523                         str.WriteByte(typeIndex);
4524                         baseType.TypeSig(str);
4525                 }
4526
4527         }
4528         /**************************************************************************/  
4529         /// <summary>
4530         /// Descriptor for a managed pointer (type &  or byref)
4531         /// </summary>
4532
4533         public class ManagedPointer : PtrType {
4534
4535                 /// <summary>
4536                 /// Create new managed pointer to baseType
4537                 /// </summary>
4538                 /// <param name="bType">the base type of the pointer</param>
4539                 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4540
4541         }
4542         /**************************************************************************/  
4543         /// <summary>
4544         /// Descriptor for an unmanaged pointer (type *)
4545         /// </summary>
4546         public class UnmanagedPointer : PtrType {
4547
4548                 /// <summary>
4549                 /// Create a new unmanaged pointer to baseType
4550                 /// </summary>
4551                 /// <param name="baseType">the base type of the pointer</param>
4552                 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4553
4554         }
4555
4556         /**************************************************************************/  
4557
4558         public interface IExternRef  {
4559                 ClassRef AddClass(string nsName, string name);
4560                 ClassRef AddValueClass(string nsName, string name);
4561         }
4562
4563         /// <summary>
4564         /// A reference to an external assembly (.assembly extern)
4565         /// </summary>
4566         public class AssemblyRef : ResolutionScope, IExternRef {
4567
4568                 private ushort major, minor, build, revision;
4569                 uint flags, keyIx, hashIx, cultIx;
4570                 bool hasVersion = false, isKeyToken = false;
4571                 byte[] keyBytes;
4572                 string culture;
4573
4574                 internal AssemblyRef(MetaData md, string name) : base(name,md) 
4575                 {
4576                         tabIx = MDTable.AssemblyRef;
4577                 }
4578
4579                 public void AddAssemblyAttr (AssemAttr aa)
4580                 {
4581                         flags |= (uint)aa;
4582                 }
4583
4584                 /// <summary>
4585                 /// Add version information about this external assembly
4586                 /// </summary>
4587                 /// <param name="majVer">Major Version</param>
4588                 /// <param name="minVer">Minor Version</param>
4589                 /// <param name="bldNo">Build Number</param>
4590                 /// <param name="revNo">Revision Number</param>
4591                 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) 
4592                 {
4593                         major = (ushort)majVer;
4594                         minor = (ushort)minVer;
4595                         build = (ushort)bldNo;
4596                         revision = (ushort)revNo;
4597                         hasVersion = true;
4598                 }
4599
4600                 /// <summary>
4601                 /// Add the hash value for this external assembly
4602                 /// </summary>
4603                 /// <param name="hash">bytes of the hash value</param>
4604                 public void AddHash(byte[] hash) 
4605                 {
4606                         hashIx = metaData.AddToBlobHeap(hash); 
4607                 }
4608
4609                 /// <summary>
4610                 /// Set the culture for this external assembly
4611                 /// </summary>
4612                 /// <param name="cult">the culture string</param>
4613                 public void AddCulture(string cult) 
4614                 {
4615                         cultIx = metaData.AddToStringsHeap(cult);
4616                         culture = cult;
4617                 }
4618
4619                 /// <summary>
4620                 /// Add the full public key for this external assembly
4621                 /// </summary>
4622                 /// <param name="key">bytes of the public key</param>
4623                 public void AddKey(byte[] key) 
4624                 {
4625                         flags |= 0x0001;   // full public key
4626                         keyBytes = key;
4627                         keyIx = metaData.AddToBlobHeap(key); 
4628                 }
4629
4630                 /// <summary>
4631                 /// Add the public key token (low 8 bytes of the public key)
4632                 /// </summary>
4633                 /// <param name="key">low 8 bytes of public key</param>
4634                 public void AddKeyToken(byte[] key) 
4635                 {
4636                         keyIx = metaData.AddToBlobHeap(key); 
4637                         keyBytes = key;
4638                         isKeyToken = true;
4639                 }
4640
4641                 /// <summary>
4642                 /// Add a class to this external assembly
4643                 /// </summary>
4644                 /// <param name="nsName">name space name</param>
4645                 /// <param name="name">class name</param>
4646                 /// <returns></returns>
4647                 public virtual ClassRef AddClass(string nsName, string name) 
4648                 {
4649                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4650                         metaData.AddToTable(MDTable.TypeRef,aClass);
4651                         aClass.SetParent(this);
4652                         return aClass;
4653                 }
4654
4655                 /// <summary>
4656                 /// Add a value class to this external assembly
4657                 /// </summary>
4658                 /// <param name="nsName">name space name</param>
4659                 /// <param name="name">class name</param>
4660                 /// <returns></returns>
4661                 public virtual ClassRef AddValueClass(string nsName, string name) 
4662                 {
4663                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4664                         metaData.AddToTable(MDTable.TypeRef,aClass);
4665                         aClass.SetParent(this);
4666                         aClass.MakeValueClass(ValueClass.ValueType);
4667                         return aClass;
4668                 }
4669
4670                 internal string TypeName() 
4671                 {
4672                         string result = name;
4673                         if (hasVersion) 
4674                                 result = result + ", Version=" + major + "." + minor + "." + 
4675                                         build + "." + revision;
4676                         if (keyBytes != null) {
4677                                 string tokenStr = "=";
4678                                 if (isKeyToken) tokenStr = "Token=";
4679                                 result = result + ", PublicKey" + tokenStr;
4680                                 for (int i=0; i < keyBytes.Length; i++) {
4681                                         result = result + Hex.Byte(keyBytes[i]);
4682                                 }
4683                         }
4684                         if (culture != null) 
4685                                 result = result + ", Culture=" + culture;
4686                         return result;
4687                 }
4688
4689                 internal sealed override uint Size(MetaData md) 
4690                 {
4691                         return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4692                 }
4693
4694                 internal sealed override void Write(FileImage output) 
4695                 {
4696                         output.Write(major);
4697                         output.Write(minor);
4698                         output.Write(build);
4699                         output.Write(revision);
4700                         output.Write(flags);
4701                         output.BlobIndex(keyIx);
4702                         output.StringsIndex(nameIx);
4703                         output.StringsIndex(cultIx);
4704                         output.BlobIndex(hashIx);
4705                 }
4706
4707                 internal sealed override uint GetCodedIx(CIx code) 
4708                 {
4709                         switch (code) {
4710                                 case (CIx.ResolutionScope) : return 2; 
4711                                 case (CIx.HasCustomAttr) : return 15; 
4712                                 case (CIx.Implementation) : return 1; 
4713                         }
4714                         return 0;
4715                 }
4716
4717         }
4718
4719         /**************************************************************************/  
4720         /// <summary>
4721         /// Descriptor for a class defined in System (mscorlib)
4722         /// </summary>
4723         internal class SystemClass : ClassRef {
4724
4725                 PrimitiveType elemType; 
4726
4727                 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4728                         : base("System",eType.GetName(),md) {
4729                                 elemType = eType;
4730                                 parent = paren;
4731                         }
4732
4733                 internal override sealed MetaDataElement GetTypeSpec(MetaData md) 
4734                 {
4735                         if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4736                         return typeSpec;
4737                 }
4738
4739
4740                 internal sealed override void TypeSig(MemoryStream str) 
4741                 {
4742                         str.WriteByte(elemType.GetTypeIndex());
4743                 }
4744
4745         }
4746
4747         /**************************************************************************/  
4748         /// <summary>
4749         /// The assembly for mscorlib.  
4750         /// </summary>
4751         public sealed class MSCorLib : AssemblyRef {
4752
4753                 private static readonly int valueTypeIx = 18;
4754                 private readonly string systemName = "System";
4755                 private Class[] systemClasses = new Class[valueTypeIx+2];
4756                 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4757
4758                 private static int[] specialNames = {
4759                         PrimitiveType.Void.GetName().GetHashCode(),
4760                         PrimitiveType.Boolean.GetName().GetHashCode(),
4761                         PrimitiveType.Char.GetName().GetHashCode(),
4762                         PrimitiveType.Int8.GetName().GetHashCode(),
4763                         PrimitiveType.UInt8.GetName().GetHashCode(),
4764                         PrimitiveType.Int16.GetName().GetHashCode(),
4765                         PrimitiveType.UInt16.GetName().GetHashCode(),
4766                         PrimitiveType.Int32.GetName().GetHashCode(),
4767                         PrimitiveType.UInt32.GetName().GetHashCode(),
4768                         PrimitiveType.Int64.GetName().GetHashCode(),
4769                         PrimitiveType.UInt64.GetName().GetHashCode(),
4770                         PrimitiveType.Float32.GetName().GetHashCode(),
4771                         PrimitiveType.Float64.GetName().GetHashCode(),
4772                         PrimitiveType.String.GetName().GetHashCode(),
4773                         PrimitiveType.TypedRef.GetName().GetHashCode(),
4774                         PrimitiveType.IntPtr.GetName().GetHashCode(),
4775                         PrimitiveType.UIntPtr.GetName().GetHashCode(),
4776                         PrimitiveType.Object.GetName().GetHashCode(),
4777                         PrimitiveType.ValueType.GetName ().GetHashCode(),
4778                         "Enum".GetHashCode()
4779                 };
4780
4781                 internal MSCorLib(MetaData md) : base(md,"mscorlib") 
4782                 {
4783                         if (!PEFile.IsMSCorlib)
4784                                 md.AddToTable(MDTable.AssemblyRef,this);
4785                         systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4786                         systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4787                         systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4788                         systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4789                         systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4790                         systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4791                         systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4792                         systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4793                         systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4794                         systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4795                         systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4796                         systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4797                         systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4798                         systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4799                         systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4800                         systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4801                         systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4802                         systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4803                 }
4804
4805                 /// <summary>
4806                 /// Add a class to the mscorlib assembly
4807                 /// </summary>
4808                 /// <param name="nsName">name space name</param>
4809                 /// <param name="name">class name</param>
4810                 /// <returns></returns>
4811                 public override ClassRef AddClass(string nsName, string name) 
4812                 {
4813                         /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4814                            it should be returning ClassRef ..*/
4815                         Class aClass = GetSpecialClass(nsName,name);
4816                         if (aClass == null) {
4817                                 aClass = new ClassRef(nsName,name,metaData);
4818                                 metaData.AddToTable(MDTable.TypeRef,aClass);
4819                                 if (aClass is ClassRef)
4820                                         ((ClassRef) aClass).SetParent(this);
4821                         }
4822                         //FIXME: Check for !ClassRef here?
4823                         return (ClassRef) aClass;
4824                 }
4825
4826                 private Class GetSpecialClass(string nsName,string name) 
4827                 {
4828                         if (nsName.CompareTo(systemName) != 0) return null;
4829                         int hash = name.GetHashCode();
4830                         for (int i=0; i < specialNames.Length; i++) {
4831                                 if (hash != specialNames[i])
4832                                         continue;
4833                                 if (systemClasses[i] == null) {
4834                                         if (i < valueTypeIx) {
4835                                                 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4836                                                 if ((systemTypes[i] != PrimitiveType.Object) &&
4837                                                                 (systemTypes[i] != PrimitiveType.String)) {
4838                                                         systemClasses[i].MakeValueClass(ValueClass.ValueType);
4839                                                 }
4840                                         } else {
4841                                                 systemClasses[i] = new ClassRef(nsName,name,metaData);
4842                                                 ((ClassRef) systemClasses[i]).SetParent(this);
4843                                                 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4844                                                         systemClasses[i].MakeValueClass(ValueClass.ValueType);
4845                                         }
4846                                         metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4847                                 }
4848                                 return systemClasses[i];
4849                         }
4850                         return null;
4851                 }
4852
4853                 internal void SetSpecialSystemClass (string nsName, string name, Class aClass) 
4854                 {
4855                         if (nsName != systemName) return;
4856                         int hash = name.GetHashCode ();
4857                         for (int i = 0; i < specialNames.Length; i++) {
4858                                 if (hash != specialNames [i])
4859                                         continue;
4860                                 if (systemClasses [i] == null) {
4861                                         systemClasses [i] = aClass;
4862                                 }
4863                         }
4864                 }
4865
4866                 internal Class GetSpecialSystemClass(PrimitiveType pType) 
4867                 {
4868                         int ix = pType.GetSystemTypeIx();
4869                         if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4870                                 systemClasses[ix] = new SystemClass(pType,this,metaData);
4871                                 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4872                         }
4873                         return systemClasses[ix];
4874                 }
4875
4876                 private ClassRef GetValueClass(string name, int hash) 
4877                 {
4878                         /* Called by MSCorLib.AddValueClass, which is called by
4879                            !mscorlib, for adding ref to value class INTO mscorlib,
4880                            so this should be classref */
4881                         int ix = valueTypeIx;
4882                         if (hash != specialNames[valueTypeIx]) ix++;
4883                         if (systemClasses[ix] == null) {
4884                                 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4885                                 ((ClassRef) systemClasses[ix]).SetParent(this);
4886                                 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4887                                 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4888                         }
4889                         return (ClassRef) systemClasses[ix];
4890                 }
4891
4892                 internal Class ValueType() 
4893                 {
4894                         if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4895                                 ClassRef valType = new ClassRef("System","ValueType",metaData);
4896                                 valType.SetParent(this);
4897                                 valType.MakeValueClass(ValueClass.ValueType);
4898                                 metaData.AddToTable(MDTable.TypeRef,valType);
4899                                 systemClasses[valueTypeIx] = valType;
4900                         }
4901                         return systemClasses[valueTypeIx];
4902                 }
4903
4904                 internal Class EnumType() 
4905                 {
4906                         /* Called by both mscorlib & !mscorlib, so can be
4907                            either ClassRef or ClassDef */
4908                         //systemClasses [ valueTypeIx + 1] -> System.Enum
4909                         if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4910                                 ClassRef valType = new ClassRef("System","Enum",metaData);
4911                                 valType.SetParent(this);
4912                                 valType.MakeValueClass(ValueClass.Enum);
4913                                 metaData.AddToTable(MDTable.TypeRef,valType);
4914                                 systemClasses[valueTypeIx + 1] = valType;
4915                         }
4916                         return systemClasses[valueTypeIx + 1];
4917                 }
4918
4919                 /// <summary>
4920                 /// Add a value class to this external assembly
4921                 /// </summary>
4922                 /// <param name="nsName">name space name</param>
4923                 /// <param name="name">class name</param>
4924                 /// <returns></returns>
4925                 public override ClassRef AddValueClass(string nsName, string name) 
4926                 {
4927                         if (nsName.CompareTo(systemName) == 0) {
4928                                 int hash = name.GetHashCode();
4929                                 if ((hash == specialNames[valueTypeIx]) ||
4930                                                 (hash == specialNames[valueTypeIx+1])) {
4931                                         return GetValueClass(name,hash);
4932                                 }
4933                         }
4934                         ClassRef aClass = new ClassRef(nsName,name,metaData);
4935                         metaData.AddToTable(MDTable.TypeRef,aClass);
4936                         aClass.SetParent(this);
4937                         aClass.MakeValueClass(ValueClass.ValueType);
4938                         return aClass;
4939                 }
4940
4941         }
4942
4943         /**************************************************************************/  
4944         /// <summary>
4945         /// MetaData 
4946         ///   Root (20 bytes + UTF-8 Version String + quad align padding)
4947         ///   StreamHeaders (8 bytes + null terminated name string + quad align padding)
4948         ///   Streams 
4949         ///     #~        (always present - holds metadata tables)
4950         ///     #Strings  (always present - holds identifier strings)
4951         ///     #US       (Userstring heap)
4952         ///     #Blob     (signature blobs)
4953         ///     #GUID     (guids for assemblies or Modules)
4954         /// </summary>
4955         public class MetaData  {
4956
4957                 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4958                 private static readonly byte StringsHeapMask = 0x1;
4959                 private static readonly byte GUIDHeapMask = 0x2;
4960                 private static readonly byte BlobHeapMask = 0x4;
4961                 private static readonly uint MetaDataSignature = 0x424A5342;
4962                 private static readonly uint maxSmlIxSize = 0xFFFF;
4963                 private static readonly uint max1BitSmlIx = 0x7FFF;
4964                 private static readonly uint max2BitSmlIx = 0x3FFF;
4965                 private static readonly uint max3BitSmlIx = 0x1FFF;
4966                 private static readonly uint max5BitSmlIx = 0x7FF;
4967                 // NOTE: version and stream name strings MUST always be quad padded
4968                 private static readonly string version = "v4.0.30319\0\0";
4969                 private static readonly char[] tildeName = {'#','~','\0','\0'};
4970                 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4971                 private static readonly char[] usName = {'#','U','S','\0'};
4972                 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4973                 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4974                 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4975                 private static readonly uint TildeHeaderSize = 24;
4976                 private static readonly uint StreamHeaderSize = 8;
4977                 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4978
4979                 MetaDataStream strings, us, guid, blob;
4980
4981                 MetaDataStream[] streams = new MetaDataStream[5];
4982                 uint numStreams = 5;
4983                 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4984                 uint numTables = 0, resourcesSize = 0;
4985                 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4986                 ArrayList byteCodes = new ArrayList();
4987                 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4988                 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4989                 bool[] largeIx = new bool[numMetaDataTables];
4990                 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4991                 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4992                 private FileImage file;
4993                 private byte heapSizes = 0;
4994                 MetaDataElement entryPoint;
4995                 BinaryWriter output;
4996                 public MSCorLib mscorlib;
4997                 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4998                 long mdStart;
4999                 private ArrayList cattr_list;
5000                 private ArrayList declsec_list;
5001                 ArrayList resources;            
5002
5003                 internal MetaData(FileImage file) 
5004                 {
5005                         // tilde = new MetaDataStream(tildeName,false,0);
5006                         this.file = file;
5007                         strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5008                         us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5009                         guid = new MetaDataStream(guidName,false);
5010                         blob = new MetaDataStream(blobName,true);
5011                         streams[1] = strings;
5012                         streams[2] = us;
5013                         streams[3] = guid;
5014                         streams[4] = blob;
5015                         for (int i=0; i < numMetaDataTables; i++) {
5016                                 largeIx[i] = false;
5017                         }
5018                         for (int i=0; i < lgeCIx.Length; i++) {
5019                                 lgeCIx[i] = false;
5020                         }
5021                         mscorlib = new MSCorLib(this);
5022                 }
5023
5024                 internal TypeSpec GetPrimitiveTypeSpec(int ix) 
5025                 {
5026                         return systemTypeSpecs[ix];
5027                 }
5028
5029                 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) 
5030                 {
5031                         systemTypeSpecs[ix] = typeSpec;
5032                 }
5033
5034                 internal uint Size() 
5035                 {
5036                         return metaDataSize;
5037                 }
5038
5039                 private void CalcHeapSizes ()
5040                 {
5041                         if (strings.LargeIx()) {
5042                                 largeStrings = true;
5043                                 heapSizes |= StringsHeapMask;
5044                         }
5045                         if (guid.LargeIx()) {
5046                                 largeGUID = true;
5047                                 heapSizes |= GUIDHeapMask;
5048                         }
5049                         if (blob.LargeIx()) {
5050                                 largeBlob = true;
5051                                 heapSizes |= BlobHeapMask;
5052                         }
5053
5054                         largeUS = us.LargeIx();
5055                 }
5056
5057                 internal void StreamSize(byte mask) 
5058                 {
5059                         heapSizes |= mask;
5060                 }
5061
5062                 internal uint AddToUSHeap(string str) 
5063                 {
5064                         if (str == null) return 0;
5065                         return us.Add(str,true);
5066                 }
5067
5068                 internal uint AddToUSHeap(byte[] str) 
5069                 {
5070                         if (str == null) return 0;
5071                         return us.Add (str, true);
5072                 }
5073
5074                 internal uint AddToStringsHeap(string str) 
5075                 {
5076                         if ((str == null) || (str.CompareTo("") == 0)) return 0;
5077                         return strings.Add(str,false);
5078                 }
5079
5080                 internal uint AddToGUIDHeap(Guid guidNum) 
5081                 {
5082                         return guid.Add(guidNum, false);
5083                 }
5084
5085                 internal uint AddToBlobHeap(byte[] blobBytes) 
5086                 {
5087                         if (blobBytes == null) return 0;
5088                         return blob.Add(blobBytes, true);
5089                 }
5090
5091                 internal uint AddToBlobHeap(byte val) 
5092                 {
5093                         return blob.Add(val, true);
5094                 }
5095
5096                 internal uint AddToBlobHeap(sbyte val) 
5097                 {
5098                         return blob.Add(val, true);
5099                 }
5100
5101                 internal uint AddToBlobHeap(ushort val) 
5102                 {
5103                         return blob.Add(val, true);
5104                 }
5105
5106                 internal uint AddToBlobHeap(short val) 
5107                 {
5108                         return blob.Add(val, true);
5109                 }
5110
5111                 internal uint AddToBlobHeap(uint val) 
5112                 {
5113                         return blob.Add(val, true);
5114                 }
5115
5116                 internal uint AddToBlobHeap(int val) 
5117                 {
5118                         return blob.Add(val, true);
5119                 }
5120
5121                 internal uint AddToBlobHeap(ulong val) 
5122                 {
5123                         return blob.Add(val, true);
5124                 }
5125
5126                 internal uint AddToBlobHeap(long val) 
5127                 {
5128                         return blob.Add(val, true);
5129                 }
5130
5131                 internal uint AddToBlobHeap(float val) 
5132                 {
5133                         return blob.Add(val, true);
5134                 }
5135
5136                 internal uint AddToBlobHeap(double val) 
5137                 {
5138                         return blob.Add(val, true);
5139                 }
5140
5141                 internal uint AddToBlobHeap(string val) 
5142                 {
5143                         return blob.Add(val,true);
5144                 }
5145
5146                 internal void AddCustomAttribute (CustomAttribute cattr)
5147                 {
5148                         if (cattr_list == null)
5149                                 cattr_list = new ArrayList ();
5150                         cattr_list.Add (cattr);
5151                 }
5152
5153                 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5154                 {
5155                         if (declsec_list == null)
5156                                 declsec_list = new ArrayList ();
5157                         declsec_list.Add (decl_sec);
5158                 }
5159
5160                 private ArrayList GetTable(MDTable tableIx) 
5161                 {
5162                         int tabIx = (int)tableIx;
5163                         if (metaDataTables[tabIx] == null) {
5164                                 metaDataTables[tabIx] = new ArrayList();
5165                                 valid |= ((ulong)0x1 << tabIx);
5166                                 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5167                                 numTables++;
5168                         }
5169                         return metaDataTables[tabIx];
5170                 }
5171
5172                 internal void AddToTable(MDTable tableIx, MetaDataElement elem) 
5173                 {
5174                         if (elem.Row > 0) {
5175                                 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5176                                 return;
5177                         }
5178                         // updates Row field of the element
5179                         // Console.WriteLine("Adding element to table " + (uint)tableIx);
5180                         ArrayList table = GetTable(tableIx);
5181                         elem.Row = (uint)table.Count + 1;
5182                         table.Add(elem);
5183                 }
5184
5185                 internal uint TableIndex(MDTable tableIx) 
5186                 {
5187                         if (metaDataTables[(int)tableIx] == null) return 1;
5188                         return (uint)metaDataTables[(int)tableIx].Count+1;
5189                 }
5190
5191                 internal uint AddCode(CILInstructions byteCode) 
5192                 {
5193                         byteCodes.Add(byteCode);
5194                         uint offset = codeSize + codeStart;
5195                         codeSize += byteCode.GetCodeSize();
5196                         return offset;
5197                 }
5198
5199                 internal void SetEntryPoint(MetaDataElement ep) 
5200                 {
5201                         entryPoint = ep;
5202                 }
5203
5204                 internal uint AddResource(byte[] resBytes) 
5205                 {
5206                         if (resources == null) resources = new ArrayList ();
5207                         resources.Add (resBytes);
5208                         uint offset = resourcesSize;
5209                         resourcesSize += (uint)resBytes.Length + 4;
5210                         return offset;
5211                 }
5212
5213                 internal void AddData(DataConstant cVal) 
5214                 {
5215                         file.AddInitData(cVal);
5216                 }
5217
5218                 internal static void CompressNum(uint val, MemoryStream sig) 
5219                 {
5220                         if (val <= 0x7F) {
5221                                 sig.WriteByte((byte)val);
5222                         } else if (val <= 0x3FFF) {
5223                                 byte b1 = (byte)((val >> 8) | 0x80);
5224                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5225                                 sig.WriteByte(b1);
5226                                 sig.WriteByte(b2);
5227                         } else {
5228                                 byte b1 = (byte)((val >> 24) | 0xC0);
5229                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5230                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5231                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5232                                 sig.WriteByte(b1);
5233                                 sig.WriteByte(b2);
5234                                 sig.WriteByte(b3);
5235                                 sig.WriteByte(b4);
5236                         }
5237                 }
5238
5239                 internal uint CodeSize() 
5240                 {
5241                         return codeSize + byteCodePadding;
5242                 }
5243
5244                 internal uint GetResourcesSize() 
5245                 { 
5246                         return resourcesSize; 
5247                 }
5248
5249                 internal uint StringsIndexSize() 
5250                 {
5251                         if (largeStrings) return 4;
5252                         return 2;
5253                 }
5254
5255                 internal uint GUIDIndexSize() 
5256                 {
5257                         if (largeGUID) return 4;
5258                         return 2;
5259                 }
5260
5261                 internal uint USIndexSize() 
5262                 {
5263                         if (largeUS) return 4;
5264                         return 2;
5265                 }
5266
5267                 internal uint BlobIndexSize() 
5268                 {
5269                         if (largeBlob) return 4;
5270                         return 2;
5271                 }
5272
5273                 internal uint CodedIndexSize(CIx code) 
5274                 {
5275                         if (lgeCIx[(uint)code]) return 4;
5276                         return 2;
5277                 }
5278
5279                 internal uint TableIndexSize(MDTable tabIx) 
5280                 {
5281                         if (largeIx[(uint)tabIx]) return 4;
5282                         return 2;
5283                 }
5284
5285                 private void SetIndexSizes() 
5286                 {
5287                         for (int i=0; i < numMetaDataTables; i++) {
5288                                 if (metaDataTables[i] == null)
5289                                         continue;
5290
5291                                 uint count = (uint)metaDataTables[i].Count;
5292                                 if (count > maxSmlIxSize)
5293                                         largeIx[i] = true;
5294
5295                                 MDTable tabIx = (MDTable)i;
5296                                 if (count > max5BitSmlIx) {
5297                                         lgeCIx[(int)CIx.HasCustomAttr] = true;
5298                                 }
5299                                 if (count > max3BitSmlIx) {
5300                                         if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field)) 
5301                                                 lgeCIx[(int)CIx.CustomAttributeType] = true;
5302                                         if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) 
5303                                                 lgeCIx[(int)CIx.MemberRefParent] = true;
5304                                 }
5305                                 if (count > max2BitSmlIx) {
5306                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property)) 
5307                                                 lgeCIx[(int)CIx.HasConst] = true;
5308                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5309                                                 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5310                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5311                                                 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5312                                         if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5313                                                 lgeCIx[(int)CIx.Implementation] = true;
5314                                         if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5315                                                 lgeCIx[(int)CIx.ResolutionScope] = true;
5316                                 }
5317                                 if (count > max1BitSmlIx) {
5318                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param)) 
5319                                                 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5320                                         if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property)) 
5321                                                 lgeCIx[(int)CIx.HasSemantics] = true;
5322                                         if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) 
5323                                                 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5324                                         if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method)) 
5325                                                 lgeCIx[(int)CIx.MemberForwarded] = true; 
5326                                         if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method)) 
5327                                                 lgeCIx[(int)CIx.TypeOrMethodDef] = true; 
5328                                 }
5329                         }
5330                 }
5331
5332                 private void SetStreamOffsets() 
5333                 {
5334                         uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5335                         for (int i=1; i < numStreams; i++) {
5336                                 sizeOfHeaders += streams[i].headerSize();
5337                         }
5338                         metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5339                         tildeStart = metaDataSize;
5340                         metaDataSize += tildeTide + tildePadding;
5341                         for (int i=1; i < numStreams; i++) {
5342                                 streams[i].Start = metaDataSize;
5343                                 metaDataSize += streams[i].Size();
5344                                 streams[i].WriteDetails();
5345                         }
5346                 }
5347
5348                 internal void CalcTildeStreamSize() 
5349                 {
5350                         CalcHeapSizes ();
5351                         //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5352                         tildeTide = TildeHeaderSize;
5353                         tildeTide += 4 * numTables;
5354                         //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5355                         for (int i=0; i < numMetaDataTables; i++) {
5356                                 if (metaDataTables[i] != null) {
5357                                         ArrayList table = metaDataTables[i];
5358                                         // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5359                                         tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5360                                         // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5361                                         // Console.WriteLine("tildeTide = " + tildeTide);
5362                                 }
5363                         }
5364                         if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5365                         //Console.WriteLine("tildePadding = " + tildePadding);
5366                 }
5367
5368                 internal void WriteTildeStream(FileImage output) 
5369                 {
5370                         output.Seek(0,SeekOrigin.Current);
5371                         output.Write((uint)0); // Reserved
5372                         output.Write((byte)2); // MajorVersion
5373                         output.Write((byte)0); // MinorVersion
5374                         output.Write(heapSizes);
5375                         output.Write((byte)1); // Reserved
5376                         output.Write(valid);
5377                         output.Write(sorted);
5378                         
5379                         for (int i=0; i < numMetaDataTables; i++) {
5380                                 if (metaDataTables[i] != null) {
5381                                         uint count = (uint)metaDataTables[i].Count;
5382                                         output.Write(count);
5383                                 }
5384                         }
5385                         
5386                         output.Seek(0,SeekOrigin.Current);
5387                         // Console.WriteLine("Starting metaData tables at " + tabStart);
5388                         for (int i=0; i < numMetaDataTables; i++) {
5389                                 if (metaDataTables[i] != null) {
5390                                         // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5391                                         ArrayList table = metaDataTables[i];
5392                                         for (int j=0; j < table.Count; j++) {
5393                                                 ((MetaDataElement)table[j]).Write(output);
5394                                         }
5395                                 }
5396                         }
5397                         // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5398                         for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5399                 }
5400
5401                 private void BuildTable(ArrayList table) 
5402                 {
5403                         if (table == null) return;
5404                         for (int j=0; j < table.Count; j++) {
5405                                 ((MetaDataElement)table[j]).BuildTables(this);
5406                         }
5407                 }
5408
5409                 private void SortTable (ArrayList mTable) 
5410                 {
5411                         if (mTable == null) return;
5412                         mTable.Sort();
5413                         for (int i=0; i < mTable.Count; i++) {
5414                                 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5415                         }
5416                 }
5417
5418                 internal void BuildMetaData(uint codeStartOffset) 
5419                 {
5420                         codeStart = codeStartOffset;
5421                         BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5422                         BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5423                         BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5424                         BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5425                         BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5426                         BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5427                         BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5428
5429                         if (cattr_list != null) {
5430                                 foreach (CustomAttribute cattr in cattr_list)
5431                                         cattr.BuildTables (this);
5432                         }
5433
5434                         if (declsec_list != null) {
5435                                 foreach (BaseDeclSecurity decl_sec in declsec_list)
5436                                         decl_sec.BuildTables (this);
5437                         }
5438
5439                         /*      for (int i=0; i < metaDataTables.Length; i++) {
5440                                 ArrayList table = metaDataTables[i];
5441                                 if (table != null) {
5442                                 for (int j=0; j < table.Count; j++) {
5443                                 ((MetaDataElement)table[j]).BuildTables(this);
5444                                 }
5445                                 }
5446                                 }
5447                          */
5448
5449                         SetIndexSizes();
5450                         for (int i=1; i < numStreams; i++) {
5451                                 streams[i].EndStream();
5452                         }
5453                         CalcTildeStreamSize();
5454                         SetStreamOffsets();
5455                         byteCodePadding = NumToAlign(codeSize,4);
5456                         if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5457
5458                         // Check ordering of specific tables
5459                         // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5460                         // ImplMap, GenericParam
5461                         // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5462                         // The tables:
5463                         //   InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5464                         // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5465
5466                         SortTable(metaDataTables[(int)MDTable.Constant]);
5467                         SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5468                         SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5469                         SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5470                         SortTable(metaDataTables[(int)MDTable.ImplMap]);
5471                         if (metaDataTables[(int)MDTable.GenericParam] != null) {
5472                                 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5473                                 // Now add GenericParamConstraints
5474                                 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5475                                   ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5476                                   }*/
5477                         }
5478                         SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5479                         SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5480                         SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5481
5482                 }
5483
5484                 internal void WriteByteCodes(FileImage output) 
5485                 {
5486                         for (int i=0; i < byteCodes.Count; i++) {
5487                                 ((CILInstructions)byteCodes[i]).Write(output);
5488                         }
5489                         for (int i=0; i < byteCodePadding; i++) {
5490                                 output.Write((byte)0);
5491                         }
5492                 }
5493
5494                 internal void WriteResources (FileImage output) 
5495                 {
5496                         if (resources == null) return;
5497                         for (int i = 0; i < resources.Count; i ++) {
5498                                 byte [] resBytes = (byte []) resources [i];
5499                                 output.Write ((uint) resBytes.Length);
5500                                 output.Write (resBytes);
5501                         } 
5502                 }
5503
5504                 internal void WriteMetaData(FileImage output) 
5505                 {
5506                         this.output = output;
5507                         mdStart = output.Seek(0,SeekOrigin.Current);
5508                         // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5509                         output.Write(MetaDataSignature);
5510                         output.Write((short)1);  // Major Version
5511                         output.Write((short)1);  // Minor Version  ECMA = 0, PEFiles = 1
5512                         output.Write(0);         // Reserved
5513                         output.Write(version.Length);
5514                         output.Write(version.ToCharArray());   // version string is already zero padded
5515                         output.Write((short)0);
5516                         output.Write((ushort)numStreams);
5517                         // write tilde header
5518                         output.Write(tildeStart);
5519                         output.Write(tildeTide + tildePadding);
5520                         output.Write(tildeName);
5521                         for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5522                         // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5523                         WriteTildeStream(output);
5524                         for (int i=1; i < numStreams; i++) streams[i].Write(output);
5525                         // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5526                 }
5527
5528                 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5529                 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5530                 internal bool LargeUSIndex() { return us.LargeIx(); }
5531                 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5532
5533                 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5534
5535
5536                 private uint NumToAlign(uint val, uint alignVal) 
5537                 {
5538                         if ((val % alignVal) == 0) return 0;
5539                         return alignVal - (val % alignVal);
5540                 }
5541
5542                 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) 
5543                 {
5544                         uint ix = 0;
5545                         if (elem != null) { 
5546                                 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5547                                 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5548                                 //} else {
5549                                 // Console.WriteLine("elem for coded index is null");
5550                         }
5551                         if (lgeCIx[(uint)code]) 
5552                                 output.Write(ix);
5553                         else
5554                                 output.Write((ushort)ix);
5555                 }
5556
5557         }
5558
5559         /**************************************************************************/  
5560         /// <summary>
5561         /// Stream in the Meta Data  (#Strings, #US, #Blob and #GUID)
5562         /// </summary>
5563
5564         internal class MetaDataStream : BinaryWriter  {
5565
5566                 private static readonly uint StreamHeaderSize = 8;
5567                 private static uint maxSmlIxSize = 0xFFFF;
5568
5569                 private uint start = 0; 
5570                 uint size = 0, tide = 1;
5571                 bool largeIx = false;
5572                 uint sizeOfHeader;
5573                 char[] name;
5574                 Hashtable htable = new Hashtable();
5575                 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5576
5577                 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) 
5578                 {
5579                         if (addInitByte) { Write((byte)0); size = 1; }
5580                         this.name = name;
5581                         sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5582                 }
5583
5584                 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) 
5585                 {
5586                         if (addInitByte) { Write((byte)0); size = 1; }
5587                         this.name = name;
5588                         sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5589                 }
5590
5591                 public uint Start {
5592                         get { return start; }
5593                         set { start = value; }
5594                 }
5595
5596                 internal uint headerSize() 
5597                 {
5598                         // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5599                         return sizeOfHeader;
5600                 }
5601
5602                 internal void SetSize(uint siz) 
5603                 {
5604                         size = siz;
5605                 }
5606
5607                 internal uint Size() 
5608                 {
5609                         return size;
5610                 }
5611
5612                 internal bool LargeIx() 
5613                 {
5614                         return largeIx;
5615                 }
5616
5617                 internal void WriteDetails() 
5618                 {
5619                         // Console.WriteLine(name + " - size = " + size);
5620                 }
5621
5622                 internal uint Add(string str, bool prependSize) 
5623                 {
5624                         Object val = htable[str];
5625                         uint index = 0;
5626                         if (val == null) { 
5627                                 index = size;
5628                                 htable[str] = index;
5629                                 char[] arr = str.ToCharArray();
5630                                 if (prependSize) CompressNum((uint)arr.Length*2+1);
5631                                 Write(arr);
5632                                 Write((byte)0);
5633                                 size = (uint)Seek(0,SeekOrigin.Current);
5634                         } else {
5635                                 index = (uint)val;
5636                         }
5637                         return index;
5638                 }
5639                 internal uint Add (byte[] str, bool prependSize) 
5640                 {
5641                         Object val = btable [str];
5642                         uint index = 0;
5643                         if (val == null) {
5644                                 index = size;
5645                                 btable [str] = index;
5646                                 if (prependSize) CompressNum ((uint) str.Length);
5647                                 Write (str);
5648                                 size = (uint) Seek (0, SeekOrigin.Current);
5649                         } else {
5650                                 index = (uint) val;
5651                         }
5652                         return index;
5653                 }
5654
5655
5656                 internal uint Add(Guid guid, bool prependSize) 
5657                 {
5658                         byte [] b = guid.ToByteArray ();
5659                         if (prependSize) CompressNum ((uint) b.Length);
5660                         Write(guid.ToByteArray());
5661                         size =(uint)Seek(0,SeekOrigin.Current);
5662                         return tide++;
5663                 }
5664
5665                 internal uint Add(byte[] blob) 
5666                 {
5667                         uint ix = size;
5668                         CompressNum((uint)blob.Length);
5669                         Write(blob);
5670                         size = (uint)Seek(0,SeekOrigin.Current);
5671                         return ix;
5672                 }
5673
5674                 internal uint Add(byte val, bool prependSize) 
5675                 {
5676                         uint ix = size;
5677                         if (prependSize) CompressNum (1);
5678                         Write(val);
5679                         size = (uint)Seek(0,SeekOrigin.Current);
5680                         return ix;
5681                 }
5682
5683                 internal uint Add(sbyte val, bool prependSize) 
5684                 {
5685                         uint ix = size;
5686                         if (prependSize) CompressNum (1);
5687                         Write(val);
5688                         size = (uint)Seek(0,SeekOrigin.Current);
5689                         return ix;
5690                 }
5691
5692                 internal uint Add(ushort val, bool prependSize) 
5693                 {
5694                         uint ix = size;
5695                         if (prependSize) CompressNum (2);
5696                         Write(val);
5697                         size = (uint)Seek(0,SeekOrigin.Current);
5698                         return ix;
5699                 }
5700
5701                 internal uint Add(short val, bool prependSize) 
5702                 {
5703                         uint ix = size;
5704                         if (prependSize) CompressNum (2);
5705                         Write(val);
5706                         size = (uint)Seek(0,SeekOrigin.Current);
5707                         return ix;
5708                 }
5709
5710                 internal uint Add(uint val, bool prependSize) 
5711                 {
5712                         uint ix = size;
5713                         if (prependSize) CompressNum (4);
5714                         Write(val);
5715                         size = (uint)Seek(0,SeekOrigin.Current);
5716                         return ix;
5717                 }
5718
5719                 internal uint Add(int val, bool prependSize) 
5720                 {
5721                         uint ix = size;
5722                         if (prependSize) CompressNum (4);
5723                         Write (val);
5724                         size = (uint)Seek(0,SeekOrigin.Current);
5725                         return ix;
5726                 }
5727
5728                 internal uint Add(ulong val, bool prependSize) 
5729                 {
5730                         uint ix = size;
5731                         if (prependSize) CompressNum (8);
5732                         Write(val);
5733                         size = (uint)Seek(0,SeekOrigin.Current);
5734                         return ix;
5735                 }
5736
5737                 internal uint Add(long val, bool prependSize) 
5738                 {
5739                         uint ix = size;
5740                         if (prependSize) CompressNum (8);
5741                         Write(val);
5742                         size = (uint)Seek(0,SeekOrigin.Current);
5743                         return ix;
5744                 }
5745
5746                 internal uint Add(float val, bool prependSize) 
5747                 {
5748                         uint ix = size;
5749                         if (prependSize) CompressNum (4);
5750                         Write(val);
5751                         size = (uint)Seek(0,SeekOrigin.Current);
5752                         return ix;
5753                 }
5754
5755                 internal uint Add(double val, bool prependSize) 
5756                 {
5757                         uint ix = size;
5758                         if (prependSize) CompressNum (8);
5759                         Write(val);
5760                         size = (uint)Seek(0,SeekOrigin.Current);
5761                         return ix;
5762                 }
5763
5764                 private void CompressNum(uint val) 
5765                 {
5766                         if (val < 0x7F) {
5767                                 Write((byte)val);
5768                         } else if (val < 0x3FFF) {
5769                                 byte b1 = (byte)((val >> 8) | 0x80);
5770                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5771                                 Write(b1);
5772                                 Write(b2);
5773                         } else {
5774                                 byte b1 = (byte)((val >> 24) | 0xC0);
5775                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5776                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5777                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5778                                 Write(b1);
5779                                 Write(b2);
5780                                 Write(b3);
5781                                 Write(b4);
5782                         }
5783                 }
5784
5785                 private void QuadAlign() 
5786                 {
5787                         if ((size % 4) != 0) {
5788                                 uint pad = 4 - (size % 4);
5789                                 size += pad;
5790                                 for (int i=0; i < pad; i++) {
5791                                         Write((byte)0);
5792                                 }
5793                         }
5794                 }
5795
5796                 internal void EndStream() 
5797                 {
5798                         QuadAlign();
5799                         if (size > maxSmlIxSize) {
5800                                 largeIx = true;
5801                         }
5802                 }
5803
5804                 internal void WriteHeader(BinaryWriter output) 
5805                 {
5806                         output.Write(start);
5807                         output.Write(size);
5808                         output.Write(name);
5809                 }
5810
5811                 internal virtual void Write(BinaryWriter output) 
5812                 {
5813                         // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5814                         MemoryStream str = (MemoryStream)BaseStream;
5815                         output.Write(str.ToArray());
5816                 }
5817
5818         }
5819
5820         /**************************************************************************/  
5821         class ByteArrayComparer : IComparer {
5822
5823                 public int Compare (object x, object y)
5824                 {
5825                         byte [] a = (byte []) x;
5826                         byte [] b = (byte []) y;
5827                         int len = a.Length;
5828
5829                         if (b.Length != len)
5830                                 return 1;
5831
5832                         for (int i = 0; i < len; ++i)
5833                                 if (a [i] != b [i])
5834                                         return 1;
5835                         return 0;
5836                 }
5837         }
5838
5839         class ByteArrayHashCodeProvider : IHashCodeProvider {
5840
5841                 public int GetHashCode (Object key)
5842                 {
5843                         byte [] arr = (byte []) key;
5844                         int len = arr.Length;
5845                         int h = 0;
5846
5847                         for (int i = 0; i < len; ++i)
5848                                 h = (h << 5) - h + arr [i];
5849
5850                         return h;
5851                 }
5852
5853         }
5854
5855
5856 }