[corlib] Allow DM with an extra param to have the first one bound to null. Fixes...
[mono-project.git] / mcs / ilasm / Driver.cs
blobfc2e213bc8730dfb332386dbb5b7447eab669dac
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)
12 using System;
13 using System.IO;
14 using System.Reflection;
15 using System.Collections;
16 using System.Security.Cryptography;
17 using Mono.Security;
19 namespace Mono.ILASM {
21 public class Driver {
23 enum Target {
24 Dll,
25 Exe
28 public static int Main (string[] args)
30 // Do everything in Invariant
31 System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
33 DriverMain driver = new DriverMain (args);
34 if (!driver.Run ())
35 return 1;
36 Report.Message ("Operation completed successfully");
37 return 0;
40 private class DriverMain {
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;
58 public DriverMain (string[] args)
60 il_file_list = new ArrayList ();
61 ParseArgs (args);
64 public bool Run ()
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);
76 if (scan_only)
77 return true;
79 if (Report.ErrorCount > 0)
80 return false;
82 if (target != Target.Dll && !codegen.HasEntryPoint)
83 Report.Error ("No entry point found.");
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);
92 try {
93 codegen.Write ();
94 } catch {
95 File.Delete (output_file);
96 throw;
98 } catch (ILAsmException e) {
99 Error (e.ToString ());
100 return false;
101 } catch (PEAPI.PEFileException pe) {
102 Error ("Error : " + pe.Message);
103 return false;
106 try {
107 if (sn != null) {
108 Report.Message ("Signing assembly with the specified strongname keypair");
109 return Sign (output_file);
111 } catch {
112 return false;
115 return true;
118 private void Error (string message)
120 Console.WriteLine (message + "\n");
121 Console.WriteLine ("***** FAILURE *****\n");
124 private void LoadKey ()
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 ();
138 sn = new StrongName (data);
142 private bool Sign (string filename)
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);
150 private void ProcessFile (string file_path)
152 if (!File.Exists (file_path)) {
153 Console.WriteLine ("File does not exist: {0}",
154 file_path);
155 Environment.Exit (2);
157 Report.AssembleFile (file_path, null,
158 target_string, output_file);
159 StreamReader reader = File.OpenText (file_path);
160 ILTokenizer scanner = new ILTokenizer (reader);
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);
169 if (scan_only) {
170 ILToken tok;
171 while ((tok = scanner.NextToken) != ILToken.EOF) {
172 Console.WriteLine (tok);
174 return;
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 ();
201 public void ShowToken (object sender, NewTokenEventArgs args)
203 Console.WriteLine ("token: '{0}'", args.Token);
206 public void ShowMethodDef (object sender, MethodDefinedEventArgs args)
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);
218 public void ShowMethodRef (object sender, MethodReferencedEventArgs args)
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);
227 private void ParseArgs (string[] args)
229 string command_arg;
230 foreach (string str in args) {
231 if ((str[0] != '-') && (str[0] != '/')) {
232 il_file_list.Add (str);
233 continue;
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;
311 private string GetCommand (string str, out string command_arg)
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);
317 if (end_index != -1) {
318 command_arg = str.Substring (end_index+1);
319 } else {
320 command_arg = null;
323 return command.ToLower ();
326 /// <summary>
327 /// Get the first file name and makes it into an output file name
328 /// </summary>
329 private string CreateOutputFilename ()
331 string file_name = (string)il_file_list[0];
332 int ext_index = file_name.LastIndexOf ('.');
334 if (ext_index == -1)
335 ext_index = file_name.Length;
337 return String.Format ("{0}.{1}", file_name.Substring (0, ext_index),
338 target_string);
341 private void Usage ()
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);
358 private void About ()
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);
366 private void Version ()
368 string version = System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
369 Console.WriteLine ("Mono IL assembler compiler version {0}", version);
370 Environment.Exit (0);