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