X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fgmcs%2Fdriver.cs;h=02f218d5e5e946da36bdda9137915c0708689059;hb=cffda3181a45b81bbf989a128da6f7a5047a6a99;hp=a09d46d5d3a24298dcf1eee2117dfee104b6b1bb;hpb=88bfcbc68d16fb2db013b396ea935839c7af4e78;p=mono.git diff --git a/mcs/gmcs/driver.cs b/mcs/gmcs/driver.cs old mode 100755 new mode 100644 index a09d46d5d3a..02f218d5e5e --- 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 Novell, Inc // namespace Mono.CSharp @@ -14,11 +15,13 @@ namespace Mono.CSharp using System.Reflection; using System.Reflection.Emit; using System.Collections; + using System.Diagnostics; using System.IO; using System.Text; using System.Globalization; + using System.Xml; - enum Target { + public enum Target { Library, Exe, Module, WinExe }; @@ -40,27 +43,25 @@ namespace Mono.CSharp // static ArrayList soft_references; + // + // Modules to be linked + // + static ArrayList modules; + // Lookup paths static ArrayList link_paths; - // Whether we want Yacc to output its progress - static bool yacc_verbose = false; - // Whether we want to only run the tokenizer static bool tokenize = false; static string first_source; - static Target target = Target.Exe; - static string target_ext = ".exe"; - static bool want_debugging_support = false; static bool parse_only = false; static bool timestamps = false; static bool pause = false; static bool show_counters = false; - public static bool parser_verbose = false; // // Whether to load the initial config file (what CSC.RSP has by default) @@ -74,6 +75,8 @@ namespace Mono.CSharp // static ArrayList resources; static ArrayList embedded_resources; + static string win32ResourceFile; + static string win32IconFile; // // An array of the defines from the command line @@ -99,7 +102,7 @@ namespace Mono.CSharp // Whether the user has specified a different encoder manually // static bool using_default_encoder = true; - + public static void ShowTime (string msg) { if (!timestamps) @@ -145,7 +148,6 @@ namespace Mono.CSharp int token, tokens = 0, errors = 0; while ((token = lexer.token ()) != Token.EOF){ - Location l = lexer.Location; tokens++; if (token == Token.ERROR) errors++; @@ -172,7 +174,6 @@ namespace Mono.CSharp SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder); parser = new CSharpParser (reader, file, defines); - parser.yacc_verbose_flag = yacc_verbose; try { parser.parse (); } catch (Exception ex) { @@ -182,43 +183,61 @@ namespace Mono.CSharp } } + static void OtherFlags () + { + Console.WriteLine ( + "Other flags in the compiler\n" + + " --fatal Makes errors fatal\n" + + " --parse Only parses the source file\n" + + " --stacktrace Shows stack trace at error location\n" + + " --timestamp Displays time stamps of various compiler events\n" + + " -2 Enables experimental C# features\n" + + " -v Verbose parsing (for debugging the parser)\n" + + " --mcs-debug X Sets MCS debugging level to X\n"); + } + static void Usage () { Console.WriteLine ( "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" + "mcs [options] source-files\n" + " --about About the Mono C# compiler\n" + + " -addmodule:MODULE Adds the module to the generated assembly\n" + " -checked[+|-] Set default context to checked\n" + " -codepage:ID Sets code page to the one in ID\n" + " (number, `utf8' or `reset')\n" + + " -clscheck[+|-] Disables CLS Compliance verifications" + Environment.NewLine + " -define:S1[;S2] Defines one or more symbols (short: /d:)\n" + - " -debug[+-] Generate debugging information\n" + + " -debug[+|-] Generate debugging information\n" + + " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" + " -doc:FILE XML Documentation file to generate\n" + " -g Generate debugging information\n" + - " --fatal Makes errors fatal\n" + + " -keycontainer:NAME The key pair container used to strongname the assembly\n" + + " -keyfile:FILE The strongname key file used to strongname the assembly\n" + + " -langversion:TEXT Specifies language version modes: ISO-1 or Default" + Environment.NewLine + " -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" + " -out:FNAME Specifies output file\n" + - " --parse Only parses the source file\n" + + " -doc:XMLFILE Generates xml documentation into specified 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" + - " --stacktrace Shows stack trace at error location\n" + " -target:KIND Specifies the target (KIND is one of: exe, winexe,\n" + " library, module), (short: /t:)\n" + - " --timestamp Displays time stamps of various compiler events\n" + " -unsafe[+|-] Allows unsafe code\n" + " -warnaserror[+|-] Treat warnings as errors\n" + - " -warn:LEVEL Sets warning level (the highest is 4, the default)\n" + - " -v Verbose parsing (for debugging the parser)\n" + + " -warn:LEVEL Sets warning level (the highest is 4, the default is 2)\n" + + " -help2 Show other help flags\n" + "\n" + "Resources:\n" + " -linkresource:FILE[,ID] Links FILE as a resource\n" + " -resource:FILE[,ID] Embed FILE as a resource\n" + - " --mcs-debug X Sets MCS debugging level to X\n" + + " -win32res:FILE Specifies Win32 resource file (.res)\n" + + " -win32icon:FILE Use this icon for the output\n" + " @file Read response file for more options\n\n" + "Options can be of the form -option or /option"); } @@ -237,7 +256,7 @@ namespace Mono.CSharp "For more information on Mono, visit the project Web site\n" + " http://www.go-mono.com\n\n" + - "The compiler was written by Miguel de Icaza, Ravi Pratap and Martin Baulig"); + "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig and Marek Safar"); Environment.Exit (0); } @@ -245,15 +264,13 @@ namespace Mono.CSharp public static int Main (string[] args) { - RootContext.V2 = true; + RootContext.Version = LanguageVersion.Default; bool ok = MainDriver (args); if (ok && Report.Errors == 0) { - Console.Write("Compilation succeeded"); if (Report.Warnings > 0) { - Console.Write(" - {0} warning(s)", Report.Warnings); + Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings); } - Console.WriteLine(); if (show_counters){ Console.WriteLine ("Counter1: " + counter1); Console.WriteLine ("Counter2: " + counter2); @@ -274,19 +291,22 @@ namespace Mono.CSharp string total_log = ""; try { - char[] path_chars = { '/', '\\', '.' }; + char[] path_chars = { '/', '\\' }; if (assembly.IndexOfAny (path_chars) != -1) { a = Assembly.LoadFrom (assembly); } else { - a = Assembly.Load (assembly); + string ass = assembly; + if (ass.EndsWith (".dll") || ass.EndsWith (".exe")) + ass = assembly.Substring (0, assembly.Length - 4); + a = Assembly.Load (ass); } TypeManager.AddAssembly (a); } catch (FileNotFoundException){ foreach (string dir in link_paths){ string full_path = Path.Combine (dir, assembly); - if (!assembly.EndsWith (".dll")) + if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) full_path += ".dll"; try { @@ -311,6 +331,52 @@ namespace Mono.CSharp } } + static public void LoadModule (MethodInfo adder_method, string module) + { + Module m; + string total_log = ""; + + try { + try { + m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module }); + } + catch (TargetInvocationException ex) { + throw ex.InnerException; + } + TypeManager.AddModule (m); + + } + catch (FileNotFoundException){ + foreach (string dir in link_paths){ + string full_path = Path.Combine (dir, module); + if (!module.EndsWith (".netmodule")) + full_path += ".netmodule"; + + try { + try { + m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path }); + } + catch (TargetInvocationException ex) { + throw ex.InnerException; + } + TypeManager.AddModule (m); + return; + } catch (FileNotFoundException ff) { + total_log += ff.FusionLog; + continue; + } + } + Report.Error (6, "Cannot find module `" + module + "'" ); + Console.WriteLine ("Log: \n" + total_log); + } catch (BadImageFormatException f) { + Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog); + } catch (FileLoadException f){ + Report.Error(6, "Cannot load module " + f.FusionLog); + } catch (ArgumentNullException){ + Report.Error(6, "Cannot load module (null argument)"); + } + } + /// /// Loads all assemblies referenced on the command line /// @@ -389,7 +455,8 @@ namespace Mono.CSharp foreach (Assembly a in assemblies){ string codebase = a.Location; - if (codebase.EndsWith ("corlib.dll")){ + string fn = System.IO.Path.GetFileName (codebase); + if (fn == "corlib.dll" || fn == "mscorlib.dll"){ return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar)); } } @@ -403,7 +470,7 @@ namespace Mono.CSharp // static void SplitPathAndPattern (string spec, out string path, out string pattern) { - int p = spec.LastIndexOf ("/"); + int p = spec.LastIndexOf ('/'); if (p != -1){ // // Windows does not like /file.cs, switch that to: @@ -419,7 +486,7 @@ namespace Mono.CSharp return; } - p = spec.LastIndexOf ("\\"); + p = spec.LastIndexOf ('\\'); if (p != -1){ path = spec.Substring (0, p); pattern = spec.Substring (p + 1); @@ -456,7 +523,7 @@ namespace Mono.CSharp string path, pattern; SplitPathAndPattern (spec, out path, out pattern); - if (pattern.IndexOf ("*") == -1){ + if (pattern.IndexOf ('*') == -1){ ProcessFile (spec); return; } @@ -546,19 +613,28 @@ namespace Mono.CSharp } catch { Report.Error ( 1900, - "--wlevel requires an value from 0 to 4"); + "--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); - } else - RootContext.WarningLevel = level; + } + 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__"); } @@ -577,12 +653,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": @@ -692,21 +764,21 @@ namespace Mono.CSharp string type = args [++i]; switch (type){ case "library": - target = Target.Library; - target_ext = ".dll"; + RootContext.Target = Target.Library; + RootContext.TargetExt = ".dll"; break; case "exe": - target = Target.Exe; + RootContext.Target = Target.Exe; break; case "winexe": - target = Target.WinExe; + RootContext.Target = Target.WinExe; break; case "module": - target = Target.Module; - target_ext = ".dll"; + RootContext.Target = Target.Module; + RootContext.TargetExt = ".dll"; break; default: TargetUsage (); @@ -742,6 +814,7 @@ namespace Mono.CSharp case "--werror": Report.WarningsAreErrors = true; + TestWarningConflict(); return true; case "--nowarn": @@ -764,7 +837,7 @@ namespace Mono.CSharp if ((i + 1) >= args.Length){ Report.Error ( 1900, - "--wlevel requires an value from 0 to 4"); + "--wlevel requires a value from 0 to 4"); Environment.Exit (1); } @@ -824,7 +897,7 @@ namespace Mono.CSharp // static bool CSCParseOption (string option, ref string [] args, ref int i) { - int idx = option.IndexOf (":"); + int idx = option.IndexOf (':'); string arg, value; if (idx == -1){ @@ -844,21 +917,21 @@ namespace Mono.CSharp case "/target": switch (value){ case "exe": - target = Target.Exe; + RootContext.Target = Target.Exe; break; case "winexe": - target = Target.WinExe; + RootContext.Target = Target.WinExe; break; case "library": - target = Target.Library; - target_ext = ".dll"; + RootContext.Target = Target.Library; + RootContext.TargetExt = ".dll"; break; case "module": - target = Target.Module; - target_ext = ".netmodule"; + RootContext.Target = Target.Module; + RootContext.TargetExt = ".netmodule"; break; default: @@ -913,21 +986,72 @@ namespace Mono.CSharp resources.Add (value); return true; + case "/pkg": { + string packages; + + if (value == ""){ + Usage (); + Environment.Exit (1); + } + packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'})); + + ProcessStartInfo pi = new ProcessStartInfo (); + pi.FileName = "pkg-config"; + pi.RedirectStandardOutput = true; + pi.UseShellExecute = false; + pi.Arguments = "--libs " + packages; + Process p = null; + try { + p = Process.Start (pi); + } catch (Exception e) { + Report.Error (-27, "Couldn't run pkg-config: " + e.Message); + Environment.Exit (1); + } + + if (p.StandardOutput == null){ + Report.Warning (-27, "Specified package did not return any information"); + return true; + } + string pkgout = p.StandardOutput.ReadToEnd (); + p.WaitForExit (); + if (p.ExitCode != 0) { + Report.Error (-27, "Error running pkg-config. Check the above output."); + Environment.Exit (1); + } + + if (pkgout != null){ + string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}). + Split (new Char [] { ' ', '\t'}); + args = AddArgs (args, xargs); + } + + p.Close (); + return true; + } + case "/res": case "/resource": if (value == ""){ - Report.Error (5, arg + " requires an argument"); + Report.Error (5, "-resource requires an argument"); Environment.Exit (1); } if (embedded_resources == null) embedded_resources = new ArrayList (); + if (embedded_resources.Contains (value)) { + Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value)); + } + else if (value.IndexOf (',') != -1 && embedded_resources.Contains (value.Split (',')[1])) { + Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value)); + } + else { embedded_resources.Add (value); + } return true; case "/recurse": if (value == ""){ - Report.Error (5, "/recurse requires an argument"); + Report.Error (5, "-recurse requires an argument"); Environment.Exit (1); } CompileFiles (value, true); @@ -936,7 +1060,7 @@ namespace Mono.CSharp case "/r": case "/reference": { if (value == ""){ - Report.Error (5, arg + " requires an argument"); + Report.Error (5, "-reference requires an argument"); Environment.Exit (1); } @@ -946,12 +1070,42 @@ namespace Mono.CSharp } return true; } - case "/doc": { + case "/addmodule": { if (value == ""){ Report.Error (5, arg + " requires an argument"); Environment.Exit (1); } - // TODO handle the /doc argument to generate xml doc + + string [] refs = value.Split (new char [] { ';', ',' }); + foreach (string r in refs){ + modules.Add (r); + } + return true; + } + case "/win32res": { + if (value == "") { + Report.Error (5, arg + " requires an argument"); + Environment.Exit (1); + } + + win32ResourceFile = value; + return true; + } + case "/win32icon": { + if (value == "") { + Report.Error (5, arg + " requires an argument"); + Environment.Exit (1); + } + + win32IconFile = value; + return true; + } + case "/doc": { + if (value == ""){ + Report.Error (2006, arg + " requires an argument"); + Environment.Exit (1); + } + RootContext.Documentation = new Documentation (value); return true; } case "/lib": { @@ -967,6 +1121,10 @@ namespace Mono.CSharp link_paths.Add (dir); return true; } + + case "/debug-": + want_debugging_support = false; + return true; case "/debug": case "/debug+": @@ -982,6 +1140,14 @@ namespace Mono.CSharp RootContext.Checked = false; return true; + case "/clscheck": + case "/clscheck+": + return true; + + case "/clscheck-": + RootContext.VerifyClsCompliance = false; + return true; + case "/unsafe": case "/unsafe+": RootContext.Unsafe = true; @@ -994,6 +1160,7 @@ namespace Mono.CSharp case "/warnaserror": case "/warnaserror+": Report.WarningsAreErrors = true; + TestWarningConflict(); return true; case "/warnaserror-": @@ -1014,15 +1181,16 @@ namespace Mono.CSharp warns = value.Split (new Char [] {','}); foreach (string wc in warns){ - int warn = 0; - try { - warn = Int32.Parse (wc); + int warn = Int32.Parse (wc); + if (warn < 1) { + throw new ArgumentOutOfRangeException("warn"); + } + Report.SetIgnoreWarning (warn); } catch { - Usage (); + Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc)); Environment.Exit (1); } - Report.SetIgnoreWarning (warn); } return true; } @@ -1036,6 +1204,11 @@ namespace Mono.CSharp load_default_config = false; return true; + case "/help2": + OtherFlags (); + Environment.Exit(0); + return true; + case "/help": case "/?": Usage (); @@ -1063,14 +1236,47 @@ namespace Mono.CSharp case "/fullpaths": return true; - case "/win32icon": - Report.Error (5, "/win32icon is currently not supported"); + case "/keyfile": + if (value == String.Empty) { + Report.Error (5, arg + " requires an argument"); + Environment.Exit (1); + } + RootContext.StrongNameKeyFile = value; return true; - + case "/keycontainer": + if (value == String.Empty) { + Report.Error (5, arg + " requires an argument"); + Environment.Exit (1); + } + RootContext.StrongNameKeyContainer = value; + return true; + case "/delaysign+": + RootContext.StrongNameDelaySign = true; + return true; + case "/delaysign-": + RootContext.StrongNameDelaySign = false; + return true; + case "/v2": + case "/2": + Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead"); SetupV2 (); return true; + case "/langversion": + switch (value.ToLower (CultureInfo.InvariantCulture)) { + case "iso-1": + RootContext.Version = LanguageVersion.ISO_1; + return true; + + case "default": + SetupV2 (); + return true; + } + Report.Error (1617, "Invalid option '{0}' for /langversion; must be ISO-1 or Default", value); + Environment.Exit (1); + return false; + case "/codepage": int cp = -1; @@ -1089,25 +1295,43 @@ namespace Mono.CSharp try { cp = Int32.Parse (value); - } catch { } - - if (cp == -1){ - Console.WriteLine ("Invalid code-page requested"); - Usage (); - } - - try { encoding = Encoding.GetEncoding (cp); using_default_encoder = false; } catch { - Console.WriteLine ("Code page: {0} not supported", cp); + Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp)); + Environment.Exit (1); } return true; - } + //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option)); + //Environment.Exit (1); return false; } + static string [] AddArgs (string [] args, string [] extra_args) + { + string [] new_args; + new_args = new string [extra_args.Length + args.Length]; + + // if args contains '--' we have to take that into account + // split args into first half and second half based on '--' + // and add the extra_args before -- + int split_position = Array.IndexOf (args, "--"); + if (split_position != -1) + { + Array.Copy (args, new_args, split_position); + extra_args.CopyTo (new_args, split_position); + Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position); + } + else + { + args.CopyTo (new_args, 0); + extra_args.CopyTo (new_args, args.Length); + } + + return new_args; + } + /// /// Parses the arguments, and drives the compilation /// process. @@ -1118,13 +1342,11 @@ namespace Mono.CSharp /// now, needs to be turned into a real driver soon. /// // [MonoTODO("Change error code for unknown argument to something reasonable")] - static bool MainDriver (string [] args) + internal static bool MainDriver (string [] args) { int i; bool parsing_options = true; - Console.WriteLine ("Mono C# Compiler {0} for Generics", - Assembly.GetExecutingAssembly ().GetName ().Version.ToString ()); try { encoding = Encoding.GetEncoding (28591); } catch { @@ -1134,6 +1356,7 @@ namespace Mono.CSharp references = new ArrayList (); soft_references = new ArrayList (); + modules = new ArrayList (); link_paths = new ArrayList (); SetupDefaultDefines (); @@ -1145,12 +1368,13 @@ namespace Mono.CSharp // path. // - int argc = args.Length; - for (i = 0; i < argc; i++){ + for (i = 0; i < args.Length; i++){ string arg = args [i]; + if (arg == "") + continue; if (arg.StartsWith ("@")){ - string [] new_args, extra_args; + string [] extra_args; string response_file = arg.Substring (1); if (response_file_list == null) @@ -1172,11 +1396,7 @@ namespace Mono.CSharp return false; } - new_args = new string [extra_args.Length + argc]; - args.CopyTo (new_args, 0); - extra_args.CopyTo (new_args, argc); - args = new_args; - argc = new_args.Length; + args = AddArgs (args, extra_args); continue; } @@ -1210,17 +1430,40 @@ namespace Mono.CSharp if (tokenize) return true; + // + // This will point to the NamespaceEntry of the last file that was parsed, and may + // not be meaningful when resolving classes from other files. So, reset it to prevent + // silent bugs. + // + RootContext.Tree.Types.NamespaceEntry = null; + + // + // If we are an exe, require a source file for the entry point + // + if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){ if (first_source == null){ Report.Error (2008, "No files to compile were specified"); return false; } + } + + // + // If there is nothing to put in the assembly, and we are not a library + // + if (first_source == null && embedded_resources == null && resources == null){ + Report.Error (2008, "No files to compile were specified"); + return false; + } + if (Report.Errors > 0) return false; if (parse_only) return true; + Tokenizer.Cleanup (); + // // Load Core Library for default compilation // @@ -1240,6 +1483,7 @@ namespace Mono.CSharp if (timestamps) ShowTime ("Loading references"); link_paths.Add (GetSystemDir ()); + link_paths.Add (Directory.GetCurrentDirectory ()); LoadReferences (); if (timestamps) @@ -1253,21 +1497,41 @@ namespace Mono.CSharp // Quick hack // if (output_file == null){ - int pos = first_source.LastIndexOf ("."); + int pos = first_source.LastIndexOf ('.'); if (pos > 0) - output_file = first_source.Substring (0, pos) + target_ext; + output_file = first_source.Substring (0, pos) + RootContext.TargetExt; else - output_file = first_source + target_ext; + output_file = first_source + RootContext.TargetExt; } CodeGen.Init (output_file, output_file, want_debugging_support); - TypeManager.AddModule (CodeGen.ModuleBuilder); + 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."); + Environment.Exit (1); + } + + MethodInfo set_method = module_only.GetSetMethod (true); + set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null); + } + + TypeManager.AddModule (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."); + Environment.Exit (1); + } + + foreach (string module in modules) + LoadModule (adder_method, module); + } - DateTime start = DateTime.Now; TypeManager.ComputeNamespaces (); - DateTime end = DateTime.Now; // // Before emitting, we need to get the core @@ -1292,6 +1556,7 @@ namespace Mono.CSharp if (timestamps) ShowTime ("Resolving tree"); RootContext.ResolveTree (); + if (Report.Errors > 0) return false; if (timestamps) @@ -1301,6 +1566,11 @@ namespace Mono.CSharp RootContext.PopulateTypes (); RootContext.DefineTypes (); + if (RootContext.Documentation != null && + !RootContext.Documentation.OutputDocComment ( + output_file)) + return false; + TypeManager.InitCodeHelpers (); // @@ -1312,6 +1582,15 @@ namespace Mono.CSharp return false; } + if (RootContext.VerifyClsCompliance) { + CodeGen.Assembly.ResolveClsCompliance (); + if (CodeGen.Assembly.IsClsCompliant) { + AttributeTester.VerifyModulesClsCompliance (); + TypeManager.LoadAllImportedTypes (); + AttributeTester.VerifyTopLevelNameClsCompliance (); + } + } + // // The code generator // @@ -1333,27 +1612,45 @@ namespace Mono.CSharp PEFileKinds k = PEFileKinds.ConsoleApplication; - if (target == Target.Library || target == Target.Module){ - k = PEFileKinds.Dll; - - if (RootContext.MainClass != null) - Report.Error (2017, "Can not specify -main: when building module or library"); - } else if (target == Target.Exe) - k = PEFileKinds.ConsoleApplication; - else if (target == Target.WinExe) - k = PEFileKinds.WindowApplication; + switch (RootContext.Target) { + case Target.Library: + case Target.Module: + k = PEFileKinds.Dll; break; + case Target.Exe: + k = PEFileKinds.ConsoleApplication; break; + case Target.WinExe: + k = PEFileKinds.WindowApplication; break; + } - if (target == Target.Exe || target == Target.WinExe){ + if (RootContext.NeedsEntryPoint) { MethodInfo ep = RootContext.EntryPoint; - if (ep == null){ + if (ep == null) { + if (RootContext.MainClass != null) { + DeclSpace main_cont = RootContext.Tree.Decls [RootContext.MainClass] as DeclSpace; + if (main_cont == null) { + Report.Error (1555, output_file, "Could not find '{0}' specified for Main method", RootContext.MainClass); + return false; + } + + if (!(main_cont is ClassOrStruct)) { + Report.Error (1556, output_file, "'{0}' specified for Main method must be a valid class or struct", RootContext.MainClass); + return false; + } + + Report.Error (1558, main_cont.Location, "'{0}' does not have a suitable static Main method", main_cont.GetSignatureForError ()); + return false; + } + if (Report.Errors == 0) Report.Error (5001, "Program " + output_file + " does not have an entry point defined"); return false; } - CodeGen.AssemblyBuilder.SetEntryPoint (ep, k); + CodeGen.Assembly.Builder.SetEntryPoint (ep, k); + } else if (RootContext.MainClass != null) { + Report.Error (2017, "Can not specify -main: when building module or library"); } // @@ -1371,7 +1668,7 @@ namespace Mono.CSharp } else file = res = spec; - CodeGen.AssemblyBuilder.AddResourceFile (res, file); + CodeGen.Assembly.Builder.AddResourceFile (res, file); } } @@ -1379,9 +1676,14 @@ namespace Mono.CSharp object[] margs = new object [2]; Type[] argst = new Type [2]; argst [0] = argst [1] = typeof (string); - MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", argst); + + MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod ( + "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic, + null, CallingConventions.Any, argst, null); + if (embed_res == null) { - Report.Warning (0, new Location (-1), "Cannot embed resources on this runtime: try the Mono runtime instead."); + Report.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; @@ -1390,11 +1692,13 @@ namespace Mono.CSharp if (cp != -1){ margs [0] = spec.Substring (cp + 1); margs [1] = spec.Substring (0, cp); - } else - margs [0] = margs [1] = spec; + } else { + margs [1] = spec; + margs [0] = Path.GetFileName (spec); + } if (File.Exists ((string) margs [1])) - embed_res.Invoke (CodeGen.AssemblyBuilder, margs); + embed_res.Invoke (CodeGen.Assembly.Builder, margs); else { Report.Error (1566, "Can not find the resource " + margs [1]); } @@ -1402,6 +1706,29 @@ namespace Mono.CSharp } } + // + // Add Win32 resources + // + + CodeGen.Assembly.Builder.DefineVersionInfoResource (); + + if (win32ResourceFile != null) { + try { + CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile); + } + catch (ArgumentException) { + Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead."); + } + } + + if (win32IconFile != null) { + MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); + if (define_icon == null) { + Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead."); + } + define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile }); + } + if (Report.Errors > 0) return false; @@ -1414,8 +1741,19 @@ namespace Mono.CSharp Timer.ShowTimers (); if (Report.ExpectedError != 0){ - Console.WriteLine("Failed to report expected error " + Report.ExpectedError); + if (Report.Errors == 0) { + Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" + + "No other errors reported."); + + Environment.Exit (2); + } else { + Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" + + "However, other errors were reported."); + Environment.Exit (1); + } + + return false; } @@ -1425,6 +1763,24 @@ namespace Mono.CSharp #endif return (Report.Errors == 0); } + } + + // + // This is the only public entry point + // + public class CompilerCallableEntryPoint : MarshalByRefObject { + static bool used = false; + + public bool InvokeCompiler (string [] args) + { + if (used) + Reset (); + bool ok = Driver.MainDriver (args); + return ok && Report.Errors == 0; + } + public void Reset () + { + } } }