* PEAPI.cs: Don't build custom attributes twice.
[mono.git] / mcs / class / PEAPI / PEAPI.cs
index 356afe998a25b9f613daf1fb589fa39b7f3be1e9..9c28a49496c3d4c6d529453bd9b02420060fbe7d 100644 (file)
@@ -381,10 +381,16 @@ namespace PEAPI
 \r
   }     \r
   /**************************************************************************/  \r
+
+        public interface IExternRef  {
+                ClassRef AddClass(string nsName, string name);
+                ClassRef AddValueClass(string nsName, string name);
+        }
+        
         /// <summary>\r
         /// A reference to an external assembly (.assembly extern)\r
         /// </summary>\r
-        public class AssemblyRef : ResolutionScope\r
+        public class AssemblyRef : ResolutionScope, IExternRef
         {\r
     private ushort major, minor, build, revision;\r
     uint flags, keyIx, hashIx, cultIx;\r
@@ -517,7 +523,7 @@ namespace PEAPI
       }\r
       return 0;\r
     }\r
\r
+
         }\r
   /**************************************************************************/  \r
 \r
@@ -1815,7 +1821,12 @@ namespace PEAPI
       fields.Add(field);\r
       return field;\r
     }\r
-\r
+
+    public void SetFieldOrder (ArrayList fields)
+    {
+            this.fields = fields;
+    }
+
     /// <summary>\r
     /// Add a method to this class\r
     /// </summary>\r
@@ -1982,7 +1993,6 @@ namespace PEAPI
         md.AddToTable(MDTable.PropertyMap,new MapElem(this,\r
                           ((Property)properties[0]).Row,MDTable.Property));\r
       }\r
-      DoCustomAttributes (md);\r
       // Console.WriteLine("End of building tables");\r
       done = true;\r
     }\r
@@ -2640,7 +2650,7 @@ namespace PEAPI
 \r
     internal sealed override void BuildTables(MetaData md) {\r
       BinaryWriter bw = new BinaryWriter(new MemoryStream());\r
-      bw.Write((ushort)1);\r
+      bw.Write(byteVal);\r
       md.AddToTable(MDTable.CustomAttribute, this);\r
       MemoryStream str = (MemoryStream)bw.BaseStream;\r
       valIx = md.AddToBlobHeap(str.ToArray());\r
@@ -3476,9 +3486,13 @@ if (rsrc != null)
      }\r
 \r
     private void WriteSDataSection() {\r
+      long size = sdata.Size ();
+      long start = BaseStream.Position;
       for (int i=0; i < data.Count; i++) {\r
         ((DataConstant)data[i]).Write(this);\r
-      }\r
+      }
+      while (BaseStream.Position < (start + size))
+              Write ((byte) 0);
     }\r
 \r
                 private void WriteRsrcSection() {\r
@@ -3648,13 +3662,13 @@ if (rsrc != null)
         /// </summary>\r
         public class FileRef : MetaDataElement\r
         {\r
-    private static readonly uint HasMetaData = 0x1;\r
+    private static readonly uint NoMetaData = 0x1;\r
     uint nameIx = 0, hashIx = 0;\r
     uint flags = 0;\r
 \r
     internal FileRef(string name, byte[] hashBytes, bool metaData,\r
                       bool entryPoint, MetaData md) {\r
-      if (metaData) flags = HasMetaData;\r
+      if (!metaData) flags = NoMetaData;\r
       if (entryPoint) md.SetEntryPoint(this);\r
       nameIx = md.AddToStringsHeap(name);\r
       hashIx = md.AddToBlobHeap(hashBytes);\r
@@ -3663,7 +3677,7 @@ if (rsrc != null)
 \r
     internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,\r
                       bool entryPoint, MetaData md) {\r
-      if (metaData) flags = HasMetaData;\r
+      if (!metaData) flags = NoMetaData;\r
       if (entryPoint) md.SetEntryPoint(this);\r
       this.nameIx = nameIx;\r
       hashIx = md.AddToBlobHeap(hashBytes);\r
@@ -4410,7 +4424,8 @@ if (rsrc != null)
     public MSCorLib mscorlib;\r
     private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];\r
     long mdStart;\r
-\r
+                private ArrayList cattr_list;
+                
     internal MetaData(FileImage file) {\r
       // tilde = new MetaDataStream(tildeName,false,0);\r
       this.file = file;\r
@@ -4515,7 +4530,13 @@ if (rsrc != null)
       return blob.Add(val,true);\r
     }\r
 \r
-\r
+                internal void AddCustomAttribute (CustomAttribute cattr)
+                {
+                        if (cattr_list == null)
+                                cattr_list = new ArrayList ();
+                        cattr_list.Add (cattr);
+                }
+
     private ArrayList GetTable(MDTable tableIx) {\r
       int tabIx = (int)tableIx;\r
       if (metaDataTables[tabIx] == null) {\r
@@ -4746,7 +4767,12 @@ if (rsrc != null)
       BuildTable(metaDataTables[(int)MDTable.GenericParam]);\r
       BuildTable(metaDataTables[(int)MDTable.MethodSpec]);\r
       BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);\r
-      BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);\r
+
+      if (cattr_list != null) {
+              foreach (CustomAttribute cattr in cattr_list)
+                      cattr.BuildTables (this);
+      }
+
 /*      for (int i=0; i < metaDataTables.Length; i++) {\r
         ArrayList table = metaDataTables[i];\r
         if (table != null) {\r
@@ -4756,6 +4782,7 @@ if (rsrc != null)
         }\r
       }\r
       */\r
+
                         SetIndexSizes();\r
                         for (int i=1; i < numStreams; i++) {\r
                                 streams[i].EndStream();\r
@@ -4875,16 +4902,7 @@ if (rsrc != null)
       } \r
 //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));\r
     }\r
-\r
-    internal void DoCustomAttributes(MetaData md) {\r
-      if (customAttributes != null) {\r
-        for (int i=0; i < customAttributes.Count; i++) {\r
-          CustomAttribute ca = (CustomAttribute)customAttributes[i];\r
-          ca.BuildTables(md);\r
-        }\r
-      }\r
-    }\r
-\r
+
     internal uint Token() {\r
       return (((uint)tabIx << 24) | row);\r
     }\r
@@ -4982,9 +5000,8 @@ if (rsrc != null)
                         if (val == null) {
                                 index = size;
                                 btable [str] = index;
-                                if (prependSize) CompressNum ((uint) str.Length+1);
+                                if (prependSize) CompressNum ((uint) str.Length);
                                 Write (str);
-                                Write ((byte) 0);
                                 size = (uint) Seek (0, SeekOrigin.Current);
                         } else {
                                 index = (uint) val;
@@ -5349,7 +5366,6 @@ if (rsrc != null)
         varArgSig.BuildTables(md);\r
       }\r
       }\r
-      DoCustomAttributes (md);\r
       // Console.WriteLine("method has " + numPars + " parameters");\r
       done = true;\r
     }\r
@@ -5516,25 +5532,51 @@ if (rsrc != null)
         /// \r
         public class MethPtrType : Type\r
         {\r
-    // MethPtrType == FNPTR\r
-    Method method;\r
-    uint sigIx = 0;\r
-\r
+                bool varArgMeth;
+                Type retType;
+                Type [] parList;
+                Type [] optParList;
+                CallConv callConv;
+                uint numPars;
+                uint numOptPars;
+                uint sigIx = 0;
+
     /// <summary>\r
     /// Create a new function pointer type\r
     /// </summary>\r
     /// <param name="meth">the function to be referenced</param>\r
-                public MethPtrType(Method meth) : base(0x1B)\r
-                {\r
-      method = meth;\r
-                        tabIx = MDTable.TypeSpec;\r
-                }\r
-\r
-    internal sealed override void TypeSig(MemoryStream str) {\r
-      str.WriteByte(typeIndex);\r
-      method.TypeSig(str);\r
-    }\r
-\r
+    public MethPtrType (CallConv callconv, Type retType, Type[] pars,
+                    bool varArgMeth, Type[] optPars) : base(0x1B) {
+      this.retType = retType;
+      callConv = callconv;
+      parList = pars;
+      this.varArgMeth = varArgMeth;
+      if (parList != null) numPars = (uint)parList.Length;
+      if (varArgMeth) {
+        optParList = optPars;
+        if (optParList != null) numOptPars = (uint)optParList.Length;
+        callConv |= CallConv.Vararg;
+      }
+      tabIx = MDTable.TypeSpec;
+    }
+  
+    internal sealed override void TypeSig(MemoryStream sig) {
+      sig.WriteByte(typeIndex);
+      // Bootlegged from method ref
+      sig.WriteByte((byte)callConv);
+      MetaData.CompressNum (numPars + numOptPars, sig);
+      retType.TypeSig (sig);
+      for (int i=0; i < numPars; i++) {
+              parList[i].TypeSig (sig);
+      }
+      if (varArgMeth) {
+              sig.WriteByte (0x41); // Write the sentinel
+        for (int i=0; i < numOptPars; i++) {
+          optParList[i].TypeSig (sig);
+        }
+      }
+    }
+
     internal sealed override void BuildTables(MetaData md) {\r
       if (done) return;\r
       MemoryStream sig = new MemoryStream();\r
@@ -5588,19 +5630,18 @@ if (rsrc != null)
                         }\r
                         return 0;\r
     }\r
-\r
-        }\r
+  }
   /**************************************************************************/  \r
         /// <summary>\r
         /// Descriptor for another module in THIS assembly\r
         /// </summary>\r
-  public class ModuleRef : ResolutionScope\r
+        public class ModuleRef : ResolutionScope, IExternRef
         {\r
 \r
                 internal ModuleRef(MetaData md, string name) : base(name,md) {\r
       tabIx = MDTable.ModuleRef;\r
-                }\r
-\r
+                }
+
     /// <summary>\r
     /// Add a class to this external module.  This is a class declared in\r
     /// another module of THIS assembly.\r
@@ -5608,7 +5649,7 @@ if (rsrc != null)
     /// <param name="nsName">name space name</param>\r
     /// <param name="name">class name</param>\r
     /// <returns>a descriptor for this class in another module</returns>\r
-    public ClassRef AddClass(string nsName, string name, bool exportClass) {\r
+    public ClassRef AddClass(string nsName, string name) {\r
       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
       metaData.AddToTable(MDTable.TypeRef,aClass);\r
       aClass.SetParent(this);\r
@@ -6026,7 +6067,12 @@ if (rsrc != null)
       fileImage = new FileImage(isDLL,outStream);\r
       InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);\r
     }\r
-\r
+
+    public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {\r
+      fileImage = new FileImage(isDLL,outStream);\r
+      InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);\r
+    }
+
     private void InitPEFile(string name, string fName, bool hasAssembly) {\r
       metaData = fileImage.GetMetaData();\r
       thisMod = new Module(fName,metaData);\r
@@ -6223,7 +6269,12 @@ if (rsrc != null)
       metaData.AddToTable(MDTable.ManifestResource,mr);\r
       //mr.FixName(metaData);\r
     }\r
-\r
+
+    public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
+    {
+            metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
+    }
+
     /// <summary>\r
     /// Write out the PEFile (the "bake" function)\r
     /// </summary>\r