2008-07-07 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / driver.cs
index 0fdfd91a138fc123014a3662d800dd1a7c72b932..7b5d86680eb3160bf5bce1f1471f8b004743b6d4 100644 (file)
@@ -1,12 +1,14 @@
 //
 // driver.cs: The compiler command line driver.
 //
-// Author: Miguel de Icaza (miguel@gnu.org)
+// Authors:
+//   Miguel de Icaza (miguel@gnu.org)
+//   Marek Safar (marek.safar@gmail.com)
 //
-// Licensed under the terms of the GNU GPL
+// Dual licensed under the terms of the MIT X11 or GNU GPL
 //
-// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
-// (C) 2004 Novell, Inc
+// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
 //
 
 namespace Mono.CSharp
@@ -15,6 +17,7 @@ namespace Mono.CSharp
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Collections;
+       using System.Collections.Specialized;
        using System.IO;
        using System.Text;
        using System.Globalization;
@@ -27,9 +30,8 @@ namespace Mono.CSharp
        /// <summary>
        ///    The compiler driver.
        /// </summary>
-       public class Driver
+       class Driver
        {
-               
                //
                // Assemblies references to be linked.   Initialized with
                // mscorlib.dll here.
@@ -42,6 +44,11 @@ namespace Mono.CSharp
                //
                static ArrayList soft_references;
 
+               // 
+               // External aliases for assemblies.
+               //
+               static Hashtable external_aliases;
+
                //
                // Modules to be linked
                //
@@ -51,74 +58,74 @@ namespace Mono.CSharp
                static ArrayList link_paths;
 
                // Whether we want to only run the tokenizer
-               static bool tokenize = false;
+               bool tokenize;
                
-               static string first_source;
+               string first_source;
 
-               static bool want_debugging_support = false;
-
-               static bool parse_only = false;
-               static bool timestamps = false;
-               static bool pause = false;
-               static bool show_counters = false;
+               bool want_debugging_support;
+               bool parse_only;
+               bool timestamps;
                
                //
                // Whether to load the initial config file (what CSC.RSP has by default)
                // 
-               static bool load_default_config = true;
+               bool load_default_config = true;
 
                //
                // A list of resource files
                //
-               static ArrayList resources;
-               static ArrayList embedded_resources;
+               static Resources embedded_resources;
                static string win32ResourceFile;
                static string win32IconFile;
 
                //
                // An array of the defines from the command line
                //
-               static ArrayList defines;
+               ArrayList defines;
 
                //
                // Output file
                //
-               static string output_file = null;
+               static string output_file;
 
                //
                // Last time we took the time
                //
-               static DateTime last_time, first_time;
-
-               //
-               // Encoding: ISO-Latin1 is 28591
-               //
-               static Encoding encoding;
+               DateTime last_time, first_time;
 
                //
-               // Whether the user has specified a different encoder manually
+               // Encoding.
                //
-               static bool using_default_encoder = true;
-
+               Encoding encoding;
 
                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;
+                       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)
+               public Driver ()
+               {
+                       encoding = Encoding.Default;
+
+                       //
+                       // Setup default defines
+                       //
+                       defines = new ArrayList ();
+                       defines.Add ("__MonoCS__");
+               }
+
+               public static Driver Create (string [] args)
+               {
+                       Driver d = new Driver ();
+                       if (!d.ParseArguments (args))
+                               return null;
+
+                       return d;
+               }
+
+               void ShowTime (string msg)
                {
                        if (!timestamps)
                                return;
@@ -132,7 +139,7 @@ namespace Mono.CSharp
                                (int) span.TotalSeconds, span.Milliseconds, msg);
                }
 
-               public static void ShowTotalTime (string msg)
+               void ShowTotalTime (string msg)
                {
                        if (!timestamps)
                                return;
@@ -146,19 +153,19 @@ namespace Mono.CSharp
                                (int) span.TotalSeconds, span.Milliseconds, msg);
                }              
               
-               static void tokenize_file (SourceFile file)
+               void tokenize_file (CompilationUnit file)
                {
                        Stream input;
 
                        try {
                                input = File.OpenRead (file.Name);
                        } catch {
-                               Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
+                               Report.Error (2001, "Source file `" + file.Name + "' could not be found");
                                return;
                        }
 
                        using (input){
-                               SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
+                               SeekableStreamReader reader = new SeekableStreamReader (input, encoding);
                                Tokenizer lexer = new Tokenizer (reader, file, defines);
                                int token, tokens = 0, errors = 0;
 
@@ -173,29 +180,40 @@ namespace Mono.CSharp
                        return;
                }
 
-               // MonoTODO("Change error code for aborted compilation to something reasonable")]               
-               static void parse (SourceFile file)
+               void Parse (CompilationUnit file)
                {
-                       CSharpParser parser;
                        Stream input;
 
                        try {
                                input = File.OpenRead (file.Name);
                        } catch {
-                               Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
+                               Report.Error (2001, "Source file `{0}' could not be found", file.Name);
                                return;
                        }
 
-                       SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
-                               
-                       parser = new CSharpParser (reader, file, defines);
+                       SeekableStreamReader reader = new SeekableStreamReader (input, encoding);
+
+                       // Check 'MZ' header
+                       if (reader.Read () == 77 && reader.Read () == 90) {
+                               Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
+                               input.Close ();
+                               return;
+                       }
+
+                       reader.Position = 0;
+                       Parse (reader, file);
+                       input.Close ();
+               }       
+               
+               void Parse (SeekableStreamReader reader, CompilationUnit file)
+               {
+                       CSharpParser parser = new CSharpParser (reader, file, defines);
                        parser.ErrorOutput = Report.Stderr;
                        try {
                                parser.parse ();
                        } catch (Exception ex) {
-                               Report.Error(666, "Compilation aborted: " + ex);
-                       } finally {
-                               input.Close ();
+                               Report.Error(589, parser.Lexer.Location,
+                                       "Compilation aborted in file `{0}', {1}", file.Name, ex);
                        }
                }
 
@@ -205,10 +223,10 @@ namespace Mono.CSharp
                                "Other flags in the compiler\n" +
                                "   --fatal            Makes errors fatal\n" +
                                "   --parse            Only parses the source file\n" +
+                               "   --typetest         Tests the tokenizer's built-in type parser\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");
                }
@@ -216,40 +234,42 @@ namespace Mono.CSharp
                static void Usage ()
                {
                        Console.WriteLine (
-                               "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" +
+                               "Mono C# compiler, Copyright 2001 - 2008 Novell, 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" +
+                               "   -addmodule:M1[,Mn] Adds the module to the generated assembly\n" + 
+                               "   -checked[+|-]      Sets default aritmetic overflow context\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" +
+                               "   -clscheck[+|-]     Disables CLS Compliance verifications\n" +
+                               "   -define:S1[;S2]    Defines one or more conditional symbols (short: -d)\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" + 
-                               "   -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" +
+                               "   -doc:FILE          Process documentation comments to XML file\n" + 
+                               "   -help              Lists all compiler options (short: -?)\n" + 
+                               "   -keycontainer:NAME The key pair container used to sign the output assembly\n" +
+                               "   -keyfile:FILE      The key file used to strongname the ouput assembly\n" +
+                               "   -langversion:TEXT  Specifies language version modes: ISO-1, ISO-2, or Default\n" + 
+                               "   -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
+                               "   -main:CLASS        Specifies the class with the Main method (short: -m)\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" +
+                               "   -nostdlib[+|-]     Does not reference mscorlib.dll library\n" +
+                               "   -nowarn:W1[,Wn]    Suppress one or more compiler warnings\n" + 
+                               "   -optimize[+|-]     Enables advanced compiler optimizations (short: -o)\n" + 
+                               "   -out:FILE          Specifies output assembly name\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" +
-                               "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
-                               "                      library, module), (short: /t:)\n" +
-                               "   -unsafe[+|-]       Allows unsafe code\n" +
-                               "   -warnaserror[+|-]  Treat warnings as errors\n" +
-                               "   -warn:LEVEL        Sets warning level (the highest is 4, the default is 2)\n" +
-                               "   -help2             Show other help flags\n" + 
+                               "   -recurse:SPEC      Recursively compiles files according to SPEC pattern\n" + 
+                               "   -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
+                               "   -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +                           
+                               "   -target:KIND       Specifies the format of the output assembly (short: -t)\n" +
+                               "                      KIND can be one of: exe, winexe, library, module\n" +
+                               "   -unsafe[+|-]       Allows to compile code which uses unsafe keyword\n" +
+                               "   -warnaserror[+|-]  Treats all warnings as errors\n" +
+                               "   -warn:0-4          Sets warning level, the default is 3 (short -w:)\n" +
+                               "   -help2             Shows internal compiler options\n" + 
                                "\n" +
                                "Resources:\n" +
-                               "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
-                               "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
+                               "   -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
+                               "   -resource:FILE[,ID]     Embed FILE as a resource (short: -res)\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" +
@@ -258,38 +278,37 @@ namespace Mono.CSharp
 
                static void TargetUsage ()
                {
-                       Report.Error (2019, "Valid options for -target: are exe, winexe, library or module");
+                       Report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
                }
                
                static void About ()
                {
                        Console.WriteLine (
-                               "The Mono C# compiler is (C) 2001, 2002, 2003 Ximian, Inc.\n\n" +
-                               "The compiler source code is released under the terms of the GNU GPL\n\n" +
+                               "The Mono C# compiler is Copyright 2001-2008, Novell, Inc.\n\n" +
+                               "The compiler source code is released under the terms of the \n"+
+                               "MIT X11 or GNU GPL licenses\n\n" +
 
                                "For more information on Mono, visit the project Web site\n" +
-                               "   http://www.go-mono.com\n\n" +
+                               "   http://www.mono-project.com\n\n" +
 
-                               "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath");
+                               "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
                        Environment.Exit (0);
                }
 
-               public static int counter1, counter2;
-               
-       public static int Main (string[] args)
+               public static int Main (string[] args)
                {
-                       bool ok = MainDriver (args);
-                       
-                       if (ok && Report.Errors == 0) {
+                       RootContext.Version = LanguageVersion.Default;
+
+                       Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
+
+                       Driver d = Driver.Create (args);
+                       if (d == null)
+                               return 1;
+
+                       if (d.Compile () && Report.Errors == 0) {
                                if (Report.Warnings > 0) {
                                        Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings);
                                }
-                               if (show_counters){
-                                       Console.WriteLine ("Counter1: " + counter1);
-                                       Console.WriteLine ("Counter2: " + counter2);
-                               }
-                               if (pause)
-                                       Console.ReadLine ();
                                return 0;
                        } else {
                                Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
@@ -300,93 +319,145 @@ namespace Mono.CSharp
 
                static public void LoadAssembly (string assembly, bool soft)
                {
-                       Assembly a;
-                       string total_log = "";
+                       LoadAssembly (assembly, null, soft);
+               }
 
-                       try {
-                               char[] path_chars = { '/', '\\' };
+               static void Error6 (string name, string log)
+               {
+                       if (log != null && log.Length > 0)
+                               Report.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
+                       Report.Error (6, "cannot find metadata file `{0}'", name);
+               }
 
-                               if (assembly.IndexOfAny (path_chars) != -1) {
-                                       a = Assembly.LoadFrom (assembly);
-                               } else {
-                                       string ass = assembly;
-                                       if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
-                                               ass = assembly.Substring (0, assembly.Length - 4);
-                                       a = Assembly.Load (ass);
-                               }
-                               TypeManager.AddAssembly (a);
+               static void Error9 (string type, string filename, string log)
+               {
+                       if (log != null && log.Length > 0)
+                               Report.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
+                       Report.Error (9, "file `{0}' has invalid `{1}' metadata", filename, type);
+               }
 
-                       } catch (FileNotFoundException){
-                               foreach (string dir in link_paths){
-                                       string full_path = Path.Combine (dir, assembly);
-                                       if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
-                                               full_path += ".dll";
+               static void BadAssembly (string filename, string log)
+               {
+                       MethodInfo adder_method = AssemblyClass.AddModule_Method;
 
+                       if (adder_method != null) {
+                               AssemblyName an = new AssemblyName ();
+                               an.Name = ".temp";
+                               AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
+                               try {
+                                       object m = null;
                                        try {
-                                               a = Assembly.LoadFrom (full_path);
-                                               TypeManager.AddAssembly (a);
+                                               m = adder_method.Invoke (ab, new object [] { filename });
+                                       } catch (TargetInvocationException ex) {
+                                               throw ex.InnerException;
+                                       }
+
+                                       if (m != null) {
+                                               Report.Error (1509, "Referenced file `{0}' is not an assembly. Consider using `-addmodule' option instead",
+                                                             Path.GetFileName (filename));
                                                return;
-                                       } catch (FileNotFoundException ff) {
-                                               total_log += ff.FusionLog;
-                                               continue;
                                        }
+                               } catch (FileNotFoundException) {
+                                       // did the file get deleted during compilation? who cares? swallow the exception
+                               } catch (BadImageFormatException) {
+                                       // swallow exception
+                               } catch (FileLoadException) {
+                                       // swallow exception
                                }
-                               if (!soft) {
-                                       Report.Error (6, "Cannot find assembly `" + assembly + "'" );
-                                       Console.WriteLine ("Log: \n" + total_log);
-                               }
-                       } catch (BadImageFormatException f) {
-                               Report.Error(6, "Cannot load assembly (bad file format)" + f.FusionLog);
-                       } catch (FileLoadException f){
-                               Report.Error(6, "Cannot load assembly " + f.FusionLog);
-                       } catch (ArgumentNullException){
-                               Report.Error(6, "Cannot load assembly (null argument)");
                        }
+                       Error9 ("assembly", filename, log);
                }
 
-               static public void LoadModule (MethodInfo adder_method, string module)
+               static public void LoadAssembly (string assembly, string alias, bool soft)
                {
-                       Module m;
+                       Assembly a = null;
                        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);
+                                       char[] path_chars = { '/', '\\' };
 
-                       } 
-                       catch (FileNotFoundException){
-                               foreach (string dir in link_paths){
-                                       string full_path = Path.Combine (dir, module);
-                                       if (!module.EndsWith (".netmodule"))
-                                               full_path += ".netmodule";
+                                       if (assembly.IndexOfAny (path_chars) != -1) {
+                                               a = Assembly.LoadFrom (assembly);
+                                       } else {
+                                               string ass = assembly;
+                                               if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
+                                                       ass = assembly.Substring (0, assembly.Length - 4);
+                                               a = Assembly.Load (ass);
+                                       }
+                               } catch (FileNotFoundException) {
+                                       bool err = !soft;
+                                       foreach (string dir in link_paths) {
+                                               string full_path = Path.Combine (dir, assembly);
+                                               if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
+                                                       full_path += ".dll";
 
-                                       try {
                                                try {
-                                                       m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
+                                                       a = Assembly.LoadFrom (full_path);
+                                                       err = false;
+                                                       break;
+                                               } catch (FileNotFoundException ff) {
+                                                       if (soft)
+                                                               return;
+                                                       total_log += ff.FusionLog;
                                                }
-                                               catch (TargetInvocationException ex) {
-                                                       throw ex.InnerException;
+                                       }
+                                       if (err) {
+                                               Error6 (assembly, total_log);
+                                               return;
+                                       }
+                               }
+
+                               // Extern aliased refs require special handling
+                               if (alias == null)
+                                       RootNamespace.Global.AddAssemblyReference (a);
+                               else
+                                       RootNamespace.DefineRootNamespace (alias, a);
+
+                       } catch (BadImageFormatException f) {
+                               // .NET 2.0 throws this if we try to load a module without an assembly manifest ...
+                               BadAssembly (f.FileName, f.FusionLog);
+                       } catch (FileLoadException f) {
+                               // ... while .NET 1.1 throws this
+                               BadAssembly (f.FileName, f.FusionLog);
+                       }
+               }
+
+               static public void LoadModule (string module)
+               {
+                       Module m = null;
+                       string total_log = "";
+
+                       try {
+                               try {
+                                       m = CodeGen.Assembly.AddModule (module);
+                               } catch (FileNotFoundException) {
+                                       bool err = true;
+                                       foreach (string dir in link_paths) {
+                                               string full_path = Path.Combine (dir, module);
+                                               if (!module.EndsWith (".netmodule"))
+                                                       full_path += ".netmodule";
+
+                                               try {
+                                                       m = CodeGen.Assembly.AddModule (full_path);
+                                                       err = false;
+                                                       break;
+                                               } catch (FileNotFoundException ff) {
+                                                       total_log += ff.FusionLog;
                                                }
-                                               TypeManager.AddModule (m);
+                                       }
+                                       if (err) {
+                                               Error6 (module, total_log);
                                                return;
-                                       } catch (FileNotFoundException ff) {
-                                               total_log += ff.FusionLog;
-                                               continue;
                                        }
                                }
-                               Report.Error (6, "Cannot find module `" + module + "'" );
-                               Console.WriteLine ("Log: \n" + total_log);
+
+                               RootNamespace.Global.AddModuleReference (m);
+
                        } 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)");
+                               Error9 ("module", f.FileName, f.FusionLog);
+                       } catch (FileLoadException f) {
+                               Error9 ("module", f.FileName, f.FusionLog);
                        }
                }
 
@@ -395,21 +466,24 @@ namespace Mono.CSharp
                /// </summary>
                static public void LoadReferences ()
                {
-                       foreach (string r in references)
-                               LoadAssembly (r, false);
+                       //
+                       // Load Core Library for default compilation
+                       //
+                       if (RootContext.StdLib)
+                               LoadAssembly ("mscorlib", false);
 
                        foreach (string r in soft_references)
                                LoadAssembly (r, true);
+
+                       foreach (string r in references)
+                               LoadAssembly (r, false);
+
+                       foreach (DictionaryEntry entry in external_aliases)
+                               LoadAssembly ((string) entry.Value, (string) entry.Key, false);
                        
                        return;
                }
 
-               static void SetupDefaultDefines ()
-               {
-                       defines = new ArrayList ();
-                       defines.Add ("__MonoCS__");
-               }
-
                static string [] LoadArgs (string file)
                {
                        StreamReader f;
@@ -499,7 +573,7 @@ namespace Mono.CSharp
                        pattern = spec;
                }
 
-               static void ProcessFile (string f)
+               void AddSourceFile (string f)
                {
                        if (first_source == null)
                                first_source = f;
@@ -507,26 +581,125 @@ namespace Mono.CSharp
                        Location.AddFile (f);
                }
 
-               static void ProcessFiles ()
+               bool ParseArguments (string[] args)
+               {
+                       references = new ArrayList ();
+                       external_aliases = new Hashtable ();
+                       soft_references = new ArrayList ();
+                       modules = new ArrayList (2);
+                       link_paths = new ArrayList ();
+
+                       ArrayList response_file_list = null;
+                       bool parsing_options = true;
+
+                       for (int i = 0; i < args.Length; i++) {
+                               string arg = args [i];
+                               if (arg.Length == 0)
+                                       continue;
+
+                               if (arg.StartsWith ("@")) {
+                                       string [] extra_args;
+                                       string response_file = arg.Substring (1);
+
+                                       if (response_file_list == null)
+                                               response_file_list = new ArrayList ();
+
+                                       if (response_file_list.Contains (response_file)) {
+                                               Report.Error (
+                                                       1515, "Response file `" + response_file +
+                                                       "' specified multiple times");
+                                               return false;
+                                       }
+
+                                       response_file_list.Add (response_file);
+
+                                       extra_args = LoadArgs (response_file);
+                                       if (extra_args == null) {
+                                               Report.Error (2011, "Unable to open response file: " +
+                                                                 response_file);
+                                               return false;
+                                       }
+
+                                       args = AddArgs (args, extra_args);
+                                       continue;
+                               }
+
+                               if (parsing_options) {
+                                       if (arg == "--") {
+                                               parsing_options = false;
+                                               continue;
+                                       }
+
+                                       if (arg.StartsWith ("-")) {
+                                               if (UnixParseOption (arg, ref args, ref i))
+                                                       continue;
+
+                                               // Try a -CSCOPTION
+                                               string csc_opt = "/" + arg.Substring (1);
+                                               if (CSCParseOption (csc_opt, ref args, ref i))
+                                                       continue;
+
+                                               Error_WrongOption (arg);
+                                               return false;
+                                       }
+                                       if (arg [0] == '/') {
+                                               if (CSCParseOption (arg, ref args, ref i))
+                                                       continue;
+
+                                               // Need to skip `/home/test.cs' however /test.cs is considered as error
+                                               if (arg.Length < 2 || arg.IndexOf ('/', 2) == -1) {
+                                                       Error_WrongOption (arg);
+                                                       return false;
+                                               }
+                                       }
+                               }
+
+                               ProcessSourceFiles (arg, false);
+                       }
+
+                       //
+                       // If we are an exe, require a source file for the entry point
+                       //
+                       if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe || RootContext.Target == Target.Module) {
+                               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) {
+                               Report.Error (2008, "No files to compile were specified");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public void Parse ()
                {
                        Location.Initialize ();
 
-                       foreach (SourceFile file in Location.SourceFiles) {
+                       int files_count = Location.SourceFiles.Length;
+                       for (int i = 0; i < files_count; ++i) {
                                if (tokenize) {
-                                       tokenize_file (file);
+                                       tokenize_file (Location.SourceFiles [i]);
                                } else {
-                                       parse (file);
+                                       Parse (Location.SourceFiles [i]);
                                }
                        }
                }
 
-               static void CompileFiles (string spec, bool recurse)
+               void ProcessSourceFiles (string spec, bool recurse)
                {
                        string path, pattern;
 
                        SplitPathAndPattern (spec, out path, out pattern);
                        if (pattern.IndexOf ('*') == -1){
-                               ProcessFile (spec);
+                               AddSourceFile (spec);
                                return;
                        }
 
@@ -541,7 +714,7 @@ namespace Mono.CSharp
                                return;
                        }
                        foreach (string f in files) {
-                               ProcessFile (f);
+                               AddSourceFile (f);
                        }
 
                        if (!recurse)
@@ -558,7 +731,7 @@ namespace Mono.CSharp
                                        
                                // Don't include path in this string, as each
                                // directory entry already does
-                               CompileFiles (d + "/" + pattern, true);
+                               ProcessSourceFiles (d + "/" + pattern, true);
                        }
                }
 
@@ -571,6 +744,12 @@ namespace Mono.CSharp
                        string [] default_config = {
                                "System",
                                "System.Xml",
+#if NET_2_1
+                               "System.Core",
+                               "System.Net",
+                               "System.Windows",
+                               "System.Windows.Browser",
+#endif
 #if false
                                //
                                // Is it worth pre-loading all this stuff?
@@ -596,41 +775,37 @@ namespace Mono.CSharp
 #endif
                        };
                        
-                       int p = 0;
-                       foreach (string def in default_config)
-                               soft_references.Insert (p++, def);
+                       if (RootContext.Version == LanguageVersion.LINQ)
+                               soft_references.Add ("System.Core");
+
+                       soft_references.AddRange (default_config);
                }
 
-               static void SetOutputFile (string name)
+               public static string OutputFile
                {
-                       output_file = name;
+                       set {
+                               output_file = value;
+                       }
+                       get {
+                               return Path.GetFileName (output_file);
+                       }
                }
 
                static void SetWarningLevel (string s)
                {
-                       int level = 0;
+                       int level = -1;
 
                        try {
                                level = Int32.Parse (s);
                        } catch {
-                               Report.Error (
-                                       1900,
-                                       "--wlevel requires a value from 0 to 4");
-                               return;
                        }
                        if (level < 0 || level > 4){
-                               Report.Error (1900, "Warning level must be 0 to 4");
+                               Report.Error (1900, "Warning level must be in the range 0-4");
                                return;
                        }
-                       RootContext.WarningLevel = level;
+                       Report.WarningLevel = level;
                }
 
-               static void SetupV2 ()
-               {
-                       RootContext.Version = LanguageVersion.Default;
-                       defines.Add ("__V2__");
-               }
-               
                static void Version ()
                {
                        string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
@@ -643,7 +818,7 @@ namespace Mono.CSharp
                // deprecated in favor of the CSCParseOption, which will also handle the
                // options that start with a dash in the future.
                //
-               static bool UnixParseOption (string arg, ref string [] args, ref int i)
+               bool UnixParseOption (string arg, ref string [] args, ref int i)
                {
                        switch (arg){
                        case "-v":
@@ -659,7 +834,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--main": case "-m":
-                               Report.Warning (-29, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
+                               Report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -668,7 +843,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--unsafe":
-                               Report.Warning (-29, "Compatibility: Use -unsafe instead of --unsafe");
+                               Report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
                                RootContext.Unsafe = true;
                                return true;
                                
@@ -679,7 +854,7 @@ namespace Mono.CSharp
                                return true;
 
                        case "--define":
-                               Report.Warning (-29, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
+                               Report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -687,39 +862,22 @@ namespace Mono.CSharp
                                defines.Add (args [++i]);
                                return true;
 
-                       case "--show-counters":
-                               show_counters = true;
-                               return true;
-                               
-                       case "--expect-error": {
-                               int code = 0;
-                               
-                               try {
-                                       code = Int32.Parse (
-                                               args [++i], NumberStyles.AllowLeadingSign);
-                                       Report.ExpectedError = code;
-                               } catch {
-                                       Report.Error (-14, "Invalid number specified");
-                               } 
-                               return true;
-                       }
-                               
                        case "--tokenize": 
                                tokenize = true;
                                return true;
                                
                        case "-o": 
                        case "--output":
-                               Report.Warning (-29, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
+                               Report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
                                }
-                               SetOutputFile (args [++i]);
+                               OutputFile = args [++i];
                                return true;
 
                        case "--checked":
-                               Report.Warning (-29, "Compatibility: Use -checked instead of --checked");
+                               Report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
                                RootContext.Checked = true;
                                return true;
                                
@@ -729,34 +887,34 @@ namespace Mono.CSharp
                                
                        case "--linkresource":
                        case "--linkres":
-                               Report.Warning (-29, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
+                               Report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Report.Error (5, "Missing argument to --linkres"); 
                                        Environment.Exit (1);
                                }
-                               if (resources == null)
-                                       resources = new ArrayList ();
+                               if (embedded_resources == null)
+                                       embedded_resources = new Resources ();
                                
-                               resources.Add (args [++i]);
+                               embedded_resources.Add (false, args [++i], args [i]);
                                return true;
                                
                        case "--resource":
                        case "--res":
-                               Report.Warning (-29, "Compatibility: Use -res:VALUE instead of --res VALUE");
+                               Report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Report.Error (5, "Missing argument to --resource"); 
                                        Environment.Exit (1);
                                }
                                if (embedded_resources == null)
-                                       embedded_resources = new ArrayList ();
+                                       embedded_resources = new Resources ();
                                
-                               embedded_resources.Add (args [++i]);
+                               embedded_resources.Add (true, args [++i], args [i]);
                                return true;
                                
                        case "--target":
-                               Report.Warning (-29, "Compatibility: Use -target:KIND instead of --target KIND");
+                               Report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
                                if ((i + 1) >= args.Length){
                                        Environment.Exit (1);
                                        return true;
@@ -788,17 +946,26 @@ namespace Mono.CSharp
                                return true;
                                
                        case "-r":
-                               Report.Warning (-29, "Compatibility: Use -r:LIBRARY instead of -r library");
+                               Report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
                                }
                                
-                               references.Add (args [++i]);
+                               string val = args [++i];
+                               int idx = val.IndexOf ('=');
+                               if (idx > -1) {
+                                       string alias = val.Substring (0, idx);
+                                       string assembly = val.Substring (idx + 1);
+                                       AddExternAlias (alias, assembly);
+                                       return true;
+                               }
+
+                               references.Add (val);
                                return true;
                                
                        case "-L":
-                               Report.Warning (-29, "Compatibility: Use -lib:ARG instead of --L arg");
+                               Report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
                                if ((i + 1) >= args.Length){
                                        Usage ();       
                                        Environment.Exit (1);
@@ -807,7 +974,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--nostdlib":
-                               Report.Warning (-29, "Compatibility: Use -nostdlib instead of --nostdlib");
+                               Report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
                                RootContext.StdLib = false;
                                return true;
                                
@@ -816,12 +983,12 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--werror":
-                               Report.Warning (-29, "Compatibility: Use -warnaserror: option instead of --werror");
+                               Report.Warning (-29, 1, "Compatibility: Use -warnaserror: option instead of --werror");
                                Report.WarningsAreErrors = true;
                                return true;
-                               
+
                        case "--nowarn":
-                               Report.Warning (-29, "Compatibility: Use -nowarn instead of --nowarn");
+                               Report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
                                if ((i + 1) >= args.Length){
                                        Usage ();
                                        Environment.Exit (1);
@@ -838,7 +1005,7 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--wlevel":
-                               Report.Warning (-29, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
+                               Report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
                                if ((i + 1) >= args.Length){
                                        Report.Error (
                                                1900,
@@ -868,12 +1035,12 @@ namespace Mono.CSharp
                                return true;
                                
                        case "--recurse":
-                               Report.Warning (-29, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
+                               Report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
                                if ((i + 1) >= args.Length){
                                        Report.Error (5, "--recurse requires an argument");
                                        Environment.Exit (1);
                                }
-                               CompileFiles (args [++i], true); 
+                               ProcessSourceFiles (args [++i], true); 
                                return true;
                                
                        case "--timestamp":
@@ -881,17 +1048,13 @@ namespace Mono.CSharp
                                last_time = first_time = DateTime.Now;
                                return true;
 
-                       case "--pause":
-                               pause = true;
-                               return true;
-                               
                        case "--debug": case "-g":
-                               Report.Warning (-29, "Compatibility: Use -debug option instead of -g or --debug");
+                               Report.Warning (-29, 1, "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");
+                               Report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
                                load_default_config = false;
                                return true;
                        }
@@ -903,7 +1066,7 @@ namespace Mono.CSharp
                // 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)
+               bool CSCParseOption (string option, ref string [] args, ref int i)
                {
                        int idx = option.IndexOf (':');
                        string arg, value;
@@ -949,18 +1112,21 @@ namespace Mono.CSharp
                                return true;
 
                        case "/out":
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Usage ();
                                        Environment.Exit (1);
                                }
-                               SetOutputFile (value);
+                               OutputFile = value;
                                return true;
 
+                       case "/o":
+                       case "/o+":
                        case "/optimize":
                        case "/optimize+":
                                RootContext.Optimize = true;
                                return true;
 
+                       case "/o-":
                        case "/optimize-":
                                RootContext.Optimize = false;
                                return true;
@@ -973,15 +1139,16 @@ namespace Mono.CSharp
 
                        case "/d":
                        case "/define": {
-                               string [] defs;
-
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Usage ();
                                        Environment.Exit (1);
                                }
 
-                               defs = value.Split (new Char [] {';', ','});
-                               foreach (string d in defs){
+                               foreach (string d in value.Split (';', ',')){
+                                       if (!Tokenizer.IsValidIdentifier (d)) {
+                                               Report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", d);
+                                               continue;
+                                       }
                                        defines.Add (d);
                                }
                                return true;
@@ -994,22 +1161,10 @@ namespace Mono.CSharp
                                Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
                                return true;
 
-                       case "/linkres":
-                       case "/linkresource":
-                               if (value == ""){
-                                       Report.Error (5, arg + " requires an argument");
-                                       Environment.Exit (1);
-                               }
-                               if (resources == null)
-                                       resources = new ArrayList ();
-                               
-                               resources.Add (value);
-                               return true;
-
                        case "/pkg": {
                                string packages;
 
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Usage ();
                                        Environment.Exit (1);
                                }
@@ -1029,7 +1184,7 @@ namespace Mono.CSharp
                                }
 
                                if (p.StandardOutput == null){
-                                       Report.Warning (-27, "Specified package did not return any information");
+                                       Report.Warning (-27, 1, "Specified package did not return any information");
                                        return true;
                                }
                                string pkgout = p.StandardOutput.ReadToEnd ();
@@ -1049,49 +1204,70 @@ namespace Mono.CSharp
                                return true;
                        }
                                
+                       case "/linkres":
+                       case "/linkresource":
                        case "/res":
                        case "/resource":
-                               if (value == ""){
-                                       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);
+                                       embedded_resources = new Resources ();
+
+                               bool embeded = arg.StartsWith ("/r");
+                               string[] s = value.Split (',');
+                               switch (s.Length) {
+                                       case 1:
+                                               if (s[0].Length == 0)
+                                                       goto default;
+                                               embedded_resources.Add (embeded, s [0], Path.GetFileName (s[0]));
+                                               break;
+                                       case 2:
+                                               embedded_resources.Add (embeded, s [0], s [1]);
+                                               break;
+                                       case 3:
+                                               if (s [2] != "public" && s [2] != "private") {
+                                                       Report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s [2]);
+                                                       return true;
+                                               }
+                                               embedded_resources.Add (embeded, s [0], s [1], s [2] == "private");
+                                               break;
+                                       default:
+                                               Report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
+                                               break;
                                }
+
                                return true;
                                
                        case "/recurse":
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, "-recurse requires an argument");
                                        Environment.Exit (1);
                                }
-                               CompileFiles (value, true); 
+                               ProcessSourceFiles (value, true); 
                                return true;
 
                        case "/r":
                        case "/reference": {
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, "-reference requires an argument");
                                        Environment.Exit (1);
                                }
 
                                string [] refs = value.Split (new char [] { ';', ',' });
                                foreach (string r in refs){
-                                       references.Add (r);
+                                       string val = r;
+                                       int index = val.IndexOf ('=');
+                                       if (index > -1) {
+                                               string alias = r.Substring (0, index);
+                                               string assembly = r.Substring (index + 1);
+                                               AddExternAlias (alias, assembly);
+                                               return true;
+                                       }
+                                       
+                                       references.Add (val);
                                }
                                return true;
                        }
                        case "/addmodule": {
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, arg + " requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1103,7 +1279,7 @@ namespace Mono.CSharp
                                return true;
                        }
                        case "/win32res": {
-                               if (value == "") {
+                               if (value.Length == 0) {
                                        Report.Error (5, arg + " requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1112,7 +1288,7 @@ namespace Mono.CSharp
                                return true;
                        }
                        case "/win32icon": {
-                               if (value == "") {
+                               if (value.Length == 0) {
                                        Report.Error (5, arg + " requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1121,7 +1297,7 @@ namespace Mono.CSharp
                                return true;
                        }
                        case "/doc": {
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (2006, arg + " requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1131,7 +1307,7 @@ namespace Mono.CSharp
                        case "/lib": {
                                string [] libdirs;
                                
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, "/lib requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1193,7 +1369,7 @@ namespace Mono.CSharp
                        case "/nowarn": {
                                string [] warns;
 
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, "/nowarn requires an argument");
                                        Environment.Exit (1);
                                }
@@ -1207,7 +1383,7 @@ namespace Mono.CSharp
                                                }
                                                Report.SetIgnoreWarning (warn);
                                        } catch {
-                                               Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc));
+                                               Report.Error (1904, String.Format("`{0}' is not a valid warning number", wc));
                                        }
                                }
                                return true;
@@ -1235,7 +1411,7 @@ namespace Mono.CSharp
 
                        case "/main":
                        case "/m":
-                               if (value == ""){
+                               if (value.Length == 0){
                                        Report.Error (5, arg + " requires an argument");                                        
                                        Environment.Exit (1);
                                }
@@ -1275,56 +1451,59 @@ namespace Mono.CSharp
                                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;
+                               case "iso-1":
+                                       RootContext.Version = LanguageVersion.ISO_1;
+                                       return true;
+                                       
+                               case "default":
+                                       RootContext.Version = LanguageVersion.Default;
+#if GMCS_SOURCE                                        
+                                       defines.Add ("__V2__");
+#endif
+                                       return true;
+#if GMCS_SOURCE
+                               case "iso-2":
+                                       RootContext.Version = LanguageVersion.ISO_2;
+                                       return true;
+                                       
+                               case "linq":
+                                       Report.Warning (-30, 1, "Deprecated: The `linq' option is no longer required and should not be used");
+                                       return true;
+#endif
                                }
-                               Report.Error (1617, "Invalid option '{0}' for /langversion; must be ISO-1 or Default", value);
+                               Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
                                return true;
 
                        case "/codepage":
-                               int cp = -1;
-
-                               if (value == "utf8"){
+                               switch (value) {
+                               case "utf8":
                                        encoding = new UTF8Encoding();
-                                       using_default_encoder = false;
-                                       return true;
-                               }
-                               if (value == "reset"){
-                                       //
-                                       // 28591 is the code page for ISO-8859-1 encoding.
-                                       //
-                                       cp = 28591;
-                                       using_default_encoder = true;
-                               }
-                               
-                               try {
-                                       cp = Int32.Parse (value);
-                                       encoding = Encoding.GetEncoding (cp);
-                                       using_default_encoder = false;
-                               } catch {
-                                       Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp));
+                                       break;
+                               case "reset":
+                                       encoding = Encoding.Default;
+                                       break;
+                               default:
+                                       try {
+                                               encoding = Encoding.GetEncoding (
+                                               Int32.Parse (value));
+                                       } catch {
+                                               Report.Error (2016, "Code page `{0}' is invalid or not installed", value);
+                                       }
+                                       break;
                                }
                                return true;
                        }
 
-                       //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option));
-                       //Environment.Exit (1);
                        return false;
                }
 
+               static void Error_WrongOption (string option)
+               {
+                       Report.Error (2007, "Unrecognized command-line option: `{0}'", option);
+               }
+
                static string [] AddArgs (string [] args, string [] extra_args)
                {
                        string [] new_args;
@@ -1348,144 +1527,59 @@ namespace Mono.CSharp
 
                        return new_args;
                }
-               
-               /// <summary>
-               ///    Parses the arguments, and drives the compilation
-               ///    process.
-               /// </summary>
-               ///
-               /// <remarks>
-               ///    TODO: Mostly structured to debug the compiler
-               ///    now, needs to be turned into a real driver soon.
-               /// </remarks>
-               // [MonoTODO("Change error code for unknown argument to something reasonable")]
-               internal static bool MainDriver (string [] args)
-               {
-                       int i;
-                       bool parsing_options = true;
 
-                       try {
-                               encoding = Encoding.GetEncoding (28591);
-                       } catch {
-                               Console.WriteLine ("Error: could not load encoding 28591, trying 1252");
-                               encoding = Encoding.GetEncoding (1252);
+               static void AddExternAlias (string identifier, string assembly)
+               {
+                       if (assembly.Length == 0) {
+                               Report.Error (1680, "Invalid reference alias '" + identifier + "='. Missing filename");
+                               return;
                        }
-                       
-                       references = new ArrayList ();
-                       soft_references = new ArrayList ();
-                       modules = new ArrayList ();
-                       link_paths = new ArrayList ();
 
-                       SetupDefaultDefines ();
+                       if (!IsExternAliasValid (identifier)) {
+                               Report.Error (1679, "Invalid extern alias for /reference. Alias '" + identifier + "' is not a valid identifier");
+                               return;
+                       }
                        
-                       //
-                       // Setup defaults
-                       //
-                       // This is not required because Assembly.Load knows about this
-                       // path.
-                       //
-
-                       Hashtable response_file_list = null;
-
-                       for (i = 0; i < args.Length; i++){
-                               string arg = args [i];
-                               if (arg == "")
-                                       continue;
-                               
-                               if (arg.StartsWith ("@")){
-                                       string [] extra_args;
-                                       string response_file = arg.Substring (1);
-
-                                       if (response_file_list == null)
-                                               response_file_list = new Hashtable ();
-                                       
-                                       if (response_file_list.Contains (response_file)){
-                                               Report.Error (
-                                                       1515, "Response file `" + response_file +
-                                                       "' specified multiple times");
-                                               Environment.Exit (1);
-                                       }
-                                       
-                                       response_file_list.Add (response_file, response_file);
-                                                   
-                                       extra_args = LoadArgs (response_file);
-                                       if (extra_args == null){
-                                               Report.Error (2011, "Unable to open response file: " +
-                                                             response_file);
-                                               return false;
-                                       }
+                       // Could here hashtable throw an exception?
+                       external_aliases [identifier] = assembly;
+               }
+               
+               static bool IsExternAliasValid (string identifier)
+               {
+                       if (identifier.Length == 0)
+                               return false;
+                       if (identifier [0] != '_' && !Char.IsLetter (identifier [0]))
+                               return false;
 
-                                       args = AddArgs (args, extra_args);
+                       for (int i = 1; i < identifier.Length; i++) {
+                               char c = identifier [i];
+                               if (Char.IsLetter (c) || Char.IsDigit (c))
                                        continue;
-                               }
-
-                               if (parsing_options){
-                                       if (arg == "--"){
-                                               parsing_options = false;
-                                               continue;
-                                       }
-                                       
-                                       if (arg.StartsWith ("-")){
-                                               if (UnixParseOption (arg, ref args, ref i))
-                                                       continue;
-
-                                               // Try a -CSCOPTION
-                                               string csc_opt = "/" + arg.Substring (1);
-                                               if (CSCParseOption (csc_opt, ref args, ref i))
-                                                       continue;
-                                       } else {
-                                               if (arg.StartsWith ("/")){
-                                                       if (CSCParseOption (arg, ref args, ref i))
-                                                               continue;
-                                               }
-                                       }
-                               }
-
-                               CompileFiles (arg, false); 
-                       }
-
-                       ProcessFiles ();
-
-                       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");
+                               UnicodeCategory category = Char.GetUnicodeCategory (c);
+                               if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
+                                               category != UnicodeCategory.SpacingCombiningMark ||
+                                               category != UnicodeCategory.ConnectorPunctuation)
                                        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;
                        }
-
+                       
+                       return true;
+               }
+               
+               //
+               // Main compilation method
+               //
+               public bool Compile ()
+               {
+                       Parse ();
                        if (Report.Errors > 0)
                                return false;
-                       
-                       if (parse_only)
+
+                       if (tokenize || parse_only)
                                return true;
 
-                       //
-                       // Load Core Library for default compilation
-                       //
-                       if (RootContext.StdLib)
-                               references.Insert (0, "mscorlib");
+                       if (RootContext.ToplevelTypes.NamespaceEntry != null)
+                               throw new InternalErrorException ("who set it?");
 
                        if (load_default_config)
                                DefineDefaultConfig ();
@@ -1514,6 +1608,11 @@ namespace Mono.CSharp
                        // Quick hack
                        //
                        if (output_file == null){
+                               if (first_source == null){
+                                       Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
+                                       return false;
+                               }
+                                       
                                int pos = first_source.LastIndexOf ('.');
 
                                if (pos > 0)
@@ -1536,39 +1635,22 @@ namespace Mono.CSharp
                                set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
                        }
 
-                       TypeManager.AddModule (CodeGen.Module.Builder);
+                       RootNamespace.Global.AddModuleReference (CodeGen.Module.Builder);
 
                        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);
+                                       LoadModule (module);
                        }
-
-                       TypeManager.ComputeNamespaces ();
                        
-                       //
-                       // Before emitting, we need to get the core
-                       // types emitted from the user defined types
-                       // or from the system ones.
-                       //
-                       if (timestamps)
-                               ShowTime ("Initializing Core Types");
-                       if (!RootContext.StdLib){
-                               RootContext.ResolveCore ();
-                               if (Report.Errors > 0)
-                                       return false;
-                       }
-                       
-                       TypeManager.InitCoreTypes ();
+                       if (!TypeManager.InitCoreTypes ())
+                               return false;
+
+                       TypeManager.InitOptionalCoreTypes ();
+
                        if (timestamps)
                                ShowTime ("   Core Types done");
 
-                       CodeGen.Module.ResolveAttributes ();
+                       CodeGen.Module.Resolve ();
 
                        //
                        // The second pass of the compiler
@@ -1583,32 +1665,31 @@ namespace Mono.CSharp
                                ShowTime ("Populate tree");
                        if (!RootContext.StdLib)
                                RootContext.BootCorlib_PopulateCoreTypes ();
-
                        RootContext.PopulateTypes ();
+
                        RootContext.DefineTypes ();
                        
-                       if (RootContext.Documentation != null &&
+                       if (Report.Errors == 0 &&
+                               RootContext.Documentation != null &&
                                !RootContext.Documentation.OutputDocComment (
                                        output_file))
                                return false;
 
-                       TypeManager.InitCodeHelpers ();
-
                        //
                        // Verify using aliases now
                        //
-                       Namespace.VerifyUsing ();
+                       NamespaceEntry.VerifyAllUsing ();
                        
                        if (Report.Errors > 0){
                                return false;
                        }
+
+                       CodeGen.Assembly.Resolve ();
                        
                        if (RootContext.VerifyClsCompliance) {
-                               CodeGen.Assembly.ResolveClsCompliance ();
                                if (CodeGen.Assembly.IsClsCompliant) {
                                        AttributeTester.VerifyModulesClsCompliance ();
                                        TypeManager.LoadAllImportedTypes ();
-                                       AttributeTester.VerifyTopLevelNameClsCompliance ();
                                }
                        }
                        if (Report.Errors > 0)
@@ -1634,7 +1715,7 @@ namespace Mono.CSharp
                        RootContext.CloseTypes ();
 
                        PEFileKinds k = PEFileKinds.ConsoleApplication;
-                       
+
                        switch (RootContext.Target) {
                        case Target.Library:
                        case Target.Module:
@@ -1650,103 +1731,59 @@ namespace Mono.CSharp
 
                                if (ep == null) {
                                        if (RootContext.MainClass != null) {
-                                               DeclSpace main_cont = RootContext.Tree.GetDecl (MemberName.FromDotted (RootContext.MainClass));
+                                               DeclSpace main_cont = RootContext.ToplevelTypes.GetDefinition (RootContext.MainClass) as DeclSpace;
                                                if (main_cont == null) {
-                                                       Report.Error (1555, output_file, "Could not find '{0}' specified for Main method", RootContext.MainClass); 
+                                                       Report.Error (1555, "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);
+                                                       Report.Error (1556, "`{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 ());
+                                               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");
+                                               Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point",
+                                                       output_file);
                                        return false;
                                }
 
                                CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
                        } else if (RootContext.MainClass != null) {
-                               Report.Error (2017, "Can not specify -main: when building module or library");
+                               Report.Error (2017, "Cannot specify -main if building a module or library");
                        }
 
-                       //
-                       // Add the resources
-                       //
-                       if (resources != null){
-                               foreach (string spec in resources){
-                                       string file, res;
-                                       int cp;
-                                       
-                                       cp = spec.IndexOf (',');
-                                       if (cp != -1){
-                                               file = spec.Substring (0, cp);
-                                               res = spec.Substring (cp + 1);
-                                       } else
-                                               file = res = spec;
-
-                                       CodeGen.Assembly.Builder.AddResourceFile (res, file);
-                               }
-                       }
-                       
                        if (embedded_resources != null){
-                               object[] margs = new object [2];
-                               Type[] argst = new Type [2];
-                               argst [0] = argst [1] = typeof (string);
-
-                               MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod (
-                                       "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
-                                       null, CallingConventions.Any, argst, null);
-                               
-                               if (embed_res == null) {
-                                       Report.RuntimeMissingSupport (Location.Null, "Resource embedding");
-                               } else {
-                                       foreach (string spec in embedded_resources) {
-                                               int cp;
-
-                                               cp = spec.IndexOf (',');
-                                               if (cp != -1){
-                                                       margs [0] = spec.Substring (cp + 1);
-                                                       margs [1] = spec.Substring (0, cp);
-                                               } else {
-                                                       margs [1] = spec;
-                                                       margs [0] = Path.GetFileName (spec);
-                                               }
-
-                                               if (File.Exists ((string) margs [1]))
-                                                       embed_res.Invoke (CodeGen.Assembly.Builder, margs);
-                                               else {
-                                                       Report.Error (1566, "Can not find the resource " + margs [1]);
-                                               }
-                                       }
+                               if (RootContext.Target == Target.Module) {
+                                       Report.Error (1507, "Cannot link resource file when building a module");
+                                       return false;
                                }
+
+                               embedded_resources.Emit ();
                        }
 
                        //
                        // Add Win32 resources
                        //
 
-                       CodeGen.Assembly.Builder.DefineVersionInfoResource ();
-
                        if (win32ResourceFile != null) {
                                try {
                                        CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
+                               } catch (ArgumentException) {
+                                       Report.RuntimeMissingSupport (Location.Null, "resource embeding");
                                }
-                               catch (ArgumentException) {
-                                       Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
-                               }
+                       } else {
+                               CodeGen.Assembly.Builder.DefineVersionInfoResource ();
                        }
 
                        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.");
+                                       Report.RuntimeMissingSupport (Location.Null, "resource embeding");
                                }
                                define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
                        }
@@ -1754,7 +1791,7 @@ namespace Mono.CSharp
                        if (Report.Errors > 0)
                                return false;
                        
-                       CodeGen.Save (output_file);
+                       CodeGen.Save (output_file, want_debugging_support);
                        if (timestamps) {
                                ShowTime ("Saved output");
                                ShowTotalTime ("Total");
@@ -1787,6 +1824,113 @@ namespace Mono.CSharp
                }
        }
 
+       class Resources
+       {
+               interface IResource
+               {
+                       void Emit ();
+                       string FileName { get; }
+               }
+
+               class EmbededResource : IResource
+               {
+                       static MethodInfo embed_res;
+
+                       static EmbededResource () {
+                               Type[] argst = new Type [] { 
+                                                                                          typeof (string), typeof (string), typeof (ResourceAttributes)
+                                                                                  };
+
+                               embed_res = typeof (AssemblyBuilder).GetMethod (
+                                       "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
+                                       null, CallingConventions.Any, argst, null);
+                               
+                               if (embed_res == null) {
+                                       Report.RuntimeMissingSupport (Location.Null, "Resource embedding");
+                               }
+                       }
+
+                       readonly object[] args;
+
+                       public EmbededResource (string name, string file, bool isPrivate)
+                       {
+                               args = new object [3];
+                               args [0] = name;
+                               args [1] = file;
+                               args [2] = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
+                       }
+
+                       public void Emit()
+                       {
+                               embed_res.Invoke (CodeGen.Assembly.Builder, args);
+                       }
+
+                       public string FileName {
+                               get {
+                                       return (string)args [1];
+                               }
+                       }
+               }
+
+               class LinkedResource : IResource
+               {
+                       readonly string file;
+                       readonly string name;
+                       readonly ResourceAttributes attribute;
+
+                       public LinkedResource (string name, string file, bool isPrivate)
+                       {
+                               this.name = name;
+                               this.file = file;
+                               this.attribute = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
+                       }
+
+                       public void Emit ()
+                       {
+                               CodeGen.Assembly.Builder.AddResourceFile (name, Path.GetFileName(file), attribute);
+                       }
+
+                       public string FileName {
+                               get {
+                                       return file;
+                               }
+                       }
+               }
+
+
+               IDictionary embedded_resources = new HybridDictionary ();
+
+               public void Add (bool embeded, string file, string name)
+               {
+                       Add (embeded, file, name, false);
+               }
+
+               public void Add (bool embeded, string file, string name, bool isPrivate)
+               {
+                       if (embedded_resources.Contains (name)) {
+                               Report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", name);
+                               return;
+                       }
+                       IResource r = embeded ? 
+                               (IResource) new EmbededResource (name, file, isPrivate) : 
+                               new LinkedResource (name, file, isPrivate);
+
+                       embedded_resources.Add (name, r);
+               }
+
+               public void Emit ()
+               {
+                       foreach (IResource r in embedded_resources.Values) {
+                               if (!File.Exists (r.FileName)) {
+                                       Report.Error (1566, "Error reading resource file `{0}'", r.FileName);
+                                       continue;
+                               }
+                               
+                               r.Emit ();
+                       }
+               }
+       }
+
        //
        // This is the only public entry point
        //
@@ -1795,24 +1939,41 @@ namespace Mono.CSharp
                {
                        Report.Stderr = error;
                        try {
-                               return Driver.MainDriver (args) && Report.Errors == 0;
+                               Driver d = Driver.Create (args);
+                               if (d == null)
+                                       return false;
+
+                               return d.Compile () && Report.Errors == 0;
                        }
                        finally {
                                Report.Stderr = Console.Error;
                                Reset ();
                        }
                }
+
+               public static int[] AllWarningNumbers {
+                       get {
+                               return Report.AllWarnings;
+                       }
+               }
                
                static void Reset ()
                {
                        Driver.Reset ();
-                       Location.Reset ();
                        RootContext.Reset ();
+                       Tokenizer.Reset ();
+                       Location.Reset ();
                        Report.Reset ();
                        TypeManager.Reset ();
                        TypeHandle.Reset ();
-                       Namespace.Reset ();
+                       RootNamespace.Reset ();
+                       NamespaceEntry.Reset ();
                        CodeGen.Reset ();
+                       Attribute.Reset ();
+                       AttributeTester.Reset ();
+                       AnonymousTypeClass.Reset ();
+                       AnonymousMethodBody.Reset ();
+                       AnonymousMethodStorey.Reset ();
                }
        }
 }