Fix LinearGradientMode parameter validation to match corefx (#5672)
[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                                 return 1;
36                         Report.Message ("Operation completed successfully");
37                         return 0;
38                 }
39
40                 private class DriverMain {
41
42                         private ArrayList il_file_list;
43                         private string output_file;
44                         private Target target = Target.Exe;
45                         private string target_string = "exe";
46                         private bool show_tokens = false;
47 //                        private bool show_method_def = false;
48 //                        private bool show_method_ref = false;
49                         private bool show_parser = false;
50                         private bool scan_only = false;
51                         private bool debugging_info = false;
52                         private CodeGen codegen;
53                         private bool keycontainer = false;
54                         private string keyname;
55                         private StrongName sn;
56                         bool noautoinherit;
57
58                         public DriverMain (string[] args)
59                         {
60                                 il_file_list = new ArrayList ();
61                                 ParseArgs (args);
62                         }
63
64                         public bool Run ()
65                         {
66                                 if (il_file_list.Count == 0)
67                                         Usage ();
68                                 if (output_file == null)
69                                         output_file = CreateOutputFilename ();
70                                 try {
71                                         codegen = new CodeGen (output_file, target == Target.Dll, debugging_info, noautoinherit);
72                                         foreach (string file_path in il_file_list) {
73                                                 Report.FilePath = file_path;
74                                                 ProcessFile (file_path);
75                                         }
76                                         if (scan_only)
77                                                 return true;
78
79                                         if (Report.ErrorCount > 0)
80                                                 return false;
81
82                                         if (target != Target.Dll && !codegen.HasEntryPoint)
83                                                 Report.Error ("No entry point found.");
84
85                                         // if we have a key and aren't assembling a netmodule
86                                         if ((keyname != null) && !codegen.IsThisAssembly (null)) {
87                                                 LoadKey ();
88                                                 // this overrides any attribute or .publickey directive in the source
89                                                 codegen.ThisAssembly.SetPublicKey (sn.PublicKey);
90                                         }
91
92                                         try {
93                                                 codegen.Write ();
94                                         } catch {
95                                                 File.Delete (output_file);
96                                                 throw;
97                                         }
98                                 } catch (ILAsmException e) {
99                                         Error (e.ToString ());
100                                         return false;
101                                 } catch (PEAPI.PEFileException pe) {
102                                         Error ("Error : " + pe.Message);
103                                         return false;
104                                 } 
105
106                                 try {
107                                         if (sn != null) {
108                                                 Report.Message ("Signing assembly with the specified strongname keypair");
109                                                 return Sign (output_file);
110                                         }
111                                 } catch {
112                                         return false;
113                                 }
114
115                                 return true;
116                         }
117
118                         private void Error (string message)
119                         {
120                                 Console.WriteLine (message + "\n");
121                                 Console.WriteLine ("***** FAILURE *****\n");
122                         }
123
124                         private void LoadKey ()
125                         {
126                                 if (keycontainer) {
127                                         CspParameters csp = new CspParameters ();
128                                         csp.KeyContainerName = keyname;
129                                         RSACryptoServiceProvider rsa = new RSACryptoServiceProvider (csp);
130                                         sn = new StrongName (rsa);
131                                 } else {
132                                         byte[] data = null;
133                                         using (FileStream fs = File.OpenRead (keyname)) {
134                                                 data = new byte [fs.Length];
135                                                 fs.Read (data, 0, data.Length);
136                                                 fs.Close ();
137                                         }
138                                         sn = new StrongName (data);
139                                 }
140                         }
141
142                         private bool Sign (string filename)
143                         {
144                                 // note: if the file cannot be signed (no public key in it) then
145                                 // we do not show an error, or a warning, if the key file doesn't 
146                                 // exists
147                                 return sn.Sign (filename);
148                         }
149
150                         private void ProcessFile (string file_path)
151                         {
152                                 if (!File.Exists (file_path)) {
153                                         Console.WriteLine ("File does not exist: {0}",
154                                                 file_path);
155                                         Environment.Exit (2);
156                                 }
157                                 Report.AssembleFile (file_path, null,
158                                                 target_string, output_file);
159                                 StreamReader reader = File.OpenText (file_path);
160                                 ILTokenizer scanner = new ILTokenizer (reader);
161
162                                 if (show_tokens)
163                                         scanner.NewTokenEvent += new NewTokenEvent (ShowToken);
164                                 //if (show_method_def)
165                                 //        MethodTable.MethodDefinedEvent += new MethodDefinedEvent (ShowMethodDef);
166                                 //if (show_method_ref)
167                                 //       MethodTable.MethodReferencedEvent += new MethodReferencedEvent (ShowMethodRef);
168
169                                 if (scan_only) {
170                                         ILToken tok;
171                                         while ((tok = scanner.NextToken) != ILToken.EOF) {
172                                                 Console.WriteLine (tok);
173                                         }
174                                         return;
175                                 }
176
177                                 ILParser parser = new ILParser (codegen, scanner);
178                                 codegen.BeginSourceFile (file_path);
179                                 try {
180                                         if (show_parser)
181                                                 parser.yyparse (new ScannerAdapter (scanner),
182                                                                 new yydebug.yyDebugSimple ());
183                                         else
184                                                 parser.yyparse (new ScannerAdapter (scanner),  null);
185                                 } catch (ILTokenizingException ilte) {
186                                         Report.Error (ilte.Location, "syntax error at token '" + ilte.Token + "'");
187                                 } catch (Mono.ILASM.yyParser.yyException ye) {
188                                         Report.Error (scanner.Reader.Location, ye.Message);
189                                 } catch (ILAsmException ie) {
190                                         ie.FilePath = file_path;
191                                         ie.Location = scanner.Reader.Location;
192                                         throw;
193                                 } catch (Exception){
194                                         Console.Write ("{0} ({1}, {2}): ",file_path, scanner.Reader.Location.line, scanner.Reader.Location.column);
195                                         throw;
196                                 } finally {
197                                         codegen.EndSourceFile ();
198                                 }
199                         }
200
201                         public void ShowToken (object sender, NewTokenEventArgs args)
202                         {
203                                 Console.WriteLine ("token: '{0}'", args.Token);
204                         }
205                         /*
206                         public void ShowMethodDef (object sender, MethodDefinedEventArgs args)
207                         {
208                                 Console.WriteLine ("***** Method defined *****");
209                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
210                                 Console.WriteLine ("-- name:        {0}", args.Name);
211                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
212                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
213                                 Console.WriteLine ("-- method atts: {0}", args.MethodAttributes);
214                                 Console.WriteLine ("-- impl atts:   {0}", args.ImplAttributes);
215                                 Console.WriteLine ("-- call conv:   {0}", args.CallConv);
216                         }
217
218                         public void ShowMethodRef (object sender, MethodReferencedEventArgs args)
219                         {
220                                 Console.WriteLine ("***** Method referenced *****");
221                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
222                                 Console.WriteLine ("-- name:        {0}", args.Name);
223                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
224                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
225                         }
226                         */
227                         private void ParseArgs (string[] args)
228                         {
229                                 string command_arg;
230                                 foreach (string str in args) {
231                                         if ((str[0] != '-') && (str[0] != '/')) {
232                                                 il_file_list.Add (str);
233                                                 continue;
234                                         }
235                                         switch (GetCommand (str, out command_arg)) {
236                                         case "out":
237                                         case "output":
238                                                 output_file = command_arg;
239                                                 break;
240                                         case "exe":
241                                                 target = Target.Exe;
242                                                 target_string = "exe";
243                                                 break;
244                                         case "dll":
245                                                 target = Target.Dll;
246                                                 target_string = "dll";
247                                                 break;
248                                         case "quiet":
249                                                 Report.Quiet = true;
250                                                 break;
251                                         case "debug":
252                                         case "deb":
253                                                 debugging_info = true;
254                                                 break;
255                                         // Stubs to stay commandline compatible with MS 
256                                         case "listing":
257                                         case "nologo":
258                                         case "clock":
259                                         case "error":
260                                         case "subsystem":
261                                         case "flags":
262                                         case "alignment":
263                                         case "base":
264                                         case "resource":
265                                                 break;
266                                         case "key":
267                                                 if (command_arg.Length > 0)
268                                                         keycontainer = (command_arg [0] == '@');
269                                                 if (keycontainer)
270                                                         keyname = command_arg.Substring (1);
271                                                 else
272                                                         keyname = command_arg;
273                                                 break;
274                                         case "noautoinherit":
275                                                 noautoinherit = true;
276                                                 break;
277                                         case "scan_only":
278                                                 scan_only = true;
279                                                 break;
280                                         case "show_tokens":
281                                                 show_tokens = true;
282                                                 break;
283                                         case "show_method_def":
284 //                                                show_method_def = true;
285                                                 break;
286                                         case "show_method_ref":
287 //                                                show_method_ref = true;
288                                                 break;
289                                         case "show_parser":
290                                                 show_parser = true;
291                                                 break;
292                                         case "-about":
293                                                 if (str[0] != '-')
294                                                         break;
295                                                 About ();
296                                                 break;
297                                         case "-version":
298                                                 if (str[0] != '-')
299                                                         break;
300                                                 Version ();
301                                                 break;
302                                         default:
303                                                 if (str [0] == '-')
304                                                         break;
305                                                 il_file_list.Add (str);
306                                                 break;
307                                         }
308                                 }
309                         }
310
311                         private string GetCommand (string str, out string command_arg)
312                         {
313                                 int end_index = str.IndexOfAny (new char[] {':', '='}, 1);
314                                 string command = str.Substring (1,
315                                         end_index == -1 ? str.Length - 1 : end_index - 1);
316
317                                 if (end_index != -1) {
318                                         command_arg = str.Substring (end_index+1);
319                                 } else {
320                                         command_arg = null;
321                                 }
322
323                                 return command.ToLower ();
324                         }
325
326                         /// <summary>
327                         ///   Get the first file name and makes it into an output file name
328                         /// </summary>
329                         private string CreateOutputFilename ()
330                         {
331                                 string file_name = (string)il_file_list[0];
332                                 int ext_index = file_name.LastIndexOf ('.');
333
334                                 if (ext_index == -1)
335                                         ext_index = file_name.Length;
336
337                                 return String.Format ("{0}.{1}", file_name.Substring (0, ext_index),
338                                         target_string);
339                         }
340
341                         private void Usage ()
342                         {
343                                 Console.WriteLine ("Mono IL assembler compiler\n" +
344                                         "ilasm [options] source-files\n" +
345                                         "   --about            About the Mono IL assembler compiler\n" +
346                                         "   --version          Print the version number of the compiler\n" +
347                                         "   /output:file_name  Specifies output file.\n" +
348                                         "   /exe               Compile to executable.\n" +
349                                         "   /dll               Compile to library.\n" +
350                                         "   /debug             Include debug information.\n" +
351                                         "   /key:keyfile       Strongname using the specified key file\n" +
352                                         "   /key:@container    Strongname using the specified key container\n" +
353                                         "   /noautoinherit     Disable inheriting from System.Object by default\n" +
354                                         "Options can be of the form -option or /option\n");
355                                 Environment.Exit (1);
356                         }
357
358                         private void About ()
359                         {
360                                 Console.WriteLine (
361                                         "For more information on Mono, visit the project Web site\n" +
362                                         "   http://www.go-mono.com\n\n");
363                                 Environment.Exit (0);
364                         }
365
366                         private void Version ()
367                         {
368                                 string version = System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
369                                 Console.WriteLine ("Mono IL assembler compiler version {0}", version);
370                                 Environment.Exit (0);
371                         }
372
373                 }
374         }
375 }
376