2 // settings.cs: All compiler settings
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
13 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
16 using System.Collections.Generic;
19 using System.Globalization;
22 namespace Mono.CSharp {
24 public enum LanguageVersion
34 Default = LanguageVersion.V_6,
37 public enum RuntimeVersion
46 Library, Exe, Module, WinExe
59 public class CompilerSettings
62 public Platform Platform;
63 public string TargetExt;
64 public bool VerifyClsCompliance;
66 public LanguageVersion Version;
67 public bool EnhancedWarnings;
68 public bool LoadDefaultReferences;
69 public string SdkVersion;
71 public string StrongNameKeyFile;
72 public string StrongNameKeyContainer;
73 public bool StrongNameDelaySign;
77 public bool WarningsAreErrors;
78 public int WarningLevel;
81 // Assemblies references to be loaded
83 public List<string> AssemblyReferences;
86 // External aliases for assemblies
88 public List<Tuple<string, string>> AssemblyReferencesAliases;
91 // Modules to be embedded
93 public List<string> Modules;
96 // Lookup paths for referenced assemblies
98 public List<string> ReferencesLookupPaths;
103 public Encoding Encoding;
106 // If set, enable XML documentation generation
108 public string DocumentationFile;
110 public string MainClass;
115 public string OutputFile;
118 // The default compiler checked state
123 // If true, the compiler is operating in statement mode,
124 // this currently turns local variable declaration into
125 // static variables of a class
127 public bool StatementMode; // TODO: SUPER UGLY
130 // Whether to allow Unsafe code
134 public string Win32ResourceFile;
135 public string Win32IconFile;
138 // A list of resource files for embedding
140 public List<AssemblyResource> Resources;
142 public bool GenerateDebugInfo;
144 #region Compiler debug flags only
145 public bool ParseOnly, TokenizeOnly, Timestamps;
146 public int DebugFlags;
147 public int VerboseParserFlag;
148 public int FatalCounter;
149 public bool Stacktrace;
150 public bool BreakOnInternalError;
153 public bool ShowFullPaths;
156 // Whether we are being linked against the standard libraries.
157 // This is only used to tell whether `System.Object' should
158 // have a base class or not.
162 public RuntimeVersion StdLibRuntimeVersion;
164 public string RuntimeMetadataVersion;
166 public bool WriteMetadataOnly;
168 readonly List<string> conditional_symbols;
170 readonly List<SourceFile> source_files;
172 List<int> warnings_as_error;
173 List<int> warnings_only;
174 HashSet<int> warning_ignore_table;
176 public CompilerSettings ()
181 Platform = Platform.AnyCPU;
182 Version = LanguageVersion.Default;
183 VerifyClsCompliance = true;
184 Encoding = Encoding.UTF8;
185 LoadDefaultReferences = true;
186 StdLibRuntimeVersion = RuntimeVersion.v4;
189 // Default to 1 or mdb files would be platform speficic
192 AssemblyReferences = new List<string> ();
193 AssemblyReferencesAliases = new List<Tuple<string, string>> ();
194 Modules = new List<string> ();
195 ReferencesLookupPaths = new List<string> ();
197 conditional_symbols = new List<string> ();
199 // Add default mcs define
201 conditional_symbols.Add ("__MonoCS__");
203 source_files = new List<SourceFile> ();
208 public SourceFile FirstSourceFile {
210 return source_files.Count > 0 ? source_files [0] : null;
214 public bool HasKeyFileOrContainer {
216 return StrongNameKeyFile != null || StrongNameKeyContainer != null;
220 public bool NeedsEntryPoint {
222 return Target == Target.Exe || Target == Target.WinExe;
226 public List<SourceFile> SourceFiles {
234 public void AddConditionalSymbol (string symbol)
236 if (!conditional_symbols.Contains (symbol))
237 conditional_symbols.Add (symbol);
240 public void AddWarningAsError (int id)
242 if (warnings_as_error == null)
243 warnings_as_error = new List<int> ();
245 warnings_as_error.Add (id);
248 public void AddWarningOnly (int id)
250 if (warnings_only == null)
251 warnings_only = new List<int> ();
253 warnings_only.Add (id);
256 public bool IsConditionalSymbolDefined (string symbol)
258 return conditional_symbols.Contains (symbol);
261 public bool IsWarningAsError (int code)
263 bool is_error = WarningsAreErrors;
265 // Check specific list
266 if (warnings_as_error != null)
267 is_error |= warnings_as_error.Contains (code);
269 // Ignore excluded warnings
270 if (warnings_only != null && warnings_only.Contains (code))
276 public bool IsWarningEnabled (int code, int level)
278 if (WarningLevel < level)
281 return !IsWarningDisabledGlobally (code);
284 public bool IsWarningDisabledGlobally (int code)
286 return warning_ignore_table != null && warning_ignore_table.Contains (code);
289 public void SetIgnoreWarning (int code)
291 if (warning_ignore_table == null)
292 warning_ignore_table = new HashSet<int> ();
294 warning_ignore_table.Add (code);
298 public class CommandLineParser
308 static readonly char[] argument_value_separator = { ';', ',' };
309 static readonly char[] numeric_value_separator = { ';', ',', ' ' };
311 readonly TextWriter output;
312 readonly Report report;
315 Dictionary<string, int> source_file_index;
317 public event Func<string[], int, int> UnknownOptionHandler;
319 CompilerSettings parser_settings;
321 public CommandLineParser (TextWriter errorOutput)
322 : this (errorOutput, Console.Out)
326 public CommandLineParser (TextWriter errorOutput, TextWriter messagesOutput)
328 var rp = new StreamReportPrinter (errorOutput);
330 parser_settings = new CompilerSettings ();
331 report = new Report (new CompilerContext (parser_settings, rp), rp);
332 this.output = messagesOutput;
335 public bool HasBeenStopped {
337 return stop_argument;
344 "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" +
345 "The compiler source code is released under the terms of the \n" +
346 "MIT X11 or GNU GPL licenses\n\n" +
348 "For more information on Mono, visit the project Web site\n" +
349 " http://www.mono-project.com\n\n" +
351 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
354 public CompilerSettings ParseArguments (string[] args)
356 CompilerSettings settings = new CompilerSettings ();
357 if (!ParseArguments (settings, args))
363 public bool ParseArguments (CompilerSettings settings, string[] args)
365 if (settings == null)
366 throw new ArgumentNullException ("settings");
368 List<string> response_file_list = null;
369 bool parsing_options = true;
370 stop_argument = false;
371 source_file_index = new Dictionary<string, int> ();
373 for (int i = 0; i < args.Length; i++) {
374 string arg = args[i];
380 string response_file = arg.Substring (1);
382 if (response_file_list == null)
383 response_file_list = new List<string> ();
385 if (response_file_list.Contains (response_file)) {
386 report.Error (1515, "Response file `{0}' specified multiple times", response_file);
390 response_file_list.Add (response_file);
392 extra_args = LoadArgs (response_file);
393 if (extra_args == null) {
394 report.Error (2011, "Unable to open response file: " + response_file);
398 args = AddArgs (args, extra_args);
402 if (parsing_options) {
404 parsing_options = false;
408 bool dash_opt = arg[0] == '-';
409 bool slash_opt = arg[0] == '/';
411 switch (ParseOptionUnix (arg, ref args, ref i, settings)) {
412 case ParseResult.Error:
413 case ParseResult.Success:
415 case ParseResult.Stop:
416 stop_argument = true;
418 case ParseResult.UnknownOption:
419 if (UnknownOptionHandler != null) {
420 var ret = UnknownOptionHandler (args, i);
430 if (dash_opt || slash_opt) {
432 string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg;
433 switch (ParseOption (csc_opt, ref args, settings)) {
434 case ParseResult.Error:
435 case ParseResult.Success:
437 case ParseResult.UnknownOption:
438 // Need to skip `/home/test.cs' however /test.cs is considered as error
439 if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0))
442 if (UnknownOptionHandler != null) {
443 var ret = UnknownOptionHandler (args, i);
450 Error_WrongOption (arg);
453 case ParseResult.Stop:
454 stop_argument = true;
460 ProcessSourceFiles (arg, false, settings.SourceFiles);
463 return report.Errors == 0;
466 void ProcessSourceFiles (string spec, bool recurse, List<SourceFile> sourceFiles)
468 string path, pattern;
470 SplitPathAndPattern (spec, out path, out pattern);
471 if (pattern.IndexOf ('*') == -1) {
472 AddSourceFile (spec, sourceFiles);
478 files = Directory.GetFiles (path, pattern);
479 } catch (System.IO.DirectoryNotFoundException) {
480 report.Error (2001, "Source file `" + spec + "' could not be found");
482 } catch (System.IO.IOException) {
483 report.Error (2001, "Source file `" + spec + "' could not be found");
486 foreach (string f in files) {
487 AddSourceFile (f, sourceFiles);
493 string[] dirs = null;
496 dirs = Directory.GetDirectories (path);
500 foreach (string d in dirs) {
502 // Don't include path in this string, as each
503 // directory entry already does
504 ProcessSourceFiles (d + "/" + pattern, true, sourceFiles);
508 static string[] AddArgs (string[] args, string[] extra_args)
511 new_args = new string[extra_args.Length + args.Length];
513 // if args contains '--' we have to take that into account
514 // split args into first half and second half based on '--'
515 // and add the extra_args before --
516 int split_position = Array.IndexOf (args, "--");
517 if (split_position != -1) {
518 Array.Copy (args, new_args, split_position);
519 extra_args.CopyTo (new_args, split_position);
520 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
522 args.CopyTo (new_args, 0);
523 extra_args.CopyTo (new_args, args.Length);
529 void AddAssemblyReference (string alias, string assembly, CompilerSettings settings)
531 if (assembly.Length == 0) {
532 report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
536 if (!IsExternAliasValid (alias)) {
537 report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
541 settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
544 void AddResource (AssemblyResource res, CompilerSettings settings)
546 if (settings.Resources == null) {
547 settings.Resources = new List<AssemblyResource> ();
548 settings.Resources.Add (res);
552 if (settings.Resources.Contains (res)) {
553 report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
557 settings.Resources.Add (res);
560 void AddSourceFile (string fileName, List<SourceFile> sourceFiles)
562 string path = Path.GetFullPath (fileName);
565 if (source_file_index.TryGetValue (path, out index)) {
566 string other_name = sourceFiles[index - 1].Name;
567 if (fileName.Equals (other_name))
568 report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name);
570 report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path);
575 var unit = new SourceFile (fileName, path, sourceFiles.Count + 1);
576 sourceFiles.Add (unit);
577 source_file_index.Add (path, unit.Index);
580 public bool ProcessWarningsList (string text, Action<int> action)
583 foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
585 if (!int.TryParse (wid, NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out id)) {
586 report.Error (1904, "`{0}' is not a valid warning number", wid);
591 if (report.CheckWarningCode (id, Location.Null))
598 void Error_RequiresArgument (string option)
600 report.Error (2006, "Missing argument for `{0}' option", option);
603 void Error_RequiresFileName (string option)
605 report.Error (2005, "Missing file specification for `{0}' option", option);
608 void Error_WrongOption (string option)
610 report.Error (2007, "Unrecognized command-line option: `{0}'", option);
613 static bool IsExternAliasValid (string identifier)
615 return Tokenizer.IsValidIdentifier (identifier);
618 static string[] LoadArgs (string file)
621 var args = new List<string> ();
624 f = new StreamReader (file);
629 StringBuilder sb = new StringBuilder ();
631 while ((line = f.ReadLine ()) != null) {
634 for (int i = 0; i < t; i++) {
637 if (c == '"' || c == '\'') {
640 for (i++; i < t; i++) {
647 } else if (c == ' ') {
649 args.Add (sb.ToString ());
656 args.Add (sb.ToString ());
661 return args.ToArray ();
667 "Other flags in the compiler\n" +
668 " --fatal[=COUNT] Makes error after COUNT fatal\n" +
669 " --lint Enhanced warnings\n" +
670 " --metadata-only Produced assembly will contain metadata only\n" +
671 " --parse Only parses the source file\n" +
672 " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" +
673 " --stacktrace Shows stack trace at error location\n" +
674 " --timestamp Displays time stamps of various compiler events\n" +
675 " -v Verbose parsing (for debugging the parser)\n" +
676 " --mcs-debug X Sets MCS debugging level to X\n" +
677 " --break-on-ice Breaks compilation on internal compiler error");
681 // This parses the -arg and /arg options to the compiler, even if the strings
682 // in the following text use "/arg" on the strings.
684 ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings)
686 int idx = option.IndexOf (':');
693 arg = option.Substring (0, idx);
695 value = option.Substring (idx + 1);
698 switch (arg.ToLowerInvariant ()) {
700 return ParseResult.Success;
706 settings.Target = Target.Exe;
710 settings.Target = Target.WinExe;
714 settings.Target = Target.Library;
715 settings.TargetExt = ".dll";
719 settings.Target = Target.Module;
720 settings.TargetExt = ".netmodule";
724 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
725 return ParseResult.Error;
727 return ParseResult.Success;
730 if (value.Length == 0) {
731 Error_RequiresFileName (option);
732 return ParseResult.Error;
734 settings.OutputFile = value;
735 return ParseResult.Success;
741 settings.Optimize = true;
742 return ParseResult.Success;
746 settings.Optimize = false;
747 return ParseResult.Success;
749 // TODO: Not supported by csc 3.5+
751 case "/incremental+":
752 case "/incremental-":
754 return ParseResult.Success;
758 if (value.Length == 0) {
759 Error_RequiresArgument (option);
760 return ParseResult.Error;
763 foreach (string d in value.Split (argument_value_separator)) {
764 string conditional = d.Trim ();
765 if (!Tokenizer.IsValidIdentifier (conditional)) {
766 report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
770 settings.AddConditionalSymbol (conditional);
772 return ParseResult.Success;
777 // We should collect data, runtime, etc and store in the file specified
779 output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
780 return ParseResult.Success;
785 if (value.Length == 0) {
786 Error_RequiresArgument (option);
787 return ParseResult.Error;
789 packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' }));
790 string pkgout = Driver.GetPackageFlags (packages, report);
793 return ParseResult.Error;
795 string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' });
796 args = AddArgs (args, xargs);
797 return ParseResult.Success;
801 case "/linkresource":
804 AssemblyResource res = null;
805 string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries);
808 if (s[0].Length == 0)
810 res = new AssemblyResource (s[0], Path.GetFileName (s[0]));
813 res = new AssemblyResource (s[0], s[1]);
816 if (s[2] != "public" && s[2] != "private") {
817 report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]);
818 return ParseResult.Error;
820 res = new AssemblyResource (s[0], s[1], s[2] == "private");
823 report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
824 return ParseResult.Error;
828 res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R';
829 AddResource (res, settings);
832 return ParseResult.Success;
835 if (value.Length == 0) {
836 Error_RequiresFileName (option);
837 return ParseResult.Error;
839 ProcessSourceFiles (value, true, settings.SourceFiles);
840 return ParseResult.Success;
844 if (value.Length == 0) {
845 Error_RequiresFileName (option);
846 return ParseResult.Error;
849 string[] refs = value.Split (argument_value_separator);
850 foreach (string r in refs) {
855 int index = val.IndexOf ('=');
857 string alias = r.Substring (0, index);
858 string assembly = r.Substring (index + 1);
859 AddAssemblyReference (alias, assembly, settings);
860 if (refs.Length != 1) {
861 report.Error (2034, "Cannot specify multiple aliases using single /reference option");
862 return ParseResult.Error;
865 settings.AssemblyReferences.Add (val);
868 return ParseResult.Success;
871 if (value.Length == 0) {
872 Error_RequiresFileName (option);
873 return ParseResult.Error;
876 string[] refs = value.Split (argument_value_separator);
877 foreach (string r in refs) {
878 settings.Modules.Add (r);
880 return ParseResult.Success;
883 if (value.Length == 0) {
884 Error_RequiresFileName (option);
885 return ParseResult.Error;
888 if (settings.Win32IconFile != null)
889 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
891 settings.Win32ResourceFile = value;
892 return ParseResult.Success;
895 if (value.Length == 0) {
896 Error_RequiresFileName (option);
897 return ParseResult.Error;
900 if (settings.Win32ResourceFile != null)
901 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
903 settings.Win32IconFile = value;
904 return ParseResult.Success;
907 if (value.Length == 0) {
908 Error_RequiresFileName (option);
909 return ParseResult.Error;
912 settings.DocumentationFile = value;
913 return ParseResult.Success;
918 if (value.Length == 0) {
919 return ParseResult.Error;
922 libdirs = value.Split (argument_value_separator);
923 foreach (string dir in libdirs)
924 settings.ReferencesLookupPaths.Add (dir);
925 return ParseResult.Success;
929 settings.GenerateDebugInfo = false;
930 return ParseResult.Success;
933 if (value.Equals ("full", StringComparison.OrdinalIgnoreCase) || value.Equals ("pdbonly", StringComparison.OrdinalIgnoreCase) || idx < 0) {
934 settings.GenerateDebugInfo = true;
935 return ParseResult.Success;
938 if (value.Length > 0) {
939 report.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
941 Error_RequiresArgument (option);
944 return ParseResult.Error;
947 settings.GenerateDebugInfo = true;
948 return ParseResult.Success;
952 settings.Checked = true;
953 return ParseResult.Success;
956 settings.Checked = false;
957 return ParseResult.Success;
961 settings.VerifyClsCompliance = true;
962 return ParseResult.Success;
965 settings.VerifyClsCompliance = false;
966 return ParseResult.Success;
970 settings.Unsafe = true;
971 return ParseResult.Success;
974 settings.Unsafe = false;
975 return ParseResult.Success;
978 case "/warnaserror+":
979 if (value.Length == 0) {
980 settings.WarningsAreErrors = true;
981 parser_settings.WarningsAreErrors = true;
983 if (!ProcessWarningsList (value, settings.AddWarningAsError))
984 return ParseResult.Error;
986 return ParseResult.Success;
988 case "/warnaserror-":
989 if (value.Length == 0) {
990 settings.WarningsAreErrors = false;
992 if (!ProcessWarningsList (value, settings.AddWarningOnly))
993 return ParseResult.Error;
995 return ParseResult.Success;
999 if (value.Length == 0) {
1000 Error_RequiresArgument (option);
1001 return ParseResult.Error;
1004 SetWarningLevel (value, settings);
1005 return ParseResult.Success;
1008 if (value.Length == 0) {
1009 Error_RequiresArgument (option);
1010 return ParseResult.Error;
1013 if (!ProcessWarningsList (value, settings.SetIgnoreWarning))
1014 return ParseResult.Error;
1016 return ParseResult.Success;
1019 settings.LoadDefaultReferences = false;
1020 return ParseResult.Success;
1023 if (value.Length == 0) {
1024 Error_RequiresArgument (option);
1025 return ParseResult.Error;
1028 switch (value.ToLowerInvariant ()) {
1030 settings.Platform = Platform.Arm;
1033 settings.Platform = Platform.AnyCPU;
1036 settings.Platform = Platform.X86;
1039 settings.Platform = Platform.X64;
1042 settings.Platform = Platform.IA64;
1044 case "anycpu32bitpreferred":
1045 settings.Platform = Platform.AnyCPU32Preferred;
1048 report.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
1050 return ParseResult.Error;
1053 return ParseResult.Success;
1056 if (value.Length == 0) {
1057 Error_RequiresArgument (option);
1058 return ParseResult.Error;
1061 settings.SdkVersion = value;
1062 return ParseResult.Success;
1064 // We just ignore this.
1065 case "/errorreport":
1067 if (value.Length == 0) {
1068 Error_RequiresArgument (option);
1069 return ParseResult.Error;
1072 return ParseResult.Success;
1074 case "/helpinternal":
1076 return ParseResult.Stop;
1081 return ParseResult.Stop;
1085 if (value.Length == 0) {
1086 Error_RequiresArgument (option);
1087 return ParseResult.Error;
1089 settings.MainClass = value;
1090 return ParseResult.Success;
1094 settings.StdLib = false;
1095 return ParseResult.Success;
1098 settings.StdLib = true;
1099 return ParseResult.Success;
1102 settings.ShowFullPaths = true;
1103 return ParseResult.Success;
1106 if (value.Length == 0) {
1107 Error_RequiresFileName (option);
1108 return ParseResult.Error;
1111 settings.StrongNameKeyFile = value;
1112 return ParseResult.Success;
1114 case "/keycontainer":
1115 if (value.Length == 0) {
1116 Error_RequiresArgument (option);
1117 return ParseResult.Error;
1120 settings.StrongNameKeyContainer = value;
1121 return ParseResult.Success;
1125 settings.StrongNameDelaySign = true;
1126 return ParseResult.Success;
1129 settings.StrongNameDelaySign = false;
1130 return ParseResult.Success;
1132 case "/langversion":
1133 if (value.Length == 0) {
1134 Error_RequiresArgument (option);
1135 return ParseResult.Error;
1138 switch (value.ToLowerInvariant ()) {
1141 settings.Version = LanguageVersion.ISO_1;
1142 return ParseResult.Success;
1144 settings.Version = LanguageVersion.Default;
1145 return ParseResult.Success;
1148 settings.Version = LanguageVersion.ISO_2;
1149 return ParseResult.Success;
1151 settings.Version = LanguageVersion.V_3;
1152 return ParseResult.Success;
1154 settings.Version = LanguageVersion.V_4;
1155 return ParseResult.Success;
1157 settings.Version = LanguageVersion.V_5;
1158 return ParseResult.Success;
1160 settings.Version = LanguageVersion.V_6;
1161 return ParseResult.Success;
1162 case "experimental":
1163 settings.Version = LanguageVersion.Experimental;
1164 return ParseResult.Success;
1166 report.Warning (8000, 1, "Language version `future' is no longer supported");
1170 report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 6", value);
1171 return ParseResult.Error;
1174 if (value.Length == 0) {
1175 Error_RequiresArgument (option);
1176 return ParseResult.Error;
1181 settings.Encoding = Encoding.UTF8;
1184 settings.Encoding = Encoding.Default;
1188 settings.Encoding = Encoding.GetEncoding (int.Parse (value));
1190 report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1192 return ParseResult.Error;
1194 return ParseResult.Success;
1196 case "runtimemetadataversion":
1197 if (value.Length == 0) {
1198 Error_RequiresArgument (option);
1199 return ParseResult.Error;
1202 settings.RuntimeMetadataVersion = value;
1203 return ParseResult.Success;
1206 return ParseResult.UnknownOption;
1211 // Currently handles the Unix-like command line options, but will be
1212 // deprecated in favor of the CSCParseOption, which will also handle the
1213 // options that start with a dash in the future.
1215 ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings)
1219 settings.VerboseParserFlag++;
1220 return ParseResult.Success;
1224 return ParseResult.Stop;
1227 settings.ParseOnly = true;
1228 return ParseResult.Success;
1230 case "--main": case "-m":
1231 report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1232 if ((i + 1) >= args.Length){
1233 Error_RequiresArgument (arg);
1234 return ParseResult.Error;
1236 settings.MainClass = args[++i];
1237 return ParseResult.Success;
1240 report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1241 settings.Unsafe = true;
1242 return ParseResult.Success;
1244 case "/?": case "/h": case "/help":
1247 return ParseResult.Stop;
1250 report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1251 if ((i + 1) >= args.Length){
1252 Error_RequiresArgument (arg);
1253 return ParseResult.Error;
1256 settings.AddConditionalSymbol (args [++i]);
1257 return ParseResult.Success;
1260 settings.TokenizeOnly = true;
1261 return ParseResult.Success;
1265 report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1266 if ((i + 1) >= args.Length){
1267 Error_RequiresArgument (arg);
1268 return ParseResult.Error;
1270 settings.OutputFile = args[++i];
1271 return ParseResult.Success;
1274 report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1275 settings.Checked = true;
1276 return ParseResult.Success;
1278 case "--stacktrace":
1279 settings.Stacktrace = true;
1280 return ParseResult.Success;
1282 case "--linkresource":
1284 report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1285 if ((i + 1) >= args.Length){
1286 Error_RequiresArgument (arg);
1287 return ParseResult.Error;
1290 AddResource (new AssemblyResource (args[++i], args[i]), settings);
1291 return ParseResult.Success;
1295 report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1296 if ((i + 1) >= args.Length){
1297 Error_RequiresArgument (arg);
1298 return ParseResult.Error;
1301 AddResource (new AssemblyResource (args[++i], args[i], true), settings);
1302 return ParseResult.Success;
1305 report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1306 if ((i + 1) >= args.Length){
1307 Error_RequiresArgument (arg);
1308 return ParseResult.Error;
1311 string type = args [++i];
1314 settings.Target = Target.Library;
1315 settings.TargetExt = ".dll";
1319 settings.Target = Target.Exe;
1323 settings.Target = Target.WinExe;
1327 settings.Target = Target.Module;
1328 settings.TargetExt = ".dll";
1331 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1334 return ParseResult.Success;
1337 report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1338 if ((i + 1) >= args.Length){
1339 Error_RequiresArgument (arg);
1340 return ParseResult.Error;
1343 string val = args [++i];
1344 int idx = val.IndexOf ('=');
1346 string alias = val.Substring (0, idx);
1347 string assembly = val.Substring (idx + 1);
1348 AddAssemblyReference (alias, assembly, settings);
1349 return ParseResult.Success;
1352 settings.AssemblyReferences.Add (val);
1353 return ParseResult.Success;
1356 report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1357 if ((i + 1) >= args.Length){
1358 Error_RequiresArgument (arg);
1359 return ParseResult.Error;
1361 settings.ReferencesLookupPaths.Add (args [++i]);
1362 return ParseResult.Success;
1365 settings.EnhancedWarnings = true;
1366 return ParseResult.Success;
1369 report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1370 settings.StdLib = false;
1371 return ParseResult.Success;
1374 report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1375 if ((i + 1) >= args.Length){
1376 Error_RequiresArgument (arg);
1377 return ParseResult.Error;
1382 warn = int.Parse (args [++i]);
1385 Environment.Exit (1);
1387 settings.SetIgnoreWarning (warn);
1388 return ParseResult.Success;
1391 report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1392 if ((i + 1) >= args.Length){
1393 Error_RequiresArgument (arg);
1394 return ParseResult.Error;
1397 SetWarningLevel (args [++i], settings);
1398 return ParseResult.Success;
1401 if ((i + 1) >= args.Length){
1402 Error_RequiresArgument (arg);
1403 return ParseResult.Error;
1407 settings.DebugFlags = int.Parse (args [++i]);
1409 Error_RequiresArgument (arg);
1410 return ParseResult.Error;
1413 return ParseResult.Success;
1417 return ParseResult.Stop;
1420 report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1421 if ((i + 1) >= args.Length){
1422 Error_RequiresArgument (arg);
1423 return ParseResult.Error;
1425 ProcessSourceFiles (args [++i], true, settings.SourceFiles);
1426 return ParseResult.Success;
1429 settings.Timestamps = true;
1430 return ParseResult.Success;
1432 case "--debug": case "-g":
1433 report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1434 settings.GenerateDebugInfo = true;
1435 return ParseResult.Success;
1438 report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1439 settings.LoadDefaultReferences = false;
1440 return ParseResult.Success;
1442 case "--metadata-only":
1443 settings.WriteMetadataOnly = true;
1444 return ParseResult.Success;
1446 case "--break-on-ice":
1447 settings.BreakOnInternalError = true;
1448 return ParseResult.Success;
1451 if (arg.StartsWith ("--fatal", StringComparison.Ordinal)){
1453 if (arg.StartsWith ("--fatal=", StringComparison.Ordinal))
1454 int.TryParse (arg.Substring (8), out fatal);
1456 settings.FatalCounter = fatal;
1457 return ParseResult.Success;
1459 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
1460 string version = arg.Substring (10);
1465 settings.StdLibRuntimeVersion = RuntimeVersion.v1;
1469 settings.StdLibRuntimeVersion = RuntimeVersion.v2;
1473 settings.StdLibRuntimeVersion = RuntimeVersion.v4;
1476 return ParseResult.Success;
1479 return ParseResult.UnknownOption;
1483 void SetWarningLevel (string s, CompilerSettings settings)
1488 level = int.Parse (s);
1491 if (level < 0 || level > 4) {
1492 report.Error (1900, "Warning level must be in the range 0-4");
1495 settings.WarningLevel = level;
1499 // Given a path specification, splits the path from the file/pattern
1501 static void SplitPathAndPattern (string spec, out string path, out string pattern)
1503 int p = spec.LastIndexOf ('/');
1506 // Windows does not like /file.cs, switch that to:
1511 pattern = spec.Substring (1);
1513 path = spec.Substring (0, p);
1514 pattern = spec.Substring (p + 1);
1519 p = spec.LastIndexOf ('\\');
1521 path = spec.Substring (0, p);
1522 pattern = spec.Substring (p + 1);
1533 "Mono C# compiler, Copyright 2001-2011 Novell, Inc., Copyright 2011-2012 Xamarin, Inc\n" +
1534 "mcs [options] source-files\n" +
1535 " --about About the Mono C# compiler\n" +
1536 " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
1537 " -checked[+|-] Sets default aritmetic overflow context\n" +
1538 " -clscheck[+|-] Disables CLS Compliance verifications\n" +
1539 " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" +
1540 " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" +
1541 " -debug[+|-], -g Generate debugging information\n" +
1542 " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
1543 " -doc:FILE Process documentation comments to XML file\n" +
1544 " -fullpaths Any issued error or warning uses absolute file path\n" +
1545 " -help Lists all compiler options (short: -?)\n" +
1546 " -keycontainer:NAME The key pair container used to sign the output assembly\n" +
1547 " -keyfile:FILE The key file used to strongname the ouput assembly\n" +
1548 " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Future\n" +
1549 " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
1550 " -main:CLASS Specifies the class with the Main method (short: -m)\n" +
1551 " -noconfig Disables implicitly referenced assemblies\n" +
1552 " -nostdlib[+|-] Does not reference mscorlib.dll library\n" +
1553 " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" +
1554 " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" +
1555 " -out:FILE Specifies output assembly name\n" +
1556 " -pkg:P1[,Pn] References packages P1..Pn\n" +
1557 " -platform:ARCH Specifies the target platform of the output assembly\n" +
1558 " ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
1559 " x86, x64 or itanium. The default is anycpu.\n" +
1560 " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
1561 " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
1562 " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
1563 " -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
1564 " VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
1565 " -target:KIND Specifies the format of the output assembly (short: -t)\n" +
1566 " KIND can be one of: exe, winexe, library, module\n" +
1567 " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +
1568 " -warnaserror[+|-] Treats all warnings as errors\n" +
1569 " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1570 " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" +
1571 " -helpinternal Shows internal and advanced compiler options\n" +
1574 " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1575 " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" +
1576 " -win32res:FILE Specifies Win32 resource file (.res)\n" +
1577 " -win32icon:FILE Use this icon for the output\n" +
1578 " @file Read response file for more options\n\n" +
1579 "Options can be of the form -option or /option");
1584 string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString ();
1585 output.WriteLine ("Mono C# compiler version {0}", version);
1589 public class RootContext
1592 // Contains the parsed tree
1594 static ModuleContainer root;
1596 static public ModuleContainer ToplevelTypes {
1597 get { return root; }
1598 set { root = value; }