Switch to compiler-tester
[mono.git] / mcs / gmcs / driver.cs
old mode 100755 (executable)
new mode 100644 (file)
index 53e6096..d50bf53
@@ -6,6 +6,7 @@
 // Licensed under the terms of the GNU GPL
 //
 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
 //
 
 namespace Mono.CSharp
@@ -14,11 +15,13 @@ namespace Mono.CSharp
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Collections;
+       using System.Diagnostics;
        using System.IO;
        using System.Text;
        using System.Globalization;
+       using System.Xml;
 
-       enum Target {
+       public enum Target {
                Library, Exe, Module, WinExe
        };
        
@@ -40,40 +43,38 @@ namespace Mono.CSharp
                //
                static ArrayList soft_references;
 
+               //
+               // Modules to be linked
+               //
+               static ArrayList modules;
+
                // Lookup paths
                static ArrayList link_paths;
 
-               // Whether we want Yacc to output its progress
-               static bool yacc_verbose = false;
-
                // Whether we want to only run the tokenizer
                static bool tokenize = false;
                
                static string first_source;
 
-               static Target target = Target.Exe;
-               static string target_ext = ".exe";
-
                static bool want_debugging_support = false;
 
                static bool parse_only = false;
                static bool timestamps = false;
                static bool pause = false;
                static bool show_counters = false;
-               public static bool parser_verbose = false;
                
                //
                // Whether to load the initial config file (what CSC.RSP has by default)
                // 
                static bool load_default_config = true;
 
-               static Hashtable response_file_list;
-
                //
                // A list of resource files
                //
                static ArrayList resources;
                static ArrayList embedded_resources;
+               static string win32ResourceFile;
+               static string win32IconFile;
                
                //
                // An array of the defines from the command line
@@ -99,7 +100,25 @@ namespace Mono.CSharp
                // Whether the user has specified a different encoder manually
                //
                static bool using_default_encoder = true;
-               
+
+
+               static public void Reset ()
+               {
+                       want_debugging_support = false;
+                       parse_only = false;
+                       timestamps = false;
+                       pause = false;
+                       show_counters = false;
+                       load_default_config = true;
+                       resources = embedded_resources = null;
+                       win32ResourceFile = win32IconFile = null;
+                       defines = null;
+                       output_file = null;
+                       encoding = null;
+                       using_default_encoder = true;
+                       first_source = null;
+               }
+
                public static void ShowTime (string msg)
                {
                        if (!timestamps)
@@ -145,7 +164,6 @@ namespace Mono.CSharp
                                int token, tokens = 0, errors = 0;
 
                                while ((token = lexer.token ()) != Token.EOF){
-                                       Location l = lexer.Location;
                                        tokens++;
                                        if (token == Token.ERROR)
                                                errors++;
@@ -172,7 +190,7 @@ namespace Mono.CSharp
                        SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
                                
                        parser = new CSharpParser (reader, file, defines);
-                       parser.yacc_verbose_flag = yacc_verbose;
+                       parser.ErrorOutput = Report.Stderr;
                        try {
                                parser.parse ();
                        } catch (Exception ex) {
@@ -182,44 +200,59 @@ namespace Mono.CSharp
                        }
                }
                
+               static void OtherFlags ()
+               {
+                       Console.WriteLine (
+                               "Other flags in the compiler\n" +
+                               "   --fatal            Makes errors fatal\n" +
+                               "   --parse            Only parses the source file\n" +
+                               "   --stacktrace       Shows stack trace at error location\n" +
+                               "   --timestamp        Displays time stamps of various compiler events\n" +
+                               "   --expect-error X   Expect that error X will be encountered\n" +
+                               "   -2                 Enables experimental C# features\n" +
+                               "   -v                 Verbose parsing (for debugging the parser)\n" + 
+                               "   --mcs-debug X      Sets MCS debugging level to X\n");
+               }
+               
                static void Usage ()
                {
                        Console.WriteLine (
                                "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" +
                                "mcs [options] source-files\n" +
                                "   --about            About the Mono C# compiler\n" +
+                               "   -addmodule:MODULE  Adds the module to the generated assembly\n" + 
                                "   -checked[+|-]      Set default context to checked\n" +
-                               "   -codepage:ID       Sets code page to the one in ID\n" +
-                               "                      (number, `utf8' or `reset')\n" +
+                               "   -codepage:ID       Sets code page to the one in ID (number, utf8, reset)\n" +
+                               "   -clscheck[+|-]     Disables CLS Compliance verifications" + Environment.NewLine +
                                "   -define:S1[;S2]    Defines one or more symbols (short: /d:)\n" +
-                               "   -debug[+-]         Generate debugging information\n" + 
+                               "   -debug[+|-], -g    Generate debugging information\n" + 
+                               "   -delaysign[+|-]    Only insert the public key into the assembly (no signing)\n" +
                                "   -doc:FILE          XML Documentation file to generate\n" + 
-                               "   -g                 Generate debugging information\n" +
-                               "   --fatal            Makes errors fatal\n" +
+                               "   -keycontainer:NAME The key pair container used to strongname the assembly\n" +
+                               "   -keyfile:FILE      The strongname key file used to strongname the assembly\n" +
+                               "   -langversion:TEXT  Specifies language version modes: ISO-1 or Default\n" + 
                                "   -lib:PATH1,PATH2   Adds the paths to the assembly link path\n" +
                                "   -main:class        Specified the class that contains the entry point\n" +
                                "   -noconfig[+|-]     Disables implicit references to assemblies\n" +
                                "   -nostdlib[+|-]     Does not load core libraries\n" +
                                "   -nowarn:W1[,W2]    Disables one or more warnings\n" + 
+                               "   -optimize[+|-]     Enables code optimalizations\n" + 
                                "   -out:FNAME         Specifies output file\n" +
-                               "   --parse            Only parses the source file\n" +
-                               "   --expect-error X   Expect that error X will be encountered\n" +
+                               "   -pkg:P1[,Pn]       References packages P1..Pn\n" + 
                                "   -recurse:SPEC      Recursively compiles the files in SPEC ([dir]/file)\n" + 
                                "   -reference:ASS     References the specified assembly (-r:ASS)\n" +
-                               "   --stacktrace       Shows stack trace at error location\n" +
                                "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
                                "                      library, module), (short: /t:)\n" +
-                               "   --timestamp        Displays time stamps of various compiler events\n" +
                                "   -unsafe[+|-]       Allows unsafe code\n" +
                                "   -warnaserror[+|-]  Treat warnings as errors\n" +
-                               "   -warn:LEVEL        Sets warning level (the highest is 4, the default)\n" +
-                               "   -v                 Verbose parsing (for debugging the parser)\n" +
-                               "   -2                 Enables experimental C# features\n" +
+                               "   -warn:LEVEL        Sets warning level (the highest is 4, the default is 2)\n" +
+                               "   -help2             Show other help flags\n" + 
                                "\n" +
                                "Resources:\n" +
                                "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
                                "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
-                               "   --mcs-debug X      Sets MCS debugging level to X\n" +
+                               "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
+                               "   -win32icon:FILE         Use this icon for the output\n" +
                                 "   @file              Read response file for more options\n\n" +
                                "Options can be of the form -option or /option");
                }
@@ -238,23 +271,21 @@ namespace Mono.CSharp
                                "For more information on Mono, visit the project Web site\n" +
                                "   http://www.go-mono.com\n\n" +
 
-                               "The compiler was written by Miguel de Icaza, Ravi Pratap and Martin Baulig");
+                               "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath");
                        Environment.Exit (0);
                }
 
                public static int counter1, counter2;
                
-               public static int Main (string[] args)
+       public static int Main (string[] args)
                {
-                       RootContext.V2 = true;
+                       RootContext.Version = LanguageVersion.Default;
                        bool ok = MainDriver (args);
                        
                        if (ok && Report.Errors == 0) {
-                               Console.Write("Compilation succeeded");
                                if (Report.Warnings > 0) {
-                                       Console.Write(" - {0} warning(s)", Report.Warnings);
+                                       Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings);
                                }
-                               Console.WriteLine();
                                if (show_counters){
                                        Console.WriteLine ("Counter1: " + counter1);
                                        Console.WriteLine ("Counter2: " + counter2);
@@ -275,19 +306,22 @@ namespace Mono.CSharp
                        string total_log = "";
 
                        try {
-                               char[] path_chars = { '/', '\\', '.' };
+                               char[] path_chars = { '/', '\\' };
 
                                if (assembly.IndexOfAny (path_chars) != -1) {
                                        a = Assembly.LoadFrom (assembly);
                                } else {
-                                       a = Assembly.Load (assembly);
+                                       string ass = assembly;
+                                       if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
+                                               ass = assembly.Substring (0, assembly.Length - 4);
+                                       a = Assembly.Load (ass);
                                }
                                TypeManager.AddAssembly (a);
 
                        } catch (FileNotFoundException){
                                foreach (string dir in link_paths){
                                        string full_path = Path.Combine (dir, assembly);
-                                       if (!assembly.EndsWith (".dll"))
+                                       if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
                                                full_path += ".dll";
 
                                        try {
@@ -312,6 +346,52 @@ namespace Mono.CSharp
                        }
                }
 
+               static public void LoadModule (MethodInfo adder_method, string module)
+               {
+                       Module m;
+                       string total_log = "";
+
+                       try {
+                               try {
+                                       m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module });
+                               }
+                               catch (TargetInvocationException ex) {
+                                       throw ex.InnerException;
+                               }
+                               TypeManager.AddModule (m);
+
+                       } 
+                       catch (FileNotFoundException){
+                               foreach (string dir in link_paths){
+                                       string full_path = Path.Combine (dir, module);
+                                       if (!module.EndsWith (".netmodule"))
+                                               full_path += ".netmodule";
+
+                                       try {
+                                               try {
+                                                       m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
+                                               }
+                                               catch (TargetInvocationException ex) {
+                                                       throw ex.InnerException;
+                                               }
+                                               TypeManager.AddModule (m);
+                                               return;
+                                       } catch (FileNotFoundException ff) {
+                                               total_log += ff.FusionLog;
+                                               continue;
+                                       }
+                               }
+                               Report.Error (6, "Cannot find module `" + module + "'" );
+                               Console.WriteLine ("Log: \n" + total_log);
+                       } catch (BadImageFormatException f) {
+                               Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
+                       } catch (FileLoadException f){
+                               Report.Error(6, "Cannot load module " + f.FusionLog);
+                       } catch (ArgumentNullException){
+                               Report.Error(6, "Cannot load module (null argument)");
+                       }
+               }
+
                /// <summary>
                ///   Loads all assemblies referenced on the command line
                /// </summary>
@@ -386,17 +466,7 @@ namespace Mono.CSharp
                //
                static string GetSystemDir ()
                {
-                       Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
-
-                       foreach (Assembly a in assemblies){
-                               string codebase = a.Location;
-                               if (codebase.EndsWith ("corlib.dll")){
-                                       return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar));
-                               }
-                       }
-
-                       Report.Error (-15, "Can not compute my system path");
-                       return "";
+                       return Path.GetDirectoryName (typeof (object).Assembly.Location);
                }
 
                //
@@ -404,7 +474,7 @@ namespace Mono.CSharp
                //
                static void SplitPathAndPattern (string spec, out string path, out string pattern)
                {
-                       int p = spec.LastIndexOf ("/");
+                       int p = spec.LastIndexOf ('/');
                        if (p != -1){
                                //
                                // Windows does not like /file.cs, switch that to:
@@ -420,7 +490,7 @@ namespace Mono.CSharp
                                return;
                        }
 
-                       p = spec.LastIndexOf ("\\");
+                       p = spec.LastIndexOf ('\\');
                        if (p != -1){
                                path = spec.Substring (0, p);
                                pattern = spec.Substring (p + 1);
@@ -457,7 +527,7 @@ namespace Mono.CSharp
                        string path, pattern;
 
                        SplitPathAndPattern (spec, out path, out pattern);
-                       if (pattern.IndexOf ("*") == -1){
+                       if (pattern.IndexOf ('*') == -1){
                                ProcessFile (spec);
                                return;
                        }
@@ -547,19 +617,19 @@ namespace Mono.CSharp
                        } catch {
                                Report.Error (
                                        1900,
-                                       "--wlevel requires an value from 0 to 4");
-                               Environment.Exit (1);
+                                       "--wlevel requires a value from 0 to 4");
+                               return;
                        }
                        if (level < 0 || level > 4){
                                Report.Error (1900, "Warning level must be 0 to 4");
-                               Environment.Exit (1);
-                       } else
-                               RootContext.WarningLevel = level;
+                               return;
+                       }
+                       RootContext.WarningLevel = level;
                }
 
                static void SetupV2 ()
                {
-                       RootContext.V2 = true;
+                       RootContext.Version = LanguageVersion.Default;
                        defines.Add ("__V2__");
                }
                
@@ -578,12 +648,8 @@ namespace Mono.CSharp
                static bool UnixParseOption (string arg, ref string [] args, ref int i)
                {
                        switch (arg){
-                       case "-vv":
-                               parser_verbose = true;
-                               return true;
-                               
                        case "-v":
-                               yacc_verbose = true;
+                               CSharpParser.yacc_verbose_flag++;
                                return true;
 
                        case "--version":
@@ -595,6 +661,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--main": case "-m":
+                               Report.Warning (-29, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -603,6 +670,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--unsafe":
+                               Report.Warning (-29, "Compatibility: Use -unsafe instead of --unsafe");
                                RootContext.Unsafe = true;
                                return true;
                                
@@ -613,6 +681,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--define":
+                               Report.Warning (-29, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -643,14 +712,16 @@ namespace Mono.CSharp
                                
                        case "-o": 
                        case "--output":
+                               Report.Warning (-29, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
                                }
                                SetOutputFile (args [++i]);
                                return true;
-                               
+
                        case "--checked":
+                               Report.Warning (-29, "Compatibility: Use -checked instead of --checked");
                                RootContext.Checked = true;
                                return true;
                                
@@ -660,6 +731,7 @@ namespace Mono.CSharp
                                
                        case "--linkresource":
                        case "--linkres":
+                               Report.Warning (-29, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Report.Error (5, "Missing argument to --linkres"); 
@@ -673,6 +745,7 @@ namespace Mono.CSharp
                                
                        case "--resource":
                        case "--res":
+                               Report.Warning (-29, "Compatibility: Use -res:VALUE instead of --res VALUE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Report.Error (5, "Missing argument to --resource"); 
@@ -685,6 +758,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--target":
+                               Report.Warning (-29, "Compatibility: Use -target:KIND instead of --target KIND");
                                if ((i + 1) >= args.Length){
                                        Environment.Exit (1);
                                        return true;
@@ -693,30 +767,30 @@ namespace Mono.CSharp
                                string type = args [++i];
                                switch (type){
                                case "library":
-                                       target = Target.Library;
-                                       target_ext = ".dll";
+                                       RootContext.Target = Target.Library;
+                                       RootContext.TargetExt = ".dll";
                                        break;
                                        
                                case "exe":
-                                       target = Target.Exe;
+                                       RootContext.Target = Target.Exe;
                                        break;
                                        
                                case "winexe":
-                                       target = Target.WinExe;
+                                       RootContext.Target = Target.WinExe;
                                        break;
                                        
                                case "module":
-                                       target = Target.Module;
-                                       target_ext = ".dll";
+                                       RootContext.Target = Target.Module;
+                                       RootContext.TargetExt = ".dll";
                                        break;
                                default:
                                        TargetUsage ();
-                                       Environment.Exit (1);
                                        break;
                                }
                                return true;
                                
                        case "-r":
+                               Report.Warning (-29, "Compatibility: Use -r:LIBRARY instead of -r library");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -726,6 +800,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "-L":
+                               Report.Warning (-29, "Compatibility: Use -lib:ARG instead of --L arg");
                                if ((i + 1) >= args.Length){
                                        Usage ();       
                                        Environment.Exit (1);
@@ -734,6 +809,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--nostdlib":
+                               Report.Warning (-29, "Compatibility: Use -nostdlib instead of --nostdlib");
                                RootContext.StdLib = false;
                                return true;
                                
@@ -742,10 +818,12 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--werror":
+                               Report.Warning (-29, "Compatibility: Use -warnaserror: option instead of --werror");
                                Report.WarningsAreErrors = true;
                                return true;
                                
                        case "--nowarn":
+                               Report.Warning (-29, "Compatibility: Use -nowarn instead of --nowarn");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -762,10 +840,11 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--wlevel":
+                               Report.Warning (-29, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
                                if ((i + 1) >= args.Length){
                                        Report.Error (
                                                1900,
-                                               "--wlevel requires an value from 0 to 4");
+                                               "--wlevel requires a value from 0 to 4");
                                        Environment.Exit (1);
                                }
 
@@ -791,6 +870,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--recurse":
+                               Report.Warning (-29, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
                                if ((i + 1) >= args.Length){
                                        Report.Error (5, "--recurse requires an argument");
                                        Environment.Exit (1);
@@ -808,10 +888,12 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--debug": case "-g":
+                               Report.Warning (-29, "Compatibility: Use -debug option instead of -g or --debug");
                                want_debugging_support = true;
                                return true;
                                
                        case "--noconfig":
+                               Report.Warning (-29, "Compatibility: Use -noconfig option instead of --noconfig");
                                load_default_config = false;
                                return true;
                        }
@@ -820,12 +902,12 @@ namespace Mono.CSharp
                }
 
                //
-               // Currently it is very basic option parsing, but eventually, this will
-               // be the complete option parser
+               // This parses the -arg and /arg options to the compiler, even if the strings
+               // in the following text use "/arg" on the strings.
                //
                static bool CSCParseOption (string option, ref string [] args, ref int i)
                {
-                       int idx = option.IndexOf (":");
+                       int idx = option.IndexOf (':');
                        string arg, value;
 
                        if (idx == -1){
@@ -845,26 +927,25 @@ namespace Mono.CSharp
                        case "/target":
                                switch (value){
                                case "exe":
-                                       target = Target.Exe;
+                                       RootContext.Target = Target.Exe;
                                        break;
 
                                case "winexe":
-                                       target = Target.WinExe;
+                                       RootContext.Target = Target.WinExe;
                                        break;
 
                                case "library":
-                                       target = Target.Library;
-                                       target_ext = ".dll";
+                                       RootContext.Target = Target.Library;
+                                       RootContext.TargetExt = ".dll";
                                        break;
 
                                case "module":
-                                       target = Target.Module;
-                                       target_ext = ".netmodule";
+                                       RootContext.Target = Target.Module;
+                                       RootContext.TargetExt = ".netmodule";
                                        break;
 
                                default:
                                        TargetUsage ();
-                                       Environment.Exit (1);
                                        break;
                                }
                                return true;
@@ -879,7 +960,13 @@ namespace Mono.CSharp
 
                        case "/optimize":
                        case "/optimize+":
+                               RootContext.Optimize = true;
+                               return true;
+
                        case "/optimize-":
+                               RootContext.Optimize = false;
+                               return true;
+
                        case "/incremental":
                        case "/incremental+":
                        case "/incremental-":
@@ -902,6 +989,13 @@ namespace Mono.CSharp
                                return true;
                        }
 
+                       case "/bugreport":
+                               //
+                               // We should collect data, runtime, etc and store in the file specified
+                               //
+                               Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
+                               return true;
+
                        case "/linkres":
                        case "/linkresource":
                                if (value == ""){
@@ -914,21 +1008,72 @@ namespace Mono.CSharp
                                resources.Add (value);
                                return true;
                                
+                       case "/pkg": {
+                               string packages;
+
+                               if (value == ""){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
+                               
+                               ProcessStartInfo pi = new ProcessStartInfo ();
+                               pi.FileName = "pkg-config";
+                               pi.RedirectStandardOutput = true;
+                               pi.UseShellExecute = false;
+                               pi.Arguments = "--libs " + packages;
+                               Process p = null;
+                               try {
+                                       p = Process.Start (pi);
+                               } catch (Exception e) {
+                                       Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
+                                       Environment.Exit (1);
+                               }
+
+                               if (p.StandardOutput == null){
+                                       Report.Warning (-27, "Specified package did not return any information");
+                                       return true;
+                               }
+                               string pkgout = p.StandardOutput.ReadToEnd ();
+                               p.WaitForExit ();
+                               if (p.ExitCode != 0) {
+                                       Report.Error (-27, "Error running pkg-config. Check the above output.");
+                                       Environment.Exit (1);
+                               }
+
+                               if (pkgout != null){
+                                       string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
+                                               Split (new Char [] { ' ', '\t'});
+                                       args = AddArgs (args, xargs);
+                               }
+                               
+                               p.Close ();
+                               return true;
+                       }
+                               
                        case "/res":
                        case "/resource":
                                if (value == ""){
-                                       Report.Error (5, arg + " requires an argument");
+                                       Report.Error (5, "-resource requires an argument");
                                        Environment.Exit (1);
                                }
                                if (embedded_resources == null)
                                        embedded_resources = new ArrayList ();
                                
+                               if (embedded_resources.Contains (value)) {
+                                       Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
+                               }
+                               else if (value.IndexOf (',') != -1 && embedded_resources.Contains (value.Split (',')[1])) {
+                                       Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
+                               }
+                               else {
                                embedded_resources.Add (value);
+                               }
                                return true;
                                
                        case "/recurse":
                                if (value == ""){
-                                       Report.Error (5, "/recurse requires an argument");
+                                       Report.Error (5, "-recurse requires an argument");
                                        Environment.Exit (1);
                                }
                                CompileFiles (value, true); 
@@ -937,7 +1082,7 @@ namespace Mono.CSharp
                        case "/r":
                        case "/reference": {
                                if (value == ""){
-                                       Report.Error (5, arg + " requires an argument");
+                                       Report.Error (5, "-reference requires an argument");
                                        Environment.Exit (1);
                                }
 
@@ -947,12 +1092,42 @@ namespace Mono.CSharp
                                }
                                return true;
                        }
-                       case "/doc": {
+                       case "/addmodule": {
                                if (value == ""){
                                        Report.Error (5, arg + " requires an argument");
                                        Environment.Exit (1);
                                }
-                               // TODO handle the /doc argument to generate xml doc
+
+                               string [] refs = value.Split (new char [] { ';', ',' });
+                               foreach (string r in refs){
+                                       modules.Add (r);
+                               }
+                               return true;
+                       }
+                       case "/win32res": {
+                               if (value == "") {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32ResourceFile = value;
+                               return true;
+                       }
+                       case "/win32icon": {
+                               if (value == "") {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32IconFile = value;
+                               return true;
+                       }
+                       case "/doc": {
+                               if (value == ""){
+                                       Report.Error (2006, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.Documentation = new Documentation (value);
                                return true;
                        }
                        case "/lib": {
@@ -968,6 +1143,10 @@ namespace Mono.CSharp
                                        link_paths.Add (dir);
                                return true;
                        }
+
+                       case "/debug-":
+                               want_debugging_support = false;
+                               return true;
                                
                        case "/debug":
                        case "/debug+":
@@ -983,6 +1162,14 @@ namespace Mono.CSharp
                                RootContext.Checked = false;
                                return true;
 
+                       case "/clscheck":
+                       case "/clscheck+":
+                               return true;
+
+                       case "/clscheck-":
+                               RootContext.VerifyClsCompliance = false;
+                               return true;
+
                        case "/unsafe":
                        case "/unsafe+":
                                RootContext.Unsafe = true;
@@ -1015,15 +1202,15 @@ namespace Mono.CSharp
                                
                                warns = value.Split (new Char [] {','});
                                foreach (string wc in warns){
-                                       int warn = 0;
-                                       
                                        try {
-                                               warn = Int32.Parse (wc);
+                                               int warn = Int32.Parse (wc);
+                                               if (warn < 1) {
+                                                       throw new ArgumentOutOfRangeException("warn");
+                                               }
+                                               Report.SetIgnoreWarning (warn);
                                        } catch {
-                                               Usage ();
-                                               Environment.Exit (1);
+                                               Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc));
                                        }
-                                       Report.SetIgnoreWarning (warn);
                                }
                                return true;
                        }
@@ -1037,6 +1224,11 @@ namespace Mono.CSharp
                                load_default_config = false;
                                return true;
 
+                       case "/help2":
+                               OtherFlags ();
+                               Environment.Exit(0);
+                               return true;
+                               
                        case "/help":
                        case "/?":
                                Usage ();
@@ -1064,15 +1256,46 @@ namespace Mono.CSharp
                        case "/fullpaths":
                                return true;
 
-                       case "/win32icon":
-                               Report.Error (5, "/win32icon is currently not supported");
+                       case "/keyfile":
+                               if (value == String.Empty) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.StrongNameKeyFile = value;
                                return true;
-                               
+                       case "/keycontainer":
+                               if (value == String.Empty) {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               RootContext.StrongNameKeyContainer = value;
+                               return true;
+                       case "/delaysign+":
+                               RootContext.StrongNameDelaySign = true;
+                               return true;
+                       case "/delaysign-":
+                               RootContext.StrongNameDelaySign = false;
+                               return true;
+
                        case "/v2":
                        case "/2":
+                               Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead");
                                SetupV2 ();
                                return true;
                                
+                       case "/langversion":
+                               switch (value.ToLower (CultureInfo.InvariantCulture)) {
+                                       case "iso-1":
+                                               RootContext.Version = LanguageVersion.ISO_1;
+                                               return true;
+
+                                       case "default":
+                                               SetupV2 ();
+                                               return true;
+                               }
+                               Report.Error (1617, "Invalid option '{0}' for /langversion; must be ISO-1 or Default", value);
+                               return true;
+
                        case "/codepage":
                                int cp = -1;
 
@@ -1091,25 +1314,42 @@ namespace Mono.CSharp
                                
                                try {
                                        cp = Int32.Parse (value);
-                               } catch { }
-                               
-                               if (cp == -1){
-                                       Console.WriteLine ("Invalid code-page requested");
-                                       Usage ();
-                               }
-
-                               try {
                                        encoding = Encoding.GetEncoding (cp);
                                        using_default_encoder = false;
                                } catch {
-                                       Console.WriteLine ("Code page: {0} not supported", cp);
+                                       Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp));
                                }
                                return true;
-
                        }
+                       //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option));
+                       //Environment.Exit (1);
                        return false;
                }
                
+               static string [] AddArgs (string [] args, string [] extra_args)
+               {
+                       string [] new_args;
+                       new_args = new string [extra_args.Length + args.Length];
+
+                       // if args contains '--' we have to take that into account
+                       // split args into first half and second half based on '--'
+                       // and add the extra_args before --
+                       int split_position = Array.IndexOf (args, "--");
+                       if (split_position != -1)
+                       {
+                               Array.Copy (args, new_args, split_position);
+                               extra_args.CopyTo (new_args, split_position);
+                               Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
+                       }
+                       else
+                       {
+                               args.CopyTo (new_args, 0);
+                               extra_args.CopyTo (new_args, args.Length);
+                       }
+
+                       return new_args;
+               }
+               
                /// <summary>
                ///    Parses the arguments, and drives the compilation
                ///    process.
@@ -1120,13 +1360,11 @@ namespace Mono.CSharp
                ///    now, needs to be turned into a real driver soon.
                /// </remarks>
                // [MonoTODO("Change error code for unknown argument to something reasonable")]
-               static bool MainDriver (string [] args)
+               internal static bool MainDriver (string [] args)
                {
                        int i;
                        bool parsing_options = true;
 
-                       Console.WriteLine ("Mono C# Compiler {0} for Generics",
-                                          Assembly.GetExecutingAssembly ().GetName ().Version.ToString ());
                        try {
                                encoding = Encoding.GetEncoding (28591);
                        } catch {
@@ -1136,6 +1374,7 @@ namespace Mono.CSharp
                        
                        references = new ArrayList ();
                        soft_references = new ArrayList ();
+                       modules = new ArrayList ();
                        link_paths = new ArrayList ();
 
                        SetupDefaultDefines ();
@@ -1147,12 +1386,15 @@ namespace Mono.CSharp
                        // path.
                        //
 
-                       int argc = args.Length;
-                       for (i = 0; i < argc; i++){
+                       Hashtable response_file_list = null;
+
+                       for (i = 0; i < args.Length; i++){
                                string arg = args [i];
+                               if (arg == "")
+                                       continue;
 
                                if (arg.StartsWith ("@")){
-                                       string [] new_args, extra_args;
+                                       string [] extra_args;
                                        string response_file = arg.Substring (1);
 
                                        if (response_file_list == null)
@@ -1174,11 +1416,7 @@ namespace Mono.CSharp
                                                return false;
                                        }
 
-                                       new_args = new string [extra_args.Length + argc];
-                                       args.CopyTo (new_args, 0);
-                                       extra_args.CopyTo (new_args, argc);
-                                       args = new_args;
-                                       argc = new_args.Length;
+                                       args = AddArgs (args, extra_args);
                                        continue;
                                }
 
@@ -1212,11 +1450,32 @@ namespace Mono.CSharp
                        if (tokenize)
                                return true;
                        
+                       //
+                       // This will point to the NamespaceEntry of the last file that was parsed, and may
+                       // not be meaningful when resolving classes from other files.  So, reset it to prevent
+                       // silent bugs.
+                       //
+                       RootContext.Tree.Types.NamespaceEntry = null;
+
+                       //
+                       // If we are an exe, require a source file for the entry point
+                       //
+                       if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
                        if (first_source == null){
                                Report.Error (2008, "No files to compile were specified");
                                return false;
                        }
 
+                       }
+
+                       //
+                       // If there is nothing to put in the assembly, and we are not a library
+                       //
+                       if (first_source == null && embedded_resources == null && resources == null){
+                                       Report.Error (2008, "No files to compile were specified");
+                                       return false;
+                       }
+
                        if (Report.Errors > 0)
                                return false;
                        
@@ -1242,6 +1501,7 @@ namespace Mono.CSharp
                        if (timestamps)
                                ShowTime ("Loading references");
                        link_paths.Add (GetSystemDir ());
+                       link_paths.Add (Directory.GetCurrentDirectory ());
                        LoadReferences ();
                        
                        if (timestamps)
@@ -1255,21 +1515,42 @@ namespace Mono.CSharp
                        // Quick hack
                        //
                        if (output_file == null){
-                               int pos = first_source.LastIndexOf (".");
+                               int pos = first_source.LastIndexOf ('.');
 
                                if (pos > 0)
-                                       output_file = first_source.Substring (0, pos) + target_ext;
+                                       output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
                                else
-                                       output_file = first_source + target_ext;
+                                       output_file = first_source + RootContext.TargetExt;
+                       }
+
+                       if (!CodeGen.Init (output_file, output_file, want_debugging_support))
+                               return false;
+
+                       if (RootContext.Target == Target.Module) {
+                               PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+                               if (module_only == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "/target:module");
+                                       Environment.Exit (1);
+                               }
+
+                               MethodInfo set_method = module_only.GetSetMethod (true);
+                               set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
                        }
 
-                       CodeGen.Init (output_file, output_file, want_debugging_support);
+                       TypeManager.AddModule (CodeGen.Module.Builder);
 
-                       TypeManager.AddModule (CodeGen.ModuleBuilder);
+                       if (modules.Count > 0) {
+                               MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
+                               if (adder_method == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "/addmodule");
+                                       Environment.Exit (1);
+                               }
+
+                               foreach (string module in modules)
+                                       LoadModule (adder_method, module);
+                       }
 
-                       DateTime start = DateTime.Now;
                        TypeManager.ComputeNamespaces ();
-                       DateTime end = DateTime.Now;
                        
                        //
                        // Before emitting, we need to get the core
@@ -1288,12 +1569,15 @@ namespace Mono.CSharp
                        if (timestamps)
                                ShowTime ("   Core Types done");
 
+                       CodeGen.Module.ResolveAttributes ();
+
                        //
                        // The second pass of the compiler
                        //
                        if (timestamps)
                                ShowTime ("Resolving tree");
                        RootContext.ResolveTree ();
+
                        if (Report.Errors > 0)
                                return false;
                        if (timestamps)
@@ -1301,9 +1585,15 @@ namespace Mono.CSharp
                        if (!RootContext.StdLib)
                                RootContext.BootCorlib_PopulateCoreTypes ();
                        RootContext.PopulateTypes ();
+
+                       TypeManager.InitCodeHelpers ();
+
                        RootContext.DefineTypes ();
                        
-                       TypeManager.InitCodeHelpers ();
+                       if (RootContext.Documentation != null &&
+                               !RootContext.Documentation.OutputDocComment (
+                                       output_file))
+                               return false;
 
                        //
                        // Verify using aliases now
@@ -1314,6 +1604,17 @@ namespace Mono.CSharp
                                return false;
                        }
                        
+                       if (RootContext.VerifyClsCompliance) {
+                               CodeGen.Assembly.ResolveClsCompliance ();
+                               if (CodeGen.Assembly.IsClsCompliant) {
+                               AttributeTester.VerifyModulesClsCompliance ();
+                               TypeManager.LoadAllImportedTypes ();
+                                       AttributeTester.VerifyTopLevelNameClsCompliance ();
+                               }
+                       }
+                       if (Report.Errors > 0)
+                               return false;
+                       
                        //
                        // The code generator
                        //
@@ -1335,27 +1636,45 @@ namespace Mono.CSharp
 
                        PEFileKinds k = PEFileKinds.ConsoleApplication;
                                
-                       if (target == Target.Library || target == Target.Module){
-                               k = PEFileKinds.Dll;
-
-                               if (RootContext.MainClass != null)
-                                       Report.Error (2017, "Can not specify -main: when building module or library");
-                       } else if (target == Target.Exe)
-                               k = PEFileKinds.ConsoleApplication;
-                       else if (target == Target.WinExe)
-                               k = PEFileKinds.WindowApplication;
+                       switch (RootContext.Target) {
+                       case Target.Library:
+                       case Target.Module:
+                               k = PEFileKinds.Dll; break;
+                       case Target.Exe:
+                               k = PEFileKinds.ConsoleApplication; break;
+                       case Target.WinExe:
+                               k = PEFileKinds.WindowApplication; break;
+                       }
 
-                       if (target == Target.Exe || target == Target.WinExe){
+                       if (RootContext.NeedsEntryPoint) {
                                MethodInfo ep = RootContext.EntryPoint;
 
-                               if (ep == null){
+                               if (ep == null) {
+                                       if (RootContext.MainClass != null) {
+                                               DeclSpace main_cont = RootContext.Tree.GetDecl (MemberName.FromDotted (RootContext.MainClass));
+                                               if (main_cont == null) {
+                                                       Report.Error (1555, output_file, "Could not find '{0}' specified for Main method", RootContext.MainClass); 
+                                                       return false;
+                                               }
+
+                                               if (!(main_cont is ClassOrStruct)) {
+                                                       Report.Error (1556, output_file, "'{0}' specified for Main method must be a valid class or struct", RootContext.MainClass);
+                                                       return false;
+                                               }
+
+                                               Report.Error (1558, main_cont.Location, "'{0}' does not have a suitable static Main method", main_cont.GetSignatureForError ());
+                                               return false;
+                                       }
+
                                        if (Report.Errors == 0)
                                                Report.Error (5001, "Program " + output_file +
                                                              " does not have an entry point defined");
                                        return false;
                                }
                                
-                               CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
+                               CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
+                       } else if (RootContext.MainClass != null) {
+                               Report.Error (2017, "Can not specify -main: when building module or library");
                        }
 
                        //
@@ -1373,7 +1692,7 @@ namespace Mono.CSharp
                                        } else
                                                file = res = spec;
 
-                                       CodeGen.AssemblyBuilder.AddResourceFile (res, file);
+                                       CodeGen.Assembly.Builder.AddResourceFile (res, file);
                                }
                        }
                        
@@ -1381,9 +1700,13 @@ namespace Mono.CSharp
                                object[] margs = new object [2];
                                Type[] argst = new Type [2];
                                argst [0] = argst [1] = typeof (string);
-                               MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", argst);
+
+                               MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod (
+                                       "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
+                                       null, CallingConventions.Any, argst, null);
+                               
                                if (embed_res == null) {
-                                       Report.Warning (0, new Location (-1), "Cannot embed resources on this runtime: try the Mono runtime instead.");
+                                       Report.RuntimeMissingSupport (Location.Null, "Resource embedding");
                                } else {
                                        foreach (string spec in embedded_resources) {
                                                int cp;
@@ -1392,11 +1715,13 @@ namespace Mono.CSharp
                                                if (cp != -1){
                                                        margs [0] = spec.Substring (cp + 1);
                                                        margs [1] = spec.Substring (0, cp);
-                                               } else
-                                                       margs [0] = margs [1] = spec;
+                                               } else {
+                                                       margs [1] = spec;
+                                                       margs [0] = Path.GetFileName (spec);
+                                               }
 
                                                if (File.Exists ((string) margs [1]))
-                                                       embed_res.Invoke (CodeGen.AssemblyBuilder, margs);
+                                                       embed_res.Invoke (CodeGen.Assembly.Builder, margs);
                                                else {
                                                        Report.Error (1566, "Can not find the resource " + margs [1]);
                                                }
@@ -1404,6 +1729,29 @@ namespace Mono.CSharp
                                }
                        }
 
+                       //
+                       // Add Win32 resources
+                       //
+
+                       CodeGen.Assembly.Builder.DefineVersionInfoResource ();
+
+                       if (win32ResourceFile != null) {
+                               try {
+                                       CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
+                               }
+                               catch (ArgumentException) {
+                                       Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
+                               }
+                       }
+
+                       if (win32IconFile != null) {
+                               MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+                               if (define_icon == null) {
+                                       Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead.");
+                               }
+                               define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
+                       }
+
                        if (Report.Errors > 0)
                                return false;
                        
@@ -1416,8 +1764,19 @@ namespace Mono.CSharp
                        Timer.ShowTimers ();
                        
                        if (Report.ExpectedError != 0){
-                               Console.WriteLine("Failed to report expected error " + Report.ExpectedError);
+                               if (Report.Errors == 0) {
+                                       Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+                                               "No other errors reported.");
+                                       
+                                       Environment.Exit (2);
+                               } else {
+                                       Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+                                               "However, other errors were reported.");
+                                       
                                Environment.Exit (1);
+                               }
+                               
+                               
                                return false;
                        }
 
@@ -1427,6 +1786,34 @@ namespace Mono.CSharp
 #endif
                        return (Report.Errors == 0);
                }
+       }
 
+       //
+       // This is the only public entry point
+       //
+       public class CompilerCallableEntryPoint : MarshalByRefObject {
+               public static bool InvokeCompiler (string [] args, TextWriter error)
+               {
+                       Report.Stderr = error;
+                       try {
+                               return Driver.MainDriver (args) && Report.Errors == 0;
+                       }
+                       finally {
+                               Report.Stderr = Console.Error;
+                               Reset ();
+                       }
+               }
+               
+               static void Reset ()
+               {
+                       Driver.Reset ();
+                       Location.Reset ();
+                       RootContext.Reset ();
+                       Report.Reset ();
+                       TypeManager.Reset ();
+                       TypeHandle.Reset ();
+                       Namespace.Reset ();
+                       CodeGen.Reset ();
+               }
        }
 }