X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fmcs%2Fdriver.cs;h=4476e56c6b0ccdc6dc4c5b3c82c64dcebb56311b;hb=5eea1c9dcc152e1232e684c7ff2bba1748eba7a1;hp=542c05b524b7c83168ebef9fc85b6594ce54f323;hpb=9d94ef745654af93546b585ab66b3f2638defdcb;p=mono.git diff --git a/mcs/mcs/driver.cs b/mcs/mcs/driver.cs index 542c05b524b..4476e56c6b0 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 @@ -28,95 +30,91 @@ namespace Mono.CSharp /// /// 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 +128,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 +142,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 +155,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 +169,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 +190,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 +223,41 @@ namespace Mono.CSharp static void Usage () { Console.WriteLine ( - "Mono C# compiler, (C) 2001 - 2007 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" + Environment.NewLine + - " -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 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 + " -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 +276,9 @@ namespace Mono.CSharp static void About () { Console.WriteLine ( - "The Mono C# compiler is (C) 2001-2007, 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 +287,29 @@ 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) @@ -348,7 +348,8 @@ namespace Mono.CSharp } if (m != null) { - Report.Error (1509, "referenced file `{0}' is not an assembly; try using the '-addmodule' option", filename); + Report.Error (1509, "Referenced file `{0}' is not an assembly. Consider using `-addmodule' option instead", + Path.GetFileName (filename)); return; } } catch (FileNotFoundException) { @@ -404,9 +405,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 ... @@ -446,7 +447,7 @@ namespace Mono.CSharp } } - RootNamespace.Global.AddModuleReference (m); + GlobalRootNamespace.Instance.AddModuleReference (m); } catch (BadImageFormatException f) { Error9 ("module", f.FileName, f.FusionLog); @@ -458,8 +459,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 // @@ -474,14 +478,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) @@ -573,7 +571,7 @@ namespace Mono.CSharp pattern = spec; } - static void ProcessFile (string f) + void AddSourceFile (string f) { if (first_source == null) first_source = f; @@ -581,26 +579,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; } @@ -615,7 +715,7 @@ namespace Mono.CSharp return; } foreach (string f in files) { - ProcessFile (f); + AddSourceFile (f); } if (!recurse) @@ -632,25 +732,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 // @@ -676,11 +777,11 @@ 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"); } public static string OutputFile @@ -708,12 +809,6 @@ namespace Mono.CSharp Report.WarningLevel = level; } - static void SetupV2 () - { - RootContext.Version = LanguageVersion.Default; - defines.Add ("__V2__"); - } - static void Version () { string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString (); @@ -726,7 +821,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": @@ -767,26 +862,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; @@ -907,11 +985,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){ @@ -965,7 +1038,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": @@ -973,10 +1046,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; @@ -991,11 +1060,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; @@ -1009,7 +1117,7 @@ namespace Mono.CSharp value = option.Substring (idx + 1); } - switch (arg){ + switch (arg.ToLower (CultureInfo.InvariantCulture)){ case "/nologo": return true; @@ -1073,12 +1181,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; } @@ -1089,7 +1197,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; @@ -1098,41 +1206,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": @@ -1140,27 +1224,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; @@ -1170,7 +1254,7 @@ namespace Mono.CSharp Report.Error (5, "-recurse requires an argument"); Environment.Exit (1); } - CompileFiles (value, true); + ProcessSourceFiles (value, true); return true; case "/r": @@ -1180,7 +1264,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 ('='); @@ -1190,8 +1274,9 @@ namespace Mono.CSharp AddExternAlias (alias, assembly); return true; } - - references.Add (val); + + if (val.Length != 0) + references.Add (val); } return true; } @@ -1201,7 +1286,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); } @@ -1212,6 +1297,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; @@ -1222,6 +1310,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; } @@ -1241,7 +1332,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; @@ -1284,11 +1375,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": @@ -1302,10 +1403,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"); @@ -1318,12 +1422,7 @@ namespace Mono.CSharp return true; } - case "/noconfig-": - load_default_config = true; - return true; - case "/noconfig": - case "/noconfig+": load_default_config = false; return true; @@ -1380,12 +1479,6 @@ 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": @@ -1393,15 +1486,17 @@ namespace Mono.CSharp return true; case "default": - SetupV2 (); + RootContext.Version = LanguageVersion.Default; +#if GMCS_SOURCE + RootContext.AddConditional ("__V2__"); +#endif return true; #if GMCS_SOURCE case "iso-2": RootContext.Version = LanguageVersion.ISO_2; return true; - - case "linq": - RootContext.Version = LanguageVersion.LINQ; + case "future": + RootContext.Version = LanguageVersion.Future; return true; #endif } @@ -1460,7 +1555,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"); @@ -1497,162 +1592,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 @@ -1685,32 +1644,32 @@ 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); } - // - // 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; - } + ShowTime ("References loaded"); - TypeManager.InitCoreTypes (); + if (!TypeManager.InitCoreTypes () || Report.Errors > 0) + return false; + + TypeManager.InitOptionalCoreTypes (); + if (timestamps) ShowTime (" Core Types done"); - CodeGen.Module.Resolve (); - // // The second pass of the compiler // @@ -1726,10 +1685,6 @@ namespace Mono.CSharp RootContext.BootCorlib_PopulateCoreTypes (); RootContext.PopulateTypes (); - TypeManager.InitCodeHelpers (); - - RootContext.DefineTypes (); - if (Report.Errors == 0 && RootContext.Documentation != null && !RootContext.Documentation.OutputDocComment ( @@ -1788,7 +1743,7 @@ namespace Mono.CSharp } if (RootContext.NeedsEntryPoint) { - MethodInfo ep = RootContext.EntryPoint; + Method ep = RootContext.EntryPoint; if (ep == null) { if (RootContext.MainClass != null) { @@ -1813,7 +1768,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"); } @@ -1831,29 +1786,29 @@ namespace Mono.CSharp // Add Win32 resources // - CodeGen.Assembly.Builder.DefineVersionInfoResource (); - if (win32ResourceFile != null) { try { CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile); - } - catch (ArgumentException) { + } 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"); + } 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"); @@ -2001,7 +1956,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; @@ -2014,21 +1973,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 (); + AnonymousTypeClass.Reset (); + AnonymousMethodBody.Reset (); + AnonymousMethodStorey.Reset (); + SymbolWriter.Reset (); + Switch.Reset (); + Linq.QueryBlock.TransparentParameter.Reset (); + Convert.Reset (); + TypeInfo.Reset (); } + } }