Thu Dec 19 00:06:57 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / AssemblyBuilder.cs
1 //
2 // System.Reflection.Emit/AssemblyBuilder.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Resources;
13 using System.IO;
14 using System.Security.Policy;
15 using System.Runtime.Serialization;
16 using System.Globalization;
17 using System.Runtime.CompilerServices;
18 using System.Collections;
19
20 namespace System.Reflection.Emit {
21
22         internal struct MonoResource {
23                 public byte[] data;
24                 public string name;
25                 public string filename;
26                 public ResourceAttributes attrs;
27         }
28
29         public sealed class AssemblyBuilder : Assembly {
30                 private IntPtr dynamic_assembly;
31                 private MethodInfo entry_point;
32                 private ModuleBuilder[] modules;
33                 private string name;
34                 private string dir;
35                 private CustomAttributeBuilder[] cattrs;
36                 private MonoResource[] resources;
37                 string keyfile;
38                 string version;
39                 string culture;
40                 uint algid;
41                 uint flags;
42                 PEFileKinds pekind = PEFileKinds.Dll;
43                 bool delay_sign;
44                 internal Type corlib_object_type = typeof (System.Object);
45                 internal Type corlib_value_type = typeof (System.ValueType);
46                 internal Type corlib_enum_type = typeof (System.Enum);
47                 private int[] table_indexes;
48                 internal ArrayList methods;
49                 Hashtable us_string_cache = new Hashtable ();
50
51                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52                 private static extern void basic_init (AssemblyBuilder ab);
53                 
54                 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access) {
55                         name = n.Name;
56                         dir = directory;
57                         basic_init (this);
58                 }
59
60                 internal int get_next_table_index (object obj, int table, bool inc) {
61                         if (table_indexes == null) {
62                                 table_indexes = new int [64];
63                                 for (int i=0; i < 64; ++i)
64                                         table_indexes [i] = 1;
65                                 /* allow room for .<Module> in TypeDef table */
66                                 table_indexes [0x02] = 2;
67                         }
68                         // Console.WriteLine ("getindex for table "+table.ToString()+" got "+table_indexes [table].ToString());
69                         if (inc) {
70                                 if ((table == 0x06) && (methods != null))
71                                         methods.Add (obj);
72                                 return table_indexes [table]++;
73                         }
74                         return table_indexes [table];
75                 }
76
77                 public override string CodeBase {
78                         get {
79                                 return null;
80                         }
81                 }
82                 
83                 public override MethodInfo EntryPoint {
84                         get {
85                                 return entry_point;
86                         }
87                 }
88
89                 public override string Location {
90                         get {
91                                 return null;
92                         }
93                 }
94
95                 public void AddResourceFile (string name, string fileName)
96                 {
97                         AddResourceFile (name, fileName, ResourceAttributes.Public);
98                 }
99
100                 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
101                 {
102                         if (resources != null) {
103                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
104                                 System.Array.Copy(resources, new_r, resources.Length);
105                                 resources = new_r;
106                         } else {
107                                 resources = new MonoResource [1];
108                         }
109                         int p = resources.Length - 1;
110                         resources [p].name = name;
111                         resources [p].filename = fileName;
112                         resources [p].attrs = attribute;
113                 }
114
115                 public void EmbedResourceFile (string name, string fileName)
116                 {
117                         EmbedResourceFile (name, fileName, ResourceAttributes.Public);
118                 }
119
120                 public void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
121                 {
122                         if (resources != null) {
123                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
124                                 System.Array.Copy(resources, new_r, resources.Length);
125                                 resources = new_r;
126                         } else {
127                                 resources = new MonoResource [1];
128                         }
129                         int p = resources.Length - 1;
130                         resources [p].name = name;
131                         resources [p].attrs = attribute;
132                         try {
133                                 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
134                                 long len = s.Length;
135                                 resources [p].data = new byte [len];
136                                 s.Read (resources [p].data, 0, (int)len);
137                                 s.Close ();
138                         } catch {
139                                 /* do something */
140                         }
141                 }
142
143                 public ModuleBuilder DefineDynamicModule (string name)
144                 {
145                         return DefineDynamicModule (name, name, false);
146                 }
147
148                 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
149                 {
150                         return DefineDynamicModule (name, name, emitSymbolInfo);
151                 }
152
153                 public ModuleBuilder DefineDynamicModule(string name, string fileName)
154                 {
155                         return DefineDynamicModule (name, fileName, false);
156                 }
157
158                 public ModuleBuilder DefineDynamicModule (string name, string fileName,
159                                                           bool emitSymbolInfo)
160                 {
161                         ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo);
162
163                         if (modules != null) {
164                                 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
165                                 System.Array.Copy(modules, new_modules, modules.Length);
166                                 new_modules [modules.Length] = r;
167                                 modules = new_modules;
168                         } else {
169                                 modules = new ModuleBuilder [1];
170                                 modules [0] = r;
171                         }
172                         return r;
173                 }
174
175                 public IResourceWriter DefineResource (string name, string description, string fileName)
176                 {
177                         return DefineResource (name, description, fileName, ResourceAttributes.Public);
178                 }
179
180                 public IResourceWriter DefineResource (string name, string description,
181                                                        string fileName, ResourceAttributes attribute)
182                 {
183                         return null;
184                 }
185
186                 public void DefineUnmanagedResource (byte[] resource)
187                 {
188                 }
189
190                 public void DefineUnmanagedResource (string resourceFileName)
191                 {
192                 }
193
194                 public void DefineVersionInfoResource ()
195                 {
196                 }
197
198                 public void DefineVersionInfoResource (string product, string productVersion,
199                                                        string company, string copyright, string trademark)
200                 {
201                 }
202
203                 public ModuleBuilder GetDynamicModule (string name)
204                 {
205                         return null;
206                 }
207
208                 public override Type[] GetExportedTypes ()
209                 {
210                         return null;
211                 }
212
213                 public override FileStream GetFile (string name)
214                 {
215                         return null;
216                 }
217
218                 /*public virtual FileStream[] GetFiles() {
219                         return null;
220                 }
221                 public override FileStream[] GetFiles(bool getResourceModules) {
222                         return null;
223                 }*/
224
225                 /*public virtual ManifestResourceInfo GetManifestResourceInfo(string resourceName)
226                   {
227                         return null;
228                 }
229                 public virtual string[] GetManifestResourceNames() {
230                         return null;
231                 }
232                 public virtual Stream GetManifestResourceStream(string name) {
233                         return null;
234                 }
235                 public virtual Stream GetManifestResourceStream(Type type, string name) {
236                         return null;
237                 }*/
238
239                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
240                 private static extern int getUSIndex (AssemblyBuilder ab, string str);
241
242                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
243                 private static extern int getToken (AssemblyBuilder ab, MemberInfo member);
244
245                 internal int GetToken (string str) {
246                         if (us_string_cache.Contains (str))
247                                 return (int)us_string_cache [str];
248                         int result = getUSIndex (this, str);
249                         us_string_cache [str] = result;
250                         return result;
251                 }
252                 
253                 internal int GetToken (MemberInfo member) {
254                         return getToken (this, member);
255                 }
256                 
257                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
258                 private static extern int getDataChunk (AssemblyBuilder ab, byte[] buf, int offset);
259
260                 public void Save (string assemblyFileName)
261                 {
262                         byte[] buf = new byte [65536];
263                         FileStream file;
264                         int count, offset;
265
266                         if (dir != null) {
267                                 assemblyFileName = String.Format ("{0}{1}{2}", dir, System.IO.Path.DirectorySeparatorChar, assemblyFileName);
268                         }
269
270                         file = new FileStream (assemblyFileName, FileMode.Create, FileAccess.Write);
271
272                         offset = 0;
273                         while ((count = getDataChunk (this, buf, offset)) != 0) {
274                                 file.Write (buf, 0, count);
275                                 offset += count;
276                         }
277                         file.Close ();
278                 }
279
280                 public void SetEntryPoint (MethodInfo entryMethod)
281                 {
282                         SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
283                 }
284
285                 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
286                 {
287                         entry_point = entryMethod;
288                         pekind = fileKind;
289                 }
290
291                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
292                         string attrname = customBuilder.Ctor.ReflectedType.FullName;
293                         byte[] data;
294                         int len, pos;
295                         if (attrname == "System.Reflection.AssemblyVersionAttribute") {
296                                 data = customBuilder.Data;
297                                 pos = 2;
298                                 len = CustomAttributeBuilder.decode_len (data, pos, out pos);
299                                 version = CustomAttributeBuilder.string_from_bytes (data, pos, len);
300                                 return;
301                         } else if (attrname == "System.Reflection.AssemblyKeyFileAttribute") {
302                                 data = customBuilder.Data;
303                                 pos = 2;
304                                 len = CustomAttributeBuilder.decode_len (data, pos, out pos);
305                                 keyfile = CustomAttributeBuilder.string_from_bytes (data, pos, len);
306                         } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
307                                 data = customBuilder.Data;
308                                 pos = 2;
309                                 len = CustomAttributeBuilder.decode_len (data, pos, out pos);
310                                 culture = CustomAttributeBuilder.string_from_bytes (data, pos, len);
311                         } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
312                                 data = customBuilder.Data;
313                                 pos = 2;
314                                 algid = (uint)data [pos];
315                                 algid |= ((uint)data [pos + 1]) << 8;
316                                 algid |= ((uint)data [pos + 2]) << 16;
317                                 algid |= ((uint)data [pos + 3]) << 24;
318                         } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
319                                 data = customBuilder.Data;
320                                 pos = 2;
321                                 flags = (uint)data [pos];
322                                 flags |= ((uint)data [pos + 1]) << 8;
323                                 flags |= ((uint)data [pos + 2]) << 16;
324                                 flags |= ((uint)data [pos + 3]) << 24;
325                                 return;
326                         } else if (attrname == "System.Reflection.AssemblyDelaySignAttribute") {
327                                 data = customBuilder.Data;
328                                 pos = 2;
329                                 delay_sign = data [2] != 0;
330                         }
331                         if (cattrs != null) {
332                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
333                                 cattrs.CopyTo (new_array, 0);
334                                 new_array [cattrs.Length] = customBuilder;
335                                 cattrs = new_array;
336                         } else {
337                                 cattrs = new CustomAttributeBuilder [1];
338                                 cattrs [0] = customBuilder;
339                         }
340                 }
341                 public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
342                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
343                 }
344
345                 public void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
346                         this.corlib_object_type = corlib_object_type;
347                         this.corlib_value_type = corlib_value_type;
348                         this.corlib_enum_type = corlib_enum_type;
349                 }
350         }
351 }