X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fdriver.cs;h=030681157da26f71b4c4e4dba22ed4f905d0d1b1;hb=11ebc5207de0ac675d6bc0240fc8a25ac4fb7c5c;hp=8ded7ffa6e2ecb4303141003e78ac9d1a383c19f;hpb=98a86ecd4ba2d3b4631d98ac5a4abf23f4e6c3e3;p=mono.git diff --git a/mcs/gmcs/driver.cs b/mcs/gmcs/driver.cs old mode 100755 new mode 100644 index 8ded7ffa6e2..030681157da --- a/mcs/gmcs/driver.cs +++ b/mcs/gmcs/driver.cs @@ -6,6 +6,7 @@ // Licensed under the terms of the GNU GPL // // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) +// (C) 2004, 2005 Novell, Inc // namespace Mono.CSharp @@ -14,10 +15,12 @@ namespace Mono.CSharp using System.Reflection; using System.Reflection.Emit; using System.Collections; + using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Text; using System.Globalization; + using System.Xml; public enum Target { Library, Exe, Module, WinExe @@ -41,6 +44,11 @@ namespace Mono.CSharp // static ArrayList soft_references; + // + // External aliases for assemblies. + // + static Hashtable external_aliases; + // // Modules to be linked // @@ -49,9 +57,6 @@ namespace Mono.CSharp // Lookup paths static ArrayList link_paths; - // Whether we want Yacc to output its progress - static bool yacc_verbose = false; - // Whether we want to only run the tokenizer static bool tokenize = false; @@ -63,20 +68,16 @@ namespace Mono.CSharp static bool timestamps = false; static bool pause = false; static bool show_counters = false; - public static bool parser_verbose = false; // // Whether to load the initial config file (what CSC.RSP has by default) // static bool load_default_config = true; - static Hashtable response_file_list; - // // A list of resource files // - static ArrayList resources; - static ArrayList embedded_resources; + static Resources embedded_resources; static string win32ResourceFile; static string win32IconFile; @@ -96,20 +97,25 @@ namespace Mono.CSharp static DateTime last_time, first_time; // - // Encoding: ISO-Latin1 is 28591 + // Encoding. // static Encoding encoding; - // - // Whether the user has specified a different encoder manually - // - static bool using_default_encoder = true; - - // - // The system version we are using, if not specified on the commandline we - // will use the same version as corlib for looking for libraries in the GAC. - // - static string sys_version; + 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) { @@ -146,12 +152,12 @@ namespace Mono.CSharp 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; @@ -175,14 +181,22 @@ namespace Mono.CSharp 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; } - SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder); - + 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; parser = new CSharpParser (reader, file, defines); - parser.yacc_verbose_flag = yacc_verbose; + parser.ErrorOutput = Report.Stderr; try { parser.parse (); } catch (Exception ex) { @@ -200,6 +214,7 @@ namespace Mono.CSharp " --parse Only parses the source file\n" + " --stacktrace Shows stack trace at error location\n" + " --timestamp Displays time stamps of various compiler events\n" + + " --expect-error X Expect that error X will be encountered\n" + " -2 Enables experimental C# features\n" + " -v Verbose parsing (for debugging the parser)\n" + " --mcs-debug X Sets MCS debugging level to X\n"); @@ -208,28 +223,28 @@ namespace Mono.CSharp static void Usage () { Console.WriteLine ( - "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" + + "Mono C# compiler, (C) 2001 - 2005 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" + - " -codepage:ID Sets code page to the one in ID\n" + - " (number, `utf8' or `reset')\n" + + " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" + " -clscheck[+|-] Disables CLS Compliance verifications" + Environment.NewLine + " -define:S1[;S2] Defines one or more symbols (short: /d:)\n" + - " -debug[+|-] Generate debugging information\n" + + " -debug[+|-], -g Generate debugging information\n" + " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" + " -doc:FILE XML Documentation file to generate\n" + - " -g Generate debugging information\n" + " -keycontainer:NAME The key pair container used to strongname the assembly\n" + " -keyfile:FILE The strongname key file used to strongname the assembly\n" + + " -langversion:TEXT Specifies language version modes: ISO-1 or Default\n" + " -lib:PATH1,PATH2 Adds the paths to the assembly link path\n" + " -main:class Specified the class that contains the entry point\n" + " -noconfig[+|-] Disables implicit references to assemblies\n" + " -nostdlib[+|-] Does not load core libraries\n" + " -nowarn:W1[,W2] Disables one or more warnings\n" + + " -optimize[+|-] Enables code optimalizations\n" + " -out:FNAME Specifies output file\n" + " -pkg:P1[,Pn] References packages P1..Pn\n" + - " --expect-error X Expect that error X will be encountered\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" + @@ -250,19 +265,19 @@ 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 Mono C# compiler is (C) 2001-2005, Novell, Inc.\n\n" + "The compiler source code is released under the terms of the GNU GPL\n\n" + "For more information on Mono, visit the project Web site\n" + " http://www.go-mono.com\n\n" + - "The compiler was written by Miguel de Icaza, Ravi Pratap and Martin Baulig"); + "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath"); Environment.Exit (0); } @@ -270,15 +285,15 @@ namespace Mono.CSharp public static int Main (string[] args) { - RootContext.V2 = true; + RootContext.Version = LanguageVersion.Default; + Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t"; + bool ok = MainDriver (args); if (ok && Report.Errors == 0) { - Console.Write("Compilation succeeded"); if (Report.Warnings > 0) { - Console.Write(" - {0} warning(s)", Report.Warnings); + Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings); } - Console.WriteLine(); if (show_counters){ Console.WriteLine ("Counter1: " + counter1); Console.WriteLine ("Counter2: " + counter2); @@ -294,6 +309,11 @@ namespace Mono.CSharp } static public void LoadAssembly (string assembly, bool soft) + { + LoadAssembly (assembly, null, soft); + } + + static public void LoadAssembly (string assembly, string alias, bool soft) { Assembly a; string total_log = ""; @@ -305,21 +325,28 @@ namespace Mono.CSharp a = Assembly.LoadFrom (assembly); } else { string ass = assembly; - if (ass.EndsWith (".dll")) + if (ass.EndsWith (".dll") || ass.EndsWith (".exe")) ass = assembly.Substring (0, assembly.Length - 4); a = Assembly.Load (ass); } - TypeManager.AddAssembly (a); + // Extern aliased refs require special handling + if (alias == null) + RootNamespace.Global.AddAssemblyReference (a); + else + RootNamespace.DefineRootNamespace (alias, a); } catch (FileNotFoundException){ foreach (string dir in link_paths){ string full_path = Path.Combine (dir, assembly); - if (!assembly.EndsWith (".dll")) + if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) full_path += ".dll"; try { a = Assembly.LoadFrom (full_path); - TypeManager.AddAssembly (a); + if (alias == null) + RootNamespace.Global.AddAssemblyReference (a); + else + RootNamespace.DefineRootNamespace (alias, a); return; } catch (FileNotFoundException ff) { total_log += ff.FusionLog; @@ -351,7 +378,7 @@ namespace Mono.CSharp catch (TargetInvocationException ex) { throw ex.InnerException; } - TypeManager.AddModule (m); + RootNamespace.Global.AddModuleReference (m); } catch (FileNotFoundException){ @@ -367,7 +394,7 @@ namespace Mono.CSharp catch (TargetInvocationException ex) { throw ex.InnerException; } - TypeManager.AddModule (m); + RootNamespace.Global.AddModuleReference (m); return; } catch (FileNotFoundException ff) { total_log += ff.FusionLog; @@ -395,6 +422,9 @@ namespace Mono.CSharp foreach (string r in soft_references) LoadAssembly (r, true); + + foreach (DictionaryEntry entry in external_aliases) + LoadAssembly ((string) entry.Value, (string) entry.Key, false); return; } @@ -459,18 +489,7 @@ namespace Mono.CSharp // static string GetSystemDir () { - Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies (); - - foreach (Assembly a in assemblies){ - string codebase = a.Location; - string fn = System.IO.Path.GetFileName (codebase); - if (fn == "corlib.dll" || fn == "mscorlib.dll"){ - return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar)); - } - } - - Report.Error (-15, "Can not compute my system path"); - return ""; + return Path.GetDirectoryName (typeof (object).Assembly.Location); } // @@ -607,42 +626,34 @@ namespace Mono.CSharp soft_references.Insert (p++, def); } - 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"); - Environment.Exit (1); } if (level < 0 || level > 4){ - Report.Error (1900, "Warning level must be 0 to 4"); - Environment.Exit (1); + Report.Error (1900, "Warning level must be in the range 0-4"); + return; } RootContext.WarningLevel = level; - TestWarningConflict (); - } - - static void TestWarningConflict () - { - if (RootContext.WarningLevel == 0 && Report.WarningsAreErrors) { - Report.Error (1901, "Conflicting options specified: Warning level 0; Treat warnings as errors"); - Environment.Exit (1); - } } static void SetupV2 () { - RootContext.V2 = true; + RootContext.Version = LanguageVersion.Default; defines.Add ("__V2__"); } @@ -661,12 +672,8 @@ namespace Mono.CSharp static bool UnixParseOption (string arg, ref string [] args, ref int i) { switch (arg){ - case "-vv": - parser_verbose = true; - return true; - case "-v": - yacc_verbose = true; + CSharpParser.yacc_verbose_flag++; return true; case "--version": @@ -678,6 +685,7 @@ namespace Mono.CSharp return true; case "--main": case "-m": + Report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS"); if ((i + 1) >= args.Length){ Usage (); Environment.Exit (1); @@ -686,6 +694,7 @@ namespace Mono.CSharp return true; case "--unsafe": + Report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe"); RootContext.Unsafe = true; return true; @@ -696,6 +705,7 @@ namespace Mono.CSharp return true; case "--define": + Report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL"); if ((i + 1) >= args.Length){ Usage (); Environment.Exit (1); @@ -726,14 +736,16 @@ namespace Mono.CSharp case "-o": case "--output": + 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, 1, "Compatibility: Use -checked instead of --checked"); RootContext.Checked = true; return true; @@ -743,31 +755,34 @@ namespace Mono.CSharp case "--linkresource": case "--linkres": + 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, 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, 1, "Compatibility: Use -target:KIND instead of --target KIND"); if ((i + 1) >= args.Length){ Environment.Exit (1); return true; @@ -794,21 +809,31 @@ namespace Mono.CSharp break; default: TargetUsage (); - Environment.Exit (1); break; } return true; case "-r": + 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, 1, "Compatibility: Use -lib:ARG instead of --L arg"); if ((i + 1) >= args.Length){ Usage (); Environment.Exit (1); @@ -817,6 +842,7 @@ namespace Mono.CSharp return true; case "--nostdlib": + Report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib"); RootContext.StdLib = false; return true; @@ -825,11 +851,12 @@ namespace Mono.CSharp return true; case "--werror": + Report.Warning (-29, 1, "Compatibility: Use -warnaserror: option instead of --werror"); Report.WarningsAreErrors = true; - TestWarningConflict(); return true; case "--nowarn": + Report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn"); if ((i + 1) >= args.Length){ Usage (); Environment.Exit (1); @@ -846,6 +873,7 @@ namespace Mono.CSharp return true; case "--wlevel": + Report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL"); if ((i + 1) >= args.Length){ Report.Error ( 1900, @@ -875,6 +903,7 @@ namespace Mono.CSharp return true; case "--recurse": + 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); @@ -892,10 +921,12 @@ namespace Mono.CSharp return true; case "--debug": case "-g": + Report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug"); want_debugging_support = true; return true; case "--noconfig": + Report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig"); load_default_config = false; return true; } @@ -904,8 +935,8 @@ namespace Mono.CSharp } // - // Currently it is very basic option parsing, but eventually, this will - // be the complete option parser + // This parses the -arg and /arg options to the compiler, even if the strings + // in the following text use "/arg" on the strings. // static bool CSCParseOption (string option, ref string [] args, ref int i) { @@ -948,7 +979,6 @@ namespace Mono.CSharp default: TargetUsage (); - Environment.Exit (1); break; } return true; @@ -958,12 +988,18 @@ namespace Mono.CSharp Usage (); Environment.Exit (1); } - SetOutputFile (value); + OutputFile = value; return true; case "/optimize": case "/optimize+": + RootContext.Optimize = true; + return true; + case "/optimize-": + RootContext.Optimize = false; + return true; + case "/incremental": case "/incremental+": case "/incremental-": @@ -986,18 +1022,13 @@ namespace Mono.CSharp 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); + case "/bugreport": + // + // We should collect data, runtime, etc and store in the file specified + // + Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs"); return true; - + case "/pkg": { string packages; @@ -1021,7 +1052,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 (); @@ -1041,16 +1072,36 @@ 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 (); - - 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": @@ -1070,7 +1121,16 @@ namespace Mono.CSharp 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; } @@ -1106,10 +1166,10 @@ namespace Mono.CSharp } case "/doc": { if (value == ""){ - Report.Error (5, arg + " requires an argument"); + Report.Error (2006, arg + " requires an argument"); Environment.Exit (1); } - // TODO handle the /doc argument to generate xml doc + RootContext.Documentation = new Documentation (value); return true; } case "/lib": { @@ -1164,7 +1224,6 @@ namespace Mono.CSharp case "/warnaserror": case "/warnaserror+": Report.WarningsAreErrors = true; - TestWarningConflict(); return true; case "/warnaserror-": @@ -1192,8 +1251,7 @@ namespace Mono.CSharp } Report.SetIgnoreWarning (warn); } catch { - Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc)); - Environment.Exit (1); + Report.Error (1904, String.Format("`{0}' is not a valid warning number", wc)); } } return true; @@ -1263,50 +1321,112 @@ namespace Mono.CSharp case "/v2": case "/2": + Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead"); SetupV2 (); return true; - case "/codepage": - int cp = -1; + case "/langversion": + switch (value.ToLower (CultureInfo.InvariantCulture)) { + case "iso-1": + RootContext.Version = LanguageVersion.ISO_1; + return true; - if (value == "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; + case "default": + SetupV2 (); + return 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)); - Environment.Exit (1); + Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1' or `Default'", value); + return true; + + case "/codepage": + switch (value) { + case "utf8": + encoding = new UTF8Encoding(); + 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; - new_args = new string [extra_args.Length + args.Length]; - args.CopyTo (new_args, 0); - extra_args.CopyTo (new_args, args.Length); + + // if args contains '--' we have to take that into account + // split args into first half and second half based on '--' + // and add the extra_args before -- + int split_position = Array.IndexOf (args, "--"); + if (split_position != -1) + { + Array.Copy (args, new_args, split_position); + extra_args.CopyTo (new_args, split_position); + Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position); + } + else + { + args.CopyTo (new_args, 0); + extra_args.CopyTo (new_args, args.Length); + } return new_args; } + + static void AddExternAlias (string identifier, string assembly) + { + if (assembly.Length == 0) { + Report.Error (1680, "Invalid reference alias '" + identifier + "='. Missing filename"); + return; + } + + if (!IsExternAliasValid (identifier)) { + Report.Error (1679, "Invalid extern alias for /reference. Alias '" + identifier + "' is not a valid identifier"); + return; + } + + // 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; + + for (int i = 1; i < identifier.Length; i++) { + char c = identifier [i]; + if (Char.IsLetter (c) || Char.IsDigit (c)) + continue; + + UnicodeCategory category = Char.GetUnicodeCategory (c); + if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark || + category != UnicodeCategory.SpacingCombiningMark || + category != UnicodeCategory.ConnectorPunctuation) + return false; + } + + return true; + } /// /// Parses the arguments, and drives the compilation @@ -1323,16 +1443,10 @@ namespace Mono.CSharp int i; bool parsing_options = true; - Console.WriteLine ("ALPHA SOFTWARE: Mono C# Compiler {0} for Generics", - Assembly.GetExecutingAssembly ().GetName ().Version.ToString ()); - try { - encoding = Encoding.GetEncoding (28591); - } catch { - Console.WriteLine ("Error: could not load encoding 28591, trying 1252"); - encoding = Encoding.GetEncoding (1252); - } - + encoding = Encoding.Default; + references = new ArrayList (); + external_aliases = new Hashtable (); soft_references = new ArrayList (); modules = new ArrayList (); link_paths = new ArrayList (); @@ -1346,6 +1460,8 @@ namespace Mono.CSharp // path. // + Hashtable response_file_list = null; + for (i = 0; i < args.Length; i++){ string arg = args [i]; if (arg == "") @@ -1392,10 +1508,19 @@ namespace Mono.CSharp string csc_opt = "/" + arg.Substring (1); if (CSCParseOption (csc_opt, ref args, ref i)) continue; + + Error_WrongOption (arg); + return false; } else { - if (arg.StartsWith ("/")){ + 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; + } } } } @@ -1408,10 +1533,17 @@ namespace Mono.CSharp if (tokenize) return true; + // + // This will point to the NamespaceEntry of the last file that was parsed, and may + // not be meaningful when resolving classes from other files. So, reset it to prevent + // silent bugs. + // + RootContext.Tree.Types.NamespaceEntry = null; + // // If we are an exe, require a source file for the entry point // - if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){ + if (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; @@ -1422,7 +1554,7 @@ namespace Mono.CSharp // // If there is nothing to put in the assembly, and we are not a library // - if (first_source == null && embedded_resources == null && resources == null){ + if (first_source == null && embedded_resources == null){ Report.Error (2008, "No files to compile were specified"); return false; } @@ -1433,8 +1565,6 @@ namespace Mono.CSharp if (parse_only) return true; - Tokenizer.Cleanup (); - // // Load Core Library for default compilation // @@ -1476,12 +1606,13 @@ namespace Mono.CSharp output_file = first_source + RootContext.TargetExt; } - CodeGen.Init (output_file, output_file, want_debugging_support); + if (!CodeGen.Init (output_file, output_file, want_debugging_support)) + return false; if (RootContext.Target == Target.Module) { PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); if (module_only == null) { - Report.Error (0, new Location (-1), "Cannot use /target:module on this runtime: try the Mono runtime instead."); + Report.RuntimeMissingSupport (Location.Null, "/target:module"); Environment.Exit (1); } @@ -1489,20 +1620,18 @@ 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.Error (0, new Location (-1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead."); + Report.RuntimeMissingSupport (Location.Null, "/addmodule"); Environment.Exit (1); } foreach (string module in modules) LoadModule (adder_method, module); } - - TypeManager.ComputeNamespaces (); // // Before emitting, we need to get the core @@ -1521,12 +1650,15 @@ namespace Mono.CSharp if (timestamps) ShowTime (" Core Types done"); + CodeGen.Module.ResolveAttributes (); + // // The second pass of the compiler // if (timestamps) ShowTime ("Resolving tree"); RootContext.ResolveTree (); + if (Report.Errors > 0) return false; if (timestamps) @@ -1534,24 +1666,36 @@ namespace Mono.CSharp if (!RootContext.StdLib) RootContext.BootCorlib_PopulateCoreTypes (); RootContext.PopulateTypes (); + + TypeManager.InitCodeHelpers (); + RootContext.DefineTypes (); - TypeManager.InitCodeHelpers (); + if (Report.Errors == 0 && + RootContext.Documentation != null && + !RootContext.Documentation.OutputDocComment ( + output_file)) + return false; // // Verify using aliases now // - Namespace.VerifyUsing (); + NamespaceEntry.VerifyAllUsing (); if (Report.Errors > 0){ return false; } + + CodeGen.Assembly.Resolve (); - if (RootContext.VerifyClsCompliance) { - CodeGen.Assembly.ResolveClsCompliance (); + if (RootContext.VerifyClsCompliance) { + if (CodeGen.Assembly.IsClsCompliant) { AttributeTester.VerifyModulesClsCompliance (); TypeManager.LoadAllImportedTypes (); + } } + if (Report.Errors > 0) + return false; // // The code generator @@ -1588,68 +1732,40 @@ namespace Mono.CSharp MethodInfo ep = RootContext.EntryPoint; if (ep == null) { + if (RootContext.MainClass != null) { + DeclSpace main_cont = RootContext.Tree.GetDecl (MemberName.FromDotted (RootContext.MainClass, Location.Null)); + if (main_cont == null) { + Report.Error (1555, "Could not find `{0}' specified for Main method", RootContext.MainClass); + return false; + } + + if (!(main_cont is ClassOrStruct)) { + 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 ()); + 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.Warning (0, new Location (-1), - "Cannot embed resources on this runtime: try the Mono runtime instead."); - } 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] = spec.Replace ('/','.').Replace ('\\', '.'); - } - - 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 (); } // @@ -1663,14 +1779,14 @@ namespace Mono.CSharp CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile); } catch (ArgumentException) { - Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead."); + Report.RuntimeMissingSupport (Location.Null, "resource embeding"); } } 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 }); } @@ -1709,25 +1825,148 @@ namespace Mono.CSharp #endif return (Report.Errors == 0); } + } + + 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, 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 // public class CompilerCallableEntryPoint : MarshalByRefObject { - static bool used = false; - - public bool InvokeCompiler (string [] args) + public static bool InvokeCompiler (string [] args, TextWriter error) { - if (used) + Report.Stderr = error; + try { + return Driver.MainDriver (args) && Report.Errors == 0; + } + finally { + Report.Stderr = Console.Error; Reset (); - bool ok = Driver.MainDriver (args); - return ok && Report.Errors == 0; + } } - public void Reset () + public static int[] AllWarningNumbers { + get { + return Report.AllWarnings; + } + } + + static void Reset () { + Driver.Reset (); + Location.Reset (); + RootContext.Reset (); + Report.Reset (); + TypeManager.Reset (); + TypeHandle.Reset (); + RootNamespace.Reset (); + NamespaceEntry.Reset (); + CodeGen.Reset (); } } }