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