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