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