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