X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdriver.cs;h=f688846d991d93787f8598985831232e4503fdda;hb=b68b65ad17932bbe2d1fd565456063d90e08aaa5;hp=09936c8e8af2bbe629305624d27b4ccadea6fec6;hpb=6f94553690b1cd6487bcc206aec7f58c99f77adb;p=mono.git diff --git a/mcs/mcs/driver.cs b/mcs/mcs/driver.cs index 09936c8e8af..f688846d991 100644 --- a/mcs/mcs/driver.cs +++ b/mcs/mcs/driver.cs @@ -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, 2005 Novell, Inc +// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc // namespace Mono.CSharp @@ -24,99 +26,101 @@ namespace Mono.CSharp public enum Target { Library, Exe, Module, WinExe }; + +#if GMCS_SOURCE + enum Platform { + AnyCPU, X86, X64, IA64 + }; +#endif /// /// The compiler driver. /// - public class Driver + class Driver { - // // Assemblies references to be linked. Initialized with // mscorlib.dll here. - static ArrayList references; + ArrayList references; // // If any of these fail, we ignore the problem. This is so // that we can list all the assemblies in Windows and not fail // if they are missing on Linux. // - static ArrayList soft_references; + ArrayList soft_references; // // External aliases for assemblies. // - static Hashtable external_aliases; + Hashtable external_aliases; // // Modules to be linked // - static ArrayList modules; + ArrayList modules; // Lookup paths static ArrayList link_paths; // Whether we want to only run the tokenizer - static bool tokenize = false; + bool tokenize; - static string first_source; - - static bool want_debugging_support = false; + string first_source; - 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 Resources embedded_resources; - static string win32ResourceFile; - static string win32IconFile; - - // - // An array of the defines from the command line - // - static ArrayList defines; + Resources embedded_resources; + string win32ResourceFile; + string win32IconFile; // // Output file // - static string output_file = null; + static string output_file; // // Last time we took the time // - static DateTime last_time, first_time; + DateTime last_time, first_time; // // Encoding. // - static Encoding encoding; + Encoding encoding; + + static readonly char[] argument_value_separator = new char [] { ';', ',' }; static public void Reset () { - want_debugging_support = false; - parse_only = false; - timestamps = false; - pause = false; - show_counters = false; - load_default_config = true; - embedded_resources = null; - win32ResourceFile = win32IconFile = null; - defines = null; output_file = null; - encoding = null; - first_source = null; } - public static void ShowTime (string msg) + public Driver () + { + encoding = Encoding.Default; + } + + public static Driver Create (string [] args, bool require_files) + { + Driver d = new Driver (); + if (!d.ParseArguments (args, require_files)) + return null; + + return d; + } + + void ShowTime (string msg) { if (!timestamps) return; @@ -130,7 +134,7 @@ namespace Mono.CSharp (int) span.TotalSeconds, span.Milliseconds, msg); } - public static void ShowTotalTime (string msg) + void ShowTotalTime (string msg) { if (!timestamps) return; @@ -144,7 +148,7 @@ namespace Mono.CSharp (int) span.TotalSeconds, span.Milliseconds, msg); } - static void tokenize_file (SourceFile file) + void tokenize_file (CompilationUnit file) { Stream input; @@ -157,7 +161,7 @@ namespace Mono.CSharp using (input){ SeekableStreamReader reader = new SeekableStreamReader (input, encoding); - Tokenizer lexer = new Tokenizer (reader, file, defines); + Tokenizer lexer = new Tokenizer (reader, file); int token, tokens = 0, errors = 0; while ((token = lexer.token ()) != Token.EOF){ @@ -171,16 +175,14 @@ 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 found"); + Report.Error (2001, "Source file `{0}' could not be found", file.Name); return; } @@ -194,16 +196,19 @@ namespace Mono.CSharp } reader.Position = 0; - parser = new CSharpParser (reader, file, defines); + Parse (reader, file); + input.Close (); + } + + void Parse (SeekableStreamReader reader, CompilationUnit file) + { + CSharpParser parser = new CSharpParser (reader, file); parser.ErrorOutput = Report.Stderr; try { parser.parse (); } catch (Exception ex) { - Report.Error( - 666, String.Format ("Compilation aborted in file {0}, parser at {1}: {2}", - file.Name, parser.Lexer.Location, ex)); - } finally { - input.Close (); + Report.Error(589, parser.Lexer.Location, + "Compilation aborted in file `{0}', {1}", file.Name, ex); } } @@ -224,38 +229,43 @@ namespace Mono.CSharp static void Usage () { Console.WriteLine ( - "Mono C# compiler, (C) 2001 - 2008 Novell, Inc.\n" + + "Mono C# compiler, Copyright 2001 - 2008 Novell, Inc.\n" + "mcs [options] source-files\n" + - " --about About the Mono C# compiler\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\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 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 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 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" + + " --about About the Mono C# compiler\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\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 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: ISO-1, ISO-2, Default, or Future\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 implicitly referenced assemblies\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" + +#if !SMCS_SOURCE + " -pkg:P1[,Pn] References packages P1..Pn\n" + +#endif + " -platform:ARCH Specifies the target platform of the output assembly\n" + + " ARCH can be one of: anycpu, x86, x64 or itanium\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" + + " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" + + " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" + + " -help2 Shows internal compiler options\n" + "\n" + "Resources:\n" + " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" + @@ -274,8 +284,9 @@ namespace Mono.CSharp static void About () { Console.WriteLine ( - "The Mono C# compiler is (C) 2001-2008, Novell, 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.mono-project.com\n\n" + @@ -284,32 +295,27 @@ namespace Mono.CSharp Environment.Exit (0); } - public static int counter1, counter2; - public static int Main (string[] args) { - RootContext.Version = LanguageVersion.Default; - Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t"; - bool ok = MainDriver (args); - - if (ok && Report.Errors == 0) { + Driver d = Driver.Create (args, true); + 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 (); + Environment.Exit (0); return 0; - } else { - Console.WriteLine("Compilation failed: {0} error(s), {1} warnings", - Report.Errors, Report.Warnings); - return 1; } + + + Console.WriteLine("Compilation failed: {0} error(s), {1} warnings", + Report.Errors, Report.Warnings); + Environment.Exit (1); + return 1; } static public void LoadAssembly (string assembly, bool soft) @@ -405,9 +411,9 @@ namespace Mono.CSharp // Extern aliased refs require special handling if (alias == null) - RootNamespace.Global.AddAssemblyReference (a); + GlobalRootNamespace.Instance.AddAssemblyReference (a); else - RootNamespace.DefineRootNamespace (alias, a); + GlobalRootNamespace.Instance.DefineRootNamespace (alias, a); } catch (BadImageFormatException f) { // .NET 2.0 throws this if we try to load a module without an assembly manifest ... @@ -447,7 +453,7 @@ namespace Mono.CSharp } } - RootNamespace.Global.AddModuleReference (m); + GlobalRootNamespace.Instance.AddModuleReference (m); } catch (BadImageFormatException f) { Error9 ("module", f.FileName, f.FusionLog); @@ -459,8 +465,11 @@ namespace Mono.CSharp /// /// Loads all assemblies referenced on the command line /// - static public void LoadReferences () + public void LoadReferences () { + link_paths.Add (GetSystemDir ()); + link_paths.Add (Directory.GetCurrentDirectory ()); + // // Load Core Library for default compilation // @@ -475,14 +484,8 @@ namespace Mono.CSharp foreach (DictionaryEntry entry in external_aliases) LoadAssembly ((string) entry.Value, (string) entry.Key, false); - - return; - } - - static void SetupDefaultDefines () - { - defines = new ArrayList (); - defines.Add ("__MonoCS__"); + + GlobalRootNamespace.Instance.ComputeNamespaces (); } static string [] LoadArgs (string file) @@ -574,7 +577,7 @@ namespace Mono.CSharp pattern = spec; } - static void ProcessFile (string f) + void AddSourceFile (string f) { if (first_source == null) first_source = f; @@ -582,26 +585,128 @@ namespace Mono.CSharp Location.AddFile (f); } - static void ProcessFiles () + bool ParseArguments (string[] args, bool require_files) + { + 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 [0] == '@') { + 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 [0] == '-') { + if (UnixParseOption (arg, ref args, ref i)) + continue; + + // Try a -CSCOPTION + string csc_opt = "/" + arg.Substring (1); + if (CSCParseOption (csc_opt, ref args)) + continue; + + Error_WrongOption (arg); + return false; + } + if (arg [0] == '/') { + if (CSCParseOption (arg, ref args)) + 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 (require_files == false) + return true; + + // + // 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) { + ArrayList cu = Location.SourceFiles; + for (int i = 0; i < cu.Count; ++i) { if (tokenize) { - tokenize_file (file); + tokenize_file ((CompilationUnit) cu [i]); } else { - parse (file); + Parse ((CompilationUnit) cu [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; } @@ -616,7 +721,7 @@ namespace Mono.CSharp return; } foreach (string f in files) { - ProcessFile (f); + AddSourceFile (f); } if (!recurse) @@ -633,25 +738,26 @@ namespace Mono.CSharp // Don't include path in this string, as each // directory entry already does - CompileFiles (d + "/" + pattern, true); + ProcessSourceFiles (d + "/" + pattern, true); } } - static void DefineDefaultConfig () + public void ProcessDefaultConfig () { + if (!load_default_config) + return; + // // For now the "default config" is harcoded into the compiler // we can move this outside later // string [] default_config = { "System", + "System.Xml", #if NET_2_1 - "agclr", - "System.Core", - "System.Silverlight", - "System.Xml.Core", -#else - "System.Xml" + "System.Net", + "System.Windows", + "System.Windows.Browser", #endif #if false // @@ -677,11 +783,13 @@ namespace Mono.CSharp "System.Windows.Forms" #endif }; - - if (RootContext.Version == LanguageVersion.LINQ) - soft_references.Add ("System.Core"); soft_references.AddRange (default_config); + + if (RootContext.Version > LanguageVersion.ISO_2) + soft_references.Add ("System.Core"); + if (RootContext.Version > LanguageVersion.V_3) + soft_references.Add ("Microsoft.CSharp"); } public static string OutputFile @@ -721,7 +829,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": @@ -762,26 +870,9 @@ namespace Mono.CSharp Usage (); Environment.Exit (1); } - defines.Add (args [++i]); + RootContext.AddConditional (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; @@ -902,11 +993,6 @@ namespace Mono.CSharp Report.Fatal = true; return true; - case "--werror": - Report.Warning (-29, 1, "Compatibility: Use -warnaserror: option instead of --werror"); - Report.WarningsAreErrors = true; - return true; - case "--nowarn": Report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn"); if ((i + 1) >= args.Length){ @@ -960,7 +1046,7 @@ namespace Mono.CSharp Report.Error (5, "--recurse requires an argument"); Environment.Exit (1); } - CompileFiles (args [++i], true); + ProcessSourceFiles (args [++i], true); return true; case "--timestamp": @@ -968,10 +1054,6 @@ namespace Mono.CSharp last_time = first_time = DateTime.Now; return true; - case "--pause": - pause = true; - return true; - case "--debug": case "-g": Report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug"); want_debugging_support = true; @@ -986,11 +1068,50 @@ namespace Mono.CSharp return false; } +#if !SMCS_SOURCE + public static string GetPackageFlags (string packages, bool fatal) + { + ProcessStartInfo pi = new ProcessStartInfo (); + pi.FileName = "pkg-config"; + pi.RedirectStandardOutput = true; + pi.UseShellExecute = false; + pi.Arguments = "--libs " + packages; + Process p = null; + try { + p = Process.Start (pi); + } catch (Exception e) { + Report.Error (-27, "Couldn't run pkg-config: " + e.Message); + if (fatal) + Environment.Exit (1); + p.Close (); + return null; + } + + if (p.StandardOutput == null){ + Report.Warning (-27, 1, "Specified package did not return any information"); + p.Close (); + return null; + } + string pkgout = p.StandardOutput.ReadToEnd (); + p.WaitForExit (); + if (p.ExitCode != 0) { + Report.Error (-27, "Error running pkg-config. Check the above output."); + if (fatal) + Environment.Exit (1); + p.Close (); + return null; + } + p.Close (); + + return pkgout; + } +#endif + // // 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) { int idx = option.IndexOf (':'); string arg, value; @@ -1004,7 +1125,7 @@ namespace Mono.CSharp value = option.Substring (idx + 1); } - switch (arg){ + switch (arg.ToLower (CultureInfo.InvariantCulture)){ case "/nologo": return true; @@ -1068,12 +1189,12 @@ namespace Mono.CSharp Environment.Exit (1); } - foreach (string d in value.Split (';', ',')){ + foreach (string d in value.Split (argument_value_separator)) { if (!Tokenizer.IsValidIdentifier (d)) { Report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", d); continue; } - defines.Add (d); + RootContext.AddConditional (d); } return true; } @@ -1084,7 +1205,7 @@ namespace Mono.CSharp // Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs"); return true; - +#if !SMCS_SOURCE case "/pkg": { string packages; @@ -1093,41 +1214,17 @@ namespace Mono.CSharp Environment.Exit (1); } packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'})); + string pkgout = GetPackageFlags (packages, true); - ProcessStartInfo pi = new ProcessStartInfo (); - pi.FileName = "pkg-config"; - pi.RedirectStandardOutput = true; - pi.UseShellExecute = false; - pi.Arguments = "--libs " + packages; - Process p = null; - try { - p = Process.Start (pi); - } catch (Exception e) { - Report.Error (-27, "Couldn't run pkg-config: " + e.Message); - Environment.Exit (1); - } - - if (p.StandardOutput == null){ - Report.Warning (-27, 1, "Specified package did not return any information"); - return true; - } - string pkgout = p.StandardOutput.ReadToEnd (); - p.WaitForExit (); - if (p.ExitCode != 0) { - Report.Error (-27, "Error running pkg-config. Check the above output."); - Environment.Exit (1); - } - if (pkgout != null){ string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}). Split (new Char [] { ' ', '\t'}); args = AddArgs (args, xargs); } - p.Close (); return true; } - +#endif case "/linkres": case "/linkresource": case "/res": @@ -1135,27 +1232,27 @@ namespace Mono.CSharp if (embedded_resources == null) embedded_resources = new Resources (); - bool embeded = arg.StartsWith ("/r"); - string[] s = value.Split (','); + bool embeded = arg [1] == 'r' || arg [1] == 'R'; + string[] s = value.Split (argument_value_separator); 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; + 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; @@ -1165,7 +1262,7 @@ namespace Mono.CSharp Report.Error (5, "-recurse requires an argument"); Environment.Exit (1); } - CompileFiles (value, true); + ProcessSourceFiles (value, true); return true; case "/r": @@ -1175,7 +1272,7 @@ namespace Mono.CSharp Environment.Exit (1); } - string [] refs = value.Split (new char [] { ';', ',' }); + string[] refs = value.Split (argument_value_separator); foreach (string r in refs){ string val = r; int index = val.IndexOf ('='); @@ -1185,8 +1282,9 @@ namespace Mono.CSharp AddExternAlias (alias, assembly); return true; } - - references.Add (val); + + if (val.Length != 0) + references.Add (val); } return true; } @@ -1196,7 +1294,7 @@ namespace Mono.CSharp Environment.Exit (1); } - string [] refs = value.Split (new char [] { ';', ',' }); + string[] refs = value.Split (argument_value_separator); foreach (string r in refs){ modules.Add (r); } @@ -1207,6 +1305,9 @@ namespace Mono.CSharp Report.Error (5, arg + " requires an argument"); Environment.Exit (1); } + + if (win32IconFile != null) + Report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); win32ResourceFile = value; return true; @@ -1217,6 +1318,9 @@ namespace Mono.CSharp Environment.Exit (1); } + if (win32ResourceFile != null) + Report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); + win32IconFile = value; return true; } @@ -1236,7 +1340,7 @@ namespace Mono.CSharp Environment.Exit (1); } - libdirs = value.Split (new Char [] { ',' }); + libdirs = value.Split (argument_value_separator); foreach (string dir in libdirs) link_paths.Add (dir); return true; @@ -1247,6 +1351,11 @@ namespace Mono.CSharp return true; case "/debug": + if (value == "full" || value == "") + want_debugging_support = true; + + return true; + case "/debug+": want_debugging_support = true; return true; @@ -1279,11 +1388,21 @@ namespace Mono.CSharp case "/warnaserror": case "/warnaserror+": - Report.WarningsAreErrors = true; + if (value.Length == 0) { + Report.WarningsAreErrors = true; + } else { + foreach (string wid in value.Split (argument_value_separator)) + Report.AddWarningAsError (wid); + } return true; case "/warnaserror-": - Report.WarningsAreErrors = false; + if (value.Length == 0) { + Report.WarningsAreErrors = false; + } else { + foreach (string wid in value.Split (argument_value_separator)) + Report.RemoveWarningAsError (wid); + } return true; case "/warn": @@ -1297,10 +1416,13 @@ namespace Mono.CSharp Report.Error (5, "/nowarn requires an argument"); Environment.Exit (1); } - - warns = value.Split (new Char [] {','}); + + warns = value.Split (argument_value_separator); foreach (string wc in warns){ try { + if (wc.Trim ().Length == 0) + continue; + int warn = Int32.Parse (wc); if (warn < 1) { throw new ArgumentOutOfRangeException("warn"); @@ -1313,15 +1435,37 @@ namespace Mono.CSharp return true; } - case "/noconfig-": - load_default_config = true; - return true; - case "/noconfig": - case "/noconfig+": load_default_config = false; return true; + case "/platform": +#if GMCS_SOURCE + switch (value.ToLower (CultureInfo.InvariantCulture)) { + case "anycpu": + RootContext.Platform = Platform.AnyCPU; + break; + case "x86": + RootContext.Platform = Platform.X86; + break; + case "x64": + RootContext.Platform = Platform.X64; + break; + case "itanium": + RootContext.Platform = Platform.IA64; + break; + default: + Report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'"); + break; + } +#endif + return true; + + // We just ignore this. + case "/errorreport": + case "/filealign": + return true; + case "/help2": OtherFlags (); Environment.Exit(0); @@ -1384,20 +1528,21 @@ namespace Mono.CSharp case "default": RootContext.Version = LanguageVersion.Default; #if GMCS_SOURCE - defines.Add ("__V2__"); + RootContext.AddConditional ("__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"); + case "3": + RootContext.Version = LanguageVersion.V_3; + return true; + case "future": + RootContext.Version = LanguageVersion.Future; return true; -#endif } - Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value); + + Report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value); return true; case "/codepage": @@ -1452,7 +1597,7 @@ namespace Mono.CSharp return new_args; } - static void AddExternAlias (string identifier, string assembly) + void AddExternAlias (string identifier, string assembly) { if (assembly.Length == 0) { Report.Error (1680, "Invalid reference alias '" + identifier + "='. Missing filename"); @@ -1489,162 +1634,26 @@ namespace Mono.CSharp return true; } - - /// - /// Parses the arguments, and drives the compilation - /// process. - /// - /// - /// - /// TODO: Mostly structured to debug the compiler - /// now, needs to be turned into a real driver soon. - /// - // [MonoTODO("Change error code for unknown argument to something reasonable")] - internal static bool MainDriver (string [] args) - { - int i; - bool parsing_options = true; - - encoding = Encoding.Default; - - references = new ArrayList (); - external_aliases = new Hashtable (); - soft_references = new ArrayList (); - modules = new ArrayList (); - link_paths = new ArrayList (); - - SetupDefaultDefines (); - - // - // 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.Length == 0) - 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; - } - - 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; - } else { - 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; - } - } - } - } - - CompileFiles (arg, false); - } + // + // Main compilation method + // + public bool Compile () + { + // TODO: Should be passed to parser as an argument + RootContext.ToplevelTypes = new ModuleContainer (RootContext.Unsafe); - ProcessFiles (); + Parse (); + if (Report.Errors > 0) + return false; - if (tokenize) + if (tokenize || parse_only) return true; if (RootContext.ToplevelTypes.NamespaceEntry != null) throw new InternalErrorException ("who set it?"); - // - // 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; - } - - if (Report.Errors > 0) - return false; - - if (parse_only) - return true; - - if (load_default_config) - DefineDefaultConfig (); - - if (Report.Errors > 0){ - return false; - } - - // - // Load assemblies required - // - if (timestamps) - ShowTime ("Loading references"); - link_paths.Add (GetSystemDir ()); - link_paths.Add (Directory.GetCurrentDirectory ()); - LoadReferences (); - - if (timestamps) - ShowTime (" References loaded"); - - if (Report.Errors > 0){ - return false; - } + ProcessDefaultConfig (); // // Quick hack @@ -1677,14 +1686,25 @@ namespace Mono.CSharp set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null); } - RootNamespace.Global.AddModuleReference (CodeGen.Module.Builder); + GlobalRootNamespace.Instance.AddModuleReference (RootContext.ToplevelTypes.Builder); + + // + // Load assemblies required + // + if (timestamps) + ShowTime ("Loading references"); + LoadReferences (); + if (modules.Count > 0) { foreach (string module in modules) LoadModule (module); } - if (!TypeManager.InitCoreTypes ()) + if (timestamps) + ShowTime ("References loaded"); + + if (!TypeManager.InitCoreTypes () || Report.Errors > 0) return false; TypeManager.InitOptionalCoreTypes (); @@ -1692,8 +1712,6 @@ namespace Mono.CSharp if (timestamps) ShowTime (" Core Types done"); - CodeGen.Module.Resolve (); - // // The second pass of the compiler // @@ -1709,8 +1727,6 @@ namespace Mono.CSharp RootContext.BootCorlib_PopulateCoreTypes (); RootContext.PopulateTypes (); - RootContext.DefineTypes (); - if (Report.Errors == 0 && RootContext.Documentation != null && !RootContext.Documentation.OutputDocComment ( @@ -1769,7 +1785,7 @@ namespace Mono.CSharp } if (RootContext.NeedsEntryPoint) { - MethodInfo ep = RootContext.EntryPoint; + Method ep = RootContext.EntryPoint; if (ep == null) { if (RootContext.MainClass != null) { @@ -1794,7 +1810,7 @@ namespace Mono.CSharp return false; } - CodeGen.Assembly.Builder.SetEntryPoint (ep, k); + CodeGen.Assembly.Builder.SetEntryPoint (ep.MethodBuilder, k); } else if (RootContext.MainClass != null) { Report.Error (2017, "Cannot specify -main if building a module or library"); } @@ -1812,29 +1828,29 @@ namespace Mono.CSharp // Add Win32 resources // - CodeGen.Assembly.Builder.DefineVersionInfoResource (); - if (win32ResourceFile != null) { try { CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile); + } catch (ArgumentException) { + Report.RuntimeMissingSupport (Location.Null, "resource embedding "); } - catch (ArgumentException) { - Report.RuntimeMissingSupport (Location.Null, "resource embeding"); - } + } else { + CodeGen.Assembly.Builder.DefineVersionInfoResource (); } if (win32IconFile != null) { - MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); + MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (define_icon == null) { - Report.RuntimeMissingSupport (Location.Null, "resource embeding"); + Report.RuntimeMissingSupport (Location.Null, "resource embedding"); + } else { + define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile }); } - define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile }); } if (Report.Errors > 0) return false; - CodeGen.Save (output_file); + CodeGen.Save (output_file, want_debugging_support); if (timestamps) { ShowTime ("Saved output"); ShowTotalTime ("Total"); @@ -1982,7 +1998,11 @@ namespace Mono.CSharp { Report.Stderr = error; try { - return Driver.MainDriver (args) && Report.Errors == 0; + Driver d = Driver.Create (args, true); + if (d == null) + return false; + + return d.Compile () && Report.Errors == 0; } finally { Report.Stderr = Console.Error; @@ -1995,23 +2015,43 @@ namespace Mono.CSharp return Report.AllWarnings; } } + + public static void Reset () + { + Reset (true); + } + + public static void PartialReset () + { + Reset (false); + } - static void Reset () + public static void Reset (bool full_flag) { Driver.Reset (); - RootContext.Reset (); - Tokenizer.Reset (); + RootContext.Reset (full_flag); Location.Reset (); Report.Reset (); TypeManager.Reset (); + PredefinedAttributes.Reset (); TypeHandle.Reset (); - RootNamespace.Reset (); + + if (full_flag) + GlobalRootNamespace.Reset (); + NamespaceEntry.Reset (); CodeGen.Reset (); Attribute.Reset (); AttributeTester.Reset (); - CompilerGeneratedClass.Reset (); AnonymousTypeClass.Reset (); + AnonymousMethodBody.Reset (); + AnonymousMethodStorey.Reset (); + SymbolWriter.Reset (); + Switch.Reset (); + Linq.QueryBlock.TransparentParameter.Reset (); + Convert.Reset (); + TypeInfo.Reset (); } + } }