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