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
33 Default = LanguageVersion.V_5,
36 public enum RuntimeVersion
45 Library, Exe, Module, WinExe
58 public class CompilerSettings
61 public Platform Platform;
62 public string TargetExt;
63 public bool VerifyClsCompliance;
65 public LanguageVersion Version;
66 public bool EnhancedWarnings;
67 public bool LoadDefaultReferences;
68 public string SdkVersion;
70 public string StrongNameKeyFile;
71 public string StrongNameKeyContainer;
72 public bool StrongNameDelaySign;
76 public bool WarningsAreErrors;
77 public int WarningLevel;
80 // Assemblies references to be loaded
82 public List<string> AssemblyReferences;
85 // External aliases for assemblies
87 public List<Tuple<string, string>> AssemblyReferencesAliases;
90 // Modules to be embedded
92 public List<string> Modules;
95 // Lookup paths for referenced assemblies
97 public List<string> ReferencesLookupPaths;
102 public Encoding Encoding;
105 // If set, enable XML documentation generation
107 public string DocumentationFile;
109 public string MainClass;
114 public string OutputFile;
117 // The default compiler checked state
122 // If true, the compiler is operating in statement mode,
123 // this currently turns local variable declaration into
124 // static variables of a class
126 public bool StatementMode; // TODO: SUPER UGLY
129 // Whether to allow Unsafe code
133 public string Win32ResourceFile;
134 public string Win32IconFile;
137 // A list of resource files for embedding
139 public List<AssemblyResource> Resources;
141 public bool GenerateDebugInfo;
143 #region Compiler debug flags only
144 public bool ParseOnly, TokenizeOnly, Timestamps;
145 public int DebugFlags;
146 public int VerboseParserFlag;
147 public int FatalCounter;
148 public bool Stacktrace;
149 public bool BreakOnInternalError;
152 public bool ShowFullPaths;
155 // Whether we are being linked against the standard libraries.
156 // This is only used to tell whether `System.Object' should
157 // have a base class or not.
161 public RuntimeVersion StdLibRuntimeVersion;
163 public bool WriteMetadataOnly;
165 readonly List<string> conditional_symbols;
167 readonly List<SourceFile> source_files;
169 List<int> warnings_as_error;
170 List<int> warnings_only;
171 HashSet<int> warning_ignore_table;
173 public CompilerSettings ()
178 Platform = Platform.AnyCPU;
179 Version = LanguageVersion.Default;
180 VerifyClsCompliance = true;
181 Encoding = Encoding.UTF8;
182 LoadDefaultReferences = true;
183 StdLibRuntimeVersion = RuntimeVersion.v4;
186 // Default to 1 or mdb files would be platform speficic
189 AssemblyReferences = new List<string> ();
190 AssemblyReferencesAliases = new List<Tuple<string, string>> ();
191 Modules = new List<string> ();
192 ReferencesLookupPaths = new List<string> ();
194 conditional_symbols = new List<string> ();
196 // Add default mcs define
198 conditional_symbols.Add ("__MonoCS__");
200 source_files = new List<SourceFile> ();
205 public SourceFile FirstSourceFile {
207 return source_files.Count > 0 ? source_files [0] : null;
211 public bool HasKeyFileOrContainer {
213 return StrongNameKeyFile != null || StrongNameKeyContainer != null;
217 public bool NeedsEntryPoint {
219 return Target == Target.Exe || Target == Target.WinExe;
223 public List<SourceFile> SourceFiles {
231 public void AddConditionalSymbol (string symbol)
233 if (!conditional_symbols.Contains (symbol))
234 conditional_symbols.Add (symbol);
237 public void AddWarningAsError (int id)
239 if (warnings_as_error == null)
240 warnings_as_error = new List<int> ();
242 warnings_as_error.Add (id);
245 public void AddWarningOnly (int id)
247 if (warnings_only == null)
248 warnings_only = new List<int> ();
250 warnings_only.Add (id);
253 public bool IsConditionalSymbolDefined (string symbol)
255 return conditional_symbols.Contains (symbol);
258 public bool IsWarningAsError (int code)
260 bool is_error = WarningsAreErrors;
262 // Check specific list
263 if (warnings_as_error != null)
264 is_error |= warnings_as_error.Contains (code);
266 // Ignore excluded warnings
267 if (warnings_only != null && warnings_only.Contains (code))
273 public bool IsWarningEnabled (int code, int level)
275 if (WarningLevel < level)
278 return !IsWarningDisabledGlobally (code);
281 public bool IsWarningDisabledGlobally (int code)
283 return warning_ignore_table != null && warning_ignore_table.Contains (code);
286 public void SetIgnoreWarning (int code)
288 if (warning_ignore_table == null)
289 warning_ignore_table = new HashSet<int> ();
291 warning_ignore_table.Add (code);
295 public class CommandLineParser
305 static readonly char[] argument_value_separator = { ';', ',' };
306 static readonly char[] numeric_value_separator = { ';', ',', ' ' };
308 readonly TextWriter output;
309 readonly Report report;
312 Dictionary<string, int> source_file_index;
314 public event Func<string[], int, int> UnknownOptionHandler;
316 CompilerSettings parser_settings;
318 public CommandLineParser (TextWriter errorOutput)
319 : this (errorOutput, Console.Out)
323 public CommandLineParser (TextWriter errorOutput, TextWriter messagesOutput)
325 var rp = new StreamReportPrinter (errorOutput);
327 parser_settings = new CompilerSettings ();
328 report = new Report (new CompilerContext (parser_settings, rp), rp);
329 this.output = messagesOutput;
332 public bool HasBeenStopped {
334 return stop_argument;
341 "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" +
342 "The compiler source code is released under the terms of the \n" +
343 "MIT X11 or GNU GPL licenses\n\n" +
345 "For more information on Mono, visit the project Web site\n" +
346 " http://www.mono-project.com\n\n" +
348 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
351 public CompilerSettings ParseArguments (string[] args)
353 CompilerSettings settings = new CompilerSettings ();
354 if (!ParseArguments (settings, args))
360 public bool ParseArguments (CompilerSettings settings, string[] args)
362 if (settings == null)
363 throw new ArgumentNullException ("settings");
365 List<string> response_file_list = null;
366 bool parsing_options = true;
367 stop_argument = false;
368 source_file_index = new Dictionary<string, int> ();
370 for (int i = 0; i < args.Length; i++) {
371 string arg = args[i];
377 string response_file = arg.Substring (1);
379 if (response_file_list == null)
380 response_file_list = new List<string> ();
382 if (response_file_list.Contains (response_file)) {
383 report.Error (1515, "Response file `{0}' specified multiple times", response_file);
387 response_file_list.Add (response_file);
389 extra_args = LoadArgs (response_file);
390 if (extra_args == null) {
391 report.Error (2011, "Unable to open response file: " + response_file);
395 args = AddArgs (args, extra_args);
399 if (parsing_options) {
401 parsing_options = false;
405 bool dash_opt = arg[0] == '-';
406 bool slash_opt = arg[0] == '/';
408 switch (ParseOptionUnix (arg, ref args, ref i, settings)) {
409 case ParseResult.Error:
410 case ParseResult.Success:
412 case ParseResult.Stop:
413 stop_argument = true;
415 case ParseResult.UnknownOption:
416 if (UnknownOptionHandler != null) {
417 var ret = UnknownOptionHandler (args, i);
427 if (dash_opt || slash_opt) {
429 string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg;
430 switch (ParseOption (csc_opt, ref args, settings)) {
431 case ParseResult.Error:
432 case ParseResult.Success:
434 case ParseResult.UnknownOption:
435 // Need to skip `/home/test.cs' however /test.cs is considered as error
436 if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0))
439 if (UnknownOptionHandler != null) {
440 var ret = UnknownOptionHandler (args, i);
447 Error_WrongOption (arg);
450 case ParseResult.Stop:
451 stop_argument = true;
457 ProcessSourceFiles (arg, false, settings.SourceFiles);
460 return report.Errors == 0;
463 void ProcessSourceFiles (string spec, bool recurse, List<SourceFile> sourceFiles)
465 string path, pattern;
467 SplitPathAndPattern (spec, out path, out pattern);
468 if (pattern.IndexOf ('*') == -1) {
469 AddSourceFile (spec, sourceFiles);
475 files = Directory.GetFiles (path, pattern);
476 } catch (System.IO.DirectoryNotFoundException) {
477 report.Error (2001, "Source file `" + spec + "' could not be found");
479 } catch (System.IO.IOException) {
480 report.Error (2001, "Source file `" + spec + "' could not be found");
483 foreach (string f in files) {
484 AddSourceFile (f, sourceFiles);
490 string[] dirs = null;
493 dirs = Directory.GetDirectories (path);
497 foreach (string d in dirs) {
499 // Don't include path in this string, as each
500 // directory entry already does
501 ProcessSourceFiles (d + "/" + pattern, true, sourceFiles);
505 static string[] AddArgs (string[] args, string[] extra_args)
508 new_args = new string[extra_args.Length + args.Length];
510 // if args contains '--' we have to take that into account
511 // split args into first half and second half based on '--'
512 // and add the extra_args before --
513 int split_position = Array.IndexOf (args, "--");
514 if (split_position != -1) {
515 Array.Copy (args, new_args, split_position);
516 extra_args.CopyTo (new_args, split_position);
517 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
519 args.CopyTo (new_args, 0);
520 extra_args.CopyTo (new_args, args.Length);
526 void AddAssemblyReference (string alias, string assembly, CompilerSettings settings)
528 if (assembly.Length == 0) {
529 report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
533 if (!IsExternAliasValid (alias)) {
534 report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
538 settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
541 void AddResource (AssemblyResource res, CompilerSettings settings)
543 if (settings.Resources == null) {
544 settings.Resources = new List<AssemblyResource> ();
545 settings.Resources.Add (res);
549 if (settings.Resources.Contains (res)) {
550 report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
554 settings.Resources.Add (res);
557 void AddSourceFile (string fileName, List<SourceFile> sourceFiles)
559 string path = Path.GetFullPath (fileName);
562 if (source_file_index.TryGetValue (path, out index)) {
563 string other_name = sourceFiles[index - 1].Name;
564 if (fileName.Equals (other_name))
565 report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name);
567 report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path);
572 var unit = new SourceFile (fileName, path, sourceFiles.Count + 1);
573 sourceFiles.Add (unit);
574 source_file_index.Add (path, unit.Index);
577 public bool ProcessWarningsList (string text, Action<int> action)
580 foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
582 if (!int.TryParse (wid, NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out id)) {
583 report.Error (1904, "`{0}' is not a valid warning number", wid);
588 if (report.CheckWarningCode (id, Location.Null))
595 void Error_RequiresArgument (string option)
597 report.Error (2006, "Missing argument for `{0}' option", option);
600 void Error_RequiresFileName (string option)
602 report.Error (2005, "Missing file specification for `{0}' option", option);
605 void Error_WrongOption (string option)
607 report.Error (2007, "Unrecognized command-line option: `{0}'", option);
610 static bool IsExternAliasValid (string identifier)
612 return Tokenizer.IsValidIdentifier (identifier);
615 static string[] LoadArgs (string file)
618 var args = new List<string> ();
621 f = new StreamReader (file);
626 StringBuilder sb = new StringBuilder ();
628 while ((line = f.ReadLine ()) != null) {
631 for (int i = 0; i < t; i++) {
634 if (c == '"' || c == '\'') {
637 for (i++; i < t; i++) {
644 } else if (c == ' ') {
646 args.Add (sb.ToString ());
653 args.Add (sb.ToString ());
658 return args.ToArray ();
664 "Other flags in the compiler\n" +
665 " --fatal[=COUNT] Makes error after COUNT fatal\n" +
666 " --lint Enhanced warnings\n" +
667 " --metadata-only Produced assembly will contain metadata only\n" +
668 " --parse Only parses the source file\n" +
669 " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" +
670 " --stacktrace Shows stack trace at error location\n" +
671 " --timestamp Displays time stamps of various compiler events\n" +
672 " -v Verbose parsing (for debugging the parser)\n" +
673 " --mcs-debug X Sets MCS debugging level to X\n" +
674 " --break-on-ice Breaks compilation on internal compiler error");
678 // This parses the -arg and /arg options to the compiler, even if the strings
679 // in the following text use "/arg" on the strings.
681 ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings)
683 int idx = option.IndexOf (':');
690 arg = option.Substring (0, idx);
692 value = option.Substring (idx + 1);
695 switch (arg.ToLowerInvariant ()) {
697 return ParseResult.Success;
703 settings.Target = Target.Exe;
707 settings.Target = Target.WinExe;
711 settings.Target = Target.Library;
712 settings.TargetExt = ".dll";
716 settings.Target = Target.Module;
717 settings.TargetExt = ".netmodule";
721 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
722 return ParseResult.Error;
724 return ParseResult.Success;
727 if (value.Length == 0) {
728 Error_RequiresFileName (option);
729 return ParseResult.Error;
731 settings.OutputFile = value;
732 return ParseResult.Success;
738 settings.Optimize = true;
739 return ParseResult.Success;
743 settings.Optimize = false;
744 return ParseResult.Success;
746 // TODO: Not supported by csc 3.5+
748 case "/incremental+":
749 case "/incremental-":
751 return ParseResult.Success;
755 if (value.Length == 0) {
756 Error_RequiresArgument (option);
757 return ParseResult.Error;
760 foreach (string d in value.Split (argument_value_separator)) {
761 string conditional = d.Trim ();
762 if (!Tokenizer.IsValidIdentifier (conditional)) {
763 report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
767 settings.AddConditionalSymbol (conditional);
769 return ParseResult.Success;
774 // We should collect data, runtime, etc and store in the file specified
776 output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
777 return ParseResult.Success;
782 if (value.Length == 0) {
783 Error_RequiresArgument (option);
784 return ParseResult.Error;
786 packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' }));
787 string pkgout = Driver.GetPackageFlags (packages, report);
790 return ParseResult.Error;
792 string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' });
793 args = AddArgs (args, xargs);
794 return ParseResult.Success;
798 case "/linkresource":
801 AssemblyResource res = null;
802 string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries);
805 if (s[0].Length == 0)
807 res = new AssemblyResource (s[0], Path.GetFileName (s[0]));
810 res = new AssemblyResource (s[0], s[1]);
813 if (s[2] != "public" && s[2] != "private") {
814 report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]);
815 return ParseResult.Error;
817 res = new AssemblyResource (s[0], s[1], s[2] == "private");
820 report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
821 return ParseResult.Error;
825 res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R';
826 AddResource (res, settings);
829 return ParseResult.Success;
832 if (value.Length == 0) {
833 Error_RequiresFileName (option);
834 return ParseResult.Error;
836 ProcessSourceFiles (value, true, settings.SourceFiles);
837 return ParseResult.Success;
841 if (value.Length == 0) {
842 Error_RequiresFileName (option);
843 return ParseResult.Error;
846 string[] refs = value.Split (argument_value_separator);
847 foreach (string r in refs) {
852 int index = val.IndexOf ('=');
854 string alias = r.Substring (0, index);
855 string assembly = r.Substring (index + 1);
856 AddAssemblyReference (alias, assembly, settings);
857 if (refs.Length != 1) {
858 report.Error (2034, "Cannot specify multiple aliases using single /reference option");
859 return ParseResult.Error;
862 settings.AssemblyReferences.Add (val);
865 return ParseResult.Success;
868 if (value.Length == 0) {
869 Error_RequiresFileName (option);
870 return ParseResult.Error;
873 string[] refs = value.Split (argument_value_separator);
874 foreach (string r in refs) {
875 settings.Modules.Add (r);
877 return ParseResult.Success;
880 if (value.Length == 0) {
881 Error_RequiresFileName (option);
882 return ParseResult.Error;
885 if (settings.Win32IconFile != null)
886 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
888 settings.Win32ResourceFile = value;
889 return ParseResult.Success;
892 if (value.Length == 0) {
893 Error_RequiresFileName (option);
894 return ParseResult.Error;
897 if (settings.Win32ResourceFile != null)
898 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
900 settings.Win32IconFile = value;
901 return ParseResult.Success;
904 if (value.Length == 0) {
905 Error_RequiresFileName (option);
906 return ParseResult.Error;
909 settings.DocumentationFile = value;
910 return ParseResult.Success;
915 if (value.Length == 0) {
916 return ParseResult.Error;
919 libdirs = value.Split (argument_value_separator);
920 foreach (string dir in libdirs)
921 settings.ReferencesLookupPaths.Add (dir);
922 return ParseResult.Success;
926 settings.GenerateDebugInfo = false;
927 return ParseResult.Success;
930 if (value.Equals ("full", StringComparison.OrdinalIgnoreCase) || value.Equals ("pdbonly", StringComparison.OrdinalIgnoreCase) || idx < 0) {
931 settings.GenerateDebugInfo = true;
932 return ParseResult.Success;
935 if (value.Length > 0) {
936 report.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
938 Error_RequiresArgument (option);
941 return ParseResult.Error;
944 settings.GenerateDebugInfo = true;
945 return ParseResult.Success;
949 settings.Checked = true;
950 return ParseResult.Success;
953 settings.Checked = false;
954 return ParseResult.Success;
958 settings.VerifyClsCompliance = true;
959 return ParseResult.Success;
962 settings.VerifyClsCompliance = false;
963 return ParseResult.Success;
967 settings.Unsafe = true;
968 return ParseResult.Success;
971 settings.Unsafe = false;
972 return ParseResult.Success;
975 case "/warnaserror+":
976 if (value.Length == 0) {
977 settings.WarningsAreErrors = true;
978 parser_settings.WarningsAreErrors = true;
980 if (!ProcessWarningsList (value, settings.AddWarningAsError))
981 return ParseResult.Error;
983 return ParseResult.Success;
985 case "/warnaserror-":
986 if (value.Length == 0) {
987 settings.WarningsAreErrors = false;
989 if (!ProcessWarningsList (value, settings.AddWarningOnly))
990 return ParseResult.Error;
992 return ParseResult.Success;
996 if (value.Length == 0) {
997 Error_RequiresArgument (option);
998 return ParseResult.Error;
1001 SetWarningLevel (value, settings);
1002 return ParseResult.Success;
1005 if (value.Length == 0) {
1006 Error_RequiresArgument (option);
1007 return ParseResult.Error;
1010 if (!ProcessWarningsList (value, settings.SetIgnoreWarning))
1011 return ParseResult.Error;
1013 return ParseResult.Success;
1016 settings.LoadDefaultReferences = false;
1017 return ParseResult.Success;
1020 if (value.Length == 0) {
1021 Error_RequiresArgument (option);
1022 return ParseResult.Error;
1025 switch (value.ToLowerInvariant ()) {
1027 settings.Platform = Platform.Arm;
1030 settings.Platform = Platform.AnyCPU;
1033 settings.Platform = Platform.X86;
1036 settings.Platform = Platform.X64;
1039 settings.Platform = Platform.IA64;
1041 case "anycpu32bitpreferred":
1042 settings.Platform = Platform.AnyCPU32Preferred;
1045 report.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
1047 return ParseResult.Error;
1050 return ParseResult.Success;
1053 if (value.Length == 0) {
1054 Error_RequiresArgument (option);
1055 return ParseResult.Error;
1058 settings.SdkVersion = value;
1059 return ParseResult.Success;
1061 // We just ignore this.
1062 case "/errorreport":
1064 if (value.Length == 0) {
1065 Error_RequiresArgument (option);
1066 return ParseResult.Error;
1069 return ParseResult.Success;
1071 case "/helpinternal":
1073 return ParseResult.Stop;
1078 return ParseResult.Stop;
1082 if (value.Length == 0) {
1083 Error_RequiresArgument (option);
1084 return ParseResult.Error;
1086 settings.MainClass = value;
1087 return ParseResult.Success;
1091 settings.StdLib = false;
1092 return ParseResult.Success;
1095 settings.StdLib = true;
1096 return ParseResult.Success;
1099 settings.ShowFullPaths = true;
1100 return ParseResult.Success;
1103 if (value.Length == 0) {
1104 Error_RequiresFileName (option);
1105 return ParseResult.Error;
1108 settings.StrongNameKeyFile = value;
1109 return ParseResult.Success;
1111 case "/keycontainer":
1112 if (value.Length == 0) {
1113 Error_RequiresArgument (option);
1114 return ParseResult.Error;
1117 settings.StrongNameKeyContainer = value;
1118 return ParseResult.Success;
1122 settings.StrongNameDelaySign = true;
1123 return ParseResult.Success;
1126 settings.StrongNameDelaySign = false;
1127 return ParseResult.Success;
1129 case "/langversion":
1130 if (value.Length == 0) {
1131 Error_RequiresArgument (option);
1132 return ParseResult.Error;
1135 switch (value.ToLowerInvariant ()) {
1137 settings.Version = LanguageVersion.ISO_1;
1138 return ParseResult.Success;
1140 settings.Version = LanguageVersion.Default;
1141 return ParseResult.Success;
1143 settings.Version = LanguageVersion.ISO_2;
1144 return ParseResult.Success;
1146 settings.Version = LanguageVersion.V_3;
1147 return ParseResult.Success;
1149 settings.Version = LanguageVersion.V_4;
1150 return ParseResult.Success;
1152 settings.Version = LanguageVersion.V_5;
1153 return ParseResult.Success;
1155 settings.Version = LanguageVersion.Future;
1156 return ParseResult.Success;
1159 report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3', `4', `5', `Default' or `Future'", value);
1160 return ParseResult.Error;
1163 if (value.Length == 0) {
1164 Error_RequiresArgument (option);
1165 return ParseResult.Error;
1170 settings.Encoding = Encoding.UTF8;
1173 settings.Encoding = Encoding.Default;
1177 settings.Encoding = Encoding.GetEncoding (int.Parse (value));
1179 report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1181 return ParseResult.Error;
1183 return ParseResult.Success;
1186 return ParseResult.UnknownOption;
1191 // Currently handles the Unix-like command line options, but will be
1192 // deprecated in favor of the CSCParseOption, which will also handle the
1193 // options that start with a dash in the future.
1195 ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings)
1199 settings.VerboseParserFlag++;
1200 return ParseResult.Success;
1204 return ParseResult.Stop;
1207 settings.ParseOnly = true;
1208 return ParseResult.Success;
1210 case "--main": case "-m":
1211 report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1212 if ((i + 1) >= args.Length){
1213 Error_RequiresArgument (arg);
1214 return ParseResult.Error;
1216 settings.MainClass = args[++i];
1217 return ParseResult.Success;
1220 report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1221 settings.Unsafe = true;
1222 return ParseResult.Success;
1224 case "/?": case "/h": case "/help":
1227 return ParseResult.Stop;
1230 report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1231 if ((i + 1) >= args.Length){
1232 Error_RequiresArgument (arg);
1233 return ParseResult.Error;
1236 settings.AddConditionalSymbol (args [++i]);
1237 return ParseResult.Success;
1240 settings.TokenizeOnly = true;
1241 return ParseResult.Success;
1245 report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1246 if ((i + 1) >= args.Length){
1247 Error_RequiresArgument (arg);
1248 return ParseResult.Error;
1250 settings.OutputFile = args[++i];
1251 return ParseResult.Success;
1254 report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1255 settings.Checked = true;
1256 return ParseResult.Success;
1258 case "--stacktrace":
1259 settings.Stacktrace = true;
1260 return ParseResult.Success;
1262 case "--linkresource":
1264 report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1265 if ((i + 1) >= args.Length){
1266 Error_RequiresArgument (arg);
1267 return ParseResult.Error;
1270 AddResource (new AssemblyResource (args[++i], args[i]), settings);
1271 return ParseResult.Success;
1275 report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1276 if ((i + 1) >= args.Length){
1277 Error_RequiresArgument (arg);
1278 return ParseResult.Error;
1281 AddResource (new AssemblyResource (args[++i], args[i], true), settings);
1282 return ParseResult.Success;
1285 report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1286 if ((i + 1) >= args.Length){
1287 Error_RequiresArgument (arg);
1288 return ParseResult.Error;
1291 string type = args [++i];
1294 settings.Target = Target.Library;
1295 settings.TargetExt = ".dll";
1299 settings.Target = Target.Exe;
1303 settings.Target = Target.WinExe;
1307 settings.Target = Target.Module;
1308 settings.TargetExt = ".dll";
1311 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1314 return ParseResult.Success;
1317 report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1318 if ((i + 1) >= args.Length){
1319 Error_RequiresArgument (arg);
1320 return ParseResult.Error;
1323 string val = args [++i];
1324 int idx = val.IndexOf ('=');
1326 string alias = val.Substring (0, idx);
1327 string assembly = val.Substring (idx + 1);
1328 AddAssemblyReference (alias, assembly, settings);
1329 return ParseResult.Success;
1332 settings.AssemblyReferences.Add (val);
1333 return ParseResult.Success;
1336 report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1337 if ((i + 1) >= args.Length){
1338 Error_RequiresArgument (arg);
1339 return ParseResult.Error;
1341 settings.ReferencesLookupPaths.Add (args [++i]);
1342 return ParseResult.Success;
1345 settings.EnhancedWarnings = true;
1346 return ParseResult.Success;
1349 report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1350 settings.StdLib = false;
1351 return ParseResult.Success;
1354 report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1355 if ((i + 1) >= args.Length){
1356 Error_RequiresArgument (arg);
1357 return ParseResult.Error;
1362 warn = int.Parse (args [++i]);
1365 Environment.Exit (1);
1367 settings.SetIgnoreWarning (warn);
1368 return ParseResult.Success;
1371 report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1372 if ((i + 1) >= args.Length){
1373 Error_RequiresArgument (arg);
1374 return ParseResult.Error;
1377 SetWarningLevel (args [++i], settings);
1378 return ParseResult.Success;
1381 if ((i + 1) >= args.Length){
1382 Error_RequiresArgument (arg);
1383 return ParseResult.Error;
1387 settings.DebugFlags = int.Parse (args [++i]);
1389 Error_RequiresArgument (arg);
1390 return ParseResult.Error;
1393 return ParseResult.Success;
1397 return ParseResult.Stop;
1400 report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1401 if ((i + 1) >= args.Length){
1402 Error_RequiresArgument (arg);
1403 return ParseResult.Error;
1405 ProcessSourceFiles (args [++i], true, settings.SourceFiles);
1406 return ParseResult.Success;
1409 settings.Timestamps = true;
1410 return ParseResult.Success;
1412 case "--debug": case "-g":
1413 report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1414 settings.GenerateDebugInfo = true;
1415 return ParseResult.Success;
1418 report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1419 settings.LoadDefaultReferences = false;
1420 return ParseResult.Success;
1422 case "--metadata-only":
1423 settings.WriteMetadataOnly = true;
1424 return ParseResult.Success;
1426 case "--break-on-ice":
1427 settings.BreakOnInternalError = true;
1428 return ParseResult.Success;
1431 if (arg.StartsWith ("--fatal", StringComparison.Ordinal)){
1433 if (arg.StartsWith ("--fatal=", StringComparison.Ordinal))
1434 int.TryParse (arg.Substring (8), out fatal);
1436 settings.FatalCounter = fatal;
1437 return ParseResult.Success;
1439 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
1440 string version = arg.Substring (10);
1445 settings.StdLibRuntimeVersion = RuntimeVersion.v1;
1449 settings.StdLibRuntimeVersion = RuntimeVersion.v2;
1453 settings.StdLibRuntimeVersion = RuntimeVersion.v4;
1456 return ParseResult.Success;
1459 return ParseResult.UnknownOption;
1463 void SetWarningLevel (string s, CompilerSettings settings)
1468 level = int.Parse (s);
1471 if (level < 0 || level > 4) {
1472 report.Error (1900, "Warning level must be in the range 0-4");
1475 settings.WarningLevel = level;
1479 // Given a path specification, splits the path from the file/pattern
1481 static void SplitPathAndPattern (string spec, out string path, out string pattern)
1483 int p = spec.LastIndexOf ('/');
1486 // Windows does not like /file.cs, switch that to:
1491 pattern = spec.Substring (1);
1493 path = spec.Substring (0, p);
1494 pattern = spec.Substring (p + 1);
1499 p = spec.LastIndexOf ('\\');
1501 path = spec.Substring (0, p);
1502 pattern = spec.Substring (p + 1);
1513 "Mono C# compiler, Copyright 2001-2011 Novell, Inc., Copyright 2011-2012 Xamarin, Inc\n" +
1514 "mcs [options] source-files\n" +
1515 " --about About the Mono C# compiler\n" +
1516 " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
1517 " -checked[+|-] Sets default aritmetic overflow context\n" +
1518 " -clscheck[+|-] Disables CLS Compliance verifications\n" +
1519 " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" +
1520 " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" +
1521 " -debug[+|-], -g Generate debugging information\n" +
1522 " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
1523 " -doc:FILE Process documentation comments to XML file\n" +
1524 " -fullpaths Any issued error or warning uses absolute file path\n" +
1525 " -help Lists all compiler options (short: -?)\n" +
1526 " -keycontainer:NAME The key pair container used to sign the output assembly\n" +
1527 " -keyfile:FILE The key file used to strongname the ouput assembly\n" +
1528 " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Future\n" +
1529 " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
1530 " -main:CLASS Specifies the class with the Main method (short: -m)\n" +
1531 " -noconfig Disables implicitly referenced assemblies\n" +
1532 " -nostdlib[+|-] Does not reference mscorlib.dll library\n" +
1533 " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" +
1534 " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" +
1535 " -out:FILE Specifies output assembly name\n" +
1536 " -pkg:P1[,Pn] References packages P1..Pn\n" +
1537 " -platform:ARCH Specifies the target platform of the output assembly\n" +
1538 " ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
1539 " x86, x64 or itanium. The default is anycpu.\n" +
1540 " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
1541 " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
1542 " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
1543 " -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
1544 " VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
1545 " -target:KIND Specifies the format of the output assembly (short: -t)\n" +
1546 " KIND can be one of: exe, winexe, library, module\n" +
1547 " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +
1548 " -warnaserror[+|-] Treats all warnings as errors\n" +
1549 " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1550 " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" +
1551 " -helpinternal Shows internal and advanced compiler options\n" +
1554 " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1555 " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" +
1556 " -win32res:FILE Specifies Win32 resource file (.res)\n" +
1557 " -win32icon:FILE Use this icon for the output\n" +
1558 " @file Read response file for more options\n\n" +
1559 "Options can be of the form -option or /option");
1564 string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString ();
1565 output.WriteLine ("Mono C# compiler version {0}", version);
1569 public class RootContext
1572 // Contains the parsed tree
1574 static ModuleContainer root;
1576 static public ModuleContainer ToplevelTypes {
1577 get { return root; }
1578 set { root = value; }