// Jackson Harper (Jackson@LatitudeGeo.com)
//
// (C) 2003 Jackson Harper, All rights reserved
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
using System;
using System.IO;
using System.Reflection;
using System.Collections;
+using System.Security.Cryptography;
+using Mono.Security;
namespace Mono.ILASM {
public static int Main (string[] args)
{
+ // Do everything in Invariant
+ System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
+
DriverMain driver = new DriverMain (args);
- try {
- driver.Run ();
- } catch (Exception e) {
- Console.WriteLine (e);
- Console.WriteLine ("Error while compiling.");
+ if (!driver.Run ())
return 1;
- }
- Console.WriteLine ("Compilation succeeded");
+ Report.Message ("Operation completed successfully");
return 0;
}
private class DriverMain {
private ArrayList il_file_list;
- private Report report;
private string output_file;
private Target target = Target.Exe;
private string target_string = "exe";
- private bool quiet = false;
private bool show_tokens = false;
private bool show_method_def = false;
private bool show_method_ref = false;
private bool show_parser = false;
private bool scan_only = false;
+ private bool debugging_info = false;
private CodeGen codegen;
+ private bool keycontainer = false;
+ private string keyname;
+ private StrongName sn;
public DriverMain (string[] args)
{
il_file_list = new ArrayList ();
ParseArgs (args);
- report = new Report (quiet);
}
- public void Run ()
+ public bool Run ()
{
+ if (il_file_list.Count == 0)
+ Usage ();
+ if (output_file == null)
+ output_file = CreateOutputFilename ();
try {
- if (il_file_list.Count == 0)
- Usage ();
- if (output_file == null)
- output_file = CreateOutputFile ();
- codegen = new CodeGen (output_file, target == Target.Dll, true, report);
- foreach (string file_path in il_file_list)
+ codegen = new CodeGen (output_file, target == Target.Dll, debugging_info);
+ foreach (string file_path in il_file_list) {
+ Report.FilePath = file_path;
ProcessFile (file_path);
+ }
if (scan_only)
- return;
+ return true;
+
+ if (Report.ErrorCount > 0)
+ return false;
+
+ if (target != Target.Dll && !codegen.HasEntryPoint)
+ Report.Error ("No entry point found.");
+
+ // if we have a key and aren't assembling a netmodule
+ if ((keyname != null) && !codegen.IsThisAssembly (null)) {
+ LoadKey ();
+ // this overrides any attribute or .publickey directive in the source
+ codegen.ThisAssembly.SetPublicKey (sn.PublicKey);
+ }
- codegen.Write ();
+ try {
+ codegen.Write ();
+ } catch {
+ File.Delete (output_file);
+ throw;
+ }
+ } catch (ILAsmException e) {
+ Error (e.ToString ());
+ return false;
+ } catch (PEAPI.PEFileException pe) {
+ Error ("Error : " + pe.Message);
+ return false;
+ }
+
+ try {
+ if (sn != null) {
+ Report.Message ("Signing assembly with the specified strongname keypair");
+ return Sign (output_file);
+ }
} catch {
- throw;
+ return false;
}
+
+ return true;
}
+ private void Error (string message)
+ {
+ Console.WriteLine (message + "\n");
+ Console.WriteLine ("***** FAILURE *****\n");
+ }
+
+ private void LoadKey ()
+ {
+ if (keycontainer) {
+ CspParameters csp = new CspParameters ();
+ csp.KeyContainerName = keyname;
+ RSACryptoServiceProvider rsa = new RSACryptoServiceProvider (csp);
+ sn = new StrongName (rsa);
+ } else {
+ byte[] data = null;
+ using (FileStream fs = File.OpenRead (keyname)) {
+ data = new byte [fs.Length];
+ fs.Read (data, 0, data.Length);
+ fs.Close ();
+ }
+ sn = new StrongName (data);
+ }
+ }
+
+ private bool Sign (string filename)
+ {
+ // note: if the file cannot be signed (no public key in it) then
+ // we do not show an error, or a warning, if the key file doesn't
+ // exists
+ return sn.Sign (filename);
+ }
+
private void ProcessFile (string file_path)
{
if (!File.Exists (file_path)) {
file_path);
Environment.Exit (2);
}
- report.AssembleFile (file_path, null,
+ Report.AssembleFile (file_path, null,
target_string, output_file);
StreamReader reader = File.OpenText (file_path);
ILTokenizer scanner = new ILTokenizer (reader);
return;
}
- ILParser parser = new ILParser (codegen);
+ ILParser parser = new ILParser (codegen, scanner);
+ codegen.BeginSourceFile (file_path);
try {
if (show_parser)
parser.yyparse (new ScannerAdapter (scanner),
new yydebug.yyDebugSimple ());
else
parser.yyparse (new ScannerAdapter (scanner), null);
- } catch {
- Console.WriteLine ("Error at: " + scanner.Reader.Location);
+ } catch (ILTokenizingException ilte) {
+ Report.Error (ilte.Location, "syntax error at token '" + ilte.Token + "'");
+ } catch (Mono.ILASM.yyParser.yyException ye) {
+ Report.Error (scanner.Reader.Location, ye.Message);
+ } catch (ILAsmException ie) {
+ ie.FilePath = file_path;
+ ie.Location = scanner.Reader.Location;
throw;
- }
+ } catch (Exception e){
+ Console.Write ("{0} ({1}, {2}): ",file_path, scanner.Reader.Location.line, scanner.Reader.Location.column);
+ throw;
+ } finally {
+ codegen.EndSourceFile ();
+ }
}
public void ShowToken (object sender, NewTokenEventArgs args)
}
switch (GetCommand (str, out command_arg)) {
case "out":
+ case "output":
output_file = command_arg;
break;
case "exe":
target_string = "dll";
break;
case "quiet":
- quiet = true;
+ Report.Quiet = true;
+ break;
+ case "debug":
+ case "deb":
+ debugging_info = true;
+ break;
+ // Stubs to stay commandline compatible with MS
+ case "listing":
+ case "nologo":
+ case "clock":
+ case "error":
+ case "subsystem":
+ case "flags":
+ case "alignment":
+ case "base":
+ case "resource":
break;
+ case "key":
+ if (command_arg.Length > 0)
+ keycontainer = (command_arg [0] == '@');
+ if (keycontainer)
+ keyname = command_arg.Substring (1);
+ else
+ keyname = command_arg;
+ break;
case "scan_only":
scan_only = true;
break;
break;
Version ();
break;
+ default:
+ if (str [0] == '-')
+ break;
+ il_file_list.Add (str);
+ break;
}
}
}
/// <summary>
/// Get the first file name and makes it into an output file name
/// </summary>
- private string CreateOutputFile ()
+ private string CreateOutputFilename ()
{
string file_name = (string)il_file_list[0];
int ext_index = file_name.LastIndexOf ('.');
"ilasm [options] source-files\n" +
" --about About the Mono ILasm compiler\n" +
" --version Print the version number of the Mono ILasm compiler\n" +
- " /out:file_name Specifies output file.\n" +
+ " /output:file_name Specifies output file.\n" +
" /exe Compile to executable.\n" +
" /dll Compile to library.\n" +
+ " /debug Include debug information.\n" +
+ " /key:keyfile Strongname using the specified key file\n" +
+ " /key:@container Strongname using the specified key container\n" +
"Options can be of the form -option or /option\n");
Environment.Exit (1);
}
private void Version ()
{
- string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
+ string version = System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
Console.WriteLine ("Mono ILasm compiler version {0}", version);
Environment.Exit (0);
}