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