Add new CAS unit tests for System.Drawing.dll
[mono.git] / mcs / ilasm / Driver.cs
1 //
2 // Mono.ILASM.Driver
3 //    Main Command line interface for Mono ILasm Compiler
4 //
5 // Author(s):
6 //  Jackson Harper (Jackson@LatitudeGeo.com)
7 //
8 // (C) 2003 Jackson Harper, All rights reserved
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 //
11
12 using System;
13 using System.IO;
14 using System.Reflection;
15 using System.Collections;
16 using System.Security.Cryptography;
17 using Mono.Security;
18
19 namespace Mono.ILASM {
20
21         public class Driver {
22
23                 enum Target {
24                         Dll,
25                         Exe
26                 }
27
28                 public static int Main (string[] args)
29                 {
30                         // Do everything in Invariant
31                         System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
32
33                         DriverMain driver = new DriverMain (args);
34                                 if (!driver.Run ()) {
35                                         Console.WriteLine ();
36                                         Console.WriteLine ("***** FAILURE *****");
37                                         return 1;
38                                 }
39                         Console.WriteLine ("Operation completed successfully");
40                         return 0;
41                 }
42
43                 private class DriverMain {
44
45                         private ArrayList il_file_list;
46                         private Report report;
47                         private string output_file;
48                         private Target target = Target.Exe;
49                         private string target_string = "exe";
50                         private bool quiet = false;
51                         private bool show_tokens = false;
52                         private bool show_method_def = false;
53                         private bool show_method_ref = false;
54                         private bool show_parser = false;
55                         private bool scan_only = false;
56                         private bool debugging_info = false;
57                         private CodeGen codegen;
58                         private bool keycontainer = false;
59                         private string keyname;
60
61                         public DriverMain (string[] args)
62                         {
63                                 il_file_list = new ArrayList ();
64                                 ParseArgs (args);
65                                 report = new Report (quiet);
66                         }
67
68                         public bool Run ()
69                         {
70                                         if (il_file_list.Count == 0)
71                                                 Usage ();
72                                         if (output_file == null)
73                                                 output_file = CreateOutputFile ();
74                                         codegen = new CodeGen (output_file, target == Target.Dll, true, debugging_info, report);
75                                         foreach (string file_path in il_file_list)
76                                                 ProcessFile (file_path);
77                                         if (scan_only)
78                                                 return true;
79
80                                         if (report.ErrorCount > 0)
81                                                 return false;
82                                         codegen.Write ();
83
84                                 try {
85                                         if (keyname != null) {
86                                                 Console.WriteLine ("Signing assembly with the specified strongname keypair");
87                                                 return Sign (output_file);
88                                         }
89                                 } catch {
90                                         return false;
91                                 }
92
93                                 return true;
94                         }
95
96                         private bool Sign (string filename)
97                         {
98                                 // note: if the file cannot be signed (no public key in it) then
99                                 // we do not show an error, or a warning, if the key file doesn't 
100                                 // exists
101                                 StrongName sn = null;
102                                 if (keycontainer) {
103                                         CspParameters csp = new CspParameters ();
104                                         csp.KeyContainerName = keyname;
105                                         RSACryptoServiceProvider rsa = new RSACryptoServiceProvider (csp);
106                                         sn = new StrongName (rsa);
107                                 } else {
108                                         byte[] data = null;
109                                         using (FileStream fs = File.OpenRead (keyname)) {
110                                                 data = new byte [fs.Length];
111                                                 fs.Read (data, 0, data.Length);
112                                                 fs.Close ();
113                                         }
114                                         sn = new StrongName (data);
115                                 }
116                                 return sn.Sign (filename);
117                         }
118
119                         private void ProcessFile (string file_path)
120                         {
121                                 if (!File.Exists (file_path)) {
122                                         Console.WriteLine ("File does not exist: {0}",
123                                                 file_path);
124                                         Environment.Exit (2);
125                                 }
126                                 report.AssembleFile (file_path, null,
127                                                 target_string, output_file);
128                                 StreamReader reader = File.OpenText (file_path);
129                                 ILTokenizer scanner = new ILTokenizer (reader);
130
131                                 if (show_tokens)
132                                         scanner.NewTokenEvent += new NewTokenEvent (ShowToken);
133                                 //if (show_method_def)
134                                 //        MethodTable.MethodDefinedEvent += new MethodDefinedEvent (ShowMethodDef);
135                                 //if (show_method_ref)
136                                 //       MethodTable.MethodReferencedEvent += new MethodReferencedEvent (ShowMethodRef);
137
138                                 if (scan_only) {
139                                         ILToken tok;
140                                         while ((tok = scanner.NextToken) != ILToken.EOF) {
141                                                 Console.WriteLine (tok);
142                                         }
143                                         return;
144                                 }
145
146                                 ILParser parser = new ILParser (codegen, scanner);
147                                 codegen.BeginSourceFile (file_path);
148                                 try {
149                                         if (show_parser)
150                                                 parser.yyparse (new ScannerAdapter (scanner),
151                                                                 new yydebug.yyDebugSimple ());
152                                         else
153                                                 parser.yyparse (new ScannerAdapter (scanner),  null);
154                                 } catch (ILTokenizingException ilte) {
155                                         report.Error (file_path + "(" + ilte.Location.line + ") : error : " +
156                                                         "syntax error at token '" + ilte.Token + "'.");
157                                 } catch {
158                                         Console.WriteLine ("Error at: " + scanner.Reader.Location);
159                                         throw;
160                                 } finally {
161                                         codegen.EndSourceFile ();
162                                 }
163                         }
164
165                         public void ShowToken (object sender, NewTokenEventArgs args)
166                         {
167                                 Console.WriteLine ("token: '{0}'", args.Token);
168                         }
169                         /*
170                         public void ShowMethodDef (object sender, MethodDefinedEventArgs args)
171                         {
172                                 Console.WriteLine ("***** Method defined *****");
173                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
174                                 Console.WriteLine ("-- name:        {0}", args.Name);
175                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
176                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
177                                 Console.WriteLine ("-- method atts: {0}", args.MethodAttributes);
178                                 Console.WriteLine ("-- impl atts:   {0}", args.ImplAttributes);
179                                 Console.WriteLine ("-- call conv:   {0}", args.CallConv);
180                         }
181
182                         public void ShowMethodRef (object sender, MethodReferencedEventArgs args)
183                         {
184                                 Console.WriteLine ("***** Method referenced *****");
185                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
186                                 Console.WriteLine ("-- name:        {0}", args.Name);
187                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
188                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
189                         }
190                         */
191                         private void ParseArgs (string[] args)
192                         {
193                                 string command_arg;
194                                 foreach (string str in args) {
195                                         if ((str[0] != '-') && (str[0] != '/')) {
196                                                 il_file_list.Add (str);
197                                                 continue;
198                                         }
199                                         switch (GetCommand (str, out command_arg)) {
200                                         case "out":
201                                         case "output":
202                                                 output_file = command_arg;
203                                                 break;
204                                         case "exe":
205                                                 target = Target.Exe;
206                                                 target_string = "exe";
207                                                 break;
208                                         case "dll":
209                                                 target = Target.Dll;
210                                                 target_string = "dll";
211                                                 break;
212                                         case "quiet":
213                                                 quiet = true;
214                                                 break;
215                                         case "debug":
216                                         case "deb":
217                                                 if (str[0] != '-')
218                                                         break;
219                                                 debugging_info = true;
220                                                 break;
221                                         // Stubs to stay commandline compatible with MS 
222                                         case "listing":
223                                         case "nologo":
224                                         case "clock":
225                                         case "error":
226                                         case "subsystem":
227                                         case "flags":
228                                         case "alignment":
229                                         case "base":
230                                         case "resource":
231                                                 break;
232                                         case "key":
233                                                 if (command_arg.Length > 0)
234                                                         keycontainer = (command_arg [0] == '@');
235                                                 if (keycontainer)
236                                                         keyname = command_arg.Substring (1);
237                                                 else
238                                                         keyname = command_arg;
239                                                 break;
240                                         case "scan_only":
241                                                 scan_only = true;
242                                                 break;
243                                         case "show_tokens":
244                                                 show_tokens = true;
245                                                 break;
246                                         case "show_method_def":
247                                                 show_method_def = true;
248                                                 break;
249                                         case "show_method_ref":
250                                                 show_method_ref = true;
251                                                 break;
252                                         case "show_parser":
253                                                 show_parser = true;
254                                                 break;
255                                         case "-about":
256                                                 if (str[0] != '-')
257                                                         break;
258                                                 About ();
259                                                 break;
260                                         case "-version":
261                                                 if (str[0] != '-')
262                                                         break;
263                                                 Version ();
264                                                 break;
265                                         default:
266                                                 if (str [0] == '-')
267                                                         break;
268                                                 il_file_list.Add (str);
269                                                 break;
270                                         }
271                                 }
272                         }
273
274                         private string GetCommand (string str, out string command_arg)
275                         {
276                                 int end_index = str.IndexOfAny (new char[] {':', '='}, 1);
277                                 string command = str.Substring (1,
278                                         end_index == -1 ? str.Length - 1 : end_index - 1);
279
280                                 if (end_index != -1) {
281                                         command_arg = str.Substring (end_index+1);
282                                 } else {
283                                         command_arg = null;
284                                 }
285
286                                 return command.ToLower ();
287                         }
288
289                         /// <summary>
290                         ///   Get the first file name and makes it into an output file name
291                         /// </summary>
292                         private string CreateOutputFile ()
293                         {
294                                 string file_name = (string)il_file_list[0];
295                                 int ext_index = file_name.LastIndexOf ('.');
296
297                                 if (ext_index == -1)
298                                         ext_index = file_name.Length;
299
300                                 return String.Format ("{0}.{1}", file_name.Substring (0, ext_index),
301                                         target_string);
302                         }
303
304                         private void Usage ()
305                         {
306                                 Console.WriteLine ("Mono ILasm compiler\n" +
307                                         "ilasm [options] source-files\n" +
308                                         "   --about            About the Mono ILasm compiler\n" +
309                                         "   --version          Print the version number of the Mono ILasm compiler\n" +
310                                         "   /output:file_name  Specifies output file.\n" +
311                                         "   /exe               Compile to executable.\n" +
312                                         "   /dll               Compile to library.\n" +
313                                         "   /debug             Include debug information.\n" +
314                                         "   /key:keyfile       Strongname using the specified key file\n" +
315                                         "   /key:@container    Strongname using the specified key container\n" +
316                                         "Options can be of the form -option or /option\n");
317                                 Environment.Exit (1);
318                         }
319
320                         private void About ()
321                         {
322                                 Console.WriteLine (
323                                         "For more information on Mono, visit the project Web site\n" +
324                                         "   http://www.go-mono.com\n\n");
325                                 Environment.Exit (0);
326                         }
327
328                         private void Version ()
329                         {
330                                 string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
331                                 Console.WriteLine ("Mono ILasm compiler version {0}", version);
332                                 Environment.Exit (0);
333                         }
334
335                 }
336         }
337 }
338