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