* PEAPI.cs (InterfaceImpl.SortKey): New.
[mono.git] / mcs / class / PEAPI / PEAPI.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5
6 namespace PEAPI 
7 {
8   public class Hex {
9     readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
10                                         '8','9','A','B','C','D','E','F'};
11     readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
12     readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 
13                                           0x0000000000FF0000, 0x00000000FF000000,
14                                           0x000000FF00000000, 0x0000FF0000000000,
15                                           0x00FF000000000000, 0xFF00000000000000 };
16     readonly static uint nibble0Mask = 0x0000000F;
17     readonly static uint nibble1Mask = 0x000000F0;
18
19     public static String Byte(int b) {
20       char[] str = new char[2];
21       uint num = (uint)b;
22       uint b1 = num & nibble0Mask;
23       uint b2 = (num & nibble1Mask) >> 4;
24       str[0] = hexDigit[b2];
25       str[1] = hexDigit[b1];
26       return new String(str);
27     }
28
29     public static String Short(int b) {
30       char[] str = new char[4];
31       uint num1 = (uint)b & iByteMask[0];
32       uint num2 = ((uint)b & iByteMask[1]) >> 8;
33       uint b1 = num1 & nibble0Mask;
34       uint b2 = (num1 & nibble1Mask) >> 4;
35       uint b3 = num2 & nibble0Mask;
36       uint b4 = (num2 & nibble1Mask) >> 4;
37       str[0] = hexDigit[b4];
38       str[1] = hexDigit[b3];
39       str[2] = hexDigit[b2];
40       str[3] = hexDigit[b1];
41       return new String(str);
42     }
43
44     public static String Int(int val) {
45       char[] str = new char[8];
46       uint num = (uint)val;
47       int strIx = 7;
48       for (int i=0; i < iByteMask.Length; i++) {
49         uint b = num & iByteMask[i];
50         b >>= (i*8);
51         uint b1 = b & nibble0Mask;
52         uint b2 = (b & nibble1Mask) >> 4;
53         str[strIx--] = hexDigit[b1];
54         str[strIx--] = hexDigit[b2];
55       }
56       return new String(str);
57     }
58  
59     public static String Int(uint num) {
60       char[] str = new char[8];
61       int strIx = 7;
62       for (int i=0; i < iByteMask.Length; i++) {
63         uint b = num & iByteMask[i];
64         b >>= (i*8);
65         uint b1 = b & nibble0Mask;
66         uint b2 = (b & nibble1Mask) >> 4;
67         str[strIx--] = hexDigit[b1];
68         str[strIx--] = hexDigit[b2];
69       }
70       return new String(str);
71     }
72
73     public static String Long(long lnum) {
74       ulong num = (ulong)lnum;
75       char[] str = new char[16];
76       int strIx = 15;
77       for (int i=0; i < lByteMask.Length; i++) {
78         ulong b = num & lByteMask[i];
79         b >>= (i*8);
80         ulong b1 = b & nibble0Mask;
81         ulong b2 = (b & nibble1Mask) >> 4;
82         str[strIx--] = hexDigit[b1];
83         str[strIx--] = hexDigit[b2];
84       }
85       return new String(str);
86     }
87   }
88
89   public class NotYetImplementedException : System.Exception 
90   {
91      public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
92   }
93
94   public class TypeSignatureException : System.Exception {
95     public TypeSignatureException(string msg) : base(msg) { }
96   }
97
98                    public class ClassRefInst : Type {
99
100                           private Type type;
101                           private bool is_value;
102
103             public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ()) {
104                     this.type = type;
105                     this.is_value = is_value;
106                     if (is_value)
107                           typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
108                     tabIx = MDTable.TypeSpec;
109             }
110
111             internal sealed override void TypeSig(MemoryStream str) {
112                     type.TypeSig (str);
113             }
114     }
115                   
116   public class MVar : Type {
117
118             private int index;
119
120             public MVar (int index) : base (0x1E) {
121                     this.index = index;
122                     tabIx = MDTable.TypeSpec;
123             }
124
125             internal sealed override void TypeSig(MemoryStream str) {
126                     str.WriteByte(typeIndex);
127                     MetaData.CompressNum ((uint) index, str);
128             }
129     }
130
131     public class GenericTypeSpec : Type {
132
133             private int index;
134
135             public GenericTypeSpec (int index) : base (0x13) {
136                     this.index = index;
137                     tabIx = MDTable.TypeSpec;
138             }
139
140             internal sealed override void TypeSig(MemoryStream str) {
141                     str.WriteByte(typeIndex);
142                     MetaData.CompressNum ((uint) index, str);
143             }
144     }
145
146   public class GenericTypeInst : Type {
147
148           private Type gen_type;
149           private Type[] gen_param;
150
151           public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
152           {
153                   typeIndex = 0x15;
154                   this.gen_type = gen_type;
155                   this.gen_param = gen_param;
156                   tabIx = MDTable.TypeSpec;
157   }
158
159           internal sealed override void TypeSig(MemoryStream str) {
160                   str.WriteByte(typeIndex);
161                   gen_type.TypeSig (str);
162                   MetaData.CompressNum ((uint) gen_param.Length, str);
163                   foreach (Type param in gen_param)
164                           param.TypeSig (str);
165             }
166   }
167
168   public class GenericMethodSig {
169
170           private Type[] gen_param;
171
172           public GenericMethodSig (Type[] gen_param)
173           {
174                   this.gen_param = gen_param;
175           }
176
177           internal void TypeSig (MemoryStream str)
178           {
179                   MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
180                   MetaData.CompressNum ((uint) gen_param.Length, str);
181                   foreach (Type param in gen_param)
182                           param.TypeSig (str);
183           }
184
185           internal uint GetSigIx (MetaData md)
186           {
187                   MemoryStream sig = new MemoryStream();
188                   TypeSig (sig);
189                   return md.AddToBlobHeap (sig.ToArray());
190           }
191   }
192
193         public class Sentinel : Type {
194
195             public Sentinel () : base (0x41) { }
196
197             internal sealed override void TypeSig(MemoryStream str) {
198                     str.WriteByte(typeIndex);
199             }
200         }
201
202         /// <summary>
203         /// The IL Array type
204         /// </summary>
205         public abstract class Array : Type
206         {
207
208     protected Type elemType;
209                 protected MetaData metaData;
210                 protected string cnameSpace, cname;
211
212     internal Array(Type eType, byte TypeId) : base(TypeId) {
213       elemType = eType;
214                         tabIx = MDTable.TypeSpec;
215     }
216
217         }
218
219   /**************************************************************************/  
220   
221   /// <summary>
222   /// Single dimensional array with zero lower bound
223   /// </summary>
224   public class ZeroBasedArray : Array {
225
226     /// <summary>
227     /// Create a new array  -   elementType[]
228     /// </summary>
229     /// <param name="elementType">the type of the array elements</param>
230     public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
231
232     internal sealed override void TypeSig(MemoryStream str) {
233       str.WriteByte(typeIndex);
234       elemType.TypeSig(str); 
235     }
236
237   }
238
239
240   /**************************************************************************/           
241
242   /// <summary>
243   /// Multi dimensional array with explicit bounds
244   /// </summary>
245   public class BoundArray : Array {
246     int[] lowerBounds;
247     int[] sizes;
248     uint numDims;
249
250     /// <summary>
251     /// Create a new multi dimensional array type 
252     /// eg. elemType[1..5,3..10,5,,] would be 
253     /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
254     /// </summary>
255     /// <param name="elementType">the type of the elements</param>
256     /// <param name="dimensions">the number of dimensions</param>
257     /// <param name="loBounds">lower bounds of dimensions</param>
258     /// <param name="upBounds">upper bounds of dimensions</param>
259     public BoundArray(Type elementType, uint dimensions, int[] loBounds, 
260       int[] upBounds) : base (elementType,0x14) {
261       numDims = dimensions;
262       lowerBounds = loBounds;
263       sizes = new int[loBounds.Length];
264       for (int i=0; i < loBounds.Length; i++) {
265         sizes[i] = upBounds[i] - loBounds[i] + 1;
266       }
267     }
268
269     /// <summary>
270     /// Create a new multi dimensional array type 
271     /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
272     /// </summary>
273     /// <param name="elementType">the type of the elements</param>
274     /// <param name="dimensions">the number of dimensions</param>
275     /// <param name="size">the sizes of the dimensions</param>
276     public BoundArray(Type elementType, uint dimensions, int[] size) 
277                                                   : base (elementType,0x14) {
278       numDims = dimensions;
279       sizes = size;
280     }
281
282     /// <summary>
283     /// Create a new multi dimensional array type 
284     /// eg. elemType[,,] would be new BoundArray(elemType,3)
285     /// </summary>
286     /// <param name="elementType">the type of the elements</param>
287     /// <param name="dimensions">the number of dimensions</param>
288     public BoundArray(Type elementType, uint dimensions)
289                                                   : base (elementType,0x14) {
290       numDims = dimensions;
291     }
292
293     internal sealed override void TypeSig(MemoryStream str) {
294       str.WriteByte(typeIndex);
295       elemType.TypeSig(str);
296       MetaData.CompressNum(numDims,str);
297       if ((sizes != null) && (sizes.Length > 0)) {
298         MetaData.CompressNum((uint)sizes.Length,str);
299         for (int i=0; i < sizes.Length; i++) {
300           MetaData.CompressNum((uint)sizes[i],str);
301         }
302       } else str.WriteByte(0);
303       if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
304         MetaData.CompressNum((uint)lowerBounds.Length,str);
305         for (int i=0; i < lowerBounds.Length; i++) {
306           MetaData.CompressNum((uint)lowerBounds[i],str);
307         }
308       } else str.WriteByte(0);
309     }
310   
311   }
312   /**************************************************************************/  
313   /// <summary>
314   /// Descriptor for THIS assembly (.assembly)
315   /// </summary>
316   public class Assembly : ResolutionScope 
317   {
318     ushort majorVer, minorVer, buildNo, revisionNo;
319     uint flags;
320     uint hashAlgId;
321     uint keyIx = 0, cultIx = 0;
322     bool hasPublicKey = false;
323     
324     internal Assembly(string name, MetaData md) : base(name,md) {
325       tabIx = MDTable.Assembly;
326     }
327
328     /// <summary>
329     /// Add details about THIS assembly
330     /// </summary>
331     /// <param name="majVer">Major Version</param>
332     /// <param name="minVer">Minor Version</param>
333     /// <param name="bldNo">Build Number</param>
334     /// <param name="revNo">Revision Number</param>
335     /// <param name="key">Hash Key</param>
336     /// <param name="hash">Hash Algorithm</param>
337     /// <param name="cult">Culture</param>
338     public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, 
339                               byte[] key, uint hash, string cult) {
340       majorVer = (ushort)majVer;
341       minorVer = (ushort)minVer;
342       buildNo = (ushort)bldNo;
343       revisionNo = (ushort)revNo;
344       hashAlgId = hash;
345       hasPublicKey = (key != null);
346       keyIx = metaData.AddToBlobHeap(key);
347       cultIx = metaData.AddToStringsHeap(cult);
348     }
349
350     /// <summary>
351     /// Add an attribute to THIS assembly
352     /// </summary>
353     /// <param name="aa">assembly attribute</param>
354     public void AddAssemblyAttr(AssemAttr aa) {
355       flags |= (uint)aa;
356     }
357
358     internal sealed override uint Size(MetaData md) {
359       return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
360     }
361
362     internal sealed override void Write(FileImage output) {
363 //      Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
364       output.Write((uint)hashAlgId);
365       output.Write(majorVer);
366       output.Write(minorVer);
367       output.Write(buildNo);
368       output.Write(revisionNo);
369       output.Write(flags);
370       output.BlobIndex(keyIx);
371       output.StringsIndex(nameIx);
372       output.StringsIndex(cultIx);
373     }
374
375     internal sealed override uint GetCodedIx(CIx code) {
376       switch (code) {
377         case (CIx.HasCustomAttr) : return 14; 
378         case (CIx.HasDeclSecurity) : return 2; 
379       }
380       return 0;
381     }
382
383     internal bool HasPublicKey {
384       get { return hasPublicKey; }
385     }
386   }     
387   /**************************************************************************/  
388
389         public interface IExternRef  {
390                 ClassRef AddClass(string nsName, string name);
391                 ClassRef AddValueClass(string nsName, string name);
392         }
393         
394         /// <summary>
395         /// A reference to an external assembly (.assembly extern)
396         /// </summary>
397         public class AssemblyRef : ResolutionScope, IExternRef
398         {
399     private ushort major, minor, build, revision;
400     uint flags, keyIx, hashIx, cultIx;
401     bool hasVersion = false, isKeyToken = false;
402     byte[] keyBytes;
403     string culture;
404
405     internal AssemblyRef(MetaData md, string name) : base(name,md) {
406       tabIx = MDTable.AssemblyRef;
407                 }
408
409     /// <summary>
410     /// Add version information about this external assembly
411     /// </summary>
412     /// <param name="majVer">Major Version</param>
413     /// <param name="minVer">Minor Version</param>
414     /// <param name="bldNo">Build Number</param>
415     /// <param name="revNo">Revision Number</param>
416     public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
417       major = (ushort)majVer;
418       minor = (ushort)minVer;
419       build = (ushort)bldNo;
420       revision = (ushort)revNo;
421       hasVersion = true;
422     }
423
424     /// <summary>
425     /// Add the hash value for this external assembly
426     /// </summary>
427     /// <param name="hash">bytes of the hash value</param>
428     public void AddHash(byte[] hash) {
429       hashIx = metaData.AddToBlobHeap(hash); 
430     }
431
432     /// <summary>
433     /// Set the culture for this external assembly
434     /// </summary>
435     /// <param name="cult">the culture string</param>
436     public void AddCulture(string cult) {
437       cultIx = metaData.AddToStringsHeap(cult);
438       culture = cult;
439     }
440
441     /// <summary>
442     /// Add the full public key for this external assembly
443     /// </summary>
444     /// <param name="key">bytes of the public key</param>
445     public void AddKey(byte[] key) {
446       flags |= 0x0001;   // full public key
447       keyBytes = key;
448       keyIx = metaData.AddToBlobHeap(key); 
449     }
450
451     /// <summary>
452     /// Add the public key token (low 8 bytes of the public key)
453     /// </summary>
454     /// <param name="key">low 8 bytes of public key</param>
455     public void AddKeyToken(byte[] key) {
456       keyIx = metaData.AddToBlobHeap(key); 
457       keyBytes = key;
458       isKeyToken = true;
459     }
460
461     /// <summary>
462     /// Add a class to this external assembly
463     /// </summary>
464     /// <param name="nsName">name space name</param>
465     /// <param name="name">class name</param>
466     /// <returns></returns>
467     public virtual ClassRef AddClass(string nsName, string name) {
468       ClassRef aClass = new ClassRef(nsName,name,metaData);
469       metaData.AddToTable(MDTable.TypeRef,aClass);
470       aClass.SetParent(this);
471       return aClass;
472     }
473
474     /// <summary>
475     /// Add a value class to this external assembly
476     /// </summary>
477     /// <param name="nsName">name space name</param>
478     /// <param name="name">class name</param>
479     /// <returns></returns>
480     public virtual ClassRef AddValueClass(string nsName, string name) {
481       ClassRef aClass = new ClassRef(nsName,name,metaData);
482       metaData.AddToTable(MDTable.TypeRef,aClass);
483       aClass.SetParent(this);
484       aClass.MakeValueClass(ValueClass.ValueType);
485       return aClass;
486     }
487
488     internal string TypeName() {
489       string result = name;
490       if (hasVersion) 
491         result = result + ", Version=" + major + "." + minor + "." + 
492                   build + "." + revision;
493       if (keyBytes != null) {
494         string tokenStr = "=";
495         if (isKeyToken) tokenStr = "Token=";
496         result = result + ", PublicKey" + tokenStr;
497         for (int i=0; i < keyBytes.Length; i++) {
498           result = result + Hex.Byte(keyBytes[i]);
499         }
500       }
501       if (culture != null) 
502         result = result + ", Culture=" + culture;
503       return result;
504     }
505
506     internal sealed override uint Size(MetaData md) {
507       return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
508     }
509
510     internal sealed override void Write(FileImage output) {
511       output.Write(major);
512       output.Write(minor);
513       output.Write(build);
514       output.Write(revision);
515       output.Write(flags);
516       output.BlobIndex(keyIx);
517       output.StringsIndex(nameIx);
518       output.StringsIndex(cultIx);
519       output.BlobIndex(hashIx);
520     }
521
522     internal sealed override uint GetCodedIx(CIx code) {
523       switch (code) {
524         case (CIx.ResolutionScope) : return 2; 
525         case (CIx.HasCustomAttr) : return 15; 
526         case (CIx.Implementation) : return 1; 
527       }
528       return 0;
529     }
530
531         }
532   /**************************************************************************/  
533
534   /// <summary>
535   /// flags for the assembly (.corflags)
536   /// </summary>
537   public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
538                         CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
539
540   /// <summary>
541   /// subsystem for the assembly (.subsystem)
542   /// </summary>
543   public enum SubSystem { Native = 1, Windows_GUI = 2, 
544     Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8, 
545     Windows_CE_GUI = 9}
546  
547   /// <summary>
548   /// Hash algorithms for the assembly
549   /// </summary>
550   public enum HashAlgorithm { None, SHA1 }
551
552   /// <summary>
553   /// Attributes for this assembly
554   /// </summary>
555   public enum AssemAttr { EnableJITCompileTracking = 0x8000, 
556                           DisableJITCompileOptimizer = 0x4000}
557
558   /// <summary>
559   /// Method call conventions
560   /// </summary>
561   public enum CallConv { Default, Cdecl, Stdcall, Thiscall, 
562     Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
563
564   /// <summary>
565   /// Type custom modifier
566   /// </summary>
567   public enum CustomModifier { modreq = 0x1F, modopt };
568
569   /// <summary>
570   /// Attibutes for a class
571   /// </summary>
572   public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, 
573     NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, 
574     SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, 
575     Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, 
576     PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, 
577     Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
578     AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
579
580   /// <summary>
581   /// Attributes for a field
582   /// </summary>
583   public enum FieldAttr {Default, Private, FamAndAssem, Assembly, 
584     Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16, 
585     Initonly = 0x20, Literal = 0x40, Notserialized = 0x80, 
586     SpecialName = 0x200, RTSpecialName = 0x400 }
587   
588   /// <summary>
589   /// Attributes for a method
590   /// </summary>
591   public enum MethAttr { Default, Private, FamAndAssem, Assembly,
592     Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, 
593     Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, 
594     PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, 
595     NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
596     RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, 
597     RequireSecObject = 0x8000}
598
599   /// <summary>
600   /// Attributes for .pinvokeimpl method declarations
601   /// </summary>
602   public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
603                             lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
604                             stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
605
606   /// <summary>
607   /// Implementation attributes for a method
608   /// </summary>
609   public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
610     ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000, 
611     Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
612
613   /// <summary>
614   /// Modes for a parameter
615   /// </summary>
616   public enum ParamAttr { Default, In, Out, Opt = 16 }
617
618   /// <summary>
619   /// CIL instructions
620   /// </summary>
621   public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
622     ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3, 
623     ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3, 
624     ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop, 
625     ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4, 
626     ldind_u4, ldind_i8, ldind_i,  ldind_r4, ldind_r8, ldind_ref, stind_ref, 
627     stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
628     div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not, 
629     conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8, 
630     conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
631     conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un, 
632     conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un, 
633     ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2, 
634     ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8, 
635     ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
636     stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2, 
637     conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3, 
638     conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf, 
639     add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, 
640     stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, 
641     localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, 
642     cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
643
644   /// <summary>
645   /// CIL instructions requiring an integer parameter
646   /// </summary>
647   public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s, 
648                      stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
649                      ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
650
651   /// <summary>
652   /// CIL instructions requiring a field parameter
653   /// </summary>
654   public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
655                        stsfld, ldtoken = 0xD0 }
656
657   /// <summary>
658   /// CIL instructions requiring a method parameter
659   /// </summary>
660   public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73, 
661                         ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
662
663   /// <summary>
664   /// CIL instructions requiring a type parameter
665   /// </summary>
666   public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, 
667                       unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, 
668                       ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, 
669                       ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
670                       ldelem = 0xA3, stelem = 0xA4, unbox_any }
671
672   /// <summary>
673   /// CIL branch instructions
674   /// </summary>
675   public enum BranchOp {
676           // short branches
677           br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
678           ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
679           // long branches
680           br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
681           bne_un, bge_un, bgt_un, ble_un, blt_un,
682
683           leave = 0xDD, leave_s }
684
685   /// <summary>
686   /// Index for all the tables in the meta data
687   /// </summary>
688   public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
689     Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute, 
690     FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig, 
691     EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics, 
692     MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20, 
693     AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor, 
694     AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
695     GenericParam, MethodSpec, GenericParamConstraint  }
696
697   public enum SafeArrayType { int16 = 2, int32, float32, float64,
698     currency, date, bstr, dispatch, error, boolean, variant, unknown,
699     Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
700
701   internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
702     HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, 
703     MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
704     TypeOrMethodDef, MaxCIx }
705
706   internal enum MapType { eventMap, propertyMap, nestedClass }
707
708   /**************************************************************************/  
709         /// <summary>
710         /// The assembly for mscorlib.  
711         /// </summary>
712         public sealed class MSCorLib : AssemblyRef
713         {
714     private static readonly int valueTypeIx = 18;
715     private readonly string systemName = "System";
716     private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
717     private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
718     private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
719     private static int[] specialNames = {
720       PrimitiveType.Void.GetName().GetHashCode(),
721       PrimitiveType.Boolean.GetName().GetHashCode(),
722       PrimitiveType.Char.GetName().GetHashCode(),
723       PrimitiveType.Int8.GetName().GetHashCode(),
724       PrimitiveType.UInt8.GetName().GetHashCode(),
725       PrimitiveType.Int16.GetName().GetHashCode(),
726       PrimitiveType.UInt16.GetName().GetHashCode(),
727       PrimitiveType.Int32.GetName().GetHashCode(),
728       PrimitiveType.UInt32.GetName().GetHashCode(),
729       PrimitiveType.Int64.GetName().GetHashCode(),
730       PrimitiveType.UInt64.GetName().GetHashCode(),
731       PrimitiveType.Float32.GetName().GetHashCode(),
732       PrimitiveType.Float64.GetName().GetHashCode(),
733       PrimitiveType.String.GetName().GetHashCode(),
734       PrimitiveType.TypedRef.GetName().GetHashCode(),
735       PrimitiveType.IntPtr.GetName().GetHashCode(),
736       PrimitiveType.UIntPtr.GetName().GetHashCode(),
737       PrimitiveType.Object.GetName().GetHashCode(),
738       PrimitiveType.ValueType.GetName ().GetHashCode(),
739       "Enum".GetHashCode()
740     };
741
742     internal MSCorLib(MetaData md) : base(md,"mscorlib") {
743       md.AddToTable(MDTable.AssemblyRef,this);
744       systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
745       systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
746       systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
747       systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
748       systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
749       systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
750       systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
751       systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
752       systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
753       systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
754       systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
755       systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
756       systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
757       systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
758       systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
759       systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
760       systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
761       systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
762     }
763
764     /// <summary>
765     /// Add a class to the mscorlib assembly
766     /// </summary>
767     /// <param name="nsName">name space name</param>
768     /// <param name="name">class name</param>
769     /// <returns></returns>
770     public override ClassRef AddClass(string nsName, string name) {
771       ClassRef aClass = GetSpecialClass(nsName,name);
772       if (aClass == null) {
773         aClass = new ClassRef(nsName,name,metaData);
774         metaData.AddToTable(MDTable.TypeRef,aClass);
775         aClass.SetParent(this);
776       }
777       return aClass;
778     }
779
780     private ClassRef GetSpecialClass(string nsName,string name) {
781       if (nsName.CompareTo(systemName) != 0) return null;
782       int hash = name.GetHashCode();
783       for (int i=0; i < specialNames.Length; i++) {
784         if (hash == specialNames[i]) {
785           if (systemClasses[i] == null) {
786             if (i < valueTypeIx) {
787               systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
788               if ((systemTypes[i] != PrimitiveType.Object) &&
789                 (systemTypes[i] != PrimitiveType.String)) {
790                 systemClasses[i].MakeValueClass(ValueClass.ValueType);
791               }
792             } else {
793               systemClasses[i] = new ClassRef(nsName,name,metaData);
794               systemClasses[i].SetParent(this);
795               if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
796                 systemClasses[i].MakeValueClass(ValueClass.ValueType);
797             }
798             metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
799           }
800           return systemClasses[i];
801         }
802       }
803       return null;
804     }
805
806     internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
807       int ix = pType.GetSystemTypeIx();
808       if (systemClasses[ix] == null) {
809         systemClasses[ix] = new SystemClass(pType,this,metaData);
810         metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
811       }
812       return systemClasses[ix];
813     }
814         
815     private ClassRef GetValueClass(string name, int hash) {
816       int ix = valueTypeIx;
817       if (hash != specialNames[valueTypeIx]) ix++;
818       if (systemClasses[ix] == null) {
819         systemClasses[ix] = new ClassRef(systemName,name,metaData);
820         systemClasses[ix].SetParent(this);
821         systemClasses[ix].MakeValueClass(ValueClass.ValueType);
822         metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
823       }
824       return systemClasses[ix];
825     }
826
827     internal ClassRef ValueType() {
828       if (systemClasses[valueTypeIx] == null) {
829         ClassRef valType = new ClassRef("System","ValueType",metaData);
830         valType.SetParent(this);
831         valType.MakeValueClass(ValueClass.ValueType);
832         metaData.AddToTable(MDTable.TypeRef,valType);
833         systemClasses[valueTypeIx] = valType;
834       }
835       return systemClasses[valueTypeIx];
836     }
837
838     internal ClassRef EnumType() {
839       //systemClasses [ valueTypeIx + 1] -> System.Enum
840       if (systemClasses[valueTypeIx + 1] == null) {
841         ClassRef valType = new ClassRef("System","Enum",metaData);
842         valType.SetParent(this);
843         valType.MakeValueClass(ValueClass.Enum);
844         metaData.AddToTable(MDTable.TypeRef,valType);
845         systemClasses[valueTypeIx + 1] = valType;
846       }
847       return systemClasses[valueTypeIx + 1];
848     }
849
850     /// <summary>
851     /// Add a value class to this external assembly
852     /// </summary>
853     /// <param name="nsName">name space name</param>
854     /// <param name="name">class name</param>
855     /// <returns></returns>
856     public override ClassRef AddValueClass(string nsName, string name) {
857       if (nsName.CompareTo(systemName) == 0) {
858         int hash = name.GetHashCode();
859         if ((hash == specialNames[valueTypeIx]) ||
860             (hash == specialNames[valueTypeIx+1])) {
861           return GetValueClass(name,hash);
862         }
863       }
864       ClassRef aClass = new ClassRef(nsName,name,metaData);
865       metaData.AddToTable(MDTable.TypeRef,aClass);
866       aClass.SetParent(this);
867       aClass.MakeValueClass(ValueClass.ValueType);
868       return aClass;
869     }
870
871         }
872         public enum ValueClass
873         {
874                 ValueType,
875                 Enum
876         }
877
878   /**************************************************************************/  
879         /// <summary>
880         /// Signature for calli instruction
881         /// </summary>
882         public class CalliSig : Signature
883         {
884     private static readonly byte Sentinel = 0x41;
885     CallConv callConv;
886     Type returnType;
887     Type[] parameters, optParams;
888                 uint numPars = 0, numOptPars = 0;
889
890     /// <summary>
891     /// Create a signature for a calli instruction
892     /// </summary>
893     /// <param name="cconv">calling conventions</param>
894     /// <param name="retType">return type</param>
895     /// <param name="pars">parameter types</param>
896     public CalliSig(CallConv cconv, Type retType, Type[] pars) {
897                         tabIx = MDTable.StandAloneSig;
898       callConv = cconv;
899       returnType = retType;
900       parameters = pars;
901                         if (pars != null) numPars = (uint)pars.Length;
902     }
903
904     /// <summary>
905     /// Add the optional parameters to a vararg method
906     /// This method sets the vararg calling convention
907     /// </summary>
908     /// <param name="optPars">the optional pars for the vararg call</param>
909     public void AddVarArgs(Type[] optPars) {
910       optParams = optPars;
911       if (optPars != null) numOptPars = (uint)optPars.Length;
912       callConv |= CallConv.Vararg;
913     }
914
915     /// <summary>
916     /// Add extra calling conventions to this callsite signature
917     /// </summary>
918     /// <param name="cconv"></param>
919     public void AddCallingConv(CallConv cconv) {
920       callConv |= cconv;
921     }
922
923     internal sealed override void BuildTables(MetaData md) {
924       if (done) return;
925       MemoryStream sig = new MemoryStream();
926       sig.WriteByte((byte)callConv);
927       MetaData.CompressNum(numPars+numOptPars,sig);
928       returnType.TypeSig(sig);
929       for (int i=0; i < numPars; i++) {
930         parameters[i].TypeSig(sig);
931       }
932       sigIx = md.AddToBlobHeap(sig.ToArray());
933       if (numOptPars > 0) {
934         sig.WriteByte(Sentinel);
935         for (int i=0; i < numOptPars; i++) {
936           optParams[i].TypeSig(sig);
937         }
938       }
939       done = true;
940     }
941
942         }
943   /**************************************************************************/  
944   /// <summary>
945   /// The IL instructions for a method
946   /// </summary>
947   public class CILInstructions 
948   {
949
950     private static readonly uint ExHeaderSize = 4;
951     private static readonly uint FatExClauseSize = 24;
952     private static readonly uint SmlExClauseSize = 12;
953     private static readonly sbyte maxByteVal = 127;
954     private static readonly sbyte minByteVal = -128;
955     private static readonly byte maxUByteVal = 255;
956     private static readonly int smallSize = 64;
957     private static readonly ushort TinyFormat = 0x2;
958     private static readonly ushort FatFormat = 0x3003;
959     private static readonly ushort MoreSects = 0x8;
960     private static readonly ushort InitLocals = 0x10;
961     private static readonly uint FatSize = 12;
962     private static readonly uint FatWords = FatSize/4;
963     private static readonly byte FatExceptTable = 0x41;
964     private static readonly byte SmlExceptTable = 0x01; 
965
966     private MetaData metaData;
967     private ArrayList exceptions, blockStack;
968     //private bool codeChecked = false;
969     private static readonly int INITSIZE = 5;
970     private CILInstruction[] buffer = new CILInstruction[INITSIZE];
971     private int tide = 0;
972     private uint offset = 0;
973     private ushort headerFlags = 0;
974     private short maxStack;
975     private uint paddingNeeded = 0;
976     private byte exceptHeader = 0;
977     uint localSigIx = 0;
978     uint codeSize = 0, exceptSize = 0;
979     bool tinyFormat, fatExceptionFormat = false;
980
981     public uint Offset {
982         get { return offset; }
983     }   
984
985     internal CILInstructions(MetaData md) {
986       metaData = md;
987     }
988
989     private void AddToBuffer(CILInstruction inst) {
990       if (tide >= buffer.Length) {
991         CILInstruction[] tmp = buffer;
992         buffer = new CILInstruction[tmp.Length * 2];
993         for (int i=0; i < tide; i++) {
994           buffer[i] = tmp[i];
995         }
996       }
997                         //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
998                         inst.offset = offset;
999       offset += inst.size;
1000       buffer[tide++] = inst;
1001     }
1002
1003     /// <summary>
1004     /// Add a simple IL instruction
1005     /// </summary>
1006     /// <param name="inst">the IL instruction</param>
1007     public void Inst(Op inst) {
1008       AddToBuffer(new Instr((int)inst));
1009     }
1010
1011     /// <summary>
1012     /// Add an IL instruction with an integer parameter
1013     /// </summary>
1014     /// <param name="inst">the IL instruction</param>
1015     /// <param name="val">the integer parameter value</param>
1016     public void IntInst(IntOp inst, int val) {
1017       int instr = (int)inst;
1018       if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4)) 
1019         AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
1020       else
1021         AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
1022                                               (inst == IntOp.unaligned))));
1023     }
1024
1025     /// <summary>
1026     /// Add the load long instruction
1027     /// </summary>
1028     /// <param name="cVal">the long value</param>
1029     public void ldc_i8(long cVal) {
1030       AddToBuffer(new LongInstr(0x21,cVal));
1031     }
1032
1033     /// <summary>
1034     /// Add the load float32 instruction
1035     /// </summary>
1036     /// <param name="cVal">the float value</param>
1037     public void ldc_r4(float cVal) {
1038       AddToBuffer(new FloatInstr(0x22,cVal));
1039     }
1040
1041     /// <summary>
1042     /// Add the load float64 instruction
1043     /// </summary>
1044     /// <param name="cVal">the float value</param>
1045     public void ldc_r8(double cVal) {
1046       AddToBuffer(new DoubleInstr(0x23,cVal));
1047     }
1048
1049     /// <summary>
1050     /// Add the load string instruction
1051     /// </summary>
1052     /// <param name="str">the string value</param>
1053     public void ldstr(string str) {
1054       AddToBuffer(new StringInstr(0x72,str));
1055     }
1056
1057           /// <summary>
1058           /// Add the load string instruction
1059           /// </summary>
1060           public void ldstr (byte[] str) {
1061                   AddToBuffer (new StringInstr (0x72, str));
1062           }
1063           
1064     /// <summary>
1065     /// Add the calli instruction
1066     /// </summary>
1067     /// <param name="sig">the signature for the calli</param>
1068     public void calli(CalliSig sig) {
1069       AddToBuffer(new SigInstr(0x29,sig));
1070     }
1071
1072     /// <summary>
1073     /// Add a label to the CIL instructions
1074     /// </summary>
1075     /// <param name="lab">the label to be added</param>
1076     public void CodeLabel(CILLabel lab) {
1077       AddToBuffer(new LabelInstr(lab));
1078     }
1079
1080     /// <summary>
1081     /// Add an instruction with a field parameter
1082     /// </summary>
1083     /// <param name="inst">the CIL instruction</param>
1084     /// <param name="f">the field parameter</param>
1085     public void FieldInst(FieldOp inst, Field f) {
1086       AddToBuffer(new FieldInstr((int)inst,f));
1087     }
1088
1089     /// <summary>
1090     /// Add an instruction with a method parameter
1091     /// </summary>
1092     /// <param name="inst">the CIL instruction</param>
1093     /// <param name="m">the method parameter</param>
1094     public void MethInst(MethodOp inst, Method m) {
1095       AddToBuffer(new MethInstr((int)inst,m));
1096     }
1097
1098     /// <summary>
1099     /// Add an instruction with a type parameter
1100     /// </summary>
1101     /// <param name="inst">the CIL instruction</param>
1102     /// <param name="t">the type argument for the CIL instruction</param>
1103     public void TypeInst(TypeOp inst, Type aType) {
1104       AddToBuffer(new TypeInstr((int)inst,aType,metaData));
1105     }
1106
1107     /// <summary>
1108     /// Add a branch instruction
1109     /// </summary>
1110     /// <param name="inst">the branch instruction</param>
1111     /// <param name="lab">the label that is the target of the branch</param>
1112     public void Branch(BranchOp inst,  CILLabel lab) {
1113       AddToBuffer(new BranchInstr((int)inst,lab));
1114     }
1115
1116     /// <summary>
1117     /// Add a switch instruction
1118     /// </summary>
1119     /// <param name="labs">the target labels for the switch</param>
1120     public void Switch(CILLabel[] labs) {
1121       AddToBuffer(new SwitchInstr(0x45,labs));
1122     }
1123
1124     /// <summary>
1125     /// Add a byte to the CIL instructions (.emitbyte)
1126     /// </summary>
1127     /// <param name="bVal"></param>
1128     public void emitbyte(byte bVal) { 
1129       AddToBuffer(new CILByte(bVal));
1130     }
1131
1132     /// <summary>
1133     /// Add an instruction which puts an integer on TOS.  This method
1134     /// selects the correct instruction based on the value of the integer.
1135     /// </summary>
1136     /// <param name="i">the integer value</param>
1137     public void PushInt(int i) {
1138       if (i == -1) {
1139         AddToBuffer(new Instr((int)Op.ldc_i4_m1));
1140       } else if ((i >= 0) && (i <= 8)) {
1141         Op op = (Op)(Op.ldc_i4_0 + i);
1142         AddToBuffer(new Instr((int)op));
1143       } else if ((i >= minByteVal) && (i <= maxByteVal)) {
1144         AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
1145       } else {
1146         AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false)); 
1147       }
1148     }
1149
1150     /// <summary>
1151     /// Add the instruction to load a long on TOS
1152     /// </summary>
1153     /// <param name="l">the long value</param>
1154     public void PushLong(long l) {
1155       AddToBuffer(new LongInstr(0x21,l));
1156     }
1157
1158     /// <summary>
1159     /// Add an instruction to push the boolean value true on TOS
1160     /// </summary>
1161     public void PushTrue() {
1162       AddToBuffer(new Instr((int)Op.ldc_i4_1));
1163     }
1164
1165     /// <summary>
1166     ///  Add an instruction to push the boolean value false on TOS
1167     /// </summary>
1168     public void PushFalse() {
1169       AddToBuffer(new Instr((int)Op.ldc_i4_0));
1170     }
1171
1172     /// <summary>
1173     /// Add the instruction to load an argument on TOS.  This method
1174     /// selects the correct instruction based on the value of argNo
1175     /// </summary>
1176     /// <param name="argNo">the number of the argument</param>
1177     public void LoadArg(int argNo) {
1178       if (argNo < 4) {
1179         int op = (int)Op.ldarg_0 + argNo;
1180         AddToBuffer(new Instr(op));
1181       } else if (argNo <= maxUByteVal) {
1182         AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
1183       } else {
1184         AddToBuffer(new UIntInstr(0x09,argNo,false)); 
1185       }
1186    }
1187
1188     /// <summary>
1189     /// Add the instruction to load the address of an argument on TOS.
1190     /// This method selects the correct instruction based on the value
1191     /// of argNo.
1192     /// </summary>
1193     /// <param name="argNo">the number of the argument</param>
1194     public void LoadArgAdr(int argNo) {
1195       if (argNo <= maxUByteVal) {
1196         AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
1197       } else {
1198         AddToBuffer(new UIntInstr(0x0A,argNo,false)); 
1199       }
1200     }
1201
1202     /// <summary>
1203     /// Add the instruction to load a local on TOS.  This method selects
1204     /// the correct instruction based on the value of locNo.
1205     /// </summary>
1206     /// <param name="locNo">the number of the local to load</param>
1207     public void LoadLocal(int locNo) {
1208       if (locNo < 4) {
1209         int op = (int)Op.ldloc_0 + locNo;
1210         AddToBuffer(new Instr(op));
1211       } else if (locNo <= maxUByteVal) {
1212         AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
1213       } else {
1214         AddToBuffer(new UIntInstr(0x0C,locNo,false)); 
1215       }
1216     }
1217
1218     /// <summary>
1219     /// Add the instruction to load the address of a local on TOS.
1220     /// This method selects the correct instruction based on the 
1221     /// value of locNo.
1222     /// </summary>
1223     /// <param name="locNo">the number of the local</param>
1224     public void LoadLocalAdr(int locNo) {
1225       if (locNo <= maxUByteVal) {
1226         AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
1227       } else {
1228         AddToBuffer(new UIntInstr(0x0D,locNo,false)); 
1229       }
1230     }
1231
1232     /// <summary>
1233     /// Add the instruction to store to an argument.  This method
1234     /// selects the correct instruction based on the value of argNo.
1235     /// </summary>
1236     /// <param name="argNo">the argument to be stored to</param>
1237     public void StoreArg(int argNo) {
1238       if (argNo <= maxUByteVal) {
1239         AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
1240       } else {
1241         AddToBuffer(new UIntInstr(0x0B,argNo,false)); 
1242       }
1243     }
1244
1245     /// <summary>
1246     /// Add the instruction to store to a local.  This method selects
1247     /// the correct instruction based on the value of locNo.
1248     /// </summary>
1249     /// <param name="locNo">the local to be stored to</param>
1250     public void StoreLocal(int locNo) {
1251       if (locNo < 4) {
1252         int op = (int)Op.stloc_0 + locNo;
1253         AddToBuffer(new Instr(op));
1254       } else if (locNo <= maxUByteVal) {
1255         AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
1256       } else {
1257         AddToBuffer(new UIntInstr(0x0E,locNo,false)); 
1258       }
1259     }
1260
1261     /// <summary>
1262     /// Create a new CIL label.  To place the label in the CIL instruction
1263     /// stream use CodeLabel.
1264     /// </summary>
1265     /// <returns>a new CIL label</returns>
1266     public CILLabel NewLabel() {
1267       return new CILLabel();
1268     }
1269
1270     public void AddTryBlock(TryBlock tryBlock) {
1271       if (exceptions == null) 
1272         exceptions = new ArrayList();
1273       else if (exceptions.Contains(tryBlock)) return;
1274       exceptions.Add(tryBlock);
1275     }
1276
1277     /// <summary>
1278     /// Create a new label at this position in the code buffer
1279     /// </summary>
1280     /// <returns>the label at the current position</returns>
1281     public CILLabel NewCodedLabel() {
1282       CILLabel lab = new CILLabel();
1283       AddToBuffer(new LabelInstr(lab));
1284       return lab;
1285     }
1286
1287     /// <summary>
1288     /// Mark this position as the start of a new block
1289     /// (try, catch, filter, finally or fault)
1290     /// </summary>
1291     public void StartBlock() {
1292       if (blockStack == null) blockStack = new ArrayList();
1293       blockStack.Insert(0,NewCodedLabel());
1294     }
1295
1296     /// <summary>
1297     /// Mark this position as the end of the last started block and
1298     /// make it a try block.  This try block is added to the current 
1299     /// instructions (ie do not need to call AddTryBlock)
1300     /// </summary>
1301     /// <returns>The try block just ended</returns>
1302     public TryBlock EndTryBlock() {
1303       TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
1304       blockStack.RemoveAt(0);
1305       AddTryBlock(tBlock);
1306       return tBlock;
1307     }
1308
1309     /// <summary>
1310     /// Mark this position as the end of the last started block and
1311     /// make it a catch block.  This catch block is associated with the
1312     /// specified try block.
1313     /// </summary>
1314     /// <param name="exceptType">the exception type to be caught</param>
1315     /// <param name="tryBlock">the try block associated with this catch block</param>
1316     public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
1317       Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
1318         NewCodedLabel());
1319       tryBlock.AddHandler(catchBlock);
1320     }
1321
1322     /// <summary>
1323     /// Mark this position as the end of the last started block and
1324     /// make it a filter block.  This filter block is associated with the
1325     /// specified try block.
1326     /// </summary>
1327     /// <param name="filterLab">the label where the filter code is</param>
1328     /// <param name="tryBlock">the try block associated with this filter block</param>
1329     public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
1330       Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
1331       tryBlock.AddHandler(filBlock);
1332     }
1333
1334     /// <summary>
1335     /// Mark this position as the end of the last started block and
1336     /// make it a finally block.  This finally block is associated with the
1337     /// specified try block.
1338     /// </summary>
1339     /// <param name="tryBlock">the try block associated with this finally block</param>
1340     public void EndFinallyBlock(TryBlock tryBlock) {
1341       Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
1342       tryBlock.AddHandler(finBlock);
1343     }
1344
1345     /// <summary>
1346     /// Mark this position as the end of the last started block and
1347     /// make it a fault block.  This fault block is associated with the
1348     /// specified try block.
1349     /// </summary>
1350     /// <param name="tryBlock">the try block associated with this fault block</param>
1351     public void EndFaultBlock(TryBlock tryBlock) {
1352       Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
1353       tryBlock.AddHandler(fBlock);
1354     }
1355
1356     internal uint GetCodeSize() {
1357       return codeSize + paddingNeeded + exceptSize;
1358     }
1359
1360     internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
1361       if (tide == 0) return;
1362       bool changed = true;
1363       while (changed) {
1364         changed = false;
1365         for (int i=0; i < tide; i++) {
1366           changed = buffer[i].Check(metaData) || changed;
1367         }
1368         if (changed) {
1369           for (int i=1; i < tide; i++) {
1370             buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
1371           }
1372           offset = buffer[tide-1].offset + buffer[tide-1].size;
1373         }
1374       }
1375                         codeSize = offset;
1376                         // Console.WriteLine("codeSize before header added = " + codeSize);
1377       if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
1378         // can use tiny header
1379         //Console.WriteLine("Tiny Header");
1380         tinyFormat = true;
1381         headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
1382         codeSize++;
1383         if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
1384       } else {
1385         //Console.WriteLine("Fat Header");
1386         tinyFormat = false;
1387         localSigIx = locSigIx;
1388         this.maxStack = (short)maxStack;
1389         headerFlags = FatFormat;
1390         if (exceptions != null) {
1391           // Console.WriteLine("Got exceptions");
1392           headerFlags |= MoreSects;
1393           uint numExceptClauses = 0;
1394           for (int i=0; i < exceptions.Count; i++) {
1395             TryBlock tryBlock = (TryBlock)exceptions[i];
1396             tryBlock.SetSize();
1397             numExceptClauses += (uint)tryBlock.NumHandlers();
1398             if (tryBlock.isFat()) fatExceptionFormat = true;
1399           }
1400
1401           uint data_size = ExHeaderSize + numExceptClauses *
1402                  (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
1403
1404           if (data_size > 256)
1405                   fatExceptionFormat = true;
1406                   
1407           // Console.WriteLine("numexceptclauses = " + numExceptClauses);
1408           if (fatExceptionFormat) {
1409             // Console.WriteLine("Fat exception format");
1410             exceptHeader = FatExceptTable;
1411             exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
1412           } else {
1413             // Console.WriteLine("Tiny exception format");
1414             exceptHeader = SmlExceptTable;
1415             exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
1416           }
1417           // Console.WriteLine("exceptSize = " + exceptSize);
1418         }
1419         if (initLocals) headerFlags |= InitLocals;
1420         if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
1421         codeSize += FatSize;
1422       }
1423                   // Console.WriteLine("codeSize = " + codeSize + "  headerFlags = " + 
1424       //                   Hex.Short(headerFlags));
1425     }
1426
1427                 internal void Write(FileImage output) {
1428       // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
1429                         if (tinyFormat) {
1430         // Console.WriteLine("Writing tiny code");
1431                                 output.Write((byte)headerFlags);
1432                         } else {
1433         // Console.WriteLine("Writing fat code");
1434                                 output.Write(headerFlags);
1435                                 output.Write((ushort)maxStack);
1436                                 output.Write(offset);
1437                                 output.Write(localSigIx);
1438                         }
1439       // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
1440       // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
1441                         for (int i=0; i < tide; i++) {
1442                                 buffer[i].Write(output);
1443                         }
1444       // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
1445       for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
1446       if (exceptions != null) {
1447         // Console.WriteLine("Writing exceptions");
1448         // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
1449         output.Write(exceptHeader);
1450         output.Write3Bytes((uint)exceptSize);
1451         for (int i=0; i < exceptions.Count; i++) {
1452           TryBlock tryBlock = (TryBlock)exceptions[i];
1453           tryBlock.Write(output,fatExceptionFormat);
1454         }
1455       }
1456                 }
1457
1458   }
1459   /**************************************************************************/  
1460         /// <summary>
1461         /// A label in the IL
1462         /// </summary>
1463         public class CILLabel
1464         {
1465     CILInstruction branch;
1466     CILInstruction[] multipleBranches;
1467     int tide = 0;
1468     CILInstruction labInstr;
1469     uint offset = 0;
1470  
1471     public CILLabel (uint offset) {
1472         this.offset = offset;
1473         }
1474         
1475
1476     internal CILLabel() {
1477     }
1478
1479     internal void AddBranch(CILInstruction instr) {
1480       if (branch == null) {
1481         branch = instr;
1482         return;
1483       }
1484       if (multipleBranches == null) {
1485         multipleBranches = new CILInstruction[2];
1486       } else if (tide >= multipleBranches.Length) {
1487         CILInstruction[] tmp = multipleBranches;
1488         multipleBranches = new CILInstruction[tmp.Length*2];
1489         for (int i=0; i < tide; i++) {
1490           multipleBranches[i] = tmp[i];
1491         }
1492       }
1493       multipleBranches[tide++] = instr;
1494     }
1495
1496     internal void AddLabelInstr(LabelInstr lInstr) {
1497       labInstr = lInstr;
1498     }
1499
1500     internal uint GetLabelOffset() {
1501       if (labInstr == null) return 0;
1502       return labInstr.offset + offset;
1503     }
1504
1505         }
1506   /**************************************************************************/  
1507   public abstract class CodeBlock {
1508
1509     private static readonly int maxCodeSize = 256;
1510     protected CILLabel start, end;
1511     protected bool small = true;
1512
1513     public CodeBlock(CILLabel start, CILLabel end) {
1514       this.start = start;
1515       this.end = end;
1516     }
1517
1518     internal virtual bool isFat() {
1519       // Console.WriteLine("block start = " + start.GetLabelOffset() +
1520       //                  "  block end = " + end.GetLabelOffset());
1521       return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
1522     }
1523
1524     internal virtual void Write(FileImage output, bool fatFormat) {
1525       if (fatFormat) output.Write(start.GetLabelOffset());
1526       else output.Write((short)start.GetLabelOffset());
1527       uint len = end.GetLabelOffset() - start.GetLabelOffset();
1528       if (fatFormat) output.Write(len);
1529       else output.Write((byte)len);
1530     }
1531
1532   }
1533
1534   /// <summary>
1535   /// The descriptor for a guarded block (.try)
1536   /// </summary>
1537   public class TryBlock : CodeBlock {
1538     protected bool fatFormat = false;
1539     protected int flags = 0;
1540     ArrayList handlers = new ArrayList();
1541
1542     /// <summary>
1543     /// Create a new try block
1544     /// </summary>
1545     /// <param name="start">start label for the try block</param>
1546     /// <param name="end">end label for the try block</param>
1547     public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
1548
1549     /// <summary>
1550     /// Add a handler to this try block
1551     /// </summary>
1552     /// <param name="handler">a handler to be added to the try block</param>
1553     public void AddHandler(HandlerBlock handler) {
1554       flags = handler.GetFlag();
1555       handlers.Add(handler);
1556     }
1557
1558     internal void SetSize() {
1559       fatFormat = base.isFat();
1560       if (fatFormat) return;
1561       for (int i=0; i < handlers.Count; i++) {
1562         HandlerBlock handler = (HandlerBlock)handlers[i];
1563         if (handler.isFat()) {
1564           fatFormat = true;
1565           return;
1566         }
1567       }
1568     }
1569
1570     internal int NumHandlers() {
1571       return handlers.Count;
1572   }
1573
1574     internal override bool isFat() {
1575       return fatFormat;
1576     }
1577
1578     internal override void Write(FileImage output, bool fatFormat) {
1579       // Console.WriteLine("writing exception details");
1580       for (int i=0; i < handlers.Count; i++) {
1581         // Console.WriteLine("Except block " + i);
1582         HandlerBlock handler = (HandlerBlock)handlers[i];
1583         if (fatFormat) output.Write(flags);
1584         else output.Write((short)flags);
1585         // Console.WriteLine("flags = " + Hex.Short(flags));
1586         base.Write(output,fatFormat);
1587         handler.Write(output,fatFormat);
1588       }
1589     }
1590   }
1591
1592   public abstract class HandlerBlock : CodeBlock 
1593   {
1594     protected static readonly short ExceptionFlag = 0;
1595     protected static readonly short FilterFlag = 0x01;
1596     protected static readonly short FinallyFlag = 0x02;
1597     protected static readonly short FaultFlag = 0x04;
1598
1599     public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
1600
1601     internal virtual short GetFlag() { return ExceptionFlag; }
1602
1603     internal override void Write(FileImage output, bool fatFormat) {
1604       base.Write(output,fatFormat);
1605     }
1606
1607   }
1608
1609   /// <summary>
1610   /// The descriptor for a catch clause (.catch)
1611   /// </summary>
1612   public class Catch : HandlerBlock 
1613   {
1614     Class exceptType;
1615     
1616     /// <summary>
1617     /// Create a new catch clause
1618     /// </summary>
1619     /// <param name="except">the exception to be caught</param>
1620     /// <param name="handlerStart">start of the handler code</param>
1621     /// <param name="handlerEnd">end of the handler code</param>
1622     public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd) 
1623                                             : base(handlerStart,handlerEnd) {
1624       exceptType = except;
1625     }
1626
1627     internal override void Write(FileImage output, bool fatFormat) {
1628       base.Write(output,fatFormat);
1629       output.Write(exceptType.Token());
1630     }
1631   }
1632
1633   /// <summary>
1634   /// The descriptor for a filter clause (.filter)
1635   /// </summary>
1636   public class Filter : HandlerBlock 
1637   {
1638     CILLabel filterLabel;
1639
1640     /// <summary>
1641     /// Create a new filter clause
1642     /// </summary>
1643     /// <param name="filterLabel">the label where the filter code starts</param>
1644     /// <param name="handlerStart">the start of the handler code</param>
1645     /// <param name="handlerEnd">the end of the handler code</param>
1646     public Filter(CILLabel filterLabel, CILLabel handlerStart, 
1647                         CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
1648       this.filterLabel = filterLabel;
1649     }
1650
1651     internal override short GetFlag() { 
1652       return FilterFlag; 
1653     }
1654
1655     internal override void Write(FileImage output, bool fatFormat) {
1656       base.Write(output,fatFormat);
1657       output.Write(filterLabel.GetLabelOffset());
1658     }
1659
1660   }
1661
1662   /// <summary>
1663   /// Descriptor for a finally block (.finally)
1664   /// </summary>
1665   public class Finally : HandlerBlock 
1666   {
1667     /// <summary>
1668     /// Create a new finally clause
1669     /// </summary>
1670     /// <param name="finallyStart">start of finally code</param>
1671     /// <param name="finallyEnd">end of finally code</param>
1672     public Finally(CILLabel finallyStart, CILLabel finallyEnd)
1673       : base(finallyStart,finallyEnd) { }
1674
1675     internal override short GetFlag() { 
1676       return FinallyFlag; 
1677     }
1678
1679     internal override void Write(FileImage output, bool fatFormat) {
1680       base.Write(output,fatFormat);
1681       output.Write((int)0);
1682     }
1683
1684   }
1685
1686   /// <summary>
1687   /// Descriptor for a fault block (.fault)
1688   /// </summary>
1689   public class Fault : HandlerBlock 
1690   {
1691     /// <summary>
1692     /// Create a new fault clause
1693     /// </summary>
1694     /// <param name="faultStart">start of the fault code</param>
1695     /// <param name="faultEnd">end of the fault code</param>
1696     public Fault(CILLabel faultStart, CILLabel faultEnd)
1697                                               : base(faultStart,faultEnd) { }
1698
1699     internal override short GetFlag() { 
1700       return FaultFlag; 
1701     }
1702
1703     internal override void Write(FileImage output, bool fatFormat) {
1704       base.Write(output,fatFormat);
1705       output.Write((int)0);
1706       
1707     }
1708   }
1709
1710   /**************************************************************************/  
1711   /// <summary>
1712         /// The base descriptor for a class 
1713         /// </summary>
1714         public abstract class Class : Type
1715         {
1716     protected int row = 0;
1717     public string name, nameSpace;
1718     protected uint nameIx, nameSpaceIx;
1719                 protected MetaData _metaData;
1720                 internal Class(string nameSpaceName, string className, MetaData md)
1721                                                               : base(PrimitiveType.Class.GetTypeIndex ()) {
1722       nameSpace = nameSpaceName;
1723       name = className;
1724       nameIx = md.AddToStringsHeap(name);
1725       nameSpaceIx = md.AddToStringsHeap(nameSpace);
1726       _metaData = md;
1727     }
1728
1729     internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ()) {
1730       nameSpaceIx = nsIx;
1731       nameIx = nIx;
1732     }
1733
1734     internal virtual uint TypeDefOrRefToken() { return 0; }
1735
1736     internal virtual void MakeValueClass(ValueClass vClass) {
1737       typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1738     }
1739         
1740     internal virtual string TypeName() {
1741       return (nameSpace + "." + name);
1742     }
1743
1744     internal override MetaDataElement GetTypeSpec(MetaData md) {
1745       return this;
1746     }
1747         }
1748   /**************************************************************************/  
1749   // This Class produces entries in the TypeDef table of the MetaData 
1750   // in the PE meta data.
1751
1752   // NOTE:  Entry 0 in TypeDef table is always the pseudo class <module> 
1753   // which is the parent for functions and variables declared a module level
1754
1755   /// <summary>
1756         /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1757         /// </summary>
1758         /// 
1759         public class ClassDef : Class
1760         {
1761     private static readonly uint HasSecurity = 0x00040000;
1762     private static readonly byte ElementType_Class = 0x12;
1763
1764     Class superType;
1765     ArrayList fields = new ArrayList();
1766     ArrayList methods = new ArrayList();
1767     ArrayList events;
1768     ArrayList properties;
1769     bool typeIndexChecked = true;
1770     uint fieldIx = 0, methodIx = 0;
1771     byte[] securityActions;
1772     uint flags;
1773     ClassLayout layout;
1774     ClassDef parentClass;
1775     MetaData metaData;
1776     
1777     internal ClassDef(TypeAttr attrSet, string nsName, string name, 
1778                       MetaData md) : base(nsName, name, md) {
1779                         metaData = md;
1780       superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1781       flags = (uint)attrSet;
1782       tabIx = MDTable.TypeDef;
1783     }
1784
1785     internal void SetSuper(Class sClass) {
1786       superType = sClass;
1787       if (sClass is ClassRef)
1788         typeIndex = superType.GetTypeIndex();
1789       else
1790         typeIndexChecked = false;
1791     }
1792
1793     internal override void MakeValueClass(ValueClass vClass) {
1794       if (vClass == ValueClass.Enum)  
1795         superType = metaData.mscorlib.EnumType();
1796       else  
1797         superType = metaData.mscorlib.ValueType();
1798
1799       typeIndex = superType.GetTypeIndex();
1800     }
1801
1802     public void SpecialNoSuper() {
1803       superType = null;
1804     }
1805
1806     /// <summary>
1807     /// Add an attribute to this class
1808     /// </summary>
1809     /// <param name="ta">the attribute to be added</param>
1810     public void AddAttribute(TypeAttr ta) { 
1811       flags |= (uint)ta;
1812     }
1813
1814     /// <summary>
1815     /// Add an interface that is implemented by this class
1816     /// </summary>
1817     /// <param name="iFace">the interface that is implemented</param>
1818     public void AddImplementedInterface(Class iFace) {
1819       metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1820     }
1821
1822     /// <summary>
1823     ///  Add a named generic type parameter
1824     /// </summary>
1825     public GenericParameter AddGenericParameter (short index, string name) {
1826             GenericParameter gp = new GenericParameter (this, metaData, index, name);
1827             metaData.AddToTable (MDTable.GenericParam, gp);
1828             return gp;
1829     }
1830
1831     /// <summary>
1832     /// Add a field to this class
1833     /// </summary>
1834     /// <param name="name">field name</param>
1835     /// <param name="fType">field type</param>
1836     /// <returns>a descriptor for this new field</returns>
1837     public FieldDef AddField(string name, Type fType) {
1838       FieldDef field = new FieldDef(name,fType);
1839       fields.Add(field);
1840       return field;
1841     }
1842
1843     /// <summary>
1844     /// Add a field to this class
1845     /// </summary>
1846     /// <param name="fAtts">attributes for this field</param>
1847     /// <param name="name">field name</param>
1848     /// <param name="fType">field type</param>
1849     /// <returns>a descriptor for this new field</returns>
1850     public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
1851       FieldDef field = new FieldDef(fAtts,name,fType);
1852       fields.Add(field);
1853       return field;
1854     }
1855
1856     public void SetFieldOrder (ArrayList fields)
1857     {
1858             this.fields = fields;
1859     }
1860
1861     /// <summary>
1862     /// Add a method to this class
1863     /// </summary>
1864     /// <param name="name">method name</param>
1865     /// <param name="retType">return type</param>
1866     /// <param name="pars">parameters</param>
1867     /// <returns>a descriptor for this new method</returns>
1868     public MethodDef AddMethod(string name, Type retType, Param[] pars) {
1869       // Console.WriteLine("Adding method " + name + " to class " + this.name);
1870       MethodDef meth = new MethodDef(metaData,name,retType, pars);
1871       methods.Add(meth);
1872       return meth;
1873     }
1874
1875     /// <summary>
1876     /// Add a method to this class
1877     /// </summary>
1878     /// <param name="mAtts">attributes for this method</param>
1879     /// <param name="iAtts">implementation attributes for this method</param>
1880     /// <param name="name">method name</param>
1881     /// <param name="retType">return type</param>
1882     /// <param name="pars">parameters</param>
1883     /// <returns>a descriptor for this new method</returns>
1884     public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, 
1885                                Type retType, Param[] pars) {
1886       // Console.WriteLine("Adding method " + name + " to class " + this.name);
1887       MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
1888       methods.Add(meth);
1889       return meth;
1890     }
1891
1892     /// <summary>
1893     /// Add an event to this class
1894     /// </summary>
1895     /// <param name="name">event name</param>
1896     /// <param name="eType">event type</param>
1897     /// <returns>a descriptor for this new event</returns>
1898     public Event AddEvent(string name, Type eType) {
1899       Event e = new Event(name,eType,this);
1900       if (events == null) events = new ArrayList();
1901       events.Add(e);
1902       return e;
1903     }
1904
1905     /// <summary>
1906     /// Add a property to this class
1907     /// </summary>
1908     /// <param name="name">property name</param>
1909     /// <param name="propType">property type</param>
1910     /// <returns>a descriptor for this new property</returns>
1911     public Property AddProperty(string name, Type retType, Type[] pars) {
1912       Property p = new Property(name, retType, pars, this);
1913       if (properties == null) properties = new ArrayList();
1914       properties.Add(p);
1915       return p;
1916     }
1917
1918
1919     /// <summary>
1920     /// Add a nested class to this class
1921     /// </summary>
1922     /// <param name="attrSet">attributes for this nested class</param>
1923     /// <param name="nsName">nested name space name</param>
1924     /// <param name="name">nested class name</param>
1925     /// <returns>a descriptor for this new nested class</returns>
1926     public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1927                                    string name) {
1928       ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1929       metaData.AddToTable(MDTable.TypeDef,nClass);
1930       metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1931       nClass.parentClass = this;
1932       return (nClass);
1933      }
1934     public static bool IsValueType (Class type)
1935     {
1936         return IsValueType (type.nameSpace, type.name);
1937     }
1938
1939     public static bool IsEnum (Class type)
1940     {
1941         return IsEnum (type.nameSpace, type.name);
1942     }
1943     
1944     public static bool IsValueType (string nsName, string name)
1945     {
1946       return ((nsName.CompareTo ("System") == 0) && 
1947         (name.CompareTo ("ValueType") == 0));
1948     }
1949
1950     public static bool IsEnum (string nsName, string name)
1951     {
1952       return ((nsName.CompareTo ("System") == 0) && 
1953         (name.CompareTo ("Enum") == 0));
1954     }
1955
1956     /// <summary>
1957     /// Add a nested class to this class
1958     /// </summary>
1959     /// <param name="attrSet">attributes for this nested class</param>
1960     /// <param name="nsName">nested name space name</param>
1961     /// <param name="name">nested class name</param>
1962     /// <param name="sType">super type of this nested class</param>
1963     /// <returns>a descriptor for this new nested class</returns>
1964     public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, 
1965                                    string name, Class sType) {
1966       ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1967       nClass.SetSuper(sType);
1968       if (ClassDef.IsValueType (sType))
1969         nClass.MakeValueClass (ValueClass.ValueType);
1970       else
1971       if (ClassDef.IsEnum (sType))
1972         nClass.MakeValueClass (ValueClass.Enum);
1973       
1974       if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1975         nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1976
1977       return (nClass);
1978     }
1979
1980     /// <summary>
1981     /// Add layout information for this class.  This class must have the
1982     /// sequential or explicit attribute.
1983     /// </summary>
1984     /// <param name="packSize">packing size (.pack)</param>
1985     /// <param name="classSize">class size (.size)</param>
1986     public void AddLayoutInfo (int packSize, int classSize) {
1987       layout = new ClassLayout(packSize,classSize,this);
1988     }
1989
1990     /// <summary>
1991     /// Use a method as the implementation for another method (.override)
1992     /// </summary>
1993     /// <param name="decl">the method to be overridden</param>
1994     /// <param name="body">the implementation to be used</param>
1995     public void AddMethodOverride(Method decl, Method body) {
1996       metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1997     }
1998
1999     /// <summary>
2000     /// Add security to this class NOT YET IMPLEMENTED
2001     /// </summary>
2002     /// <param name="permissionSet"></param>
2003     public void AddSecurity(byte[] permissionSet) {
2004       throw(new NotYetImplementedException("Class security "));
2005       //flags |= HasSecurity;
2006      // securityActions = permissionSet;
2007     }
2008
2009     //public void AddLineInfo(int row, int col) { }
2010
2011     internal void CheckTypeIndex() {
2012       if (typeIndexChecked) return;
2013       if (!(superType is ClassRef)) 
2014         ((ClassDef)superType).CheckTypeIndex();
2015       typeIndex = superType.GetTypeIndex();
2016       typeIndexChecked = true;
2017     }
2018
2019     internal sealed override void BuildTables(MetaData md) {
2020       if (done) return;
2021       if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
2022       // Console.WriteLine("Building tables for " + name);
2023       if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
2024       // Console.WriteLine("adding methods " + methods.Count);
2025       methodIx = md.TableIndex(MDTable.Method);
2026       for (int i=0; i < methods.Count; i++) {
2027         md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
2028         ((MethodDef)methods[i]).BuildTables(md);
2029       }
2030       // Console.WriteLine("adding fields");
2031       fieldIx = md.TableIndex(MDTable.Field);
2032       for (int i=0; i < fields.Count; i++) {
2033         md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
2034         ((FieldDef)fields[i]).BuildTables(md);
2035       }
2036       // Console.WriteLine("adding events and properties");
2037       if (events != null) { 
2038         for (int i=0; i < events.Count; i++) {
2039           md.AddToTable(MDTable.Event,(Event)events[i]);
2040           ((Event)events[i]).BuildTables(md);
2041         }
2042         md.AddToTable(MDTable.EventMap,
2043           new MapElem(this,((Event)events[0]).Row,MDTable.Event));
2044       }
2045       if (properties != null) { 
2046         for (int i=0; i < properties.Count; i++) {
2047           md.AddToTable(MDTable.Property,(Property)properties[i]);
2048           ((Property)properties[i]).BuildTables(md);
2049         }
2050         md.AddToTable(MDTable.PropertyMap,new MapElem(this,
2051                           ((Property)properties[0]).Row,MDTable.Property));
2052       }
2053       // Console.WriteLine("End of building tables");
2054       done = true;
2055     }
2056
2057     internal sealed override uint Size(MetaData md) {
2058       return 4 + 2 * md.StringsIndexSize() + 
2059         md.CodedIndexSize(CIx.TypeDefOrRef) +
2060         md.TableIndexSize(MDTable.Field) + 
2061         md.TableIndexSize(MDTable.Method);
2062     }
2063
2064     internal sealed override void Write(FileImage output) {
2065       output.Write(flags);
2066       output.StringsIndex(nameIx);
2067       output.StringsIndex(nameSpaceIx);
2068       //if (superType != null) 
2069       // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
2070       output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
2071       output.WriteIndex(MDTable.Field,fieldIx);
2072       output.WriteIndex(MDTable.Method,methodIx);
2073     }
2074
2075     internal sealed override uint TypeDefOrRefToken() {
2076       uint cIx = Row;
2077       cIx = cIx << 2;
2078       return cIx;
2079     }
2080
2081     internal sealed override void TypeSig(MemoryStream sig) {
2082       if (!typeIndexChecked) CheckTypeIndex();
2083       sig.WriteByte(GetTypeIndex());
2084       MetaData.CompressNum(TypeDefOrRefToken(),sig);
2085     }
2086
2087     internal sealed override uint GetCodedIx(CIx code) {
2088       switch (code) {
2089         case (CIx.TypeDefOrRef) : return 0; 
2090         case (CIx.HasCustomAttr) : return 3; 
2091         case (CIx.HasDeclSecurity) : return 0; 
2092         case (CIx.TypeOrMethodDef) : return 0; 
2093       }
2094       return 0;
2095     }
2096  
2097         }
2098   /**************************************************************************/  
2099         /// <summary>
2100         /// Layout information for a class (.class [sequential | explicit])
2101         /// </summary>
2102         internal class ClassLayout : MetaDataElement
2103         {
2104     ClassDef parent;
2105     ushort packSize = 0;
2106     uint classSize = 0;
2107
2108                 internal ClassLayout(int pack, int cSize, ClassDef par) {
2109       packSize = (ushort)pack;
2110       classSize = (uint)cSize;
2111       parent = par;
2112       tabIx = MDTable.ClassLayout;
2113                 }
2114
2115     internal sealed override uint Size(MetaData md) {
2116       return 6 + md.TableIndexSize(MDTable.TypeDef);
2117     }
2118
2119     internal sealed override void Write(FileImage output) {
2120       output.Write(packSize);
2121       output.Write(classSize);
2122       output.WriteIndex(MDTable.TypeDef,parent.Row);
2123     }
2124
2125         }
2126   /**************************************************************************/  
2127         /// <summary>
2128         /// Descriptor for a class/interface declared in another module of THIS 
2129         /// assembly, or in another assembly.
2130         /// </summary>
2131         public class ClassRef : Class
2132         {
2133     protected ResolutionScope parent;
2134     ExternClass externClass;
2135     protected MetaData metaData;
2136
2137                 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
2138       metaData = md;
2139       tabIx = MDTable.TypeRef;
2140     }
2141
2142     /// <summary>
2143     /// Add a method to this class
2144     /// </summary>
2145     /// <param name="name">method name</param>
2146     /// <param name="retType">return type</param>
2147     /// <param name="pars">parameter types</param>
2148     /// <returns>a descriptor for this method</returns>
2149     public MethodRef AddMethod(string name, Type retType, Type[] pars) {
2150       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
2151       metaData.AddToTable(MDTable.MemberRef,meth);
2152       return meth;
2153     }
2154
2155     /// <summary>
2156     /// Add a method to this class
2157     /// </summary>
2158     /// <param name="name">method name</param>
2159     /// <param name="retType">return type</param>
2160     /// <param name="pars">parameter types</param>
2161     /// <returns>a descriptor for this method</returns>
2162     public MethodRef AddVarArgMethod(string name, Type retType, 
2163                                      Type[] pars, Type[] optPars) {
2164       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
2165       metaData.AddToTable(MDTable.MemberRef,meth);
2166       return meth;
2167     }
2168
2169     /// <summary>
2170     /// Add a field to this class
2171     /// </summary>
2172     /// <param name="name">field name</param>
2173     /// <param name="fType">field type</param>
2174     /// <returns>a descriptor for this field</returns>
2175     public FieldRef AddField(string name, Type fType) {
2176       FieldRef field = new FieldRef(this,name,fType);
2177       metaData.AddToTable(MDTable.MemberRef,field);
2178       return field;
2179     }
2180
2181     internal void SetParent(ResolutionScope par) {
2182       parent = par;
2183     }
2184
2185     internal override string TypeName() {
2186       if ((parent != null) && (parent is AssemblyRef))
2187         return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2188       else 
2189         return (nameSpace + name);
2190     }
2191
2192     internal sealed override uint Size(MetaData md) {
2193       return md.CodedIndexSize(CIx.ResolutionScope) + 2 * 
2194              md.StringsIndexSize();
2195     }
2196
2197     internal sealed override void Write(FileImage output) {
2198       output.WriteCodedIndex(CIx.ResolutionScope,parent);
2199       output.StringsIndex(nameIx);
2200       output.StringsIndex(nameSpaceIx);
2201     }
2202
2203     internal override sealed uint TypeDefOrRefToken() {
2204       uint cIx = Row;
2205       cIx = (cIx << 2) | 0x1;
2206       return cIx;
2207     }
2208
2209     internal override void TypeSig(MemoryStream sig) {
2210       sig.WriteByte(GetTypeIndex());
2211       MetaData.CompressNum(TypeDefOrRefToken(),sig);
2212     }
2213
2214     internal sealed override uint GetCodedIx(CIx code) {
2215       switch (code) {
2216         case (CIx.TypeDefOrRef) : return 1; 
2217         case (CIx.HasCustomAttr) : return 2; 
2218         case (CIx.MemberRefParent) : return 1; 
2219         case (CIx.ResolutionScope) : return 3; 
2220       }
2221       return 0;
2222     }
2223  
2224         }
2225   /**************************************************************************/  
2226
2227   public class ExternClassRef : ClassRef {
2228
2229     ExternClass externClass;
2230
2231     internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2232                           FileRef declFile, MetaData md) : base(nsName,name,md) {
2233       externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
2234       metaData.AddToTable(MDTable.ExportedType,externClass);
2235     }
2236
2237     internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
2238     }
2239
2240     public ClassRef AddNestedClass(TypeAttr attrs, string name) {
2241       ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2242       externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2243       metaData.AddToTable(MDTable.ExportedType,externClass);
2244       return nestedClass;
2245     }
2246  
2247   }
2248   /**************************************************************************/  
2249   /// <summary>
2250   /// Descriptor for a constant value
2251   /// </summary>
2252   public abstract class Constant {
2253     protected uint size = 0;
2254     protected Type type;
2255     protected uint blobIndex;
2256     protected bool addedToBlobHeap = false;
2257
2258                 internal Constant()     {       }
2259
2260     internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2261
2262     internal uint GetSize() { return size; }
2263
2264     internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2265
2266     internal virtual void Write(BinaryWriter bw) {  }
2267
2268         }
2269   /// <summary>
2270   /// Descriptor for a constant value
2271   /// </summary>
2272   public abstract class DataConstant : Constant {
2273     private uint dataOffset = 0;
2274
2275     internal DataConstant() { }
2276
2277     public uint DataOffset {
2278       get { return dataOffset; }
2279       set { dataOffset = value; }
2280     }
2281
2282   }
2283
2284   /// <summary>
2285   /// Boolean constant
2286   /// </summary>
2287   public class BoolConst : Constant {
2288     bool val;
2289
2290     /// <summary>
2291     /// Create a new boolean constant with the value "val"
2292     /// </summary>
2293     /// <param name="val">value of this boolean constant</param>
2294     public BoolConst(bool val) {
2295       this.val = val;
2296       size = 1;
2297       type = PrimitiveType.Boolean;
2298     }
2299
2300     internal sealed override uint GetBlobIndex(MetaData md) {
2301       if (!addedToBlobHeap) {
2302         if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2303         else blobIndex = md.AddToBlobHeap((sbyte)0);
2304         addedToBlobHeap = true;
2305       }
2306       return blobIndex;
2307     }
2308
2309     internal sealed override void Write(BinaryWriter bw) {
2310       if (val) bw.Write((sbyte)1);
2311       else bw.Write((sbyte)0);
2312     }
2313
2314   }
2315
2316   public class ByteArrConst : DataConstant {
2317     byte[] val;
2318
2319     public ByteArrConst(byte[] val) {
2320       type = PrimitiveType.String;
2321       this.val = val;
2322       size = (uint)val.Length;
2323     }
2324
2325     public Type Type {
2326             get { return type; }
2327             set { type = value; }
2328     }
2329
2330     internal sealed override uint GetBlobIndex(MetaData md) {
2331       if (!addedToBlobHeap) {
2332         blobIndex = md.AddToBlobHeap(val);
2333         addedToBlobHeap = true;
2334       }
2335       return blobIndex;
2336     }
2337
2338     internal sealed override void Write(BinaryWriter bw) {
2339       bw.Write(val);
2340     }
2341
2342   }
2343
2344   public class CharConst : Constant {
2345     char val;
2346
2347     public CharConst(char val) {
2348       this.val = val;
2349       size = 2;
2350       type = PrimitiveType.Char;
2351     }
2352
2353     internal sealed override uint GetBlobIndex(MetaData md) {
2354       if (!addedToBlobHeap) {
2355         blobIndex = md.AddToBlobHeap(val);
2356         addedToBlobHeap = true;
2357       }
2358       return blobIndex;
2359     }
2360
2361     internal sealed override void Write(BinaryWriter bw) {
2362       bw.Write(val);
2363     }
2364
2365   }
2366
2367   public class FloatConst : DataConstant {
2368     float val;
2369
2370     public FloatConst(float val) {
2371       this.val = val;
2372       size = 4;
2373       type = PrimitiveType.Float32;
2374     }
2375
2376     internal sealed override uint GetBlobIndex(MetaData md) {
2377       if (!addedToBlobHeap) {
2378         blobIndex = md.AddToBlobHeap(val);
2379         addedToBlobHeap = true;
2380       }
2381       return blobIndex;
2382     }
2383
2384     internal sealed override void Write(BinaryWriter bw) {
2385       bw.Write(val);
2386     }
2387
2388   }
2389
2390   public class DoubleConst : DataConstant {
2391     double val;
2392
2393     public DoubleConst(double val) {
2394       this.val = val;
2395       size = 8;
2396       type = PrimitiveType.Float64;
2397     }
2398
2399     internal sealed override uint GetBlobIndex(MetaData md) {
2400       if (!addedToBlobHeap) {
2401         blobIndex = md.AddToBlobHeap(val);
2402         addedToBlobHeap = true;
2403       }
2404       return blobIndex;
2405     }
2406
2407     internal sealed override void Write(BinaryWriter bw) {
2408       bw.Write(val);
2409     }
2410
2411   }
2412
2413   public class IntConst : DataConstant {
2414     long val;
2415
2416     public IntConst(sbyte val) {
2417       this.val = val;
2418       size = 1;
2419       type = PrimitiveType.Int8;
2420     }
2421
2422     public IntConst(short val) {
2423       this.val = val;
2424       size = 2;
2425       type = PrimitiveType.Int16;
2426     }
2427
2428     public IntConst(int val) {
2429       this.val = val;
2430       size = 4;
2431       type = PrimitiveType.Int32;
2432     }
2433
2434     public IntConst(long val) {
2435       this.val = val;
2436       size = 8;
2437       type = PrimitiveType.Int64;
2438     }
2439
2440     internal sealed override uint GetBlobIndex(MetaData md) {
2441       if (!addedToBlobHeap) {
2442         switch (size) {
2443           case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
2444           case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
2445           case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
2446           default : blobIndex = md.AddToBlobHeap(val); break; 
2447         }
2448         addedToBlobHeap = true;
2449       }
2450       return blobIndex;
2451     }
2452
2453     internal sealed override void Write(BinaryWriter bw) {
2454       switch (size) {
2455         case (1) : bw.Write((sbyte)val); break;
2456         case (2) : bw.Write((short)val); break;
2457         case (4) : bw.Write((int)val); break;
2458         default : bw.Write(val); break; 
2459       }
2460     }
2461
2462   }
2463
2464   public class UIntConst : Constant {
2465     long val;
2466
2467     public UIntConst(sbyte val) {
2468       this.val = val;
2469       size = 1;
2470       type = PrimitiveType.UInt8;
2471     }
2472     public UIntConst(short val) {
2473       this.val = val;
2474       size = 2;
2475       type = PrimitiveType.UInt16;
2476     }
2477     public UIntConst(int val) {
2478       this.val = val;
2479       size = 4;
2480       type = PrimitiveType.UInt32;
2481     }
2482     public UIntConst(long val) {
2483       this.val = val;
2484       size = 8;
2485       type = PrimitiveType.UInt64;
2486     }
2487
2488     internal sealed override uint GetBlobIndex(MetaData md) {
2489       if (!addedToBlobHeap) {
2490         switch (size) {
2491           case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
2492           case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
2493           case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
2494           default : blobIndex = md.AddToBlobHeap(val); break;
2495         }
2496         addedToBlobHeap = true;
2497       }
2498       return blobIndex;
2499     }
2500
2501     internal sealed override void Write(BinaryWriter bw) {
2502       switch (size) {
2503         case (1) : bw.Write((sbyte)val); break;
2504         case (2) : bw.Write((short)val); break;
2505         case (4) : bw.Write((int)val); break;
2506         default : bw.Write(val); break;
2507       }
2508     }
2509
2510   }
2511
2512   public class StringConst : DataConstant {
2513     string val;
2514
2515     public StringConst(string val) {
2516       this.val = val;
2517       size = (uint)val.Length;  // need to add null ??
2518       type = PrimitiveType.String;
2519     }
2520
2521     internal sealed override uint GetBlobIndex(MetaData md) {
2522       if (!addedToBlobHeap) {
2523         byte [] b = Encoding.Unicode.GetBytes (val);
2524         blobIndex = md.AddToBlobHeap(b);
2525         addedToBlobHeap = true;
2526       }
2527       return blobIndex;
2528     }
2529
2530     internal sealed override void Write(BinaryWriter bw) {
2531       bw.Write(val);
2532     }
2533
2534   }
2535
2536   public class NullConst : Constant {
2537  
2538     public NullConst() { 
2539       size = 4;
2540       type = PrimitiveType.Class;
2541     }
2542
2543     internal sealed override uint GetBlobIndex(MetaData md) {
2544       if (!addedToBlobHeap) {
2545         blobIndex = md.AddToBlobHeap((int)0);
2546         addedToBlobHeap = true;
2547       }
2548       return blobIndex;
2549     }
2550
2551     internal sealed override void Write(BinaryWriter bw) {
2552       bw.Write((int)0); 
2553     }
2554
2555   }
2556
2557   public class AddressConstant : DataConstant {
2558     DataConstant data;
2559
2560     public AddressConstant(DataConstant dConst) {
2561       data = dConst;
2562       size = 4;
2563       type = PrimitiveType.TypedRef;
2564     }
2565
2566     internal sealed override void Write(BinaryWriter bw) {
2567       ((FileImage)bw).WriteDataRVA(data.DataOffset);
2568     }
2569
2570   }
2571
2572   public class RepeatedConstant : DataConstant {
2573     DataConstant data;
2574     uint repCount;
2575
2576     public RepeatedConstant(DataConstant dConst, int repeatCount) {
2577       data = dConst;
2578       repCount = (uint)repeatCount;
2579       int[] sizes = new int[1];
2580       sizes[0] = repeatCount;
2581       type = new BoundArray(type,1,sizes);
2582       size = data.GetSize() * repCount;
2583     }
2584
2585     internal sealed override void Write(BinaryWriter bw) {
2586       for (int i=0; i < repCount; i++) {
2587         data.Write(bw);
2588       }
2589     }
2590
2591   }
2592
2593   public class ArrayConstant : DataConstant {
2594     DataConstant[] dataVals;
2595
2596     public ArrayConstant(DataConstant[] dVals) {
2597       dataVals = dVals;
2598       for (int i=0; i < dataVals.Length; i++) {
2599         size += dataVals[i].GetSize();
2600       }
2601     }
2602
2603     internal sealed override void Write(BinaryWriter bw) {
2604       for (int i=0; i < dataVals.Length; i++) {
2605         dataVals[i].Write(bw);
2606       }
2607     }
2608
2609   }
2610
2611   public class ClassType : Constant {
2612     string name;
2613     Class desc;
2614
2615     public ClassType(string className) {
2616       name = className;
2617       type = PrimitiveType.ClassType;
2618     }
2619
2620     public ClassType(Class classDesc) {
2621       desc = classDesc;
2622       type = PrimitiveType.ClassType;
2623     }
2624
2625     internal override void Write(BinaryWriter bw) {
2626       if (name == null)  name = desc.TypeName();
2627       bw.Write(name);
2628     }
2629
2630   }
2631
2632
2633
2634   /**************************************************************************/  
2635         /// <summary>
2636         /// Summary description for ConstantElem.
2637         /// </summary>
2638         internal class ConstantElem : MetaDataElement
2639         {
2640     MetaDataElement parent;
2641     Constant cValue;
2642     uint valIx = 0;
2643
2644                 internal ConstantElem(MetaDataElement parent, Constant val) {
2645       this.parent = parent;
2646       cValue = val;
2647                         tabIx = MDTable.Constant;
2648                         sortTable = true;
2649                 }
2650
2651    internal override uint SortKey() 
2652    {  
2653      return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst]) 
2654              | parent.GetCodedIx(CIx.HasConst);
2655    }
2656
2657     internal sealed override void BuildTables(MetaData md) {
2658       if (done) return;
2659       valIx = cValue.GetBlobIndex(md);
2660       done = true;
2661     }
2662
2663     internal void AddToBlob(BinaryWriter bw) {
2664       cValue.Write(bw);
2665     }
2666
2667     internal sealed override uint Size(MetaData md) {
2668       return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
2669     }
2670
2671     internal sealed override void Write(FileImage output) {
2672       output.Write(cValue.GetTypeIndex());
2673       output.Write((byte)0);
2674       output.WriteCodedIndex(CIx.HasConst,parent);
2675       output.BlobIndex(valIx);
2676     }
2677
2678         }
2679   /**************************************************************************/  
2680         /// <summary>
2681         /// Descriptor for a Custom Attribute (.custom) 
2682         /// </summary>
2683
2684         public class CustomAttribute : MetaDataElement
2685         {
2686     private static readonly ushort prolog = 0x0001;
2687     MetaDataElement parent;
2688     Method type;
2689     uint valIx;
2690     Constant cVal;
2691     byte[] byteVal;
2692     ushort numNamed = 0;
2693     ArrayList names, vals;
2694
2695                 internal CustomAttribute(MetaDataElement paren, Method constrType, 
2696                                                           Constant val) {
2697       parent = paren;
2698       type = constrType;
2699       cVal = val;
2700       tabIx = MDTable.CustomAttribute;
2701                 }
2702
2703     internal CustomAttribute(MetaDataElement paren, Method constrType,
2704                                                           byte[] val) {
2705       parent = paren;
2706       type = constrType;
2707       tabIx = MDTable.CustomAttribute;
2708       byteVal = val;
2709     }
2710
2711     internal override uint SortKey() {
2712       return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
2713               | parent.GetCodedIx(CIx.HasCustomAttr);
2714     }
2715
2716     public void AddFieldOrProp(string name, Constant val) {
2717       if (numNamed == 0) {
2718         names = new ArrayList();
2719         vals = new ArrayList();
2720       }
2721       names.Add(name);
2722       vals.Add(val);
2723     }
2724
2725     internal sealed override void BuildTables(MetaData md) {
2726       BinaryWriter bw = new BinaryWriter(new MemoryStream());
2727       bw.Write(byteVal);
2728       md.AddToTable(MDTable.CustomAttribute, this);
2729       MemoryStream str = (MemoryStream)bw.BaseStream;
2730       valIx = md.AddToBlobHeap(str.ToArray());
2731     }
2732
2733     internal sealed override uint Size(MetaData md) {
2734       return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
2735     }
2736
2737     internal sealed override void Write(FileImage output) {
2738       output.WriteCodedIndex(CIx.HasCustomAttr,parent);
2739       output.WriteCodedIndex(CIx.CustomAttributeType,type);
2740       output.BlobIndex(valIx);
2741     }
2742
2743         }
2744   /**************************************************************************/  
2745         /// <summary>
2746         /// Descriptor for a custom modifier of a type (modopt or modreq)
2747         /// </summary>
2748
2749         public class CustomModifiedType : Type
2750         {
2751     Type type;
2752     Class cmodType;
2753
2754     /// <summary>
2755     /// Create a new custom modifier for a type
2756     /// </summary>
2757     /// <param name="type">the type to be modified</param>
2758     /// <param name="cmod">the modifier</param>
2759     /// <param name="cmodType">the type reference to be associated with the type</param>
2760                 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
2761                                                           : base((byte)cmod) {
2762       this.type = type;
2763       this.cmodType = cmodType;
2764                 }
2765
2766     internal sealed override void TypeSig(MemoryStream str) {
2767       str.WriteByte(typeIndex);
2768       MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
2769       type.TypeSig(str);
2770     }
2771   
2772   }
2773   /**************************************************************************/  
2774   /// <summary>
2775   /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
2776   /// </summary>
2777         
2778         public class DeclSecurity : MetaDataElement
2779         {
2780     ushort action;
2781     MetaDataElement parent;
2782     uint permissionIx;
2783
2784                 internal DeclSecurity(MetaDataElement paren, ushort act)        {
2785       parent = paren;
2786       action = act;
2787       tabIx = MDTable.DeclSecurity;
2788       throw(new NotYetImplementedException("Security "));
2789                 }
2790
2791     internal override uint SortKey() {
2792       return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
2793               | parent.GetCodedIx(CIx.HasDeclSecurity);
2794     }
2795
2796     internal sealed override uint Size(MetaData md) {
2797       return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
2798     }
2799
2800     internal sealed override void BuildTables(MetaData md) {
2801       if (done) return;
2802 // add permission to blob heap
2803       done = true;
2804     }
2805
2806     internal sealed override void Write(FileImage output) {
2807       output.Write(action);
2808       output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
2809       output.BlobIndex(permissionIx);
2810     }
2811  
2812         }
2813   /**************************************************************************/  
2814         /// <summary>
2815         /// Descriptor for an event
2816         /// </summary>
2817   public class Event : Feature
2818         {
2819     Type eventType;
2820
2821     internal Event(string name, Type eType, ClassDef parent) 
2822                                             : base(name, parent) {
2823       eventType = eType;
2824                         tabIx = MDTable.Event;
2825     }
2826
2827     /// <summary>
2828     /// Add the addon method to this event
2829     /// </summary>
2830     /// <param name="addon">the addon method</param>
2831     public void AddAddon(MethodDef addon) {
2832       AddMethod(addon,MethodType.AddOn);
2833     }
2834
2835     /// <summary>
2836     /// Add the removeon method to this event
2837     /// </summary>
2838     /// <param name="removeOn">the removeon method</param>
2839     public void AddRemoveOn(MethodDef removeOn) {
2840       AddMethod(removeOn,MethodType.RemoveOn);
2841     }
2842
2843     /// <summary>
2844     /// Add the fire method to this event
2845     /// </summary>
2846     /// <param name="fire">the fire method</param>
2847     public void AddFire(MethodDef fire) {
2848       AddMethod(fire,MethodType.Fire);
2849     }
2850
2851     /// <summary>
2852     /// Add another method to this event
2853     /// </summary>
2854     /// <param name="other">the method to be added</param>
2855     public void AddOther(MethodDef other) {
2856       AddMethod(other,MethodType.Other);
2857     }
2858
2859     internal sealed override void BuildTables(MetaData md) {
2860       if (done) return;
2861       nameIx = md.AddToStringsHeap(name);
2862       for (int i=0; i < tide; i++) {
2863         md.AddToTable(MDTable.MethodSemantics,methods[i]);
2864       }
2865       done = true;
2866     }
2867
2868     internal sealed override uint Size(MetaData md) {
2869       return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
2870     }
2871
2872     internal sealed override void Write(FileImage output) {
2873       output.Write(flags);
2874       output.StringsIndex(nameIx);
2875       output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
2876     }
2877
2878     internal sealed override uint GetCodedIx(CIx code) {
2879       switch (code) {
2880         case (CIx.HasCustomAttr) : return 10; 
2881         case (CIx.HasSemantics) : return 0; 
2882       }
2883       return 0;
2884     }
2885    
2886         }
2887   /**************************************************************************/  
2888         /// <summary>
2889         /// Descriptor for a class defined in another module of THIS assembly 
2890         /// and exported (.class extern)
2891         /// </summary>
2892
2893   internal class ExternClass : Class
2894         {
2895                 MetaDataElement parent;
2896     uint flags;
2897
2898     internal ExternClass(TypeAttr attr, uint nsIx, uint nIx, 
2899                          MetaDataElement paren) : base(nsIx,nIx) {
2900       flags = (uint)attr;
2901             parent = paren;
2902                         tabIx = MDTable.ExportedType;
2903     }
2904
2905     internal sealed override uint Size(MetaData md) {
2906       return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2907     }
2908
2909     internal sealed override void Write(FileImage output) {
2910       output.Write(flags);
2911       output.Write(0);
2912       output.StringsIndex(nameIx);
2913       output.StringsIndex(nameSpaceIx);
2914       output.WriteCodedIndex(CIx.Implementation,parent);
2915     }
2916
2917     internal sealed override uint GetCodedIx(CIx code) {
2918       switch (code) {
2919         case (CIx.HasCustomAttr) : return 17; 
2920         case (CIx.Implementation) : return 2; 
2921       }
2922       return 0;
2923     }
2924
2925         }
2926   /**************************************************************************/  
2927         /// <summary>
2928         /// Base class for Event and Property descriptors
2929         /// </summary>
2930
2931   public class Feature : MetaDataElement
2932         {
2933     internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08, 
2934       RemoveOn = 0x10, Fire = 0x20 }
2935
2936     private static readonly int INITSIZE = 5;
2937     private static readonly ushort specialName = 0x200;
2938     private static readonly ushort rtSpecialName = 0x400;
2939
2940     protected ClassDef parent;
2941     protected ushort flags = 0;
2942     protected string name;
2943     protected int tide = 0;
2944     protected uint nameIx;
2945     protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
2946     
2947     internal Feature(string name, ClassDef par) {
2948       parent = par;
2949       this.name = name;
2950     }
2951
2952     internal void AddMethod(MethodDef meth, MethodType mType) {
2953       if (tide >= methods.Length) { 
2954         int len = methods.Length;
2955         MethodSemantics[] mTmp = methods;
2956         methods = new MethodSemantics[len * 2];
2957         for (int i=0; i < len; i++) {
2958           methods[i] = mTmp[i];
2959         }
2960       }
2961       methods[tide++] = new MethodSemantics(mType,meth,this);
2962     }
2963
2964     /// <summary>
2965     /// Set the specialName attribute for this Event or Property
2966     /// </summary>
2967     public void SetSpecialName() {
2968       flags |= specialName;
2969     }
2970
2971     /// <summary>
2972     /// Set the RTSpecialName attribute for this Event or Property
2973     /// </summary>
2974     public void SetRTSpecialName() {
2975       flags |= rtSpecialName;
2976     }
2977   
2978         }
2979   /*****************************************************************************/  
2980         /// <summary>
2981         /// Descriptor for a field of a class
2982         /// </summary>
2983
2984   public abstract class Field : Member
2985         {
2986     protected static readonly byte FieldSig = 0x6;
2987
2988     protected Type type;
2989
2990                 internal Field(string pfName, Type pfType) : base(pfName)
2991                 {
2992       type = pfType;
2993                 }
2994
2995         }
2996   /**************************************************************************/  
2997         /// <summary>
2998         /// Descriptor for a field defined in a class of THIS assembly/module
2999         /// </summary>
3000   public class FieldDef : Field
3001         {
3002     //private static readonly uint PInvokeImpl = 0x2000;
3003     private static readonly ushort HasFieldMarshal = 0x1000;
3004     private static readonly ushort HasFieldRVA = 0x100;
3005     private static readonly ushort HasDefault = 0x8000;
3006
3007     FieldRVA rva;
3008     ConstantElem constVal;
3009     FieldLayout layout;
3010     FieldMarshal marshalInfo;
3011     ushort flags;
3012
3013     internal FieldDef(string name, Type fType) : base(name,fType) {
3014       tabIx = MDTable.Field;
3015     }
3016
3017     internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) { 
3018       flags = (ushort)attrSet;
3019       tabIx = MDTable.Field;
3020     }
3021
3022     /// <summary>
3023     /// Add an attribute(s) to this field
3024     /// </summary>
3025     /// <param name="fa">the attribute(s) to be added</param>
3026     public void AddFieldAttr(FieldAttr fa) {
3027       flags |= (ushort)fa;
3028     }
3029  
3030     /// <summary>
3031     /// Add a value for this field
3032     /// </summary>
3033     /// <param name="val">the value for the field</param>
3034     public void AddValue(Constant val) {
3035       constVal = new ConstantElem(this,val);
3036       flags |= HasDefault;
3037     }
3038
3039     /// <summary>
3040     /// Add an initial value for this field (at dataLabel) (.data)
3041     /// </summary>
3042     /// <param name="val">the value for the field</param>
3043     /// <param name="repeatVal">the number of repetitions of this value</param>
3044     public void AddDataValue(DataConstant val) {
3045       flags |= HasFieldRVA;
3046       rva = new FieldRVA(this,val);
3047     }
3048
3049     /// <summary>
3050     /// Set the offset of the field.  Used for sequential or explicit classes.
3051     /// (.field [offs])
3052     /// </summary>
3053     /// <param name="offs">field offset</param>
3054     public void SetOffset(uint offs) {
3055       layout = new FieldLayout(this,offs);
3056     }
3057
3058     /// <summary>
3059     /// Set the marshalling info for a field
3060     /// </summary>
3061     /// <param name="mInf"></param>
3062     public void SetMarshalInfo(NativeType marshallType) {
3063       flags |= HasFieldMarshal;
3064       marshalInfo = new FieldMarshal(this,marshallType);
3065     }
3066
3067     internal sealed override void BuildTables(MetaData md) {
3068       if (done) return;
3069       nameIx = md.AddToStringsHeap(name);
3070       MemoryStream sig = new MemoryStream();
3071       sig.WriteByte(FieldSig);
3072       type.TypeSig(sig);
3073       sigIx = md.AddToBlobHeap(sig.ToArray());
3074       if (rva != null) {
3075         md.AddToTable(MDTable.FieldRVA,rva);
3076         rva.BuildTables(md);
3077       } else if (constVal != null) {
3078         md.AddToTable(MDTable.Constant,constVal);
3079         constVal.BuildTables(md);
3080       }
3081       if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3082       if (marshalInfo != null) {
3083         md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3084         marshalInfo.BuildTables(md);
3085       }
3086       done = true;
3087     }
3088
3089     internal sealed override uint Size(MetaData md) {
3090       return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3091     }
3092
3093     internal sealed override void Write(FileImage output) {
3094       output.Write(flags);
3095       output.StringsIndex(nameIx);
3096       output.BlobIndex(sigIx);
3097     }
3098
3099     internal sealed override uint GetCodedIx(CIx code) {
3100       switch (code) {
3101         case (CIx.HasConst) : return 0; 
3102         case (CIx.HasCustomAttr) : return 1; 
3103         case (CIx.HasFieldMarshal) : return 0; 
3104         case (CIx.MemberForwarded) : return 0; 
3105       }
3106       return 0;
3107     }
3108
3109         }
3110   /**************************************************************************/  
3111         /// <summary>
3112         /// Descriptor for layout information for a field
3113         /// </summary>
3114         
3115         public class FieldLayout : MetaDataElement
3116         {
3117     Field field;
3118     uint offset;
3119
3120     internal FieldLayout(Field field, uint offset)      {
3121       this.field = field;
3122       this.offset = offset;
3123                         tabIx = MDTable.FieldLayout;
3124     }
3125
3126     internal sealed override uint Size(MetaData md) {
3127       return 4 + md.TableIndexSize(MDTable.Field);
3128     }
3129
3130     internal sealed override void Write(FileImage output) {
3131       output.Write(offset);
3132       output.WriteIndex(MDTable.Field,field.Row);
3133     }
3134
3135         }
3136   /*****************************************************************************/  
3137         /// <summary>
3138         /// Marshalling information for a field or param
3139         /// </summary>
3140   public class FieldMarshal : MetaDataElement
3141         {
3142     MetaDataElement field;
3143     NativeType nt;
3144     uint ntIx;
3145
3146     internal FieldMarshal(MetaDataElement field, NativeType nType)      {
3147       this.field = field;
3148       this.nt = nType;
3149                         tabIx = MDTable.FieldMarshal;
3150                 }
3151
3152     internal override uint SortKey() { 
3153       return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
3154               | field.GetCodedIx(CIx.HasFieldMarshal);
3155     }
3156
3157     internal sealed override void BuildTables(MetaData md) {
3158       if (done) return;
3159       ntIx = md.AddToBlobHeap(nt.ToBlob());
3160       done = true;
3161     }
3162
3163     internal sealed override uint Size(MetaData md) {
3164       return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
3165     }
3166
3167     internal sealed override void Write(FileImage output) {
3168       output.WriteCodedIndex(CIx.HasFieldMarshal,field);
3169       output.BlobIndex(ntIx);
3170     }
3171
3172         }
3173   /**************************************************************************/  
3174         /// <summary>
3175         /// Descriptor for a field of a class defined in another assembly/module
3176         /// </summary>
3177   public class FieldRef : Field
3178         {
3179     MetaDataElement parent;
3180
3181                 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)   {       
3182       parent = paren;
3183     }
3184
3185     internal sealed override void BuildTables(MetaData md) {
3186       if (done) return;
3187       nameIx = md.AddToStringsHeap(name);
3188       MemoryStream sig = new MemoryStream();
3189       sig.WriteByte(FieldSig);
3190       type.TypeSig(sig);
3191       sigIx = md.AddToBlobHeap(sig.ToArray());
3192       done = true;
3193     }
3194
3195     internal sealed override uint Size(MetaData md) {
3196       return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3197     }
3198
3199     internal sealed override void Write(FileImage output) {
3200       output.WriteCodedIndex(CIx.MemberRefParent,parent);
3201       output.StringsIndex(nameIx);
3202       output.BlobIndex(sigIx);
3203     }
3204
3205     internal sealed override uint GetCodedIx(CIx code) { return 6; }
3206
3207         }
3208   /**************************************************************************/  
3209         /// <summary>
3210         /// Descriptor for the address of a field's value in the PE file
3211         /// </summary>
3212   public class FieldRVA : MetaDataElement
3213         {
3214     Field field;
3215     DataConstant data;
3216
3217     internal FieldRVA(Field field, DataConstant data)   {
3218       this.field = field;
3219       this.data = data;
3220       tabIx = MDTable.FieldRVA;
3221                 }
3222
3223     internal sealed override void BuildTables(MetaData md) {
3224       if (done) return;
3225       md.AddData(data);
3226       done = true;
3227     }
3228
3229     internal sealed override uint Size(MetaData md) {
3230       return 4 + md.TableIndexSize(MDTable.Field);
3231     }
3232
3233     internal sealed override void Write(FileImage output) {
3234       output.WriteDataRVA(data.DataOffset);
3235       output.WriteIndex(MDTable.Field,field.Row);
3236     }
3237
3238         }
3239   /**************************************************************************/  
3240         /// <summary>
3241         /// Image for a PEFile
3242         /// File Structure
3243   ///     DOS Header (128 bytes) 
3244   ///     PE Signature ("PE\0\0") 
3245   ///     PEFileHeader (20 bytes)
3246   ///     PEOptionalHeader (224 bytes) 
3247   ///     SectionHeaders (40 bytes * NumSections)
3248   ///
3249   ///     Sections .text (always present - contains metadata)
3250   ///              .sdata (contains any initialised data in the file - may not be present)
3251   ///                     (for ilams /debug this contains the Debug table)
3252   ///              .reloc (always present - in pure CIL only has one fixup)
3253   ///               others???  c# produces .rsrc section containing a Resource Table
3254   ///
3255   /// .text layout
3256   ///     IAT (single entry 8 bytes for pure CIL)
3257   ///     CLIHeader (72 bytes)
3258   ///     CIL instructions for all methods (variable size)
3259   ///     MetaData 
3260   ///       Root (20 bytes + UTF-8 Version String + quad align padding)
3261   ///       StreamHeaders (8 bytes + null terminated name string + quad align padding)
3262   ///       Streams 
3263   ///         #~        (always present - holds metadata tables)
3264   ///         #Strings  (always present - holds identifier strings)
3265   ///         #US       (Userstring heap)
3266   ///         #Blob     (signature blobs)
3267   ///         #GUID     (guids for assemblies or Modules)
3268   ///    ImportTable (40 bytes)
3269   ///    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
3270   ///    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
3271   ///    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
3272   ///    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
3273   ///
3274   ///  #~ stream structure
3275   ///    Header (24 bytes)
3276   ///    Rows   (4 bytes * numTables)
3277   ///    Tables
3278   /// </summary>
3279         internal class FileImage : BinaryWriter
3280         {
3281     internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
3282     internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
3283                                                   0x0000000000FF0000, 0x00000000FF000000,
3284                                                   0x000000FF00000000, 0x0000FF0000000000,
3285                                                   0x00FF000000000000, 0xFF00000000000000 };
3286     internal readonly static uint nibble0Mask = 0x0000000F;
3287     internal readonly static uint nibble1Mask = 0x000000F0;
3288
3289     private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
3290                                                  0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
3291                                                  0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3292                                                  0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3293                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3294                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3295                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3296                                                  0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
3297                                                  0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
3298                                                  0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
3299                                                  0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
3300                                                  0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
3301                                                  0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
3302                                                  0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
3303                                                  0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
3304                                                  0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3305                                                  0x50,0x45,0x00,0x00};
3306     private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
3307                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3308                                        0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
3309                                        0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
3310                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
3311                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3312                                      };
3313
3314     private static readonly uint minFileAlign = 0x200;
3315     private static readonly uint maxFileAlign = 0x1000;
3316     private static readonly uint fileHeaderSize = 0x178;
3317     private static readonly uint sectionHeaderSize = 40;
3318     private static readonly uint SectionAlignment = 0x2000;
3319     private static readonly uint ImageBase = 0x400000;
3320     private static readonly uint ImportTableSize = 40;
3321     private static readonly uint IATSize = 8;
3322     private static readonly uint CLIHeaderSize = 72;
3323     private uint runtimeFlags = 0x01;  // COMIMAGE_FLAGS_ILONLY
3324     // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
3325     private static readonly uint StrongNameSignatureSize = 128;
3326     private bool reserveStrongNameSignatureSpace = false;
3327
3328                 private static readonly uint relocFlags = 0x42000040;
3329                 private static readonly ushort exeCharacteristics = 0x010E;
3330                 private static readonly ushort dllCharacteristics = 0x210E;
3331     // section names are all 8 bytes
3332     private static readonly string textName = ".text\0\0\0";
3333     private static readonly string sdataName = ".sdata\0\0";
3334     private static readonly string relocName = ".reloc\0\0";
3335     private static readonly string rsrcName = ".rsrc\0\0\0";
3336     private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
3337     private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
3338     private static readonly string runtimeEngineName = "mscoree.dll\0\0";
3339
3340                 private Section text, sdata, rsrc;
3341                 ArrayList data;
3342     BinaryWriter reloc = new BinaryWriter(new MemoryStream());
3343     uint dateStamp = 0;
3344     DateTime origin = new DateTime(1970,1,1);
3345     uint numSections = 2; // always have .text  and .reloc sections
3346     internal SubSystem subSys = SubSystem.Windows_CUI;  // default is Windows Console mode
3347     internal uint fileAlign = minFileAlign;
3348     uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
3349     uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
3350     uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
3351     uint resourcesSize, resourcesOffset;
3352     uint strongNameSigOffset;
3353     uint importTableOffset, importLookupTableOffset, totalImportTableSize;
3354     MetaData metaData;
3355     char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
3356                 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
3357                 ushort characteristics;
3358
3359     internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
3360       InitFileImage(makeDLL);
3361       TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
3362       dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
3363     }
3364
3365     internal FileImage(bool makeDLL, Stream str) : base(str) {
3366       InitFileImage(makeDLL);
3367       TimeSpan tmp = DateTime.Now.Subtract(origin);
3368       dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
3369     }
3370
3371     private void InitFileImage(bool makeDLL) {
3372       doDLL = makeDLL;
3373                         if (doDLL) {
3374                                 hintNameTable = dllHintNameTable.ToCharArray();
3375                                 characteristics = dllCharacteristics;
3376                         } else {
3377                                 hintNameTable = exeHintNameTable.ToCharArray();
3378                                 characteristics = exeCharacteristics;
3379                         }
3380       text = new Section(textName,0x60000020);     // IMAGE_SCN_CNT  CODE, EXECUTE, READ
3381 //                      rsrc = new Section(rsrcName,0x40000040);     // IMAGE_SCN_CNT  INITIALIZED_DATA, READ
3382       metaData = new MetaData(this);
3383     }
3384
3385                 internal MetaData GetMetaData() {
3386                         return metaData;
3387                 }
3388
3389     private uint GetNextSectStart(uint rva, uint tide) {
3390       if (tide < SectionAlignment) return rva + SectionAlignment;
3391       return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
3392     }
3393
3394     private void BuildTextSection() {
3395       // .text layout
3396       //    IAT (single entry 8 bytes for pure CIL)
3397       //    CLIHeader (72 bytes)
3398       //    CIL instructions for all methods (variable size)
3399       //    MetaData 
3400       //    ImportTable (40 bytes)
3401       //    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
3402       //    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
3403       //    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
3404       //    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
3405       metaData.BuildMetaData(IATSize + CLIHeaderSize);
3406       metaDataOffset = IATSize + CLIHeaderSize;
3407       // Console.WriteLine("Code starts at " + metaDataOffset);
3408       metaDataOffset += metaData.CodeSize();
3409       // resourcesStart =
3410       resourcesOffset = metaDataOffset + metaData.Size ();
3411       resourcesSize = metaData.GetResourcesSize ();
3412       if (reserveStrongNameSignatureSpace) {
3413         strongNameSigOffset = resourcesOffset + resourcesSize;
3414         // fixUps = RVA for vtable
3415         importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
3416       } else {
3417         strongNameSigOffset = 0;
3418         // fixUps = RVA for vtable
3419         importTableOffset = resourcesOffset + resourcesSize;
3420       }
3421       importTablePadding = NumToAlign(importTableOffset,16);
3422       importTableOffset += importTablePadding;
3423       importLookupTableOffset = importTableOffset + ImportTableSize;
3424       hintNameTableOffset = importLookupTableOffset + IATSize;
3425       runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
3426       entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
3427       totalImportTableSize = entryPointOffset - importTableOffset;
3428       // Console.WriteLine("total import table size = " + totalImportTableSize);
3429       // Console.WriteLine("entrypoint offset = " + entryPointOffset);
3430       entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
3431       entryPointOffset += entryPointPadding;
3432       text.AddReloc(entryPointOffset+2);
3433       text.IncTide(entryPointOffset + 6);
3434       //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
3435                         text.SetSize(NumToAlign(text.Tide(),fileAlign));
3436       // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
3437                         // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
3438                         // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
3439                         // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
3440                         // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
3441                         // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
3442                         // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
3443                         // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
3444
3445     }
3446
3447     internal void BuildRelocSection() {
3448                         text.DoRelocs(reloc);
3449                         if (sdata != null) sdata.DoRelocs(reloc);
3450                         if (rsrc != null) rsrc.DoRelocs(reloc);
3451       relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
3452       relocPadding = NumToAlign(relocTide,fileAlign);
3453       relocSize = relocTide + relocPadding;
3454                         imageSize = relocRVA + SectionAlignment;
3455       initDataSize += relocSize;
3456     }
3457
3458     private void CalcOffsets() {
3459 if (sdata != null)
3460         numSections++;
3461 if (rsrc != null)
3462         numSections++;
3463       headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
3464       headerPadding = NumToAlign(headerSize,fileAlign);
3465       headerSize += headerPadding;
3466       uint offset = headerSize;
3467       uint rva = SectionAlignment;
3468       text.SetOffset(offset);
3469       text.SetRVA(rva);
3470       offset += text.Size();
3471       rva  = GetNextSectStart(rva,text.Tide());
3472                         // Console.WriteLine("headerSize = " + headerSize);
3473                         // Console.WriteLine("headerPadding = " + headerPadding);
3474                         // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
3475                         if (sdata != null) { 
3476                                 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
3477                                 sdata.SetOffset(offset);
3478         sdata.SetRVA(rva);
3479         offset += sdata.Size();
3480         rva = GetNextSectStart(rva,sdata.Tide());
3481                                 initDataSize += sdata.Size();
3482       }
3483       if (rsrc != null) { 
3484                      rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
3485                                 rsrc.SetOffset(offset);
3486         rsrc.SetRVA(rva);
3487         offset += rsrc.Size();
3488         rva = GetNextSectStart(rva,rsrc.Tide());
3489                                 initDataSize += rsrc.Size();
3490       }
3491       relocOffset = offset;
3492       relocRVA = rva;
3493     }
3494
3495     internal void MakeFile() {
3496       if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
3497       else hintNameTable = exeHintNameTable.ToCharArray();
3498       BuildTextSection();
3499       CalcOffsets();
3500       BuildRelocSection();
3501       // now write it out
3502       WriteHeader();
3503       WriteSections();
3504       Flush();
3505       Close();
3506     }
3507
3508     private void WriteHeader() {
3509       Write(DOSHeader);
3510                         // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
3511                         WritePEHeader();
3512                          // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
3513                         text.WriteHeader(this,relocRVA);
3514       if (sdata != null) sdata.WriteHeader(this,relocRVA);
3515       if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
3516                         // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
3517                         WriteRelocSectionHeader();
3518                         // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
3519                         WriteZeros(headerPadding);
3520     }
3521
3522     private void WriteSections() {
3523                         // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
3524       WriteTextSection();
3525       if (sdata != null) WriteSDataSection();
3526       if (rsrc != null) WriteRsrcSection();
3527       WriteRelocSection();
3528     }
3529
3530      private void WriteIAT() {
3531       Write(text.RVA() + hintNameTableOffset);
3532       Write(0);
3533     }
3534
3535                 private void WriteImportTables() {
3536                         // Import Table
3537       WriteZeros(importTablePadding);
3538       // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
3539                         Write(importLookupTableOffset + text.RVA());
3540                         WriteZeros(8); 
3541                         Write(runtimeEngineOffset + text.RVA());
3542                         Write(text.RVA());    // IAT is at the beginning of the text section
3543                         WriteZeros(20);
3544                         // Import Lookup Table
3545                         WriteIAT();                // lookup table and IAT are the same
3546                         // Hint/Name Table
3547        // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3548                         Write(hintNameTable);
3549       Write(runtimeEngineName.ToCharArray());
3550                 }
3551
3552     private void WriteTextSection() {
3553       WriteIAT();
3554       WriteCLIHeader();
3555       // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3556       metaData.WriteByteCodes(this);
3557       // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3558       largeStrings = metaData.LargeStringsIndex();
3559       largeGUID = metaData.LargeGUIDIndex();
3560       largeUS = metaData.LargeUSIndex();
3561       largeBlob = metaData.LargeBlobIndex();
3562       metaData.WriteMetaData(this);
3563       metaData.WriteResources (this);
3564       if (reserveStrongNameSignatureSpace) {
3565         WriteZeros(StrongNameSignatureSize);
3566       }
3567       WriteImportTables();
3568                         WriteZeros(entryPointPadding);
3569                         Write((ushort)0x25FF);
3570                         Write(ImageBase + text.RVA());
3571                         WriteZeros(text.Padding());
3572     }
3573
3574     private void WriteCLIHeader() {
3575       Write(CLIHeaderSize);       // Cb
3576       Write((short)2);            // Major runtime version
3577       Write((short)0);            // Minor runtime version
3578       Write(text.RVA() + metaDataOffset);
3579       Write(metaData.Size());
3580       Write(runtimeFlags);
3581       Write(entryPointToken);
3582       if (resourcesSize > 0) {
3583         Write (text.RVA () + resourcesOffset);
3584         Write (resourcesSize);
3585       } else {
3586         WriteZeros (8);
3587       }
3588       // Strong Name Signature (RVA, size)
3589       if (reserveStrongNameSignatureSpace) {
3590         Write(text.RVA() + strongNameSigOffset); 
3591         Write(StrongNameSignatureSize);
3592       } else {
3593         WriteZeros(8);
3594       }
3595       WriteZeros(8);                     // CodeManagerTable
3596       WriteZeros(8);                     // VTableFixups NYI
3597       WriteZeros(16);                    // ExportAddressTableJumps, ManagedNativeHeader
3598      }
3599
3600     private void WriteSDataSection() {
3601       long size = sdata.Size ();
3602       long start = BaseStream.Position;
3603       for (int i=0; i < data.Count; i++) {
3604         ((DataConstant)data[i]).Write(this);
3605       }
3606       while (BaseStream.Position < (start + size))
3607               Write ((byte) 0);
3608     }
3609
3610                 private void WriteRsrcSection() {
3611                 }
3612
3613     private void WriteRelocSection() {
3614      // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
3615       MemoryStream str = (MemoryStream)reloc.BaseStream;
3616       Write(str.ToArray());
3617       WriteZeros(NumToAlign((uint)str.Position,fileAlign));
3618     }
3619
3620     internal void SetEntryPoint(uint entryPoint) {
3621       entryPointToken = entryPoint;
3622     }
3623
3624     internal void AddInitData(DataConstant cVal) {
3625                         if (sdata == null) {                    
3626                                 sdata = new Section(sdataName,0xC0000040);   // IMAGE_SCN_CNT  INITIALIZED_DATA, READ, WRITE
3627                                 data = new ArrayList(); 
3628                         }
3629       data.Add(cVal);
3630       cVal.DataOffset = sdata.Tide();
3631       sdata.IncTide(cVal.GetSize());
3632     }
3633
3634     internal void WriteZeros(uint numZeros) {
3635       for (int i=0; i < numZeros; i++) {
3636         Write((byte)0);
3637       }
3638     }
3639
3640     internal void WritePEHeader() {
3641       Write((ushort)0x014C);  // Machine - always 0x14C for Managed PE Files (allow others??)
3642       Write((ushort)numSections);
3643       Write(dateStamp);
3644       WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
3645       Write((ushort)0x00E0);  // Size of Optional Header
3646       Write(characteristics);
3647       // PE Optional Header
3648       Write((ushort)0x010B);   // Magic
3649       Write((byte)0x6);        // LMajor pure-IL = 6   C++ = 7
3650       Write((byte)0x0);        // LMinor
3651       Write(text.Size());
3652       Write(initDataSize);
3653       Write(0);                // Check other sections here!!
3654       Write(text.RVA() + entryPointOffset);
3655       Write(text.RVA());
3656                         uint dataBase = 0;
3657                         if (sdata != null) dataBase = sdata.RVA();
3658                         else if (rsrc != null) dataBase = rsrc.RVA();
3659       else dataBase = relocRVA;
3660                         Write(dataBase);
3661       Write(ImageBase);
3662       Write(SectionAlignment);
3663       Write(fileAlign);
3664       Write((ushort)0x04);     // OS Major
3665       WriteZeros(6);                  // OS Minor, User Major, User Minor
3666       Write((ushort)0x04);     // SubSys Major
3667       WriteZeros(6);           // SybSys Minor, Reserved
3668       Write(imageSize);
3669       Write(headerSize);
3670       Write((int)0);           // File Checksum
3671       Write((ushort)subSys);
3672       Write((short)0);         // DLL Flags
3673       Write((uint)0x100000);   // Stack Reserve Size
3674       Write((uint)0x1000);     // Stack Commit Size
3675       Write((uint)0x100000);   // Heap Reserve Size
3676       Write((uint)0x1000);     // Heap Commit Size
3677       Write(0);                // Loader Flags
3678       Write(0x10);             // Number of Data Directories
3679       WriteZeros(8);                  // Export Table
3680       Write(importTableOffset + text.RVA());
3681       Write(totalImportTableSize);
3682       WriteZeros(24);            // Resource, Exception and Certificate Tables
3683       Write(relocRVA);
3684       Write(relocTide);
3685       WriteZeros(48);            // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
3686       Write(text.RVA());         // IATRVA - IAT is at start of .text Section
3687       Write(IATSize);
3688       WriteZeros(8);             // Delay Import Descriptor
3689       Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
3690       Write(CLIHeaderSize);    
3691       WriteZeros(8);             // Reserved
3692     }
3693
3694     internal void WriteRelocSectionHeader() {
3695       Write(relocName.ToCharArray());
3696       Write(relocTide);
3697       Write(relocRVA);
3698       Write(relocSize);
3699       Write(relocOffset);
3700       WriteZeros(12);
3701       Write(relocFlags);
3702     }
3703
3704     private void Align (MemoryStream str, int val) {
3705       if ((str.Position % val) != 0) {
3706         for (int i=val - (int)(str.Position % val); i > 0; i--) {
3707           str.WriteByte(0);
3708         }
3709       }
3710     }
3711
3712     private uint Align(uint val, uint alignVal) {
3713       if ((val % alignVal) != 0) {
3714         val += alignVal - (val % alignVal);
3715       }
3716       return val;
3717     }
3718
3719     private uint NumToAlign(uint val, uint alignVal) {
3720       if ((val % alignVal) == 0) return 0;
3721       return alignVal - (val % alignVal);
3722     }
3723
3724     internal void StringsIndex(uint ix) {
3725       if (largeStrings) Write(ix);
3726       else Write((ushort)ix);
3727     }
3728
3729     internal void GUIDIndex(uint ix) {
3730       if (largeGUID) Write(ix);
3731       else Write((ushort)ix);
3732     }
3733
3734     internal void USIndex(uint ix) {
3735       if (largeUS) Write(ix);
3736       else Write((ushort)ix);
3737     }
3738
3739     internal void BlobIndex(uint ix) {
3740       if (largeBlob) Write(ix);
3741       else Write((ushort)ix);
3742     }
3743
3744     internal void WriteIndex(MDTable tabIx,uint ix) {
3745       if (metaData.LargeIx(tabIx)) Write(ix);
3746       else Write((ushort)ix);
3747     }
3748
3749     internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
3750       metaData.WriteCodedIndex(code,elem,this);
3751     }
3752     
3753     internal void WriteCodeRVA(uint offs) {
3754       Write(text.RVA() + offs);
3755     }
3756
3757     internal void WriteDataRVA(uint offs) {
3758       Write(sdata.RVA() + offs);
3759     }
3760
3761     internal void Write3Bytes(uint val) {
3762       byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
3763       byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
3764       byte b1 = (byte)(val & FileImage.iByteMask[0]);
3765       Write(b1);
3766       Write(b2);
3767       Write(b3);
3768     }
3769
3770     internal bool ReserveStrongNameSignatureSpace {
3771       get { return reserveStrongNameSignatureSpace; }
3772       set { reserveStrongNameSignatureSpace = value; }
3773     }
3774
3775         }
3776   /**************************************************************************/  
3777         /// <summary>
3778         /// Descriptor for a file referenced in THIS assembly/module (.file)
3779         /// </summary>
3780         public class FileRef : MetaDataElement
3781         {
3782     private static readonly uint NoMetaData = 0x1;
3783     uint nameIx = 0, hashIx = 0;
3784     uint flags = 0;
3785     protected string name;
3786
3787     internal FileRef(string name, byte[] hashBytes, bool metaData,
3788                       bool entryPoint, MetaData md) {
3789       if (!metaData) flags = NoMetaData;
3790       if (entryPoint) md.SetEntryPoint(this);
3791       this.name = name;
3792       nameIx = md.AddToStringsHeap(name);
3793       hashIx = md.AddToBlobHeap(hashBytes);
3794       tabIx = MDTable.File;
3795                 }
3796
3797     internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
3798                       bool entryPoint, MetaData md) {
3799       if (!metaData) flags = NoMetaData;
3800       if (entryPoint) md.SetEntryPoint(this);
3801       this.nameIx = nameIx;
3802       hashIx = md.AddToBlobHeap(hashBytes);
3803       tabIx = MDTable.File;
3804     }
3805
3806     internal sealed override uint Size(MetaData md) {
3807       return 4 + md.StringsIndexSize() + md.BlobIndexSize();
3808     }
3809
3810     internal sealed override void BuildTables(MetaData md) {
3811       md.AddToTable(MDTable.File,this);
3812     }
3813
3814     internal sealed override void Write(FileImage output) {
3815       output.Write(flags);
3816       output.StringsIndex(nameIx);
3817       output.BlobIndex(hashIx);
3818     }
3819
3820     internal sealed override uint GetCodedIx(CIx code) {
3821       switch (code) {
3822         case (CIx.HasCustomAttr) : return 16; 
3823         case (CIx.Implementation) : return 0;
3824       }
3825       return 0;
3826     }
3827
3828         }
3829   /**************************************************************************/  
3830         /// <summary>
3831         /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
3832         /// </summary>
3833         public class ImplMap : MetaDataElement
3834         {
3835     private static readonly ushort NoMangle = 0x01;
3836     ushort flags;
3837     Method meth;
3838     string importName;
3839     uint iNameIx;
3840     ModuleRef importScope;
3841
3842                 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
3843       flags = flag;
3844       meth = implMeth;
3845       importName = iName;
3846       importScope = mScope;
3847       tabIx = MDTable.ImplMap;
3848       if (iName == null) flags |= NoMangle;
3849       //throw(new NotYetImplementedException("PInvoke "));
3850                 }
3851
3852     internal override uint SortKey() {
3853       return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded]) 
3854               | meth.GetCodedIx(CIx.MemberForwarded);
3855     }
3856
3857     internal sealed override void BuildTables(MetaData md) {
3858       if (done) return;
3859       iNameIx = md.AddToStringsHeap(importName);
3860       done = true;
3861     }
3862
3863     internal sealed override uint Size(MetaData md) {
3864       return 2+ md.CodedIndexSize(CIx.MemberForwarded) + 
3865         md.StringsIndexSize() +  md.TableIndexSize(MDTable.ModuleRef);
3866     }
3867
3868     internal sealed override void Write(FileImage output) {
3869       output.Write(flags);
3870       output.WriteCodedIndex(CIx.MemberForwarded,meth);
3871       output.StringsIndex(iNameIx);
3872       output.WriteIndex(MDTable.ModuleRef,importScope.Row);
3873     }
3874
3875         }
3876
3877   /**************************************************************************/  
3878   /// <summary>
3879   /// Descriptor for an IL instruction
3880   /// </summary>
3881   internal abstract class CILInstruction {
3882     protected static readonly sbyte maxByteVal = 127;
3883     protected static readonly sbyte minByteVal = -128;
3884     protected static readonly byte leadByte = 0xFE;
3885                 protected static readonly uint USHeapIndex = 0x70000000;
3886     protected static readonly int longInstrStart = (int)Op.arglist;
3887     public bool twoByteInstr = false;
3888     public uint size = 0;
3889     public uint offset;
3890
3891     internal virtual bool Check(MetaData md) {
3892       return false;
3893     }
3894
3895                 internal virtual void Write(FileImage output) { }
3896
3897   }
3898
3899   internal class CILByte : CILInstruction {
3900     byte byteVal;
3901
3902     internal CILByte(byte bVal) {
3903       byteVal = bVal;
3904       size = 1;
3905     }
3906
3907     internal override void Write(FileImage output) {
3908       output.Write(byteVal);
3909     }
3910
3911   }
3912
3913   
3914   internal class Instr : CILInstruction {
3915     protected int instr;
3916
3917     internal Instr(int inst) {
3918       if (inst >= longInstrStart) {
3919         instr = inst - longInstrStart;
3920         twoByteInstr = true;
3921         size = 2;
3922       } else {
3923         instr = inst;
3924         size = 1;
3925       }
3926     }
3927
3928                 internal override void Write(FileImage output) {
3929       //Console.WriteLine("Writing instruction " + instr + " with size " + size);
3930       if (twoByteInstr) output.Write(leadByte);
3931       output.Write((byte)instr);
3932                 }
3933
3934   }
3935
3936   internal class IntInstr : Instr {
3937     int val;
3938     bool byteNum;
3939
3940     internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
3941       val = num;
3942       byteNum = byteSize;
3943       if (byteNum) size++;
3944       else size += 4;
3945     }
3946
3947                 internal sealed override void Write(FileImage output) {
3948                         base.Write(output);
3949       if (byteNum) 
3950         output.Write((sbyte)val);
3951       else 
3952                                 output.Write(val); 
3953                 }
3954
3955   }
3956
3957   internal class UIntInstr : Instr {
3958     int val;
3959     bool byteNum;
3960
3961                 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
3962                         val = num;
3963       byteNum = byteSize;
3964       if (byteNum) size++;
3965       else size += 2;
3966                 }
3967
3968                 internal sealed override void Write(FileImage output) {
3969                         base.Write(output);
3970       if (byteNum)
3971                           output.Write((byte)val);
3972       else
3973                                 output.Write((ushort)val); 
3974                 }
3975         
3976   }
3977
3978         internal class LongInstr : Instr {
3979                 long val;
3980
3981                 internal LongInstr(int inst, long l) : base(inst) {
3982                         val = l;
3983                         size += 8;
3984                 }
3985
3986                 internal sealed override void Write(FileImage output) {
3987                         base.Write(output);
3988                         output.Write(val);
3989                 }
3990
3991         }
3992
3993   internal class FloatInstr : Instr {
3994     float fVal;
3995
3996     internal FloatInstr(int inst, float f) : base(inst) {
3997       fVal = f;
3998       size += 4;
3999     }
4000
4001                 internal sealed override void Write(FileImage output) {
4002                         base.Write(output);
4003                         output.Write(fVal);
4004                 }
4005
4006         }
4007
4008   internal class DoubleInstr : Instr {
4009     double val;
4010
4011     internal DoubleInstr(int inst, double d) : base(inst) {
4012       val = d;
4013       size += 8;
4014     }
4015
4016                 internal sealed override void Write(FileImage output) {
4017                         base.Write(output);
4018                         output.Write(val);
4019                 }
4020
4021         }
4022
4023   internal class StringInstr : Instr {
4024     string val;
4025           byte[] bval;                                                  
4026     uint strIndex;
4027
4028     internal StringInstr(int inst, string str) : base(inst) {
4029       val = str;  
4030       size += 4;
4031     }
4032
4033           internal StringInstr (int inst, byte[] str) : base (inst) {
4034                   bval = str;
4035                   size += 4;
4036           }
4037                    
4038     internal sealed override bool Check(MetaData md) {
4039             if (val != null)
4040                     strIndex = md.AddToUSHeap(val);
4041             else
4042                     strIndex = md.AddToUSHeap (bval);
4043       return false;
4044     }
4045
4046                 internal sealed override void Write(FileImage output) {
4047                         base.Write(output);
4048                         output.Write(USHeapIndex  | strIndex);
4049                 }
4050
4051         }
4052
4053   internal class LabelInstr : CILInstruction {
4054     CILLabel label;
4055
4056     internal LabelInstr(CILLabel lab) {
4057       label = lab;
4058       label.AddLabelInstr(this);
4059     }
4060   }
4061
4062   internal class FieldInstr : Instr {
4063     Field field;
4064
4065     internal FieldInstr(int inst, Field f) : base(inst) {
4066       field = f;
4067       size += 4;
4068     }
4069
4070                 internal sealed override void Write(FileImage output) {
4071                         base.Write(output);
4072                         output.Write(field.Token());
4073                 }
4074
4075         }
4076
4077   internal class MethInstr : Instr {
4078     Method meth;
4079
4080     internal MethInstr(int inst, Method m) : base(inst) {
4081       meth = m;
4082       size += 4;
4083     }
4084
4085                 internal sealed override void Write(FileImage output) {
4086                         base.Write(output);
4087                         output.Write(meth.Token());
4088                 }
4089
4090   }
4091
4092   internal class SigInstr : Instr {
4093     CalliSig signature;
4094
4095     internal SigInstr(int inst, CalliSig sig) : base(inst) {
4096       signature = sig;
4097       size += 4;
4098     }
4099
4100     internal sealed override bool Check(MetaData md) {
4101       md.AddToTable(MDTable.StandAloneSig,signature);
4102       signature.BuildTables(md);
4103       return false;
4104     }
4105
4106                 internal sealed override void Write(FileImage output) {
4107                         base.Write(output);
4108                         output.Write(signature.Token());
4109                 }
4110   }
4111
4112   internal class TypeInstr : Instr {
4113     MetaDataElement theType;
4114
4115     internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
4116       theType = aType.GetTypeSpec(md);
4117       size += 4;
4118     }
4119
4120     internal sealed override void Write(FileImage output) {
4121       base.Write(output);
4122       output.Write(theType.Token());
4123                 }
4124
4125   }
4126
4127   internal class BranchInstr : Instr {
4128     CILLabel dest;
4129     private bool shortVer = true;
4130     private static readonly byte longInstrOffset = 13;
4131     private int target = 0;
4132
4133     internal BranchInstr(int inst, CILLabel dst) : base(inst) {
4134       dest = dst;
4135       dest.AddBranch(this);
4136       size++;
4137
4138       if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
4139               shortVer = false;
4140               size += 3;
4141       }
4142     }
4143
4144     internal sealed override bool Check(MetaData md) {
4145       target = (int)dest.GetLabelOffset() - (int)(offset + size);
4146       return false;
4147     }
4148
4149                 internal sealed override void Write(FileImage output) {
4150                         base.Write(output);
4151                         if (shortVer)
4152                                 output.Write((sbyte)target);
4153                         else
4154                                 output.Write(target);
4155                 }
4156
4157   }
4158
4159   internal class SwitchInstr : Instr {
4160     CILLabel[] cases;
4161                 uint numCases = 0;
4162
4163     internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
4164       cases = dsts;
4165                         if (cases != null) numCases = (uint)cases.Length;
4166       size += 4 + (numCases * 4);
4167       for (int i=0; i < numCases; i++) {
4168         cases[i].AddBranch(this);
4169       }
4170     }
4171
4172                 internal sealed override void Write(FileImage output) {
4173                         base.Write(output);
4174                         output.Write(numCases);
4175                         for (int i=0; i < numCases; i++) {
4176                                 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
4177                                 output.Write(target);
4178                         }
4179                 }
4180
4181   }
4182   /**************************************************************************/  
4183
4184         public class GenericParameter : MetaDataElement
4185         {
4186                 MetaDataElement owner;
4187                 MetaData metadata;
4188                 string name;
4189                 uint nameIx;
4190                 short index;
4191
4192                 internal GenericParameter (ClassDef owner, MetaData metadata,
4193                                 short index, string name) : this (owner, metadata, index, name, true)
4194                 {
4195                 }
4196
4197                 internal GenericParameter (MethodDef owner, MetaData metadata,
4198                                 short index, string name) : this (owner, metadata, index, name, true)
4199                 {
4200                 }
4201
4202                 private GenericParameter (MetaDataElement owner, MetaData metadata,
4203                                 short index, string name, bool nadda)
4204                 {
4205                         this.owner = owner;
4206                         this.metadata = metadata;
4207                         this.index = index;
4208                         tabIx = MDTable.GenericParam;
4209                         this.name = name;
4210                 }
4211
4212     internal override uint SortKey() {
4213       return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
4214               | owner.GetCodedIx(CIx.TypeOrMethodDef);
4215     }
4216
4217                 public void AddConstraint  (Type constraint) {
4218                         metadata.AddToTable (MDTable.GenericParamConstraint,
4219                                         new GenericParamConstraint (this, constraint));
4220                 }
4221
4222                 internal sealed override uint Size(MetaData md) {
4223                         return (uint) (4 +
4224                                md.CodedIndexSize(CIx.TypeOrMethodDef) + 
4225                                4 +
4226                                md.TableIndexSize(MDTable.TypeDef));
4227                 }
4228
4229                 internal sealed override void BuildTables(MetaData md) {
4230                         if (done) return;
4231                         nameIx = md.AddToStringsHeap(name);
4232                         done = true;
4233                 }
4234
4235                 internal sealed override void Write(FileImage output) {
4236                         output.Write ((short) index);
4237                         output.Write ((short) 0);
4238                         output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
4239                         output.Write ((uint) nameIx);
4240                         output.WriteIndex(MDTable.TypeDef,owner.Row);
4241                 }
4242
4243     
4244         }
4245
4246         internal class GenericParamConstraint : MetaDataElement
4247         {
4248                 GenericParameter param;
4249                 Type type;
4250
4251                 public GenericParamConstraint (GenericParameter param, Type type) {
4252                         this.param = param;
4253                         this.type = type;
4254                         tabIx = MDTable.GenericParamConstraint;
4255                 }
4256
4257                 internal sealed override uint Size(MetaData md) {
4258                         return (uint) (md.TableIndexSize(MDTable.GenericParam) +
4259                                        md.CodedIndexSize(CIx.TypeDefOrRef));
4260                 }
4261
4262                 internal sealed override void Write(FileImage output) {
4263                         output.WriteIndex(MDTable.GenericParam, param.Row);
4264                         output.WriteCodedIndex(CIx.TypeDefOrRef, type);
4265                 }
4266
4267
4268         }
4269
4270         internal class MethodSpec : MetaDataElement
4271         {
4272                 Method meth;
4273                 GenericMethodSig g_sig;
4274                 uint sidx;
4275
4276                 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4277                         this.meth = meth;
4278                         this.g_sig = g_sig;
4279                         tabIx = MDTable.MethodSpec;
4280                 }
4281
4282                 internal sealed override void BuildTables (MetaData md) {
4283                         if (done) return;
4284                         sidx = g_sig.GetSigIx (md);
4285                         done = true;
4286                 }
4287
4288                 internal sealed override uint Size (MetaData md) {
4289                         return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4290                                        md.BlobIndexSize ());
4291                 }
4292
4293                 internal sealed override void Write (FileImage output) {
4294                     output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4295                     output.BlobIndex (sidx);
4296                 }
4297         }
4298
4299   /**************************************************************************/
4300         /// <summary>
4301         /// Descriptor for interface implemented by a class
4302         /// </summary>
4303         public class InterfaceImpl: MetaDataElement
4304         { 
4305     ClassDef theClass;
4306     Class theInterface;
4307
4308                 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
4309       this.theClass = theClass;
4310       this.theInterface = theInterface;
4311                         tabIx = MDTable.InterfaceImpl;
4312                 }
4313
4314     internal sealed override uint Size(MetaData md) {
4315       return md.TableIndexSize(MDTable.TypeDef) + 
4316              md.CodedIndexSize(CIx.TypeDefOrRef);
4317     }
4318
4319     internal sealed override void Write(FileImage output) {
4320       output.WriteIndex(MDTable.TypeDef,theClass.Row);
4321       output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
4322     }
4323
4324     internal sealed override uint GetCodedIx(CIx code) { return 5; }
4325
4326     internal override uint SortKey ()
4327     {
4328         return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
4329                 | theClass.GetCodedIx (CIx.TypeDefOrRef);
4330     }
4331
4332         }
4333   /**************************************************************************/  
4334         /// <summary>
4335         /// Descriptor for a local of a method
4336         /// </summary>
4337   public class Local
4338         {
4339     private static readonly byte Pinned = 0x45;
4340     string name;
4341     Type type;
4342     bool pinned = false, byref = false;
4343
4344     /// <summary>
4345     /// Create a new local variable 
4346     /// </summary>
4347     /// <param name="lName">name of the local variable</param>
4348     /// <param name="lType">type of the local variable</param>
4349     public Local(string lName, Type lType) {
4350       name = lName;
4351       type = lType;
4352     }
4353
4354     /// <summary>
4355     /// Create a new local variable that is byref and/or pinned
4356     /// </summary>
4357     /// <param name="lName">local name</param>
4358     /// <param name="lType">local type</param>
4359     /// <param name="byRef">is byref</param>
4360     /// <param name="isPinned">has pinned attribute</param>
4361                 public Local(string lName, Type lType, bool byRef, bool isPinned)
4362                 {
4363       name = lName;
4364       type = lType;
4365       byref = byRef;
4366       pinned = isPinned;
4367                 }
4368
4369     internal void TypeSig(MemoryStream str) {
4370       if (pinned) str.WriteByte(Pinned);
4371       type.TypeSig(str);
4372     }
4373
4374         }
4375   /**************************************************************************/  
4376         /// <summary>
4377         /// Descriptor for the locals for a method
4378         /// </summary>
4379
4380   public class LocalSig : Signature
4381         {
4382                 private static readonly byte LocalSigByte = 0x7;
4383     Local[] locals;
4384
4385                 public LocalSig(Local[] locals)         {
4386       this.locals = locals;
4387       tabIx = MDTable.StandAloneSig;
4388                 }
4389
4390     internal sealed override void BuildTables(MetaData md) {
4391       if (done) return;
4392       MemoryStream sig = new MemoryStream();
4393       sig.WriteByte(LocalSigByte);
4394       MetaData.CompressNum((uint)locals.Length,sig);
4395       for (int i=0; i < locals.Length; i++) {
4396         ((Local)locals[i]).TypeSig(sig);
4397       }
4398       sigIx = md.AddToBlobHeap(sig.ToArray());
4399       done = true;
4400     }
4401
4402   }
4403
4404   /**************************************************************************/  
4405         /// <summary>
4406         /// Descriptor for resources used in this PE file 
4407         /// </summary>
4408
4409   public class ManifestResource : MetaDataElement
4410         {
4411     public static readonly uint PublicResource = 0x1;
4412     public static readonly uint PrivateResource = 0x2;
4413
4414     string mrName;
4415     MetaDataElement rRef;
4416     uint fileOffset;
4417     uint nameIx = 0;
4418     uint flags = 0;
4419     byte [] resourceBytes;
4420
4421     public ManifestResource (string name, byte[] resBytes, uint flags) {
4422       InitResource (name, flags);
4423       this.resourceBytes = resBytes;
4424     }
4425
4426     public ManifestResource(string name, uint flags, FileRef fileRef) {
4427       InitResource (name, flags);
4428       rRef = fileRef;
4429     }
4430
4431     public ManifestResource(string name, uint flags, FileRef fileRef, 
4432                                                             uint fileIx) {
4433       InitResource (name, flags);
4434       rRef = fileRef;
4435       fileOffset = fileIx;
4436     }
4437
4438     public ManifestResource(string name, uint flags, AssemblyRef assemRef) {
4439       InitResource (name, flags);
4440       rRef = assemRef;
4441     }
4442
4443     internal ManifestResource (ManifestResource mres) {
4444       mrName = mres.mrName;
4445       flags = mres.flags;
4446       this.rRef = rRef;
4447       this.fileOffset = fileOffset;
4448       this.resourceBytes = resourceBytes;
4449     }
4450
4451     private void InitResource (string name, uint flags) {
4452       mrName = name;
4453       this.flags = flags;
4454       tabIx = MDTable.ManifestResource;
4455     }
4456
4457     internal sealed override void BuildTables(MetaData md) {
4458       if (done) return;
4459       md.AddToTable (MDTable.ManifestResource, this);
4460       nameIx = md.AddToStringsHeap(mrName);
4461       if (resourceBytes != null) {
4462         if (rRef != null)
4463           throw new Exception("ERROR:  Manifest Resource has byte value and file reference");
4464         fileOffset = md.AddResource(resourceBytes);
4465       } else {
4466         if (rRef == null)
4467           throw new Exception("ERROR:  Manifest Resource has no implementation or value");
4468         rRef.BuildTables (md);
4469       }
4470
4471       done = true;
4472     }
4473
4474     internal sealed override uint Size(MetaData md) {
4475       return 8 + md.StringsIndexSize() + 
4476                  md.CodedIndexSize(CIx.Implementation);
4477     }
4478
4479     internal sealed override void Write(FileImage output) {
4480       output.Write(fileOffset);
4481       output.Write(flags);
4482       output.StringsIndex(nameIx);
4483       output.WriteCodedIndex(CIx.Implementation,rRef);
4484     }
4485
4486     internal sealed override uint GetCodedIx(CIx code) { return 18; }
4487     
4488     public string Name {
4489       get { return mrName; }
4490       set { mrName = value; }
4491     }
4492
4493         }
4494   /**************************************************************************/  
4495         /// <summary>
4496         /// Base class for elements in the PropertyMap, EventMap and 
4497         /// NestedClass MetaData tables
4498         /// </summary>
4499   public class MapElem : MetaDataElement
4500         {
4501     ClassDef parent;
4502     uint elemIx;
4503     MDTable elemTable;
4504
4505                 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
4506       parent = par;
4507       elemIx = elIx;
4508       elemTable = elemTab;
4509                 }
4510
4511     internal sealed override uint Size(MetaData md) {
4512       return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
4513     }
4514
4515     internal sealed override void Write(FileImage output) {
4516       output.WriteIndex(MDTable.TypeDef,parent.Row);
4517       output.WriteIndex(elemTable,elemIx);
4518     }
4519         }
4520   /**************************************************************************/  
4521         /// <summary>
4522         /// Base class for field/methods (member of a class)
4523         /// </summary>
4524         public abstract class Member : MetaDataElement
4525         {
4526     protected string name;
4527     protected uint nameIx = 0, sigIx = 0;
4528     
4529                 internal Member(string memName)
4530                 {
4531       name = memName;
4532                         tabIx = MDTable.MemberRef;
4533                 }
4534
4535         }
4536   /**************************************************************************/  
4537         /// <summary>
4538   /// MetaData 
4539   ///   Root (20 bytes + UTF-8 Version String + quad align padding)
4540   ///   StreamHeaders (8 bytes + null terminated name string + quad align padding)
4541   ///   Streams 
4542   ///     #~        (always present - holds metadata tables)
4543   ///     #Strings  (always present - holds identifier strings)
4544   ///     #US       (Userstring heap)
4545   ///     #Blob     (signature blobs)
4546   ///     #GUID     (guids for assemblies or Modules)
4547   /// </summary>
4548
4549   public class MetaData 
4550         {
4551                 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4552                 private static readonly byte StringsHeapMask = 0x1;
4553                 private static readonly byte GUIDHeapMask = 0x2;
4554                 private static readonly byte BlobHeapMask = 0x4;
4555     private static readonly uint MetaDataSignature = 0x424A5342;
4556     private static readonly uint maxSmlIxSize = 0xFFFF;
4557     private static readonly uint max1BitSmlIx = 0x7FFF;
4558     private static readonly uint max2BitSmlIx = 0x3FFF;
4559     private static readonly uint max3BitSmlIx = 0x1FFF;
4560     private static readonly uint max5BitSmlIx = 0x7FF;
4561     // NOTE: version and stream name strings MUST always be quad padded
4562     private static readonly string version = "v1.0.3705\0\0\0";
4563     private static readonly char[] tildeName = {'#','~','\0','\0'};
4564     private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4565     private static readonly char[] usName = {'#','U','S','\0'};
4566     private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4567     private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4568                 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4569     private static readonly uint TildeHeaderSize = 24;
4570     private static readonly uint StreamHeaderSize = 8;
4571     private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4572     private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4573
4574     MetaDataStream strings, us, guid, blob;
4575
4576     MetaDataStream[] streams = new MetaDataStream[5];
4577     uint numStreams = 5;
4578     uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4579     uint numTables = 0, resourcesSize = 0;
4580     ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4581     ArrayList byteCodes = new ArrayList();
4582     uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4583                 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4584     bool[] largeIx = new bool[numMetaDataTables];
4585     bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4586                 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4587                 private FileImage file;
4588     private byte heapSizes = 0;
4589                 MetaDataElement entryPoint;
4590                 BinaryWriter output;
4591     public MSCorLib mscorlib;
4592     private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4593     long mdStart;
4594                 private ArrayList cattr_list;
4595     ArrayList resources;            
4596                 
4597     internal MetaData(FileImage file) {
4598       // tilde = new MetaDataStream(tildeName,false,0);
4599       this.file = file;
4600                         strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4601       us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4602       guid = new MetaDataStream(guidName,false);
4603       blob = new MetaDataStream(blobName,true);
4604       streams[1] = strings;
4605       streams[2] = us;
4606       streams[3] = guid;
4607       streams[4] = blob;
4608       for (int i=0; i < numMetaDataTables; i++) {
4609         largeIx[i] = false;
4610       }
4611       for (int i=0; i < lgeCIx.Length; i++) {
4612         lgeCIx[i] = false;
4613       }
4614       mscorlib = new MSCorLib(this);
4615                 }
4616  
4617     internal TypeSpec GetPrimitiveTypeSpec(int ix) {
4618       return systemTypeSpecs[ix];
4619     }
4620
4621     internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
4622       systemTypeSpecs[ix] = typeSpec;
4623     }
4624
4625     internal uint Size() {
4626       return metaDataSize;
4627     }
4628
4629     
4630     private void CalcHeapSizes ()
4631     {
4632             if (strings.LargeIx()) {
4633                     largeStrings = true;
4634                     heapSizes |= StringsHeapMask;
4635             }
4636             if (guid.LargeIx()) {
4637                     largeGUID = true;
4638                     heapSizes |= GUIDHeapMask;
4639             }
4640             if (blob.LargeIx()) {
4641                     largeBlob = true;
4642                     heapSizes |= BlobHeapMask;
4643             }
4644
4645             largeUS = us.LargeIx();
4646    }
4647
4648                 internal void StreamSize(byte mask) {
4649                         heapSizes |= mask;
4650                 }
4651
4652     internal uint AddToUSHeap(string str) {
4653       if (str == null) return 0;
4654       return us.Add(str,true);
4655    }
4656
4657                 internal uint AddToUSHeap(byte[] str) {
4658                         if (str == null) return 0;
4659                         return us.Add (str, true);
4660                 }
4661                                 
4662     internal uint AddToStringsHeap(string str) {
4663       if ((str == null) || (str.CompareTo("") == 0)) return 0;
4664       return strings.Add(str,false);
4665     }
4666
4667     internal uint AddToGUIDHeap(Guid guidNum) {
4668       return guid.Add(guidNum, false);
4669     }
4670
4671     internal uint AddToBlobHeap(byte[] blobBytes) {
4672       if (blobBytes == null) return 0;
4673       return blob.Add(blobBytes, true);
4674     }
4675
4676     internal uint AddToBlobHeap(byte val) {
4677       return blob.Add(val, true);
4678     }
4679
4680     internal uint AddToBlobHeap(sbyte val) {
4681       return blob.Add(val, true);
4682     }
4683
4684     internal uint AddToBlobHeap(ushort val) {
4685       return blob.Add(val, true);
4686     }
4687
4688     internal uint AddToBlobHeap(short val) {
4689       return blob.Add(val, true);
4690     }
4691
4692     internal uint AddToBlobHeap(uint val) {
4693       return blob.Add(val, true);
4694     }
4695
4696     internal uint AddToBlobHeap(int val) {
4697       return blob.Add(val, true);
4698     }
4699
4700     internal uint AddToBlobHeap(ulong val) {
4701       return blob.Add(val, true);
4702     }
4703
4704     internal uint AddToBlobHeap(long val) {
4705       return blob.Add(val, true);
4706     }
4707
4708     internal uint AddToBlobHeap(float val) {
4709       return blob.Add(val, true);
4710     }
4711
4712     internal uint AddToBlobHeap(double val) {
4713       return blob.Add(val, true);
4714     }
4715
4716     internal uint AddToBlobHeap(string val) {
4717       return blob.Add(val,true);
4718     }
4719
4720                 internal void AddCustomAttribute (CustomAttribute cattr)
4721                 {
4722                         if (cattr_list == null)
4723                                 cattr_list = new ArrayList ();
4724                         cattr_list.Add (cattr);
4725                 }
4726
4727     private ArrayList GetTable(MDTable tableIx) {
4728       int tabIx = (int)tableIx;
4729       if (metaDataTables[tabIx] == null) {
4730         metaDataTables[tabIx] = new ArrayList();
4731         valid |= ((ulong)0x1 << tabIx);
4732         // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
4733         numTables++;
4734       }
4735       return metaDataTables[tabIx];
4736     }
4737  
4738     internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
4739       if (elem.Row > 0) {
4740         // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
4741         return;
4742       }
4743       // updates Row field of the element
4744       // Console.WriteLine("Adding element to table " + (uint)tableIx);
4745       ArrayList table = GetTable(tableIx);
4746       elem.Row = (uint)table.Count + 1;
4747       table.Add(elem);
4748     }
4749
4750     internal uint TableIndex(MDTable tableIx) {
4751       if (metaDataTables[(int)tableIx] == null) return 1;
4752       return (uint)metaDataTables[(int)tableIx].Count+1;
4753     }
4754
4755     internal uint AddCode(CILInstructions byteCode) {
4756       byteCodes.Add(byteCode);
4757       uint offset = codeSize + codeStart;
4758       codeSize += byteCode.GetCodeSize();
4759       return offset;
4760     }
4761
4762     internal void SetEntryPoint(MetaDataElement ep) {
4763       entryPoint = ep;
4764     }
4765
4766     internal uint AddResource(byte[] resBytes) {
4767       if (resources == null) resources = new ArrayList ();
4768       resources.Add (resBytes);
4769       uint offset = resourcesSize;
4770       resourcesSize += (uint)resBytes.Length + 4;
4771       return offset;
4772     }
4773
4774     internal void AddData(DataConstant cVal) {
4775       file.AddInitData(cVal);
4776     }
4777
4778                 internal static void CompressNum(uint val, MemoryStream sig) {
4779                         if (val < 0x7F) {
4780                                 sig.WriteByte((byte)val);
4781                         } else if (val < 0x3FFF) {
4782                                 byte b1 = (byte)((val >> 8) | 0x80);
4783                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);
4784                                 sig.WriteByte(b1);
4785                                 sig.WriteByte(b2);
4786                         } else {
4787                                 byte b1 = (byte)((val >> 24) | 0xC0);
4788                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
4789                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
4790                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);
4791                                 sig.WriteByte(b1);
4792                                 sig.WriteByte(b2);
4793                                 sig.WriteByte(b3);
4794                                 sig.WriteByte(b4);
4795                         }
4796                 }
4797
4798     internal uint CodeSize() {
4799       return codeSize + byteCodePadding;
4800     }
4801
4802     internal uint GetResourcesSize() 
4803     { 
4804         return resourcesSize; 
4805     }
4806
4807     internal uint StringsIndexSize() {
4808       if (largeStrings) return 4;
4809       return 2;
4810     }
4811
4812     internal uint GUIDIndexSize() {
4813       if (largeGUID) return 4;
4814       return 2;
4815     }
4816
4817     internal uint USIndexSize() {
4818       if (largeUS) return 4;
4819       return 2;
4820     }
4821
4822     internal uint BlobIndexSize() {
4823       if (largeBlob) return 4;
4824       return 2;
4825     }
4826
4827     internal uint CodedIndexSize(CIx code) {
4828       if (lgeCIx[(uint)code]) return 4;
4829       return 2;
4830     }
4831
4832     internal uint TableIndexSize(MDTable tabIx) {
4833       if (largeIx[(uint)tabIx]) return 4;
4834       return 2;
4835     }
4836     
4837     private void SetIndexSizes() {
4838       for (int i=0; i < numMetaDataTables; i++) {
4839           if (metaDataTables[i] == null)
4840                   continue;
4841
4842           uint count = (uint)metaDataTables[i].Count;
4843           if (count > maxSmlIxSize)
4844                   largeIx[i] = true;
4845
4846             MDTable tabIx = (MDTable)i;
4847             if (count > max5BitSmlIx) {
4848               lgeCIx[(int)CIx.HasCustomAttr] = true;
4849             }
4850             if (count > max3BitSmlIx) {
4851               if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field)) 
4852                 lgeCIx[(int)CIx.CustomAttributeType] = true;
4853               if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) 
4854                 lgeCIx[(int)CIx.MemberRefParent] = true;
4855             }
4856             if (count > max2BitSmlIx) {
4857               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property)) 
4858                 lgeCIx[(int)CIx.HasConst] = true;
4859               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
4860                 lgeCIx[(int)CIx.TypeDefOrRef] = true;
4861               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
4862                 lgeCIx[(int)CIx.HasDeclSecurity] = true;
4863               if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
4864                 lgeCIx[(int)CIx.Implementation] = true;
4865               if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
4866                 lgeCIx[(int)CIx.ResolutionScope] = true;
4867             }
4868             if (count > max1BitSmlIx) {
4869               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param)) 
4870                 lgeCIx[(int)CIx.HasFieldMarshal] = true;
4871               if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property)) 
4872                 lgeCIx[(int)CIx.HasSemantics] = true;
4873               if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) 
4874                 lgeCIx[(int)CIx.MethodDefOrRef] = true;
4875               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method)) 
4876                 lgeCIx[(int)CIx.MemberForwarded] = true; 
4877               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method)) 
4878                 lgeCIx[(int)CIx.TypeOrMethodDef] = true; 
4879             }
4880       }
4881     }
4882
4883     private void SetStreamOffsets() {
4884       uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
4885       for (int i=1; i < numStreams; i++) {
4886         sizeOfHeaders += streams[i].headerSize();
4887       }
4888       metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
4889       tildeStart = metaDataSize;
4890       metaDataSize += tildeTide + tildePadding;
4891       for (int i=1; i < numStreams; i++) {
4892         streams[i].Start = metaDataSize;
4893         metaDataSize += streams[i].Size();
4894         streams[i].WriteDetails();
4895       }
4896     }
4897
4898     internal void CalcTildeStreamSize() {
4899 CalcHeapSizes ();
4900       //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
4901       tildeTide = TildeHeaderSize;
4902       tildeTide += 4 * numTables;
4903       //Console.WriteLine("Tilde header + sizes = " + tildeTide);
4904       for (int i=0; i < numMetaDataTables; i++) {
4905         if (metaDataTables[i] != null) {
4906           ArrayList table = metaDataTables[i];
4907           // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
4908           tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
4909           // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
4910           // Console.WriteLine("tildeTide = " + tildeTide);
4911         }
4912       }
4913       if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
4914       //Console.WriteLine("tildePadding = " + tildePadding);
4915     }
4916
4917     internal void WriteTildeStream(FileImage output) {
4918       long startTilde = output.Seek(0,SeekOrigin.Current);
4919                         output.Write((uint)0); // Reserved
4920                         output.Write((byte)1); // MajorVersion
4921                         output.Write((byte)0); // MinorVersion
4922                         output.Write(heapSizes);
4923                         output.Write((byte)1); // Reserved
4924                         output.Write(valid);
4925                         output.Write(sorted);
4926                         for (int i=0; i < numMetaDataTables; i++) {
4927                                 if (metaDataTables[i] != null) {
4928                                         uint count = (uint)metaDataTables[i].Count;
4929                                         output.Write(count);
4930                                 }
4931                         }
4932       long tabStart = output.Seek(0,SeekOrigin.Current);
4933       // Console.WriteLine("Starting metaData tables at " + tabStart);
4934                         for (int i=0; i < numMetaDataTables; i++) {
4935                                 if (metaDataTables[i] != null) {
4936           // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
4937           ArrayList table = metaDataTables[i];
4938                                         for (int j=0; j < table.Count; j++) {
4939              ((MetaDataElement)table[j]).Write(output);
4940                                         }
4941                                 }
4942                         }
4943       // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
4944       for (int i=0; i < tildePadding; i++) output.Write((byte)0);
4945                 }
4946
4947     private void BuildTable(ArrayList table) {
4948       if (table == null) return;
4949       for (int j=0; j < table.Count; j++) {
4950         ((MetaDataElement)table[j]).BuildTables(this);
4951       }
4952     }
4953
4954     private void SortTable (ArrayList mTable) {
4955       if (mTable == null) return;
4956       mTable.Sort();
4957       for (int i=0; i < mTable.Count; i++) {
4958         ((MetaDataElement)mTable[i]).Row = (uint)i+1;
4959       }
4960     }
4961
4962     internal void BuildMetaData(uint codeStartOffset) {
4963       codeStart = codeStartOffset;
4964       BuildTable(metaDataTables[(int)MDTable.TypeDef]);
4965       BuildTable(metaDataTables[(int)MDTable.MemberRef]);
4966       BuildTable(metaDataTables[(int)MDTable.GenericParam]);
4967       BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
4968       BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
4969       BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
4970
4971       if (cattr_list != null) {
4972               foreach (CustomAttribute cattr in cattr_list)
4973                       cattr.BuildTables (this);
4974       }
4975
4976 /*      for (int i=0; i < metaDataTables.Length; i++) {
4977         ArrayList table = metaDataTables[i];
4978         if (table != null) {
4979           for (int j=0; j < table.Count; j++) {
4980             ((MetaDataElement)table[j]).BuildTables(this);
4981           }
4982         }
4983       }
4984       */
4985
4986                         SetIndexSizes();
4987                         for (int i=1; i < numStreams; i++) {
4988                                 streams[i].EndStream();
4989                         }
4990                         CalcTildeStreamSize();
4991                         SetStreamOffsets();
4992       byteCodePadding = NumToAlign(codeSize,4);
4993       if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
4994       
4995       // Check ordering of specific tables
4996       // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
4997       // ImplMap, GenericParam
4998       // Need to load GenericParamConstraint AFTER GenericParam table in correct order
4999       // The tables:
5000       //   InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5001       // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5002       
5003       SortTable(metaDataTables[(int)MDTable.Constant]);
5004       SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5005       SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5006       SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5007       SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5008       SortTable(metaDataTables[(int)MDTable.ImplMap]);
5009       if (metaDataTables[(int)MDTable.GenericParam] != null) {
5010         SortTable(metaDataTables[(int)MDTable.GenericParam]);
5011         // Now add GenericParamConstraints
5012         /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5013           ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5014         }*/
5015       }
5016       SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5017       SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5018
5019     }
5020
5021     internal void WriteByteCodes(FileImage output) {
5022       for (int i=0; i < byteCodes.Count; i++) {
5023         ((CILInstructions)byteCodes[i]).Write(output);
5024       }
5025       for (int i=0; i < byteCodePadding; i++) {
5026         output.Write((byte)0);
5027       }
5028     }
5029
5030     internal void WriteResources (FileImage output) {
5031       if (resources == null) return;
5032       for (int i = 0; i < resources.Count; i ++) {
5033         byte [] resBytes = (byte []) resources [i];
5034         output.Write ((uint) resBytes.Length);
5035         output.Write (resBytes);
5036       } 
5037     }
5038
5039     internal void WriteMetaData(FileImage output) {
5040                         this.output = output;
5041       mdStart = output.Seek(0,SeekOrigin.Current);
5042       // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5043       output.Write(MetaDataSignature);
5044       output.Write((short)1);  // Major Version
5045       output.Write((short)1);  // Minor Version  ECMA = 0, PEFiles = 1
5046       output.Write(0);         // Reserved
5047       output.Write(version.Length);
5048       output.Write(version.ToCharArray());   // version string is already zero padded
5049       output.Write((short)0);
5050       output.Write((ushort)numStreams);
5051       // write tilde header
5052       output.Write(tildeStart);
5053       output.Write(tildeTide + tildePadding);
5054       output.Write(tildeName);
5055       for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5056       // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5057       WriteTildeStream(output);
5058       for (int i=1; i < numStreams; i++) streams[i].Write(output);
5059       // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5060     }
5061
5062                 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5063                 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5064                 internal bool LargeUSIndex() { return us.LargeIx(); }
5065                 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5066
5067     internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5068
5069
5070                 private uint NumToAlign(uint val, uint alignVal) {
5071                         if ((val % alignVal) == 0) return 0;
5072                         return alignVal - (val % alignVal);
5073                 }
5074
5075     internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
5076       uint ix = 0;
5077       if (elem != null) { 
5078         ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5079         // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5080       //} else {
5081         // Console.WriteLine("elem for coded index is null");
5082       }
5083       if (lgeCIx[(uint)code]) 
5084         output.Write(ix);
5085       else
5086         output.Write((ushort)ix);
5087     }
5088
5089         }
5090     /// <summary>
5091     /// Error for invalid PE file
5092     /// </summary>
5093     public class PEFileException : System.Exception {
5094       public PEFileException(string msg) : base("Error in PE File:  " + msg) { }
5095     }
5096
5097   /**************************************************************************/  
5098         /// <summary>
5099         /// Base class for all Meta Data table elements
5100         /// </summary>
5101
5102   public abstract class MetaDataElement: IComparable
5103         {
5104
5105     protected ArrayList customAttributes;
5106     private uint row = 0;
5107     protected bool done = false;
5108                 protected MDTable tabIx;
5109     protected bool sortTable = false;
5110
5111     internal MetaDataElement() { }
5112
5113     public uint Row {
5114       get {
5115         return row;
5116       }
5117       set {
5118         if (row == 0) row = value;
5119       }
5120     }
5121
5122     internal virtual uint GetCodedIx(CIx code) { return 0; }
5123
5124     /// <summary>
5125     /// Add a custom attribute to this item
5126     /// </summary>
5127     /// <param name="ctorMeth">the constructor method for this attribute</param>
5128     /// <param name="val">the byte value of the parameters</param>
5129     public void AddCustomAttribute(Method ctorMeth, byte[] val) {
5130       if (customAttributes == null) {
5131         customAttributes = new ArrayList();
5132       } 
5133       customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
5134     }
5135
5136     /// <summary>
5137     /// Add a custom attribute to this item
5138     /// </summary>
5139     /// <param name="ctorMeth">the constructor method for this attribute</param>
5140     /// <param name="val">the constant values of the parameters</param>
5141     public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
5142       if (customAttributes == null) {
5143         customAttributes = new ArrayList();
5144       } 
5145 //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
5146     }
5147
5148     internal uint Token() {
5149       return (((uint)tabIx << 24) | row);
5150     }
5151
5152     internal virtual void BuildTables(MetaData md) {
5153       done = true;
5154     }
5155
5156     internal virtual uint Size(MetaData md) { 
5157       return 0;
5158     }
5159
5160     internal virtual void Write(FileImage output) {   }
5161
5162     internal virtual uint SortKey() 
5163     { 
5164       throw new PEFileException("Trying to sort table of " + this);
5165       //return 0; 
5166     }
5167
5168     internal virtual uint SortKey2()
5169     {
5170       return 0;
5171     }
5172
5173
5174     public int CompareTo(object obj) 
5175     {
5176       uint otherKey = ((MetaDataElement)obj).SortKey();
5177       uint thisKey = SortKey();
5178
5179       if (thisKey == otherKey) 
5180       {
5181         otherKey = ((MetaDataElement)obj).SortKey2();
5182         thisKey = SortKey2();
5183         if (thisKey == otherKey)
5184           return 0;
5185         if (thisKey < otherKey)
5186           return -1;
5187         return 1;
5188       }
5189       if (thisKey < otherKey) return -1;
5190
5191       return 1;
5192     }
5193
5194         }
5195   /**************************************************************************/  
5196         /// <summary>
5197         /// Stream in the Meta Data  (#Strings, #US, #Blob and #GUID)
5198         /// </summary>
5199
5200   internal class MetaDataStream : BinaryWriter 
5201         {
5202                 private static readonly uint StreamHeaderSize = 8;
5203                 private static uint maxSmlIxSize = 0xFFFF;
5204                 
5205     private uint start = 0; 
5206     uint size = 0, tide = 1;
5207     bool largeIx = false;
5208     uint sizeOfHeader;
5209     char[] name;
5210     Hashtable htable = new Hashtable();
5211     Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5212
5213     internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
5214       if (addInitByte) { Write((byte)0); size = 1; }
5215       this.name = name;
5216       sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5217     }
5218
5219     internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
5220       if (addInitByte) { Write((byte)0); size = 1; }
5221       this.name = name;
5222       sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5223                 }
5224
5225     public uint Start {
5226       get {
5227         return start;
5228       }
5229       set {
5230         start = value;
5231       }
5232     }
5233   
5234     internal uint headerSize() {
5235       // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5236       return sizeOfHeader;
5237     }
5238
5239     internal void SetSize(uint siz) {
5240       size = siz;
5241     }
5242
5243     internal uint Size() {
5244       return size;
5245     }
5246
5247     internal bool LargeIx() {
5248       return largeIx;
5249     }
5250
5251     internal void WriteDetails() {
5252       // Console.WriteLine(name + " - size = " + size);
5253     }
5254
5255                 internal uint Add(string str, bool prependSize) {
5256       Object val = htable[str];
5257       uint index = 0;
5258       if (val == null) { 
5259         index = size;
5260         htable[str] = index;
5261         char[] arr = str.ToCharArray();
5262         if (prependSize) CompressNum((uint)arr.Length*2+1);
5263         Write(arr);
5264         Write((byte)0);
5265         size = (uint)Seek(0,SeekOrigin.Current);
5266       } else {
5267         index = (uint)val;
5268       }
5269                         return index;
5270                 }
5271                 internal uint Add (byte[] str, bool prependSize) {
5272                         Object val = btable [str];
5273                         uint index = 0;
5274                         if (val == null) {
5275                                 index = size;
5276                                 btable [str] = index;
5277                                 if (prependSize) CompressNum ((uint) str.Length);
5278                                 Write (str);
5279                                 size = (uint) Seek (0, SeekOrigin.Current);
5280                         } else {
5281                                 index = (uint) val;
5282                         }
5283                         return index;
5284                 }
5285
5286                     
5287                 internal uint Add(Guid guid, bool prependSize) {
5288                         byte [] b = guid.ToByteArray ();
5289                         if (prependSize) CompressNum ((uint) b.Length);
5290                         Write(guid.ToByteArray());
5291                         size =(uint)Seek(0,SeekOrigin.Current);
5292                         return tide++;
5293                 }
5294
5295                 internal uint Add(byte[] blob) {
5296                         uint ix = size;
5297                         CompressNum((uint)blob.Length);
5298                         Write(blob);
5299                         size = (uint)Seek(0,SeekOrigin.Current);
5300                         return ix;
5301                 }
5302
5303     internal uint Add(byte val, bool prependSize) {
5304       uint ix = size;
5305       if (prependSize) CompressNum (1);
5306       Write(val);
5307       size = (uint)Seek(0,SeekOrigin.Current);
5308       return ix;
5309     }
5310
5311     internal uint Add(sbyte val, bool prependSize) {
5312       uint ix = size;
5313       if (prependSize) CompressNum (1);
5314       Write(val);
5315       size = (uint)Seek(0,SeekOrigin.Current);
5316       return ix;
5317     }
5318
5319     internal uint Add(ushort val, bool prependSize) {
5320       uint ix = size;
5321       if (prependSize) CompressNum (2);
5322       Write(val);
5323       size = (uint)Seek(0,SeekOrigin.Current);
5324       return ix;
5325     }
5326
5327     internal uint Add(short val, bool prependSize) {
5328       uint ix = size;
5329       if (prependSize) CompressNum (2);
5330       Write(val);
5331       size = (uint)Seek(0,SeekOrigin.Current);
5332       return ix;
5333     }
5334
5335     internal uint Add(uint val, bool prependSize) {
5336       uint ix = size;
5337       if (prependSize) CompressNum (4);
5338       Write(val);
5339       size = (uint)Seek(0,SeekOrigin.Current);
5340       return ix;
5341     }
5342
5343     internal uint Add(int val, bool prependSize) {
5344       uint ix = size;
5345       if (prependSize) CompressNum (4);
5346       Write (val);
5347       size = (uint)Seek(0,SeekOrigin.Current);
5348       return ix;
5349     }
5350
5351     internal uint Add(ulong val, bool prependSize) {
5352       uint ix = size;
5353       if (prependSize) CompressNum (8);
5354       Write(val);
5355       size = (uint)Seek(0,SeekOrigin.Current);
5356       return ix;
5357     }
5358
5359     internal uint Add(long val, bool prependSize) {
5360       uint ix = size;
5361       if (prependSize) CompressNum (8);
5362       Write(val);
5363       size = (uint)Seek(0,SeekOrigin.Current);
5364       return ix;
5365     }
5366
5367     internal uint Add(float val, bool prependSize) {
5368       uint ix = size;
5369       if (prependSize) CompressNum (4);
5370       Write(val);
5371       size = (uint)Seek(0,SeekOrigin.Current);
5372       return ix;
5373     }
5374
5375     internal uint Add(double val, bool prependSize) {
5376       uint ix = size;
5377       if (prependSize) CompressNum (8);
5378       Write(val);
5379       size = (uint)Seek(0,SeekOrigin.Current);
5380       return ix;
5381     }
5382
5383                 private void CompressNum(uint val) {
5384       if (val < 0x7F) {
5385         Write((byte)val);
5386       } else if (val < 0x3FFF) {
5387         byte b1 = (byte)((val >> 8) | 0x80);
5388         byte b2 = (byte)(val & FileImage.iByteMask[0]);
5389         Write(b1);
5390         Write(b2);
5391       } else {
5392         byte b1 = (byte)((val >> 24) | 0xC0);
5393         byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5394         byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5395         byte b4 = (byte)(val & FileImage.iByteMask[0]);
5396         Write(b1);
5397         Write(b2);
5398         Write(b3);
5399         Write(b4);
5400       }
5401     }
5402
5403     private void QuadAlign() {
5404       if ((size % 4) != 0) {
5405         uint pad = 4 - (size % 4);
5406         size += pad;
5407         for (int i=0; i < pad; i++) {
5408           Write((byte)0);
5409         }
5410       }
5411     }
5412
5413                 internal void EndStream() {
5414                         QuadAlign();
5415                         if (size > maxSmlIxSize) {
5416                                 largeIx = true;
5417                         }
5418                 }
5419
5420     internal void WriteHeader(BinaryWriter output) {
5421       output.Write(start);
5422       output.Write(size);
5423       output.Write(name);
5424     }
5425
5426                 internal virtual void Write(BinaryWriter output) {
5427        // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5428       MemoryStream str = (MemoryStream)BaseStream;
5429                         output.Write(str.ToArray());
5430                 }
5431
5432         }
5433   /**************************************************************************/  
5434         /// <summary>
5435         /// Base class for Method Descriptors
5436         /// </summary>
5437
5438   public abstract class Method : Member
5439         {
5440     protected CallConv callConv = CallConv.Default;
5441     protected Type retType;
5442
5443     internal Method(string methName, Type rType) : base(methName)
5444                 {
5445       retType = rType;
5446                 }
5447
5448     /// <summary>
5449     /// Add calling conventions to this method descriptor
5450     /// </summary>
5451     /// <param name="cconv"></param>
5452     public void AddCallConv(CallConv cconv) {
5453       callConv |= cconv;
5454     }
5455
5456                 internal abstract void TypeSig(MemoryStream sig);
5457
5458     internal uint GetSigIx(MetaData md) {
5459       MemoryStream sig = new MemoryStream();
5460                         TypeSig(sig);
5461       return md.AddToBlobHeap(sig.ToArray());
5462     }
5463
5464     internal Type GetRetType() {
5465       return retType;
5466     }
5467
5468         }
5469   /**************************************************************************/  
5470         /// <summary>
5471         /// Descriptor for a method defined in THIS assembly/module
5472         /// IL     .method
5473         /// </summary>
5474
5475   public class MethodDef : Method
5476         {
5477     private static readonly ushort PInvokeImpl = 0x2000;
5478     //private static readonly uint UnmanagedExport = 0x0008;
5479    // private static readonly byte LocalSigByte = 0x7;
5480     uint parIx = 0, textOffset = 0;
5481
5482     MetaData metaData;
5483     CILInstructions code;
5484     ArrayList securityActions = new ArrayList();
5485                 Param[] parList;
5486     Local[] locals;
5487     bool initLocals;
5488     ushort methFlags = 0, implFlags = 0;
5489     int maxStack = 0, numPars = 0;
5490     bool entryPoint = false;
5491     LocalSig localSig;
5492                 ArrayList varArgSigList;
5493     ImplMap pinvokeImpl;
5494
5495
5496                 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
5497       metaData = md;
5498                         parList = pars;
5499                         if (parList != null) numPars = parList.Length;
5500       tabIx = MDTable.Method;
5501                 }
5502
5503     internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
5504       metaData = md;
5505                         parList = pars;
5506                         if (parList != null) numPars = parList.Length;
5507       // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
5508                         methFlags = (ushort)mAttrSet;
5509       implFlags = (ushort)iAttrSet;
5510       tabIx = MDTable.Method;
5511     }
5512
5513                 internal Param[] GetPars() {
5514                         return parList;
5515                 }
5516
5517     /// <summary>
5518     /// Add some attributes to this method descriptor
5519     /// </summary>
5520     /// <param name="ma">the attributes to be added</param>
5521     public void AddMethAttribute(MethAttr ma) {
5522       methFlags |= (ushort)ma;
5523     }
5524
5525     /// <summary>
5526     /// Add some implementation attributes to this method descriptor
5527     /// </summary>
5528     /// <param name="ia">the attributes to be added</param>
5529     public void AddImplAttribute(ImplAttr ia) {
5530       implFlags |= (ushort)ia;
5531     }
5532
5533     public void AddPInvokeInfo(ModuleRef scope, string methName,
5534                                PInvokeAttr callAttr) {
5535       pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
5536       methFlags |= PInvokeImpl;
5537     }
5538
5539     /// <summary>
5540     ///  Add a named generic type parameter
5541     /// </summary>
5542     public GenericParameter AddGenericParameter (short index, string name) {
5543             GenericParameter gp = new GenericParameter (this, metaData, index, name);
5544             metaData.AddToTable (MDTable.GenericParam, gp);
5545             return gp;
5546     }
5547
5548     /// <summary>
5549     /// Set the maximum stack height for this method
5550     /// </summary>
5551     /// <param name="maxStack">the maximum height of the stack</param>
5552     public void SetMaxStack(int maxStack) {
5553       this.maxStack = maxStack; 
5554     }
5555
5556     /// <summary>
5557     /// Add local variables to this method
5558     /// </summary>
5559     /// <param name="locals">the locals to be added</param>
5560     /// <param name="initLocals">are locals initialised to default values</param>
5561     public void AddLocals(Local[] locals, bool initLocals) {
5562       this.locals = locals;
5563       this.initLocals = initLocals;
5564     }
5565
5566     /// <summary>
5567     /// Mark this method as having an entry point
5568     /// </summary>
5569     public void DeclareEntryPoint() {
5570       entryPoint = true;
5571     }
5572
5573     /// <summary>
5574     /// Create a code buffer for this method to add the IL instructions to
5575     /// </summary>
5576     /// <returns>a buffer for this method's IL instructions</returns>
5577     public CILInstructions CreateCodeBuffer() {
5578       code = new CILInstructions(metaData);
5579       return code;
5580     }
5581
5582     /// <summary>
5583     /// Make a method reference descriptor for this method to be used 
5584     /// as a callsite signature for this vararg method
5585     /// </summary>
5586     /// <param name="optPars">the optional pars for the vararg method call</param>
5587     /// <returns></returns>
5588     public MethodRef MakeVarArgSignature(Type[] optPars) {
5589       Type[] pars = new Type[numPars];
5590       MethodRef varArgSig;
5591       for (int i=0; i < numPars; i++) {
5592         pars[i] = parList[i].GetParType();
5593       }
5594       varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
5595
5596       if (varArgSigList == null)
5597               varArgSigList = new ArrayList ();
5598       varArgSigList.Add (varArgSig);
5599       return varArgSig;
5600     }
5601
5602                 internal sealed override void TypeSig(MemoryStream sig) {
5603                         sig.WriteByte((byte)callConv);
5604                         MetaData.CompressNum((uint)numPars,sig);
5605                         retType.TypeSig(sig);
5606                         for (ushort i=0; i < numPars; i++) {
5607                                 parList[i].seqNo = (ushort)(i+1);
5608                                 parList[i].TypeSig(sig);
5609                         }
5610                 }
5611
5612     internal sealed override void BuildTables(MetaData md) {
5613       if (done) return;
5614       if (pinvokeImpl != null) {
5615         md.AddToTable(MDTable.ImplMap,pinvokeImpl);
5616         pinvokeImpl.BuildTables(md);
5617       }
5618       if (entryPoint) md.SetEntryPoint(this);
5619       uint locToken = 0;
5620       if (locals != null) {
5621         localSig = new LocalSig(locals);
5622         md.AddToTable(MDTable.StandAloneSig,localSig);
5623         localSig.BuildTables(md);
5624         locToken = localSig.Token();
5625       }
5626                         if (code != null) {
5627                                 code.CheckCode(locToken,initLocals,maxStack);
5628                                 textOffset = md.AddCode(code);
5629                         }
5630       nameIx = md.AddToStringsHeap(name);
5631       sigIx = GetSigIx(md);
5632       parIx = md.TableIndex(MDTable.Param);
5633                         for (int i=0; i < numPars; i++) {
5634                                 md.AddToTable(MDTable.Param,parList[i]);
5635                                 parList[i].BuildTables(md);
5636                         }
5637       if (varArgSigList != null) {
5638               foreach (MethodRef varArgSig in varArgSigList) {
5639         md.AddToTable(MDTable.MemberRef,varArgSig);
5640         varArgSig.BuildTables(md);
5641       }
5642       }
5643       // Console.WriteLine("method has " + numPars + " parameters");
5644       done = true;
5645     }
5646
5647     internal sealed override uint Size(MetaData md) {
5648       return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
5649     }
5650
5651     internal sealed override void Write(FileImage output) {
5652       if (ZeroRva ()) output.Write(0);
5653       else output.WriteCodeRVA(textOffset);
5654       output.Write(implFlags);
5655       output.Write(methFlags);
5656       output.StringsIndex(nameIx);
5657       output.BlobIndex(sigIx);
5658       output.WriteIndex(MDTable.Param,parIx);
5659     }
5660
5661     internal bool ZeroRva () {
5662         return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5663                         ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5664                         ((implFlags & (ushort)ImplAttr.InternalCall) != 0) || 
5665                         (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5666     }
5667
5668     internal sealed override uint GetCodedIx(CIx code) {
5669                         switch (code) {
5670                                 case (CIx.HasCustomAttr) : return 0; 
5671                                 case (CIx.HasDeclSecurity) : return 1; 
5672                                 case (CIx.MemberRefParent) : return 3; 
5673                                 case (CIx.MethodDefOrRef) : return 0; 
5674                                 case (CIx.MemberForwarded) : return 1; 
5675                                 case (CIx.CustomAttributeType) : return 2; 
5676                                 case (CIx.TypeOrMethodDef) : return 1; 
5677                         }
5678                         return 0;
5679     }
5680
5681         }
5682   /**************************************************************************/  
5683         /// <summary>
5684         /// Descriptor for an overriding method (.override)
5685         /// </summary>
5686   public class MethodImpl : MetaDataElement
5687         {
5688     ClassDef parent;
5689     Method header, body;
5690
5691                 internal MethodImpl(ClassDef par, Method decl, Method bod)      {
5692       parent = par;
5693       header = decl;
5694       body = bod;
5695                         tabIx = MDTable.MethodImpl;
5696                 }
5697
5698     internal sealed override uint Size(MetaData md) {
5699       return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
5700     }
5701
5702     internal sealed override void Write(FileImage output) {
5703       output.WriteIndex(MDTable.TypeDef,parent.Row);
5704       output.WriteCodedIndex(CIx.MethodDefOrRef,body);
5705       output.WriteCodedIndex(CIx.MethodDefOrRef,header);
5706     }
5707
5708         }
5709   /**************************************************************************/  
5710         /// <summary>
5711         /// Descriptor for a method defined in another assembly/module
5712         /// </summary>
5713   public class MethodRef : Method
5714   {
5715     private static readonly byte Sentinel = 0x41;
5716                 Type[] parList, optParList;
5717     MetaDataElement parent;
5718     uint numPars = 0, numOptPars = 0;
5719
5720     internal MethodRef(MetaDataElement paren, string name, Type retType,
5721         Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
5722       parent = paren;
5723       parList = pars;
5724       if (parList != null) numPars = (uint)parList.Length;
5725       if (varArgMeth) {
5726         optParList = optPars;
5727         if (optParList != null) numOptPars = (uint)optParList.Length;
5728         callConv = CallConv.Vararg;
5729       }
5730     }
5731
5732                 internal sealed override void TypeSig(MemoryStream sig) {
5733                         sig.WriteByte((byte)callConv);
5734                         MetaData.CompressNum(numPars+numOptPars,sig);
5735                         retType.TypeSig(sig);
5736                         for (int i=0; i < numPars; i++) {
5737                                 parList[i].TypeSig(sig);
5738                         }
5739       if (numOptPars > 0) {
5740         sig.WriteByte(Sentinel);
5741         for (int i=0; i < numOptPars; i++) {
5742           optParList[i].TypeSig(sig);
5743         }
5744       }
5745                 }
5746
5747     internal sealed override void BuildTables(MetaData md) {
5748       if (done) return;
5749       nameIx = md.AddToStringsHeap(name);
5750       sigIx = GetSigIx(md);
5751       done = true;
5752     }
5753
5754     internal sealed override uint Size(MetaData md) {
5755       return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
5756     }
5757
5758     internal sealed override void Write(FileImage output) {
5759       output.WriteCodedIndex(CIx.MemberRefParent,parent);
5760       output.StringsIndex(nameIx);
5761       output.BlobIndex(sigIx);
5762     }
5763
5764     internal sealed override uint GetCodedIx(CIx code) {
5765       switch (code) {
5766         case (CIx.HasCustomAttr) : return 6; 
5767         case (CIx.MethodDefOrRef) : return 1; 
5768         case (CIx.CustomAttributeType) : return 3; 
5769       }
5770                         return 0;
5771     }
5772
5773         }
5774   /**************************************************************************/  
5775         /// <summary>
5776         /// Descriptor for Property and Event methods
5777         /// </summary>
5778   public class MethodSemantics : MetaDataElement {
5779
5780     Feature.MethodType type;
5781     MethodDef meth;
5782     Feature eventOrProp;
5783
5784     internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
5785       type = mType;
5786       meth = method;
5787       eventOrProp = feature;
5788                         tabIx = MDTable.MethodSemantics;
5789                 }
5790
5791     internal override uint SortKey() {
5792       return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
5793               | eventOrProp.GetCodedIx (CIx.HasSemantics);
5794     }
5795
5796     internal sealed override uint Size(MetaData md) {
5797       return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
5798     }
5799
5800     internal sealed override void Write(FileImage output) {
5801       output.Write((ushort)type);
5802       output.WriteIndex(MDTable.Method,meth.Row);
5803       output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
5804     }
5805
5806         }
5807   /**************************************************************************/  
5808         /// <summary>
5809         /// Descriptor for a FunctionPointer type
5810         /// </summary>
5811         /// 
5812         public class MethPtrType : Type
5813         {
5814                 bool varArgMeth;
5815                 Type retType;
5816                 Type [] parList;
5817                 Type [] optParList;
5818                 CallConv callConv;
5819                 uint numPars;
5820                 uint numOptPars;
5821                 uint sigIx = 0;
5822
5823     /// <summary>
5824     /// Create a new function pointer type
5825     /// </summary>
5826     /// <param name="meth">the function to be referenced</param>
5827     public MethPtrType (CallConv callconv, Type retType, Type[] pars,
5828                     bool varArgMeth, Type[] optPars) : base(0x1B) {
5829       this.retType = retType;
5830       callConv = callconv;
5831       parList = pars;
5832       this.varArgMeth = varArgMeth;
5833       if (parList != null) numPars = (uint)parList.Length;
5834       if (varArgMeth) {
5835         optParList = optPars;
5836         if (optParList != null) numOptPars = (uint)optParList.Length;
5837         callConv |= CallConv.Vararg;
5838       }
5839       tabIx = MDTable.TypeSpec;
5840     }
5841   
5842     internal sealed override void TypeSig(MemoryStream sig) {
5843       sig.WriteByte(typeIndex);
5844       // Bootlegged from method ref
5845       sig.WriteByte((byte)callConv);
5846       MetaData.CompressNum (numPars + numOptPars, sig);
5847       retType.TypeSig (sig);
5848       for (int i=0; i < numPars; i++) {
5849               parList[i].TypeSig (sig);
5850       }
5851       if (varArgMeth) {
5852               sig.WriteByte (0x41); // Write the sentinel
5853         for (int i=0; i < numOptPars; i++) {
5854           optParList[i].TypeSig (sig);
5855         }
5856       }
5857     }
5858
5859     internal sealed override void BuildTables(MetaData md) {
5860       if (done) return;
5861       MemoryStream sig = new MemoryStream();
5862       TypeSig(sig);
5863       sigIx = md.AddToBlobHeap(sig.ToArray());
5864       done = true;
5865     }
5866
5867                 internal sealed override uint Size(MetaData md) {
5868                         return md.BlobIndexSize();
5869                 }
5870
5871                 internal sealed override void Write(FileImage output) {
5872                         output.BlobIndex(sigIx);
5873                 }
5874
5875                 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
5876
5877         }
5878   /**************************************************************************/  
5879         /// <summary>
5880         /// Descriptor for THIS module
5881         /// </summary>
5882   public class Module : ResolutionScope
5883         {
5884     Guid mvid;
5885     uint mvidIx = 0;
5886
5887                 internal Module(string name, MetaData md) : base(name,md)       {
5888       mvid = Guid.NewGuid();
5889       mvidIx = md.AddToGUIDHeap(mvid);
5890       tabIx = MDTable.Module;
5891     }
5892
5893     public Guid Guid {
5894       get { return mvid; }
5895     }
5896
5897     internal sealed override uint Size(MetaData md) {
5898       return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
5899     }
5900
5901     internal sealed override void Write(FileImage output) {
5902       output.Write((short)0);
5903       output.StringsIndex(nameIx);
5904       output.GUIDIndex(mvidIx);
5905       output.GUIDIndex(0);
5906       output.GUIDIndex(0);
5907     }
5908
5909     internal sealed override uint GetCodedIx(CIx code) {
5910                         switch (code) {
5911                                 case (CIx.HasCustomAttr) : return 7; 
5912                                 case (CIx.ResolutionScope) : return 0;
5913                         }
5914                         return 0;
5915     }
5916   }
5917   /**************************************************************************/  
5918         /// <summary>
5919         /// Descriptor for another module in THIS assembly
5920         /// </summary>
5921         public class ModuleRef : ResolutionScope, IExternRef
5922         {
5923
5924                 internal ModuleRef(MetaData md, string name) : base(name,md) {
5925       tabIx = MDTable.ModuleRef;
5926                 }
5927
5928     /// <summary>
5929     /// Add a class to this external module.  This is a class declared in
5930     /// another module of THIS assembly.
5931     /// </summary>
5932     /// <param name="nsName">name space name</param>
5933     /// <param name="name">class name</param>
5934     /// <returns>a descriptor for this class in another module</returns>
5935     public ClassRef AddClass(string nsName, string name) {
5936       ClassRef aClass = new ClassRef(nsName,name,metaData);
5937       metaData.AddToTable(MDTable.TypeRef,aClass);
5938       aClass.SetParent(this);
5939       return aClass;
5940     }
5941
5942     /// <summary>
5943     /// Make a file descriptor to correspond to this module.  The file
5944     /// descriptor will have the same name as the module descriptor
5945     /// </summary>
5946     /// <param name="hashBytes">the hash of the file</param>
5947     /// <param name="hasMetaData">the file contains metadata</param>
5948     /// <param name="entryPoint">the program entry point is in this file</param>
5949     /// <returns>a descriptor for the file which contains this module</returns>
5950     public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
5951       FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
5952       metaData.AddToTable(MDTable.File,file);
5953       return file;
5954     }
5955
5956     /// <summary>
5957     /// Add a value class to this module.  This is a class declared in
5958     /// another module of THIS assembly.
5959     /// </summary>
5960     /// <param name="nsName">name space name</param>
5961     /// <param name="name">class name</param>
5962     /// <returns></returns>
5963     public ClassRef AddValueClass(string nsName, string name) {
5964       ClassRef aClass = new ClassRef(nsName,name,metaData);
5965       metaData.AddToTable(MDTable.TypeRef,aClass);
5966       aClass.SetParent(this);
5967       aClass.MakeValueClass(ValueClass.ValueType);
5968       return aClass;
5969     }
5970
5971     /// <summary>
5972     /// Add a class which is declared public in this external module of
5973     /// THIS assembly.  This class will be exported from this assembly.
5974     /// The ilasm syntax for this is .extern class
5975     /// </summary>
5976     /// <param name="attrSet">attributes of the class to be exported</param>
5977     /// <param name="nsName">name space name</param>
5978     /// <param name="name">external class name</param>
5979     /// <param name="declFile">the file where the class is declared</param>
5980     /// <param name="isValueClass">is this class a value type?</param>
5981     /// <returns>a descriptor for this external class</returns>
5982     public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName, 
5983                                          string name, FileRef declFile, 
5984                                          bool isValueClass) {
5985       ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
5986       metaData.AddToTable(MDTable.TypeRef,cRef);
5987       cRef.SetParent(this);
5988       if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
5989       return cRef;
5990     }
5991
5992     /// <summary>
5993     /// Add a "global" method in another module
5994     /// </summary>
5995     /// <param name="name">method name</param>
5996     /// <param name="retType">return type</param>
5997     /// <param name="pars">method parameter types</param>
5998     /// <returns>a descriptor for this method in anther module</returns>
5999     public MethodRef AddMethod(string name, Type retType, Type[] pars) {
6000       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
6001       metaData.AddToTable(MDTable.MemberRef,meth);
6002       return meth;
6003     }
6004
6005     /// <summary>
6006     /// Add a vararg method to this class
6007     /// </summary>
6008     /// <param name="name">method name</param>
6009     /// <param name="retType">return type</param>
6010     /// <param name="pars">parameter types</param>
6011     /// <param name="optPars">optional param types for this vararg method</param>
6012     /// <returns>a descriptor for this method</returns>
6013     public MethodRef AddVarArgMethod(string name, Type retType, 
6014       Type[] pars, Type[] optPars) {
6015       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
6016       metaData.AddToTable(MDTable.MemberRef,meth);
6017       return meth;
6018     }
6019
6020     /// <summary>
6021     /// Add a field in another module
6022     /// </summary>
6023     /// <param name="name">field name</param>
6024     /// <param name="fType">field type</param>
6025     /// <returns>a descriptor for this field in another module</returns>
6026     public FieldRef AddField(string name, Type fType) {
6027       FieldRef field = new FieldRef(this,name,fType);
6028       metaData.AddToTable(MDTable.MemberRef,field);
6029       return field;
6030     }
6031
6032     internal sealed override uint Size(MetaData md) {
6033       return md.StringsIndexSize();
6034     }
6035
6036     internal sealed override void Write(FileImage output) {
6037       output.StringsIndex(nameIx);
6038     }
6039
6040     internal sealed override uint GetCodedIx(CIx code) {
6041       switch (code) {
6042         case (CIx.HasCustomAttr) : return 12; 
6043         case (CIx.MemberRefParent) : return 2; 
6044         case (CIx.ResolutionScope) : return 1; 
6045       }
6046                         return 0;
6047     }
6048  
6049   }
6050   /**************************************************************************/  
6051         /// <summary>
6052         /// Descriptors for native types used for marshalling
6053         /// </summary>
6054   public class NativeType {
6055     public static readonly NativeType Void = new NativeType(0x01);
6056     public static readonly NativeType Boolean = new NativeType(0x02);
6057     public static readonly NativeType Int8 = new NativeType(0x03);
6058     public static readonly NativeType UInt8 = new NativeType(0x04);
6059     public static readonly NativeType Int16 = new NativeType(0x05);
6060     public static readonly NativeType UInt16 = new NativeType(0x06);
6061     public static readonly NativeType Int32 = new NativeType(0x07);
6062     public static readonly NativeType UInt32 = new NativeType(0x08);
6063     public static readonly NativeType Int64 = new NativeType(0x09);
6064     public static readonly NativeType UInt64 = new NativeType(0x0A);
6065     public static readonly NativeType Float32 = new NativeType(0x0B);
6066     public static readonly NativeType Float64 = new NativeType(0x0C);
6067     public static readonly NativeType Currency = new NativeType(0x0F);
6068     public static readonly NativeType BStr = new NativeType(0x13);
6069     public static readonly NativeType LPStr = new NativeType(0x14);
6070     public static readonly NativeType LPWStr = new NativeType(0x15);
6071     public static readonly NativeType LPTStr = new NativeType(0x16);
6072     public static readonly NativeType FixedSysString = new NativeType(0x17);
6073     public static readonly NativeType IUnknown = new NativeType(0x19);
6074     public static readonly NativeType IDispatch = new NativeType(0x1A);
6075     public static readonly NativeType Struct = new NativeType(0x1B);
6076     public static readonly NativeType Interface = new NativeType(0x1C);
6077     public static readonly NativeType Int = new NativeType(0x1F);
6078     public static readonly NativeType UInt = new NativeType(0x20);
6079     public static readonly NativeType ByValStr = new NativeType(0x22);
6080     public static readonly NativeType AnsiBStr = new NativeType(0x23);
6081     public static readonly NativeType TBstr = new NativeType(0x24);
6082     public static readonly NativeType VariantBool = new NativeType(0x25);
6083     public static readonly NativeType FuncPtr = new NativeType(0x26);
6084     public static readonly NativeType AsAny = new NativeType(0x28);
6085
6086     protected byte typeIndex;
6087
6088     internal NativeType(byte tyIx) { typeIndex = tyIx; }
6089
6090     internal byte GetTypeIndex() { return typeIndex; }
6091
6092     internal virtual byte[] ToBlob() {
6093       byte[] bytes = new byte[1];
6094       bytes[0] = GetTypeIndex();
6095       return bytes;
6096     }
6097
6098    }
6099
6100   public class NativeArray : NativeType 
6101   {
6102     NativeType elemType;
6103     uint len = 0, parNum = 0;
6104
6105     /*
6106     public NativeArray(NativeType elemType) : base(0x2A) {
6107       this.elemType = elemType;
6108     }
6109
6110     public NativeArray(NativeType elemType, int len) : base(0x2A) {
6111       this.elemType = elemType;
6112       this.len = len;
6113     }
6114 */
6115     public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
6116       this.elemType = elemType;
6117       len = (uint)numElem;
6118       parNum = (uint)parNumForLen;
6119     }
6120
6121     internal override byte[] ToBlob() {
6122       MemoryStream str = new MemoryStream();
6123       str.WriteByte(GetTypeIndex());
6124       if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
6125       else str.WriteByte(elemType.GetTypeIndex());
6126       MetaData.CompressNum(parNum,str);
6127       str.WriteByte(1);
6128       MetaData.CompressNum(len,str);
6129       return str.ToArray();
6130     }
6131
6132   }
6133
6134   public class SafeArray : NativeType 
6135   {
6136     SafeArrayType elemType;
6137
6138     public SafeArray(SafeArrayType elemType) : base(0x1D) {
6139       this.elemType = elemType;
6140     }
6141
6142     internal override byte[] ToBlob() {
6143       byte[] bytes = new byte[2];
6144       bytes[0] = GetTypeIndex();
6145       bytes[1] = (byte)elemType;
6146       return bytes;
6147     }
6148
6149   }
6150
6151   public class FixedArray : NativeType 
6152   {
6153     NativeType elemType;
6154     uint numElem;
6155
6156     public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
6157       this.elemType = elemType;
6158       numElem = (uint)numElems;
6159     }
6160
6161     internal override byte[] ToBlob() {
6162       MemoryStream str = new MemoryStream();
6163       str.WriteByte(GetTypeIndex());
6164       MetaData.CompressNum(numElem,str);
6165       if (elemType == null) str.WriteByte(0x50);  // no info (MAX)
6166       else str.WriteByte(elemType.GetTypeIndex());
6167       return str.ToArray();
6168     }
6169
6170   }
6171
6172   public class CustomMarshaller : NativeType 
6173   {
6174     string typeName;
6175     string marshallerName;
6176     string cookie;
6177
6178     public CustomMarshaller(string typeNameOrGUID, string marshallerName, 
6179                 string optCookie) : base(0x2C) {
6180       typeName = typeNameOrGUID;
6181       this.marshallerName = marshallerName;
6182       cookie = optCookie;
6183     }
6184
6185     internal override byte[] ToBlob() {
6186       MemoryStream str = new MemoryStream();
6187       BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
6188       bw.Write(GetTypeIndex());
6189       bw.Write(typeName.ToCharArray());
6190       bw.Write((byte)0);
6191       bw.Write(marshallerName.ToCharArray());
6192       bw.Write((byte)0);
6193       if (cookie != null) bw.Write(cookie.ToCharArray());
6194       bw.Write((byte)0);
6195       bw.Flush();
6196       return str.ToArray();
6197     }
6198   }
6199
6200   /**************************************************************************/  
6201         /// <summary>
6202         /// Descriptor for a parameter of a method defined in this assembly/module
6203         /// </summary>
6204   public class Param : MetaDataElement
6205         {
6206     private static readonly ushort hasDefault = 0x1000;
6207     private static readonly ushort hasFieldMarshal = 0x2000;
6208
6209     Type pType;
6210     string pName;
6211     internal ushort seqNo = 0;
6212     ushort parMode;
6213     ConstantElem defaultVal;
6214     uint nameIx = 0;
6215     FieldMarshal marshalInfo;
6216
6217     /// <summary>
6218     /// Create a new parameter for a method
6219     /// </summary>
6220     /// <param name="mode">param mode (in, out, opt)</param>
6221     /// <param name="parName">parameter name</param>
6222     /// <param name="parType">parameter type</param>
6223     public Param(ParamAttr mode, string parName, Type parType) {
6224       pName = parName;
6225       pType = parType;
6226       parMode = (ushort)mode;
6227                         tabIx = MDTable.Param;
6228                 }
6229
6230     /// <summary>
6231     /// Add a default value to this parameter
6232     /// </summary>
6233     /// <param name="c">the default value for the parameter</param>
6234     public void AddDefaultValue(Constant cVal) {
6235       defaultVal = new ConstantElem(this,cVal);
6236       parMode |= hasDefault;
6237     }
6238
6239     /// <summary>
6240     /// Add marshalling information about this parameter
6241     /// </summary>
6242     public void AddMarshallInfo(NativeType marshallType) {
6243       parMode |= hasFieldMarshal;
6244       marshalInfo = new FieldMarshal(this,marshallType);
6245     }
6246
6247     internal Type GetParType() { return pType; }
6248
6249     internal sealed override void BuildTables(MetaData md) {
6250       if (done) return;
6251       nameIx = md.AddToStringsHeap(pName);
6252       if (defaultVal != null) {
6253         md.AddToTable(MDTable.Constant,defaultVal);
6254         defaultVal.BuildTables(md);
6255       }
6256       if (marshalInfo != null) {
6257         md.AddToTable(MDTable.FieldMarshal,marshalInfo);
6258         marshalInfo.BuildTables(md);
6259       }
6260       done = true;
6261     }
6262
6263     internal void TypeSig(MemoryStream str) {
6264       pType.TypeSig(str);
6265     }
6266
6267     internal sealed override uint Size(MetaData md) {
6268       return 4 + md.StringsIndexSize();
6269     }
6270
6271     internal sealed override void Write(FileImage output) {
6272       output.Write(parMode);
6273       output.Write(seqNo);
6274       output.StringsIndex(nameIx);
6275     }
6276
6277     internal sealed override uint GetCodedIx(CIx code) {
6278       switch (code) {
6279         case (CIx.HasCustomAttr) : return 4; 
6280         case (CIx.HasConst) : return 1; 
6281         case (CIx.HasFieldMarshal) : return 1; 
6282       }
6283                         return 0;
6284     }
6285
6286         }
6287   /**************************************************************************/  
6288         /// <summary>
6289         /// Base class for the PEFile (starting point)
6290         /// </summary>
6291   public class PEFile
6292         {
6293     private static readonly string mscorlibName = "mscorlib";
6294     private Module thisMod;
6295     private ClassDef moduleClass;
6296     private ArrayList classRefList = new ArrayList();
6297     private ArrayList classDefList = new ArrayList();
6298     private ArrayList resources = new ArrayList ();
6299     private Assembly thisAssembly;
6300     private int corFlags = 1;
6301     FileImage fileImage;
6302                 MetaData metaData;
6303
6304     /// <summary>
6305     /// Create a new PEFile.  Each PEFile is a module.
6306     /// </summary>
6307     /// <param name="name">module name, also used for the file name</param>
6308     /// <param name="isDLL">create a .dll or .exe file</param>
6309     /// <param name="hasAssembly">this file is an assembly and 
6310     /// will contain the assembly manifest.  The assembly name is the 
6311     /// same as the module name</param>
6312     public PEFile(string name, bool isDLL, bool hasAssembly) {
6313       // Console.WriteLine(Hex.Byte(0x12));
6314       // Console.WriteLine(Hex.Short(0x1234));
6315       // Console.WriteLine(Hex.Int(0x12345678));
6316       string fName = MakeFileName(null,name,isDLL);
6317       fileImage = new FileImage(isDLL,fName);
6318       InitPEFile(name, fName, hasAssembly);
6319     }
6320
6321     /// <summary>
6322     /// Create a new PEFile.  Each PEFile is a module.
6323     /// </summary>
6324     /// <param name="name">module name, also used for the file name</param>
6325     /// <param name="isDLL">create a .dll or .exe file</param>
6326     /// <param name="hasAssembly">this file is an assembly and 
6327     /// will contain the assembly manifest.  The assembly name is the 
6328     /// same as the module name</param>
6329     /// <param name="outputDir">write the PEFile to this directory.  If this
6330     /// string is null then the output will be to the current directory</param>
6331     public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
6332       // Console.WriteLine(Hex.Byte(0x12));
6333       // Console.WriteLine(Hex.Short(0x1234));
6334       // Console.WriteLine(Hex.Int(0x12345678));
6335       string fName = MakeFileName(outputDir,name,isDLL);
6336                         fileImage = new FileImage(isDLL,fName);
6337       InitPEFile(name, fName, hasAssembly);
6338     }
6339
6340     /// <summary>
6341     /// Create a new PEFile
6342     /// </summary>
6343     /// <param name="name">module name</param>
6344     /// <param name="isDLL">create a .dll or .exe</param>
6345     /// <param name="hasAssembly">this PEfile is an assembly and
6346     /// will contain the assemly manifest.  The assembly name is the
6347     /// same as the module name</param>
6348     /// <param name="outStream">write the PEFile to this stream instead
6349     /// of to a new file</param>
6350     public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
6351       fileImage = new FileImage(isDLL,outStream);
6352       InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
6353     }
6354
6355     public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
6356       fileImage = new FileImage(isDLL,outStream);
6357       InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
6358     }
6359
6360     private void InitPEFile(string name, string fName, bool hasAssembly) {
6361       metaData = fileImage.GetMetaData();
6362       thisMod = new Module(fName,metaData);
6363       if (hasAssembly) {
6364         thisAssembly = new Assembly(name,metaData);
6365         metaData.AddToTable(MDTable.Assembly,thisAssembly);      
6366       }
6367       moduleClass = AddClass(TypeAttr.Private,"","<Module>");
6368       moduleClass.SpecialNoSuper();
6369       metaData.AddToTable(MDTable.Module,thisMod);
6370     }
6371  
6372
6373     public ClassDef ModuleClass {
6374             get { return moduleClass; }
6375     }
6376
6377     /// <summary>
6378     /// Set the subsystem (.subsystem) (Default is Windows Console mode)
6379     /// </summary>
6380     /// <param name="subS">subsystem value</param>
6381     public void SetSubSystem(SubSystem subS) {
6382       fileImage.subSys = subS;
6383     }
6384
6385     /// <summary>
6386     /// Set the flags (.corflags)
6387     /// </summary>
6388     /// <param name="flags">the flags value</param>
6389     public void SetCorFlags(int flags) {
6390       corFlags = flags;
6391     }
6392
6393     private string MakeFileName(string dirName, string name, bool isDLL) {
6394       string result = "";
6395       if ((dirName != null) && (dirName.CompareTo("") != 0)) {
6396         result = dirName;
6397         if (!dirName.EndsWith("\\")) result += "\\";
6398       }
6399       result += name;
6400        
6401       // if (isDLL) result += ".dll";  else result += ".exe";
6402       
6403       return result;
6404     }
6405
6406     /// <summary>
6407     /// Add an external assembly to this PEFile (.assembly extern)
6408     /// </summary>
6409     /// <param name="assemName">the external assembly name</param>
6410     /// <returns>a descriptor for this external assembly</returns>
6411     public AssemblyRef AddExternAssembly(string assemName) {
6412       if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
6413       AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
6414       metaData.AddToTable(MDTable.AssemblyRef,anAssem);
6415       // Console.WriteLine("Adding assembly " + assemName);
6416       return anAssem;
6417     }
6418
6419     /// <summary>
6420     /// Add an external module to this PEFile (.module extern)
6421     /// </summary>
6422     /// <param name="name">the external module name</param>
6423     /// <returns>a descriptor for this external module</returns>
6424     public ModuleRef AddExternModule(string name) {
6425       ModuleRef modRef = new ModuleRef(metaData,name);
6426       metaData.AddToTable(MDTable.ModuleRef,modRef);
6427       return modRef;
6428     }
6429
6430     /// <summary>
6431     /// Add a "global" method to this module
6432     /// </summary>
6433     /// <param name="name">method name</param>
6434     /// <param name="retType">return type</param>
6435     /// <param name="pars">method parameters</param>
6436     /// <returns>a descriptor for this new "global" method</returns>
6437     public MethodDef AddMethod(string name, Type retType, Param[] pars) {
6438       return moduleClass.AddMethod(name,retType,pars);
6439     }
6440
6441     /// <summary>
6442     /// Add a "global" method to this module
6443     /// </summary>
6444     /// <param name="mAtts">method attributes</param>
6445     /// <param name="iAtts">method implementation attributes</param>
6446     /// <param name="name">method name</param>
6447     /// <param name="retType">return type</param>
6448     /// <param name="pars">method parameters</param>
6449     /// <returns>a descriptor for this new "global" method</returns>
6450     public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
6451       return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
6452     }
6453
6454     public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
6455             MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
6456             metaData.AddToTable (MDTable.MemberRef,meth);
6457             return meth;
6458     }
6459
6460     public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
6461                     Type[] pars, Type[] optPars) {
6462             MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
6463             metaData.AddToTable(MDTable.MemberRef,meth);
6464             return meth;
6465     }
6466
6467     public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
6468             FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
6469             metaData.AddToTable (MDTable.MemberRef,field);
6470             return field;
6471     }
6472
6473     public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6474     {
6475             MethodSpec ms = new MethodSpec (m, g_sig);
6476             metaData.AddToTable (MDTable.MethodSpec, ms);
6477     }
6478
6479     /// <summary>
6480     /// Add a "global" field to this module
6481     /// </summary>
6482     /// <param name="name">field name</param>
6483     /// <param name="fType">field type</param>
6484     /// <returns>a descriptor for this new "global" field</returns>
6485     public FieldDef AddField(string name, Type fType) {
6486       return moduleClass.AddField(name,fType);
6487     }
6488
6489     /// <summary>
6490     /// Add a "global" field to this module
6491     /// </summary>
6492     /// <param name="attrSet">attributes of this field</param>
6493     /// <param name="name">field name</param>
6494     /// <param name="fType">field type</param>
6495     /// <returns>a descriptor for this new "global" field</returns>
6496     public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
6497       return moduleClass.AddField(attrSet,name,fType);
6498     }
6499
6500     /// <summary>
6501     /// Add a class to this module
6502     /// </summary>
6503     /// <param name="attrSet">attributes of this class</param>
6504     /// <param name="nsName">name space name</param>
6505     /// <param name="name">class name</param>
6506     /// <returns>a descriptor for this new class</returns>
6507     public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
6508       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6509       metaData.AddToTable(MDTable.TypeDef,aClass);
6510       return aClass;
6511     }
6512
6513     /// <summary>
6514     /// Add a class which extends System.ValueType to this module
6515     /// </summary>
6516     /// <param name="attrSet">attributes of this class</param>
6517     /// <param name="nsName">name space name</param>
6518     /// <param name="name">class name</param>
6519     /// <returns>a descriptor for this new class</returns>
6520     public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) {
6521       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6522       aClass.MakeValueClass(vClass);
6523       aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
6524       metaData.AddToTable(MDTable.TypeDef,aClass);
6525       return aClass;
6526     }
6527
6528     /// <summary>
6529     /// Add a class to this module
6530     /// </summary>
6531     /// <param name="attrSet">attributes of this class</param>
6532     /// <param name="nsName">name space name</param>
6533     /// <param name="name">class name</param>
6534     /// <param name="superType">super type of this class (extends)</param>
6535     /// <returns>a descriptor for this new class</returns>
6536     public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
6537       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6538       aClass.SetSuper(superType);
6539       metaData.AddToTable(MDTable.TypeDef,aClass);
6540       return aClass;
6541     }
6542
6543     public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
6544       FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
6545       metaData.AddToTable(MDTable.File,file);
6546       return file;
6547     }
6548
6549     /// <summary>
6550     /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
6551     /// </summary>
6552     /// <param name="mr"></param>
6553     public void AddManifestResource(ManifestResource mr) {
6554       metaData.AddToTable(MDTable.ManifestResource,mr);
6555       resources.Add (mr);
6556       //mr.FixName(metaData);
6557     }
6558
6559     public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
6560     {
6561             metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
6562     }
6563
6564     /// <summary>
6565     /// Add a managed resource from another assembly.
6566     /// </summary>
6567     /// <param name="resName">The name of the resource</param>
6568     /// <param name="assem">The assembly where the resource is</param>
6569     /// <param name="isPublic">Access for the resource</param>
6570     public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) {
6571       resources.Add (new ManifestResource (resName, flags, assem));
6572     }
6573
6574     /// <summary>
6575     /// Add a managed resource from another assembly.
6576     /// </summary>
6577     /// <param name="mr"></param>
6578     /// <param name="isPublic"></param>
6579     public void AddExternalManagedResource (ManifestResource mr) {
6580       resources.Add (new ManifestResource (mr));
6581     }
6582     /// <summary>
6583     /// Find a resource
6584     /// </summary>
6585     /// <param name="name">The name of the resource</param>
6586     /// <returns>The resource with the name "name" or null </returns>
6587     public ManifestResource GetResource (string name) {
6588       for (int i = 0; i < resources.Count; i ++) {
6589         if (((ManifestResource) resources [i]).Name == name)
6590           return (ManifestResource) resources [i];
6591       }
6592       return null;
6593     }
6594
6595     public ManifestResource [] GetResources() {
6596       return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
6597     }
6598
6599     /// <summary>
6600     /// Write out the PEFile (the "bake" function)
6601     /// </summary>
6602     public void WritePEFile() { /* the "bake" function */
6603       fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
6604       fileImage.MakeFile();
6605     }
6606
6607     /// <summary>
6608     /// Get the descriptor of this module
6609     /// </summary>
6610     /// <returns>the descriptor for this module</returns>
6611     public Module GetThisModule() {
6612       return thisMod;
6613     }
6614
6615     /// <summary>
6616     /// Get the descriptor for this assembly.  The PEFile must have been
6617     /// created with hasAssembly = true
6618     /// </summary>
6619     /// <returns>the descriptor for this assembly</returns>
6620     public Assembly GetThisAssembly() {
6621       return thisAssembly;
6622     }
6623
6624         }
6625
6626   /**************************************************************************/  
6627         /// <summary>
6628         /// Descriptor for the Primitive types defined in IL
6629         /// </summary>
6630   public class PrimitiveType : Type
6631         {
6632     private string name;
6633     private int systemTypeIndex;
6634     public static int NumSystemTypes = 18;
6635
6636     public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
6637     public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
6638     public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
6639     public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
6640     public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
6641     public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
6642     public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
6643     public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
6644     public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
6645     public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
6646     public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
6647     public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
6648     public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
6649     public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
6650                 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
6651     public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
6652     public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
6653     public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
6654     public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
6655     internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
6656     internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
6657     internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
6658     public static readonly PrimitiveType NativeInt = IntPtr;
6659     public static readonly PrimitiveType NativeUInt = UIntPtr;
6660
6661     internal PrimitiveType(byte typeIx) : base(typeIx) { }
6662
6663                 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
6664       this.name = name;
6665       this.systemTypeIndex = STIx;
6666     }
6667
6668     internal string GetName() { return name; }
6669
6670     internal int GetSystemTypeIx() { return systemTypeIndex; }
6671
6672     internal sealed override void TypeSig(MemoryStream str) {
6673       str.WriteByte(typeIndex);
6674     }
6675
6676     internal override MetaDataElement GetTypeSpec(MetaData md) {
6677       TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
6678       if (tS == null) {
6679         tS = new TypeSpec(this,md);
6680         md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
6681         md.AddToTable(MDTable.TypeSpec,tS);
6682       }
6683       return tS;
6684     }
6685
6686         }
6687
6688   /**************************************************************************/  
6689         /// <summary>
6690         /// Descriptor for the Property of a class
6691         /// </summary>
6692   public class Property : Feature
6693         {
6694     private static readonly byte PropertyTag = 0x8;
6695     MethodDef getterMeth;
6696     ConstantElem constVal;
6697     uint typeBlobIx = 0;
6698     Type[] parList;
6699     Type returnType;
6700     uint numPars = 0;
6701
6702     internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
6703       returnType = retType;
6704       parList = pars;
6705       if (pars != null) numPars = (uint)pars.Length;
6706                         tabIx = MDTable.Property;
6707                 }
6708
6709     /// <summary>
6710     /// Add a set method to this property
6711     /// </summary>
6712     /// <param name="setter">the set method</param>
6713     public void AddSetter(MethodDef setter) {
6714       AddMethod(setter,MethodType.Setter);
6715     }
6716
6717     /// <summary>
6718     /// Add a get method to this property
6719     /// </summary>
6720     /// <param name="getter">the get method</param>
6721     public void AddGetter(MethodDef getter) {
6722       AddMethod(getter,MethodType.Getter);
6723       getterMeth = getter;
6724     }
6725
6726     /// <summary>
6727     /// Add another method to this property
6728     /// </summary>
6729     /// <param name="other">the method</param>
6730     public void AddOther(MethodDef other) {
6731       AddMethod(other,MethodType.Other);
6732     }
6733
6734     /// <summary>
6735     /// Add an initial value for this property
6736     /// </summary>
6737     /// <param name="constVal">the initial value for this property</param>
6738     public void AddInitValue(Constant constVal) {
6739       this.constVal = new ConstantElem(this,constVal);
6740     }
6741
6742     internal sealed override void BuildTables(MetaData md) {
6743       if (done) return;
6744       nameIx = md.AddToStringsHeap(name);
6745       MemoryStream sig = new MemoryStream();
6746       sig.WriteByte(PropertyTag);
6747       MetaData.CompressNum(numPars,sig);
6748       returnType.TypeSig(sig);
6749       for (int i=0; i < numPars; i++) {
6750         parList[i].TypeSig(sig);
6751       }
6752       typeBlobIx = md.AddToBlobHeap(sig.ToArray());
6753       for (int i=0; i < tide; i++) {
6754         md.AddToTable(MDTable.MethodSemantics,methods[i]);
6755       }
6756       if (constVal != null) {
6757         md.AddToTable(MDTable.Constant,constVal);
6758         constVal.BuildTables(md);
6759       }
6760       done = true;
6761     }
6762
6763     internal sealed override uint Size(MetaData md) {
6764       return 2 + md.StringsIndexSize() + md.BlobIndexSize();
6765     }
6766
6767     internal sealed override void Write(FileImage output) {
6768       output.Write(flags);
6769       output.StringsIndex(nameIx);
6770       output.BlobIndex(typeBlobIx);
6771     }
6772
6773     internal sealed override uint GetCodedIx(CIx code) {
6774                         switch (code) {
6775                                 case (CIx.HasCustomAttr) : return 9; 
6776                                 case (CIx.HasConst) : return 2; 
6777                                 case (CIx.HasSemantics) : return 1; 
6778                         }
6779                         return 0;
6780     }
6781
6782         }
6783   /**************************************************************************/  
6784         /// <summary>
6785         /// Descriptor for an pointer (type * or type &)
6786         /// </summary>
6787   public abstract class PtrType : Type
6788         {
6789     Type baseType;
6790
6791                 internal PtrType(Type bType, byte typeIx) : base(typeIx)
6792                 {
6793       baseType = bType;
6794       tabIx = MDTable.TypeSpec;
6795                 }
6796
6797     internal sealed override void TypeSig(MemoryStream str) {
6798       str.WriteByte(typeIndex);
6799       baseType.TypeSig(str);
6800     }
6801
6802         }
6803   /**************************************************************************/  
6804   /// <summary>
6805   /// Descriptor for a managed pointer (type &  or byref)
6806   /// </summary>
6807
6808   public class ManagedPointer : PtrType  // <type> & (BYREF)  
6809   {
6810
6811     /// <summary>
6812     /// Create new managed pointer to baseType
6813     /// </summary>
6814     /// <param name="bType">the base type of the pointer</param>
6815     public ManagedPointer(Type baseType) : base(baseType,0x10) { }
6816  
6817   }
6818   /**************************************************************************/  
6819   /// <summary>
6820   /// Descriptor for an unmanaged pointer (type *)
6821   /// </summary>
6822   public class UnmanagedPointer : PtrType // PTR
6823   {
6824     /// <summary>
6825     /// Create a new unmanaged pointer to baseType
6826     /// </summary>
6827     /// <param name="baseType">the base type of the pointer</param>
6828     public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
6829
6830   }
6831   /**************************************************************************/  
6832         /// <summary>
6833         /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
6834         /// </summary>
6835   public abstract class ResolutionScope : MetaDataElement
6836         {
6837     protected uint nameIx = 0;
6838     protected MetaData metaData;
6839     protected string name;
6840
6841                 internal ResolutionScope(string name, MetaData md)
6842                 {
6843       metaData = md;
6844       this.name = name;
6845       nameIx = md.AddToStringsHeap(name);
6846                 }
6847
6848     internal string GetName() { return name; }
6849
6850         }
6851   /**************************************************************************/  
6852         /// <summary>
6853         /// Descriptor for a Section in a PEFile  eg .text, .sdata
6854         /// </summary>
6855   internal class Section {
6856                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups
6857
6858                 char[] name; 
6859                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
6860                 //uint relocOff = 0;
6861     uint flags = 0, padding = 0;
6862                 uint[] relocs; 
6863
6864                 internal Section(string sName, uint sFlags) {
6865                   name = sName.ToCharArray();
6866                   flags = sFlags;
6867                 }
6868
6869                 internal uint Tide() { return tide; }
6870
6871                 internal void IncTide(uint incVal) { tide += incVal; }
6872
6873                 internal uint Padding() { return padding; }
6874
6875                 internal uint Size() { return size; }
6876
6877                 internal void SetSize(uint pad) {
6878                         padding = pad;
6879                         size = tide + padding;
6880                 }
6881
6882                 internal uint RVA() { return rva; }
6883
6884                 internal void SetRVA(uint rva) { this.rva = rva; }
6885
6886                 internal uint Offset() { return offset; }
6887
6888                 internal void SetOffset(uint offs) { offset = offs; }
6889
6890     internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
6891       //Console.WriteLine("rva = " + rva + "  page = " + page);
6892       reloc.Write(rva + page);
6893       reloc.Write((uint)(((end-start+1)*2) + 8));
6894       for (int j=start; j < end; j++) {
6895         //Console.WriteLine("reloc offset = " + relocs[j]);
6896         reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
6897       }
6898       reloc.Write((ushort)0);
6899     }
6900
6901                 internal void DoRelocs(BinaryWriter reloc) {
6902       if (relocTide > 0) {
6903         //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
6904         uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
6905         int start = 0;
6906         for (int i=1; i < relocTide; i++) {
6907           if (relocs[i] >= block) {
6908             DoBlock(reloc,block-relocPageSize,start,i);
6909             start = i;
6910             block = (relocs[i]/relocPageSize + 1) * relocPageSize;
6911           }
6912         }
6913         DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
6914       }
6915                 }
6916
6917                 internal void AddReloc(uint offs) {
6918                         int pos = 0;
6919                         if (relocs == null) {
6920                                 relocs = new uint[5];
6921                         } else {
6922                                 if (relocTide >= relocs.Length) {
6923                                         uint[] tmp = relocs;
6924                                         relocs = new uint[tmp.Length + 5];
6925                                         for (int i=0; i < relocTide; i++) {
6926                                                 relocs[i] = tmp[i];
6927                                         }
6928                                 }
6929                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
6930                                 for (int i=pos; i < relocTide; i++) {
6931                                         relocs[i+1] = relocs[i];
6932                                 }
6933                         }
6934                         relocs[pos] = offs;
6935                         relocTide++;    
6936                 }
6937       
6938                 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
6939                         output.Write(name);
6940                         output.Write(tide);
6941                         output.Write(rva);
6942                         output.Write(size);
6943                         output.Write(offset);
6944                         output.Write(0);
6945                         //output.Write(relocRVA + relocOff);
6946                         output.Write(0);
6947       output.Write(0);
6948                         //output.Write((ushort)relocTide);
6949                         //output.Write((ushort)0);
6950                         output.Write(flags);
6951                 }
6952
6953         }
6954   /**************************************************************************/  
6955   public abstract class Signature : MetaDataElement 
6956   {
6957     protected uint sigIx;
6958
6959     internal Signature() {
6960       tabIx = MDTable.StandAloneSig;
6961     }
6962
6963     internal sealed override uint Size(MetaData md) {
6964       return md.BlobIndexSize();
6965     }
6966
6967     internal sealed override void Write(FileImage output) {
6968       output.BlobIndex(sigIx);
6969     }
6970
6971     internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
6972
6973   }
6974   /**************************************************************************/  
6975         /// <summary>
6976         /// Descriptor for a class defined in System (mscorlib)
6977         /// </summary>
6978   internal class SystemClass : ClassRef
6979         {
6980     PrimitiveType elemType; 
6981
6982                 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
6983                                     : base("System",eType.GetName(),md) {
6984       elemType = eType;
6985       parent = paren;
6986                 }
6987
6988     internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
6989       if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
6990       return typeSpec;
6991     }
6992
6993
6994     internal sealed override void TypeSig(MemoryStream str) {
6995         str.WriteByte(elemType.GetTypeIndex());
6996     }
6997
6998         }
6999   /**************************************************************************/  
7000         /// <summary>
7001         /// Base class for all IL types
7002         /// </summary>
7003   public abstract class Type : MetaDataElement {
7004     protected byte typeIndex;
7005     protected TypeSpec typeSpec;
7006
7007     internal Type(byte tyIx) { typeIndex = tyIx; }
7008
7009     internal byte GetTypeIndex() { return typeIndex; }
7010     internal void SetTypeIndex (byte b) { typeIndex = b; }
7011           
7012     internal virtual MetaDataElement GetTypeSpec(MetaData md) {
7013       if (typeSpec == null) {
7014         typeSpec = new TypeSpec(this,md);
7015         md.AddToTable(MDTable.TypeSpec,typeSpec);
7016       }
7017       return typeSpec;
7018     }
7019  
7020     internal virtual void TypeSig(MemoryStream str) {
7021       throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
7022         " doesn't have a type signature!!"));   
7023     }
7024
7025   }
7026
7027   /**************************************************************************/  
7028
7029   public class TypeSpec : MetaDataElement {
7030     uint sigIx = 0;
7031
7032     internal TypeSpec(Type aType, MetaData md) {
7033       MemoryStream sig = new MemoryStream();
7034       aType.TypeSig(sig);
7035       sigIx = md.AddToBlobHeap(sig.ToArray());
7036       tabIx = MDTable.TypeSpec;
7037     }
7038
7039     internal sealed override uint GetCodedIx(CIx code) {
7040       switch (code) {
7041         case (CIx.TypeDefOrRef) : return 2; 
7042         case (CIx.HasCustomAttr) : return 13; 
7043         case (CIx.MemberRefParent) : return 4; 
7044       }
7045       return 0;
7046     }
7047
7048     internal override uint Size(MetaData md) { 
7049       return md.BlobIndexSize();
7050     }
7051
7052     internal sealed override void Write(FileImage output) {
7053       //Console.WriteLine("Writing the blob index for a TypeSpec");
7054       output.BlobIndex(sigIx);
7055     }
7056
7057   }
7058
7059           class ByteArrayComparer : IComparer {
7060
7061                 public int Compare (object x, object y)
7062                 {
7063                         byte [] a = (byte []) x;
7064                         byte [] b = (byte []) y;
7065                         int len = a.Length;
7066
7067                         if (b.Length != len)
7068                                 return 1;
7069
7070                         for (int i = 0; i < len; ++i)
7071                                 if (a [i] != b [i])
7072                                         return 1;
7073                         return 0;
7074                 }
7075         }
7076
7077         class ByteArrayHashCodeProvider : IHashCodeProvider {
7078
7079                 public int GetHashCode (Object key)
7080                 {
7081                         byte [] arr = (byte []) key;
7082                         int len = arr.Length;
7083                         int h = 0;
7084
7085                         for (int i = 0; i < len; ++i)
7086                                 h = (h << 5) - h + arr [i];
7087
7088                         return h;
7089                 }
7090
7091         }
7092 }
7093
7094