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;
151 public bool ShowFullPaths;
154 // Whether we are being linked against the standard libraries.
155 // This is only used to tell whether `System.Object' should
156 // have a base class or not.
160 public RuntimeVersion StdLibRuntimeVersion;
162 readonly List<string> conditional_symbols;
164 readonly List<SourceFile> source_files;
166 List<int> warnings_as_error;
167 List<int> warnings_only;
168 HashSet<int> warning_ignore_table;
170 public CompilerSettings ()
175 Platform = Platform.AnyCPU;
176 Version = LanguageVersion.Default;
177 VerifyClsCompliance = true;
178 Encoding = Encoding.UTF8;
179 LoadDefaultReferences = true;
180 StdLibRuntimeVersion = RuntimeVersion.v4;
183 if (Environment.OSVersion.Platform == PlatformID.Win32NT)
188 AssemblyReferences = new List<string> ();
189 AssemblyReferencesAliases = new List<Tuple<string, string>> ();
190 Modules = new List<string> ();
191 ReferencesLookupPaths = new List<string> ();
193 conditional_symbols = new List<string> ();
195 // Add default mcs define
197 conditional_symbols.Add ("__MonoCS__");
199 source_files = new List<SourceFile> ();
204 public SourceFile FirstSourceFile {
206 return source_files.Count > 0 ? source_files [0] : null;
210 public bool HasKeyFileOrContainer {
212 return StrongNameKeyFile != null || StrongNameKeyContainer != null;
216 public bool NeedsEntryPoint {
218 return Target == Target.Exe || Target == Target.WinExe;
222 public List<SourceFile> SourceFiles {
230 public void AddConditionalSymbol (string symbol)
232 if (!conditional_symbols.Contains (symbol))
233 conditional_symbols.Add (symbol);
236 public void AddWarningAsError (int id)
238 if (warnings_as_error == null)
239 warnings_as_error = new List<int> ();
241 warnings_as_error.Add (id);
244 public void AddWarningOnly (int id)
246 if (warnings_only == null)
247 warnings_only = new List<int> ();
249 warnings_only.Add (id);
252 public bool IsConditionalSymbolDefined (string symbol)
254 return conditional_symbols.Contains (symbol);
257 public bool IsWarningAsError (int code)
259 bool is_error = WarningsAreErrors;
261 // Check specific list
262 if (warnings_as_error != null)
263 is_error |= warnings_as_error.Contains (code);
265 // Ignore excluded warnings
266 if (warnings_only != null && warnings_only.Contains (code))
272 public bool IsWarningEnabled (int code, int level)
274 if (WarningLevel < level)
277 return !IsWarningDisabledGlobally (code);
280 public bool IsWarningDisabledGlobally (int code)
282 return warning_ignore_table != null && warning_ignore_table.Contains (code);
285 public void SetIgnoreWarning (int code)
287 if (warning_ignore_table == null)
288 warning_ignore_table = new HashSet<int> ();
290 warning_ignore_table.Add (code);
294 public class CommandLineParser
304 static readonly char[] argument_value_separator = new char[] { ';', ',' };
305 static readonly char[] numeric_value_separator = new char[] { ';', ',', ' ' };
307 readonly TextWriter output;
308 readonly Report report;
311 Dictionary<string, int> source_file_index;
313 public event Func<string[], int, int> UnknownOptionHandler;
315 CompilerSettings parser_settings;
317 public CommandLineParser (TextWriter errorOutput)
318 : this (errorOutput, Console.Out)
322 public CommandLineParser (TextWriter errorOutput, TextWriter messagesOutput)
324 var rp = new StreamReportPrinter (errorOutput);
326 parser_settings = new CompilerSettings ();
327 report = new Report (new CompilerContext (parser_settings, rp), rp);
328 this.output = messagesOutput;
331 public bool HasBeenStopped {
333 return stop_argument;
340 "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" +
341 "The compiler source code is released under the terms of the \n" +
342 "MIT X11 or GNU GPL licenses\n\n" +
344 "For more information on Mono, visit the project Web site\n" +
345 " http://www.mono-project.com\n\n" +
347 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
350 public CompilerSettings ParseArguments (string[] args)
352 CompilerSettings settings = new CompilerSettings ();
353 List<string> response_file_list = null;
354 bool parsing_options = true;
355 stop_argument = false;
356 source_file_index = new Dictionary<string, int> ();
358 for (int i = 0; i < args.Length; i++) {
359 string arg = args[i];
365 string response_file = arg.Substring (1);
367 if (response_file_list == null)
368 response_file_list = new List<string> ();
370 if (response_file_list.Contains (response_file)) {
371 report.Error (1515, "Response file `{0}' specified multiple times", response_file);
375 response_file_list.Add (response_file);
377 extra_args = LoadArgs (response_file);
378 if (extra_args == null) {
379 report.Error (2011, "Unable to open response file: " + response_file);
383 args = AddArgs (args, extra_args);
387 if (parsing_options) {
389 parsing_options = false;
393 bool dash_opt = arg[0] == '-';
394 bool slash_opt = arg[0] == '/';
396 switch (ParseOptionUnix (arg, ref args, ref i, settings)) {
397 case ParseResult.Error:
398 case ParseResult.Success:
400 case ParseResult.Stop:
401 stop_argument = true;
403 case ParseResult.UnknownOption:
404 if (UnknownOptionHandler != null) {
405 var ret = UnknownOptionHandler (args, i);
415 if (dash_opt || slash_opt) {
417 string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg;
418 switch (ParseOption (csc_opt, ref args, settings)) {
419 case ParseResult.Error:
420 case ParseResult.Success:
422 case ParseResult.UnknownOption:
423 // Need to skip `/home/test.cs' however /test.cs is considered as error
424 if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0))
427 if (UnknownOptionHandler != null) {
428 var ret = UnknownOptionHandler (args, i);
435 Error_WrongOption (arg);
438 case ParseResult.Stop:
439 stop_argument = true;
445 ProcessSourceFiles (arg, false, settings.SourceFiles);
448 if (report.Errors > 0)
454 void ProcessSourceFiles (string spec, bool recurse, List<SourceFile> sourceFiles)
456 string path, pattern;
458 SplitPathAndPattern (spec, out path, out pattern);
459 if (pattern.IndexOf ('*') == -1) {
460 AddSourceFile (spec, sourceFiles);
464 string[] files = null;
466 files = Directory.GetFiles (path, pattern);
467 } catch (System.IO.DirectoryNotFoundException) {
468 report.Error (2001, "Source file `" + spec + "' could not be found");
470 } catch (System.IO.IOException) {
471 report.Error (2001, "Source file `" + spec + "' could not be found");
474 foreach (string f in files) {
475 AddSourceFile (f, sourceFiles);
481 string[] dirs = null;
484 dirs = Directory.GetDirectories (path);
488 foreach (string d in dirs) {
490 // Don't include path in this string, as each
491 // directory entry already does
492 ProcessSourceFiles (d + "/" + pattern, true, sourceFiles);
496 static string[] AddArgs (string[] args, string[] extra_args)
499 new_args = new string[extra_args.Length + args.Length];
501 // if args contains '--' we have to take that into account
502 // split args into first half and second half based on '--'
503 // and add the extra_args before --
504 int split_position = Array.IndexOf (args, "--");
505 if (split_position != -1) {
506 Array.Copy (args, new_args, split_position);
507 extra_args.CopyTo (new_args, split_position);
508 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
510 args.CopyTo (new_args, 0);
511 extra_args.CopyTo (new_args, args.Length);
517 void AddAssemblyReference (string alias, string assembly, CompilerSettings settings)
519 if (assembly.Length == 0) {
520 report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
524 if (!IsExternAliasValid (alias)) {
525 report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
529 settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
532 void AddResource (AssemblyResource res, CompilerSettings settings)
534 if (settings.Resources == null) {
535 settings.Resources = new List<AssemblyResource> ();
536 settings.Resources.Add (res);
540 if (settings.Resources.Contains (res)) {
541 report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
545 settings.Resources.Add (res);
548 void AddSourceFile (string fileName, List<SourceFile> sourceFiles)
550 string path = Path.GetFullPath (fileName);
553 if (source_file_index.TryGetValue (path, out index)) {
554 string other_name = sourceFiles[index - 1].Name;
555 if (fileName.Equals (other_name))
556 report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name);
558 report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path);
563 var unit = new SourceFile (fileName, path, sourceFiles.Count + 1);
564 sourceFiles.Add (unit);
565 source_file_index.Add (path, unit.Index);
568 void AddWarningAsError (string warningId, CompilerSettings settings)
572 id = int.Parse (warningId);
574 report.CheckWarningCode (warningId, Location.Null);
578 if (!report.CheckWarningCode (id, Location.Null))
581 settings.AddWarningAsError (id);
584 void RemoveWarningAsError (string warningId, CompilerSettings settings)
588 id = int.Parse (warningId);
590 report.CheckWarningCode (warningId, Location.Null);
594 if (!report.CheckWarningCode (id, Location.Null))
597 settings.AddWarningOnly (id);
600 void Error_RequiresArgument (string option)
602 report.Error (2006, "Missing argument for `{0}' option", option);
605 void Error_RequiresFileName (string option)
607 report.Error (2005, "Missing file specification for `{0}' option", option);
610 void Error_WrongOption (string option)
612 report.Error (2007, "Unrecognized command-line option: `{0}'", option);
615 static bool IsExternAliasValid (string identifier)
617 if (identifier.Length == 0)
619 if (identifier[0] != '_' && !char.IsLetter (identifier[0]))
622 for (int i = 1; i < identifier.Length; i++) {
623 char c = identifier[i];
624 if (char.IsLetter (c) || char.IsDigit (c))
627 UnicodeCategory category = char.GetUnicodeCategory (c);
628 if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
629 category != UnicodeCategory.SpacingCombiningMark ||
630 category != UnicodeCategory.ConnectorPunctuation)
637 static string[] LoadArgs (string file)
640 var args = new List<string> ();
643 f = new StreamReader (file);
648 StringBuilder sb = new StringBuilder ();
650 while ((line = f.ReadLine ()) != null) {
653 for (int i = 0; i < t; i++) {
656 if (c == '"' || c == '\'') {
659 for (i++; i < t; i++) {
666 } else if (c == ' ') {
668 args.Add (sb.ToString ());
675 args.Add (sb.ToString ());
680 return args.ToArray ();
686 "Other flags in the compiler\n" +
687 " --fatal[=COUNT] Makes errors after COUNT fatal\n" +
688 " --lint Enhanced warnings\n" +
689 " --parse Only parses the source file\n" +
690 " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" +
691 " --stacktrace Shows stack trace at error location\n" +
692 " --timestamp Displays time stamps of various compiler events\n" +
693 " -v Verbose parsing (for debugging the parser)\n" +
694 " --mcs-debug X Sets MCS debugging level to X\n");
698 // This parses the -arg and /arg options to the compiler, even if the strings
699 // in the following text use "/arg" on the strings.
701 ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings)
703 int idx = option.IndexOf (':');
710 arg = option.Substring (0, idx);
712 value = option.Substring (idx + 1);
715 switch (arg.ToLowerInvariant ()) {
717 return ParseResult.Success;
723 settings.Target = Target.Exe;
727 settings.Target = Target.WinExe;
731 settings.Target = Target.Library;
732 settings.TargetExt = ".dll";
736 settings.Target = Target.Module;
737 settings.TargetExt = ".netmodule";
741 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
742 return ParseResult.Error;
744 return ParseResult.Success;
747 if (value.Length == 0) {
748 Error_RequiresFileName (option);
749 return ParseResult.Error;
751 settings.OutputFile = value;
752 return ParseResult.Success;
758 settings.Optimize = true;
759 return ParseResult.Success;
763 settings.Optimize = false;
764 return ParseResult.Success;
766 // TODO: Not supported by csc 3.5+
768 case "/incremental+":
769 case "/incremental-":
771 return ParseResult.Success;
775 if (value.Length == 0) {
776 Error_RequiresArgument (option);
777 return ParseResult.Error;
780 foreach (string d in value.Split (argument_value_separator)) {
781 string conditional = d.Trim ();
782 if (!Tokenizer.IsValidIdentifier (conditional)) {
783 report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
787 settings.AddConditionalSymbol (conditional);
789 return ParseResult.Success;
794 // We should collect data, runtime, etc and store in the file specified
796 output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
797 return ParseResult.Success;
802 if (value.Length == 0) {
803 Error_RequiresArgument (option);
804 return ParseResult.Error;
806 packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' }));
807 string pkgout = Driver.GetPackageFlags (packages, report);
810 return ParseResult.Error;
812 string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' });
813 args = AddArgs (args, xargs);
814 return ParseResult.Success;
818 case "/linkresource":
821 AssemblyResource res = null;
822 string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries);
825 if (s[0].Length == 0)
827 res = new AssemblyResource (s[0], Path.GetFileName (s[0]));
830 res = new AssemblyResource (s[0], s[1]);
833 if (s[2] != "public" && s[2] != "private") {
834 report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]);
835 return ParseResult.Error;
837 res = new AssemblyResource (s[0], s[1], s[2] == "private");
840 report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
841 return ParseResult.Error;
845 res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R';
846 AddResource (res, settings);
849 return ParseResult.Success;
852 if (value.Length == 0) {
853 Error_RequiresFileName (option);
854 return ParseResult.Error;
856 ProcessSourceFiles (value, true, settings.SourceFiles);
857 return ParseResult.Success;
861 if (value.Length == 0) {
862 Error_RequiresFileName (option);
863 return ParseResult.Error;
866 string[] refs = value.Split (argument_value_separator);
867 foreach (string r in refs) {
872 int index = val.IndexOf ('=');
874 string alias = r.Substring (0, index);
875 string assembly = r.Substring (index + 1);
876 AddAssemblyReference (alias, assembly, settings);
877 if (refs.Length != 1) {
878 report.Error (2034, "Cannot specify multiple aliases using single /reference option");
879 return ParseResult.Error;
882 settings.AssemblyReferences.Add (val);
885 return ParseResult.Success;
888 if (value.Length == 0) {
889 Error_RequiresFileName (option);
890 return ParseResult.Error;
893 string[] refs = value.Split (argument_value_separator);
894 foreach (string r in refs) {
895 settings.Modules.Add (r);
897 return ParseResult.Success;
900 if (value.Length == 0) {
901 Error_RequiresFileName (option);
902 return ParseResult.Error;
905 if (settings.Win32IconFile != null)
906 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
908 settings.Win32ResourceFile = value;
909 return ParseResult.Success;
912 if (value.Length == 0) {
913 Error_RequiresFileName (option);
914 return ParseResult.Error;
917 if (settings.Win32ResourceFile != null)
918 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
920 settings.Win32IconFile = value;
921 return ParseResult.Success;
924 if (value.Length == 0) {
925 Error_RequiresFileName (option);
926 return ParseResult.Error;
929 settings.DocumentationFile = value;
930 return ParseResult.Success;
935 if (value.Length == 0) {
936 return ParseResult.Error;
939 libdirs = value.Split (argument_value_separator);
940 foreach (string dir in libdirs)
941 settings.ReferencesLookupPaths.Add (dir);
942 return ParseResult.Success;
946 settings.GenerateDebugInfo = false;
947 return ParseResult.Success;
950 if (value == "full" || value == "pdbonly" || idx < 0) {
951 settings.GenerateDebugInfo = true;
952 return ParseResult.Success;
955 if (value.Length > 0) {
956 report.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
958 Error_RequiresArgument (option);
961 return ParseResult.Error;
964 settings.GenerateDebugInfo = true;
965 return ParseResult.Success;
969 settings.Checked = true;
970 return ParseResult.Success;
973 settings.Checked = false;
974 return ParseResult.Success;
978 settings.VerifyClsCompliance = true;
979 return ParseResult.Success;
982 settings.VerifyClsCompliance = false;
983 return ParseResult.Success;
987 settings.Unsafe = true;
988 return ParseResult.Success;
991 settings.Unsafe = false;
992 return ParseResult.Success;
995 case "/warnaserror+":
996 if (value.Length == 0) {
997 settings.WarningsAreErrors = true;
998 parser_settings.WarningsAreErrors = true;
1000 foreach (string wid in value.Split (numeric_value_separator))
1001 AddWarningAsError (wid, settings);
1003 return ParseResult.Success;
1005 case "/warnaserror-":
1006 if (value.Length == 0) {
1007 settings.WarningsAreErrors = false;
1009 foreach (string wid in value.Split (numeric_value_separator))
1010 RemoveWarningAsError (wid, settings);
1012 return ParseResult.Success;
1015 if (value.Length == 0) {
1016 Error_RequiresArgument (option);
1017 return ParseResult.Error;
1020 SetWarningLevel (value, settings);
1021 return ParseResult.Success;
1024 if (value.Length == 0) {
1025 Error_RequiresArgument (option);
1026 return ParseResult.Error;
1029 var warns = value.Split (numeric_value_separator);
1030 foreach (string wc in warns) {
1032 if (wc.Trim ().Length == 0)
1035 int warn = Int32.Parse (wc);
1037 throw new ArgumentOutOfRangeException ("warn");
1039 settings.SetIgnoreWarning (warn);
1041 report.Error (1904, "`{0}' is not a valid warning number", wc);
1042 return ParseResult.Error;
1045 return ParseResult.Success;
1048 settings.LoadDefaultReferences = false;
1049 return ParseResult.Success;
1052 if (value.Length == 0) {
1053 Error_RequiresArgument (option);
1054 return ParseResult.Error;
1057 switch (value.ToLowerInvariant ()) {
1059 settings.Platform = Platform.Arm;
1062 settings.Platform = Platform.AnyCPU;
1065 settings.Platform = Platform.X86;
1068 settings.Platform = Platform.X64;
1071 settings.Platform = Platform.IA64;
1073 case "anycpu32bitpreferred":
1074 settings.Platform = Platform.AnyCPU32Preferred;
1077 report.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
1079 return ParseResult.Error;
1082 return ParseResult.Success;
1085 if (value.Length == 0) {
1086 Error_RequiresArgument (option);
1087 return ParseResult.Error;
1090 settings.SdkVersion = value;
1091 return ParseResult.Success;
1093 // We just ignore this.
1094 case "/errorreport":
1096 if (value.Length == 0) {
1097 Error_RequiresArgument (option);
1098 return ParseResult.Error;
1101 return ParseResult.Success;
1103 case "/helpinternal":
1105 return ParseResult.Stop;
1110 return ParseResult.Stop;
1114 if (value.Length == 0) {
1115 Error_RequiresArgument (option);
1116 return ParseResult.Error;
1118 settings.MainClass = value;
1119 return ParseResult.Success;
1123 settings.StdLib = false;
1124 return ParseResult.Success;
1127 settings.StdLib = true;
1128 return ParseResult.Success;
1131 settings.ShowFullPaths = true;
1132 return ParseResult.Success;
1135 if (value.Length == 0) {
1136 Error_RequiresFileName (option);
1137 return ParseResult.Error;
1140 settings.StrongNameKeyFile = value;
1141 return ParseResult.Success;
1143 case "/keycontainer":
1144 if (value.Length == 0) {
1145 Error_RequiresArgument (option);
1146 return ParseResult.Error;
1149 settings.StrongNameKeyContainer = value;
1150 return ParseResult.Success;
1154 settings.StrongNameDelaySign = true;
1155 return ParseResult.Success;
1158 settings.StrongNameDelaySign = false;
1159 return ParseResult.Success;
1161 case "/langversion":
1162 if (value.Length == 0) {
1163 Error_RequiresArgument (option);
1164 return ParseResult.Error;
1167 switch (value.ToLowerInvariant ()) {
1169 settings.Version = LanguageVersion.ISO_1;
1170 return ParseResult.Success;
1172 settings.Version = LanguageVersion.Default;
1173 return ParseResult.Success;
1175 settings.Version = LanguageVersion.ISO_2;
1176 return ParseResult.Success;
1178 settings.Version = LanguageVersion.V_3;
1179 return ParseResult.Success;
1181 settings.Version = LanguageVersion.V_4;
1182 return ParseResult.Success;
1184 settings.Version = LanguageVersion.V_5;
1185 return ParseResult.Success;
1187 settings.Version = LanguageVersion.Future;
1188 return ParseResult.Success;
1191 report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3', `4', `5', `Default' or `Future'", value);
1192 return ParseResult.Error;
1195 if (value.Length == 0) {
1196 Error_RequiresArgument (option);
1197 return ParseResult.Error;
1202 settings.Encoding = Encoding.UTF8;
1205 settings.Encoding = Encoding.Default;
1209 settings.Encoding = Encoding.GetEncoding (int.Parse (value));
1211 report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1213 return ParseResult.Error;
1215 return ParseResult.Success;
1218 return ParseResult.UnknownOption;
1223 // Currently handles the Unix-like command line options, but will be
1224 // deprecated in favor of the CSCParseOption, which will also handle the
1225 // options that start with a dash in the future.
1227 ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings)
1231 settings.VerboseParserFlag++;
1232 return ParseResult.Success;
1236 return ParseResult.Stop;
1239 settings.ParseOnly = true;
1240 return ParseResult.Success;
1242 case "--main": case "-m":
1243 report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1244 if ((i + 1) >= args.Length){
1245 Error_RequiresArgument (arg);
1246 return ParseResult.Error;
1248 settings.MainClass = args[++i];
1249 return ParseResult.Success;
1252 report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1253 settings.Unsafe = true;
1254 return ParseResult.Success;
1256 case "/?": case "/h": case "/help":
1259 return ParseResult.Stop;
1262 report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1263 if ((i + 1) >= args.Length){
1264 Error_RequiresArgument (arg);
1265 return ParseResult.Error;
1268 settings.AddConditionalSymbol (args [++i]);
1269 return ParseResult.Success;
1272 settings.TokenizeOnly = true;
1273 return ParseResult.Success;
1277 report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1278 if ((i + 1) >= args.Length){
1279 Error_RequiresArgument (arg);
1280 return ParseResult.Error;
1282 settings.OutputFile = args[++i];
1283 return ParseResult.Success;
1286 report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1287 settings.Checked = true;
1288 return ParseResult.Success;
1290 case "--stacktrace":
1291 settings.Stacktrace = true;
1292 return ParseResult.Success;
1294 case "--linkresource":
1296 report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1297 if ((i + 1) >= args.Length){
1298 Error_RequiresArgument (arg);
1299 return ParseResult.Error;
1302 AddResource (new AssemblyResource (args[++i], args[i]), settings);
1303 return ParseResult.Success;
1307 report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1308 if ((i + 1) >= args.Length){
1309 Error_RequiresArgument (arg);
1310 return ParseResult.Error;
1313 AddResource (new AssemblyResource (args[++i], args[i], true), settings);
1314 return ParseResult.Success;
1317 report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1318 if ((i + 1) >= args.Length){
1319 Error_RequiresArgument (arg);
1320 return ParseResult.Error;
1323 string type = args [++i];
1326 settings.Target = Target.Library;
1327 settings.TargetExt = ".dll";
1331 settings.Target = Target.Exe;
1335 settings.Target = Target.WinExe;
1339 settings.Target = Target.Module;
1340 settings.TargetExt = ".dll";
1343 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1346 return ParseResult.Success;
1349 report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1350 if ((i + 1) >= args.Length){
1351 Error_RequiresArgument (arg);
1352 return ParseResult.Error;
1355 string val = args [++i];
1356 int idx = val.IndexOf ('=');
1358 string alias = val.Substring (0, idx);
1359 string assembly = val.Substring (idx + 1);
1360 AddAssemblyReference (alias, assembly, settings);
1361 return ParseResult.Success;
1364 settings.AssemblyReferences.Add (val);
1365 return ParseResult.Success;
1368 report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1369 if ((i + 1) >= args.Length){
1370 Error_RequiresArgument (arg);
1371 return ParseResult.Error;
1373 settings.ReferencesLookupPaths.Add (args [++i]);
1374 return ParseResult.Success;
1377 settings.EnhancedWarnings = true;
1378 return ParseResult.Success;
1381 report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1382 settings.StdLib = false;
1383 return ParseResult.Success;
1386 report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1387 if ((i + 1) >= args.Length){
1388 Error_RequiresArgument (arg);
1389 return ParseResult.Error;
1394 warn = int.Parse (args [++i]);
1397 Environment.Exit (1);
1399 settings.SetIgnoreWarning (warn);
1400 return ParseResult.Success;
1403 report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1404 if ((i + 1) >= args.Length){
1405 Error_RequiresArgument (arg);
1406 return ParseResult.Error;
1409 SetWarningLevel (args [++i], settings);
1410 return ParseResult.Success;
1413 if ((i + 1) >= args.Length){
1414 Error_RequiresArgument (arg);
1415 return ParseResult.Error;
1419 settings.DebugFlags = int.Parse (args [++i]);
1421 Error_RequiresArgument (arg);
1422 return ParseResult.Error;
1425 return ParseResult.Success;
1429 return ParseResult.Stop;
1432 report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1433 if ((i + 1) >= args.Length){
1434 Error_RequiresArgument (arg);
1435 return ParseResult.Error;
1437 ProcessSourceFiles (args [++i], true, settings.SourceFiles);
1438 return ParseResult.Success;
1441 settings.Timestamps = true;
1442 return ParseResult.Success;
1444 case "--debug": case "-g":
1445 report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1446 settings.GenerateDebugInfo = true;
1447 return ParseResult.Success;
1450 report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1451 settings.LoadDefaultReferences = false;
1452 return ParseResult.Success;
1455 if (arg.StartsWith ("--fatal", StringComparison.Ordinal)){
1457 if (arg.StartsWith ("--fatal=", StringComparison.Ordinal))
1458 int.TryParse (arg.Substring (8), out fatal);
1460 settings.FatalCounter = fatal;
1461 return ParseResult.Success;
1463 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
1464 string version = arg.Substring (10);
1469 settings.StdLibRuntimeVersion = RuntimeVersion.v1;
1473 settings.StdLibRuntimeVersion = RuntimeVersion.v2;
1477 settings.StdLibRuntimeVersion = RuntimeVersion.v4;
1480 return ParseResult.Success;
1483 return ParseResult.UnknownOption;
1487 void SetWarningLevel (string s, CompilerSettings settings)
1492 level = int.Parse (s);
1495 if (level < 0 || level > 4) {
1496 report.Error (1900, "Warning level must be in the range 0-4");
1499 settings.WarningLevel = level;
1503 // Given a path specification, splits the path from the file/pattern
1505 static void SplitPathAndPattern (string spec, out string path, out string pattern)
1507 int p = spec.LastIndexOf ('/');
1510 // Windows does not like /file.cs, switch that to:
1515 pattern = spec.Substring (1);
1517 path = spec.Substring (0, p);
1518 pattern = spec.Substring (p + 1);
1523 p = spec.LastIndexOf ('\\');
1525 path = spec.Substring (0, p);
1526 pattern = spec.Substring (p + 1);
1537 "Mono C# compiler, Copyright 2001-2011 Novell, Inc., Copyright 2011-2012 Xamarin, Inc\n" +
1538 "mcs [options] source-files\n" +
1539 " --about About the Mono C# compiler\n" +
1540 " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
1541 " -checked[+|-] Sets default aritmetic overflow context\n" +
1542 " -clscheck[+|-] Disables CLS Compliance verifications\n" +
1543 " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" +
1544 " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" +
1545 " -debug[+|-], -g Generate debugging information\n" +
1546 " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
1547 " -doc:FILE Process documentation comments to XML file\n" +
1548 " -fullpaths Any issued error or warning uses absolute file path\n" +
1549 " -help Lists all compiler options (short: -?)\n" +
1550 " -keycontainer:NAME The key pair container used to sign the output assembly\n" +
1551 " -keyfile:FILE The key file used to strongname the ouput assembly\n" +
1552 " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Future\n" +
1553 " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
1554 " -main:CLASS Specifies the class with the Main method (short: -m)\n" +
1555 " -noconfig Disables implicitly referenced assemblies\n" +
1556 " -nostdlib[+|-] Does not reference mscorlib.dll library\n" +
1557 " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" +
1558 " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" +
1559 " -out:FILE Specifies output assembly name\n" +
1560 " -pkg:P1[,Pn] References packages P1..Pn\n" +
1561 " -platform:ARCH Specifies the target platform of the output assembly\n" +
1562 " ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
1563 " x86, x64 or itanium. The default is anycpu.\n" +
1564 " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
1565 " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
1566 " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
1567 " -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
1568 " VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
1569 " -target:KIND Specifies the format of the output assembly (short: -t)\n" +
1570 " KIND can be one of: exe, winexe, library, module\n" +
1571 " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +
1572 " -warnaserror[+|-] Treats all warnings as errors\n" +
1573 " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1574 " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" +
1575 " -helpinternal Shows internal and advanced compiler options\n" +
1578 " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1579 " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" +
1580 " -win32res:FILE Specifies Win32 resource file (.res)\n" +
1581 " -win32icon:FILE Use this icon for the output\n" +
1582 " @file Read response file for more options\n\n" +
1583 "Options can be of the form -option or /option");
1588 string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString ();
1589 output.WriteLine ("Mono C# compiler version {0}", version);
1593 public class RootContext
1596 // Contains the parsed tree
1598 static ModuleContainer root;
1600 static public ModuleContainer ToplevelTypes {
1601 get { return root; }
1602 set { root = value; }