[amd64] Save missing register
[mono.git] / mcs / mcs / settings.cs
1 //
2 // settings.cs: All compiler settings
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //            Ravi Pratap  (ravi@ximian.com)
6 //            Marek Safar  (marek.safar@gmail.com)
7 //
8 //
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 //
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
13 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
14 //
15
16 using System.Collections.Generic;
17 using System.IO;
18 using System.Text;
19 using System.Globalization;
20 using System;
21
22 namespace Mono.CSharp {
23
24         public enum LanguageVersion
25         {
26                 ISO_1 = 1,
27                 ISO_2 = 2,
28                 V_3 = 3,
29                 V_4 = 4,
30                 V_5 = 5,
31                 V_6 = 6,
32                 V_7 = 7,
33                 Experimental = 100,
34
35                 Default = V_7,
36         }
37
38         public enum RuntimeVersion
39         {
40                 v1,
41                 v2,
42                 v4
43         }
44
45         public enum Target
46         {
47                 Library, Exe, Module, WinExe
48         }
49
50         public enum Platform
51         {
52                 AnyCPU,
53                 AnyCPU32Preferred,
54                 Arm,
55                 X86,
56                 X64,
57                 IA64
58         }
59
60         public class CompilerSettings
61         {
62                 public Target Target;
63                 public Platform Platform;
64                 public string TargetExt;
65                 public bool VerifyClsCompliance;
66                 public bool Optimize;
67                 public LanguageVersion Version;
68                 public bool EnhancedWarnings;
69                 public bool LoadDefaultReferences;
70                 public string SdkVersion;
71
72                 public string StrongNameKeyFile;
73                 public string StrongNameKeyContainer;
74                 public bool StrongNameDelaySign;
75
76                 public int TabSize;
77
78                 public bool WarningsAreErrors;
79                 public int WarningLevel;
80
81                 //
82                 // Assemblies references to be loaded
83                 //
84                 public List<string> AssemblyReferences;
85
86                 // 
87                 // External aliases for assemblies
88                 //
89                 public List<Tuple<string, string>> AssemblyReferencesAliases;
90
91                 public List<KeyValuePair<string, string>> PathMap;
92
93                 //
94                 // Modules to be embedded
95                 //
96                 public List<string> Modules;
97
98                 //
99                 // Lookup paths for referenced assemblies
100                 //
101                 public List<string> ReferencesLookupPaths;
102
103                 //
104                 // Encoding.
105                 //
106                 public Encoding Encoding;
107
108                 //
109                 // If set, enable XML documentation generation
110                 //
111                 public string DocumentationFile;
112
113                 public string MainClass;
114
115                 //
116                 // Output file
117                 //
118                 public string OutputFile;
119
120                 // 
121                 // The default compiler checked state
122                 //
123                 public bool Checked;
124
125                 //
126                 // If true, the compiler is operating in statement mode,
127                 // this currently turns local variable declaration into
128                 // static variables of a class
129                 //
130                 public bool StatementMode;      // TODO: SUPER UGLY
131                 
132                 //
133                 // Whether to allow Unsafe code
134                 //
135                 public bool Unsafe;
136
137                 public string Win32ResourceFile;
138                 public string Win32IconFile;
139
140                 //
141                 // A list of resource files for embedding
142                 //
143                 public List<AssemblyResource> Resources;
144
145                 public bool GenerateDebugInfo;
146
147                 #region Compiler debug flags only
148                 public bool ParseOnly, TokenizeOnly, Timestamps;
149                 public int DebugFlags;
150                 public int VerboseParserFlag;
151                 public int FatalCounter;
152                 public bool Stacktrace;
153                 public bool BreakOnInternalError;
154                 #endregion
155
156                 public List<string> GetResourceStrings;
157
158                 public bool ShowFullPaths;
159
160                 //
161                 // Whether we are being linked against the standard libraries.
162                 // This is only used to tell whether `System.Object' should
163                 // have a base class or not.
164                 //
165                 public bool StdLib;
166
167                 public RuntimeVersion StdLibRuntimeVersion;
168
169                 public string RuntimeMetadataVersion;
170
171                 public bool WriteMetadataOnly;
172
173                 readonly List<string> conditional_symbols;
174
175                 readonly List<SourceFile> source_files;
176
177                 List<int> warnings_as_error;
178                 List<int> warnings_only;
179                 HashSet<int> warning_ignore_table;
180
181                 public CompilerSettings ()
182                 {
183                         StdLib = true;
184                         Target = Target.Exe;
185                         TargetExt = ".exe";
186                         Platform = Platform.AnyCPU;
187                         Version = LanguageVersion.Default;
188                         VerifyClsCompliance = true;
189                         Encoding = Encoding.UTF8;
190                         LoadDefaultReferences = true;
191                         StdLibRuntimeVersion = RuntimeVersion.v4;
192                         WarningLevel = 4;
193
194                         // Default to 1 or mdb files would be platform speficic
195                         TabSize = 1;
196
197                         AssemblyReferences = new List<string> ();
198                         AssemblyReferencesAliases = new List<Tuple<string, string>> ();
199                         Modules = new List<string> ();
200                         ReferencesLookupPaths = new List<string> ();
201
202                         conditional_symbols = new List<string> ();
203                         //
204                         // Add default mcs define
205                         //
206                         conditional_symbols.Add ("__MonoCS__");
207
208                         source_files = new List<SourceFile> ();
209                 }
210
211                 #region Properties
212
213                 public SourceFile FirstSourceFile {
214                         get {
215                                 return source_files.Count > 0 ? source_files [0] : null;
216                         }
217                 }
218
219                 public bool HasKeyFileOrContainer {
220                         get {
221                                 return StrongNameKeyFile != null || StrongNameKeyContainer != null;
222                         }
223                 }
224
225                 public bool NeedsEntryPoint {
226                         get {
227                                 return Target == Target.Exe || Target == Target.WinExe;
228                         }
229                 }
230
231                 public List<SourceFile> SourceFiles {
232                         get {
233                                 return source_files;
234                         }
235                 }
236
237                 #endregion
238
239                 public void AddConditionalSymbol (string symbol)
240                 {
241                         if (!conditional_symbols.Contains (symbol))
242                                 conditional_symbols.Add (symbol);
243                 }
244
245                 public void AddWarningAsError (int id)
246                 {
247                         if (warnings_as_error == null)
248                                 warnings_as_error = new List<int> ();
249
250                         warnings_as_error.Add (id);
251                 }
252
253                 public void AddWarningOnly (int id)
254                 {
255                         if (warnings_only == null)
256                                 warnings_only = new List<int> ();
257
258                         warnings_only.Add (id);
259                 }
260
261                 public bool IsConditionalSymbolDefined (string symbol)
262                 {
263                         return conditional_symbols.Contains (symbol);
264                 }
265
266                 public bool IsWarningAsError (int code)
267                 {
268                         bool is_error = WarningsAreErrors;
269
270                         // Check specific list
271                         if (warnings_as_error != null)
272                                 is_error |= warnings_as_error.Contains (code);
273
274                         // Ignore excluded warnings
275                         if (warnings_only != null && warnings_only.Contains (code))
276                                 is_error = false;
277
278                         return is_error;
279                 }
280
281                 public bool IsWarningEnabled (int code, int level)
282                 {
283                         if (WarningLevel < level)
284                                 return false;
285
286                         return !IsWarningDisabledGlobally (code);
287                 }
288
289                 public bool IsWarningDisabledGlobally (int code)
290                 {
291                         return warning_ignore_table != null && warning_ignore_table.Contains (code);
292                 }
293
294                 public void SetIgnoreWarning (int code)
295                 {
296                         if (warning_ignore_table == null)
297                                 warning_ignore_table = new HashSet<int> ();
298
299                         warning_ignore_table.Add (code);
300                 }
301         }
302
303         public class CommandLineParser
304         {
305                 enum ParseResult
306                 {
307                         Success,
308                         Error,
309                         Stop,
310                         UnknownOption
311                 }
312
313                 static readonly char[] argument_value_separator = { ';', ',' };
314                 static readonly char[] numeric_value_separator = { ';', ',', ' ' };
315
316                 readonly TextWriter output;
317                 readonly Report report;
318                 bool stop_argument;
319
320                 Dictionary<string, int> source_file_index;
321
322                 public event Func<string[], int, int> UnknownOptionHandler;
323
324                 CompilerSettings parser_settings;
325
326                 public CommandLineParser (TextWriter errorOutput)
327                         : this (errorOutput, Console.Out)
328                 {
329                 }
330
331                 public CommandLineParser (TextWriter errorOutput, TextWriter messagesOutput)
332                 {
333                         var rp = new StreamReportPrinter (errorOutput);
334
335                         parser_settings = new CompilerSettings ();
336                         report = new Report (new CompilerContext (parser_settings, rp), rp);
337                         this.output = messagesOutput;
338                 }
339
340                 public bool HasBeenStopped {
341                         get {
342                                 return stop_argument;
343                         }
344                 }
345
346                 void About ()
347                 {
348                         output.WriteLine (
349                                 "The Turbo C# compiler is Copyright 2001-2011, Novell, Inc. 2011-2016 Xamarin Inc, 2016-2017 Microsoft Corp\n\n" +
350                                 "The compiler source code is released under the terms of the \n" +
351                                 "MIT X11 or GNU GPL licenses\n\n" +
352
353                                 "For more information on Mono, visit the project Web site\n" +
354                                 "   http://www.mono-project.com\n\n" +
355
356                                 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
357                 }
358
359                 public CompilerSettings ParseArguments (string[] args)
360                 {
361                         CompilerSettings settings = new CompilerSettings ();
362                         if (!ParseArguments (settings, args))
363                                 return null;
364
365                         return settings;
366                 }
367
368                 public bool ParseArguments (CompilerSettings settings, string[] args)
369                 {
370                         if (settings == null)
371                                 throw new ArgumentNullException ("settings");
372
373                         List<string> response_file_list = null;
374                         bool parsing_options = true;
375                         stop_argument = false;
376                         source_file_index = new Dictionary<string, int> ();
377
378                         for (int i = 0; i < args.Length; i++) {
379                                 string arg = args[i];
380                                 if (arg.Length == 0)
381                                         continue;
382
383                                 if (arg[0] == '@') {
384                                         string[] extra_args;
385                                         string response_file = arg.Substring (1);
386
387                                         if (response_file_list == null)
388                                                 response_file_list = new List<string> ();
389
390                                         if (response_file_list.Contains (response_file)) {
391                                                 report.Error (1515, "Response file `{0}' specified multiple times", response_file);
392                                                 return false;
393                                         }
394
395                                         response_file_list.Add (response_file);
396
397                                         extra_args = LoadArgs (response_file);
398                                         if (extra_args == null) {
399                                                 report.Error (2011, "Unable to open response file: " + response_file);
400                                                 return false;
401                                         }
402
403                                         args = AddArgs (args, extra_args);
404                                         continue;
405                                 }
406
407                                 if (parsing_options) {
408                                         if (arg == "--") {
409                                                 parsing_options = false;
410                                                 continue;
411                                         }
412
413                                         bool dash_opt = arg[0] == '-';
414                                         bool slash_opt = arg[0] == '/';
415                                         if (dash_opt) {
416                                                 switch (ParseOptionUnix (arg, ref args, ref i, settings)) {
417                                                 case ParseResult.Error:
418                                                 case ParseResult.Success:
419                                                         continue;
420                                                 case ParseResult.Stop:
421                                                         stop_argument = true;
422                                                         return true;
423                                                 case ParseResult.UnknownOption:
424                                                         if (UnknownOptionHandler != null) {
425                                                                 var ret = UnknownOptionHandler (args, i);
426                                                                 if (ret != -1) {
427                                                                         i = ret;
428                                                                         continue;
429                                                                 }
430                                                         }
431                                                         break;
432                                                 }
433                                         }
434
435                                         if (dash_opt || slash_opt) {
436                                                 // Try a -CSCOPTION
437                                                 string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg;
438                                                 switch (ParseOption (csc_opt, ref args, settings)) {
439                                                 case ParseResult.Error:
440                                                 case ParseResult.Success:
441                                                         continue;
442                                                 case ParseResult.UnknownOption:
443                                                         // Need to skip `/home/test.cs' however /test.cs is considered as error
444                                                         if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0))
445                                                                 break;
446
447                                                         if (UnknownOptionHandler != null) {
448                                                                 var ret = UnknownOptionHandler (args, i);
449                                                                 if (ret != -1) {
450                                                                         i = ret;
451                                                                         continue;
452                                                                 }
453                                                         }
454
455                                                         Error_WrongOption (arg);
456                                                         return false;
457
458                                                 case ParseResult.Stop:
459                                                         stop_argument = true;
460                                                         return true;
461                                                 }
462                                         }
463                                 }
464
465                                 ProcessSourceFiles (arg, false, settings.SourceFiles);
466                         }
467
468                         return report.Errors == 0;
469                 }
470
471                 void ProcessSourceFiles (string spec, bool recurse, List<SourceFile> sourceFiles)
472                 {
473                         string path, pattern;
474
475                         SplitPathAndPattern (spec, out path, out pattern);
476                         if (pattern.IndexOf ('*') == -1) {
477                                 AddSourceFile (spec, sourceFiles);
478                                 return;
479                         }
480
481                         string[] files;
482                         try {
483                                 files = Directory.GetFiles (path, pattern);
484                         } catch (System.IO.DirectoryNotFoundException) {
485                                 report.Error (2001, "Source file `" + spec + "' could not be found");
486                                 return;
487                         } catch (System.IO.IOException) {
488                                 report.Error (2001, "Source file `" + spec + "' could not be found");
489                                 return;
490                         }
491                         foreach (string f in files) {
492                                 AddSourceFile (f, sourceFiles);
493                         }
494
495                         if (!recurse)
496                                 return;
497
498                         string[] dirs = null;
499
500                         try {
501                                 dirs = Directory.GetDirectories (path);
502                         } catch {
503                         }
504
505                         foreach (string d in dirs) {
506
507                                 // Don't include path in this string, as each
508                                 // directory entry already does
509                                 ProcessSourceFiles (d + "/" + pattern, true, sourceFiles);
510                         }
511                 }
512
513                 static string[] AddArgs (string[] args, string[] extra_args)
514                 {
515                         string[] new_args;
516                         new_args = new string[extra_args.Length + args.Length];
517
518                         // if args contains '--' we have to take that into account
519                         // split args into first half and second half based on '--'
520                         // and add the extra_args before --
521                         int split_position = Array.IndexOf (args, "--");
522                         if (split_position != -1) {
523                                 Array.Copy (args, new_args, split_position);
524                                 extra_args.CopyTo (new_args, split_position);
525                                 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
526                         } else {
527                                 args.CopyTo (new_args, 0);
528                                 extra_args.CopyTo (new_args, args.Length);
529                         }
530
531                         return new_args;
532                 }
533
534                 void AddAssemblyReference (string alias, string assembly, CompilerSettings settings)
535                 {
536                         if (assembly.Length == 0) {
537                                 report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
538                                 return;
539                         }
540
541                         if (!IsExternAliasValid (alias)) {
542                                 report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
543                                 return;
544                         }
545
546                         settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
547                 }
548
549                 void AddResource (AssemblyResource res, CompilerSettings settings)
550                 {
551                         if (settings.Resources == null) {
552                                 settings.Resources = new List<AssemblyResource> ();
553                                 settings.Resources.Add (res);
554                                 return;
555                         }
556
557                         if (settings.Resources.Contains (res)) {
558                                 report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
559                                 return;
560                         }
561
562                         settings.Resources.Add (res);
563                 }
564
565                 void AddSourceFile (string fileName, List<SourceFile> sourceFiles)
566                 {
567                         string path = Path.GetFullPath (fileName);
568
569                         int index;
570                         if (source_file_index.TryGetValue (path, out index)) {
571                                 string other_name = sourceFiles[index - 1].Name;
572                                 if (fileName.Equals (other_name))
573                                         report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name);
574                                 else
575                                         report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path);
576
577                                 return;
578                         }
579
580                         var unit = new SourceFile (fileName, path, sourceFiles.Count + 1);
581                         sourceFiles.Add (unit);
582                         source_file_index.Add (path, unit.Index);
583                 }
584
585                 public bool ProcessWarningsList (string text, Action<int> action)
586                 {
587                         foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
588                                 var warning = wid;
589                                 if (warning.Length == 6 && warning [0] == 'C' && warning [1] == 'S')
590                                         warning = warning.Substring (2);
591
592                                 int id;
593                                 if (!int.TryParse (warning, NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out id)) {
594                                         continue;
595                                 }
596
597                                 action (id);
598                         }
599
600                         return true;
601                 }
602
603                 void Error_RequiresArgument (string option)
604                 {
605                         report.Error (2006, "Missing argument for `{0}' option", option);
606                 }
607
608                 void Error_RequiresFileName (string option)
609                 {
610                         report.Error (2005, "Missing file specification for `{0}' option", option);
611                 }
612
613                 void Error_WrongOption (string option)
614                 {
615                         report.Error (2007, "Unrecognized command-line option: `{0}'", option);
616                 }
617
618                 static bool IsExternAliasValid (string identifier)
619                 {
620                         return Tokenizer.IsValidIdentifier (identifier);
621                 }
622
623                 static string[] LoadArgs (string file)
624                 {
625                         StreamReader f;
626                         var args = new List<string> ();
627                         string line;
628                         try {
629                                 f = new StreamReader (file);
630                         } catch {
631                                 return null;
632                         }
633
634                         StringBuilder sb = new StringBuilder ();
635
636                         while ((line = f.ReadLine ()) != null) {
637                                 int t = line.Length;
638
639                                 for (int i = 0; i < t; i++) {
640                                         char c = line[i];
641
642                                         if (c == '"' || c == '\'') {
643                                                 char end = c;
644
645                                                 for (i++; i < t; i++) {
646                                                         c = line[i];
647
648                                                         if (c == end)
649                                                                 break;
650                                                         sb.Append (c);
651                                                 }
652                                         } else if (c == ' ') {
653                                                 if (sb.Length > 0) {
654                                                         args.Add (sb.ToString ());
655                                                         sb.Length = 0;
656                                                 }
657                                         } else
658                                                 sb.Append (c);
659                                 }
660                                 if (sb.Length > 0) {
661                                         args.Add (sb.ToString ());
662                                         sb.Length = 0;
663                                 }
664                         }
665
666                         return args.ToArray ();
667                 }
668
669                 void OtherFlags ()
670                 {
671                         output.WriteLine (
672                                 "Other flags in the compiler\n" +
673                                 "   --fatal[=COUNT]    Makes error after COUNT fatal\n" +
674                                 "   --lint             Enhanced warnings\n" +
675                                 "   --metadata-only    Produced assembly will contain metadata only\n" +
676                                 "   --parse            Only parses the source file\n" +
677                                 "   --runtime:VERSION  Sets mscorlib.dll metadata version: v1, v2, v4\n" +
678                                 "   --stacktrace       Shows stack trace at error location\n" +
679                                 "   --timestamp        Displays time stamps of various compiler events\n" +
680                                 "   -v                 Verbose parsing (for debugging the parser)\n" +
681                                 "   --mcs-debug X      Sets MCS debugging level to X\n" +
682                                 "   --break-on-ice     Breaks compilation on internal compiler error");
683                 }
684
685                 //
686                 // This parses the -arg and /arg options to the compiler, even if the strings
687                 // in the following text use "/arg" on the strings.
688                 //
689                 ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings)
690                 {
691                         int idx = option.IndexOf (':');
692                         string arg, value;
693
694                         if (idx == -1) {
695                                 arg = option;
696                                 value = "";
697                         } else {
698                                 arg = option.Substring (0, idx);
699
700                                 value = option.Substring (idx + 1);
701                         }
702
703                         switch (arg.ToLowerInvariant ()) {
704                         case "/nologo":
705                                 return ParseResult.Success;
706
707                         case "/t":
708                         case "/target":
709                                 switch (value) {
710                                 case "exe":
711                                         settings.Target = Target.Exe;
712                                         break;
713
714                                 case "winexe":
715                                         settings.Target = Target.WinExe;
716                                         break;
717
718                                 case "library":
719                                         settings.Target = Target.Library;
720                                         settings.TargetExt = ".dll";
721                                         break;
722
723                                 case "module":
724                                         settings.Target = Target.Module;
725                                         settings.TargetExt = ".netmodule";
726                                         break;
727
728                                 default:
729                                         report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
730                                         return ParseResult.Error;
731                                 }
732                                 return ParseResult.Success;
733
734                         case "/out":
735                                 if (value.Length == 0) {
736                                         Error_RequiresFileName (option);
737                                         return ParseResult.Error;
738                                 }
739                                 settings.OutputFile = value;
740                                 return ParseResult.Success;
741
742                         case "/o":
743                         case "/o+":
744                         case "/optimize":
745                         case "/optimize+":
746                                 settings.Optimize = true;
747                                 return ParseResult.Success;
748
749                         case "/o-":
750                         case "/optimize-":
751                                 settings.Optimize = false;
752                                 return ParseResult.Success;
753
754                         // TODO: Not supported by csc 3.5+
755                         case "/incremental":
756                         case "/incremental+":
757                         case "/incremental-":
758                                 // nothing.
759                                 return ParseResult.Success;
760
761                         case "/d":
762                         case "/define": {
763                                         if (value.Length == 0) {
764                                                 Error_RequiresArgument (option);
765                                                 return ParseResult.Error;
766                                         }
767
768                                         foreach (string d in value.Split (argument_value_separator)) {
769                                                 string conditional = d.Trim ();
770                                                 if (!Tokenizer.IsValidIdentifier (conditional)) {
771                                                         report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
772                                                         continue;
773                                                 }
774
775                                                 settings.AddConditionalSymbol (conditional);
776                                         }
777                                         return ParseResult.Success;
778                                 }
779
780                         case "/bugreport":
781                                 //
782                                 // We should collect data, runtime, etc and store in the file specified
783                                 //
784                                 output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
785                                 return ParseResult.Success;
786
787                         case "/pkg": {
788                                         string packages;
789
790                                         if (value.Length == 0) {
791                                                 Error_RequiresArgument (option);
792                                                 return ParseResult.Error;
793                                         }
794                                         packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' }));
795                                         string pkgout = Driver.GetPackageFlags (packages, report);
796
797                                         if (pkgout == null)
798                                                 return ParseResult.Error;
799
800                                         string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' });
801                                         args = AddArgs (args, xargs);
802                                         return ParseResult.Success;
803                                 }
804
805                         case "/linkres":
806                         case "/linkresource":
807                         case "/res":
808                         case "/resource":
809                                 AssemblyResource res = null;
810                                 string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries);
811                                 switch (s.Length) {
812                                 case 1:
813                                         if (s[0].Length == 0)
814                                                 goto default;
815                                         res = new AssemblyResource (s[0], Path.GetFileName (s[0]));
816                                         break;
817                                 case 2:
818                                         res = new AssemblyResource (s[0], s[1]);
819                                         break;
820                                 case 3:
821                                         if (s[2] != "public" && s[2] != "private") {
822                                                 report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]);
823                                                 return ParseResult.Error;
824                                         }
825                                         res = new AssemblyResource (s[0], s[1], s[2] == "private");
826                                         break;
827                                 default:
828                                         report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
829                                         return ParseResult.Error;
830                                 }
831
832                                 if (res != null) {
833                                         res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R';
834                                         AddResource (res, settings);
835                                 }
836
837                                 return ParseResult.Success;
838
839                         case "/recurse":
840                                 if (value.Length == 0) {
841                                         Error_RequiresFileName (option);
842                                         return ParseResult.Error;
843                                 }
844                                 ProcessSourceFiles (value, true, settings.SourceFiles);
845                                 return ParseResult.Success;
846
847                         case "/r":
848                         case "/reference": {
849                                         if (value.Length == 0) {
850                                                 Error_RequiresFileName (option);
851                                                 return ParseResult.Error;
852                                         }
853
854                                         string[] refs = value.Split (argument_value_separator);
855                                         foreach (string r in refs) {
856                                                 if (r.Length == 0)
857                                                         continue;
858
859                                                 string val = r;
860                                                 int index = val.IndexOf ('=');
861                                                 if (index > -1) {
862                                                         string alias = r.Substring (0, index);
863                                                         string assembly = r.Substring (index + 1);
864                                                         AddAssemblyReference (alias, assembly, settings);
865                                                         if (refs.Length != 1) {
866                                                                 report.Error (2034, "Cannot specify multiple aliases using single /reference option");
867                                                                 return ParseResult.Error;
868                                                         }
869                                                 } else {
870                                                         settings.AssemblyReferences.Add (val);
871                                                 }
872                                         }
873                                         return ParseResult.Success;
874                                 }
875                         case "/addmodule": {
876                                         if (value.Length == 0) {
877                                                 Error_RequiresFileName (option);
878                                                 return ParseResult.Error;
879                                         }
880
881                                         string[] refs = value.Split (argument_value_separator);
882                                         foreach (string r in refs) {
883                                                 settings.Modules.Add (r);
884                                         }
885                                         return ParseResult.Success;
886                                 }
887                         case "/win32res": {
888                                         if (value.Length == 0) {
889                                                 Error_RequiresFileName (option);
890                                                 return ParseResult.Error;
891                                         }
892
893                                         if (settings.Win32IconFile != null)
894                                                 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
895
896                                         settings.Win32ResourceFile = value;
897                                         return ParseResult.Success;
898                                 }
899                         case "/win32icon": {
900                                         if (value.Length == 0) {
901                                                 Error_RequiresFileName (option);
902                                                 return ParseResult.Error;
903                                         }
904
905                                         if (settings.Win32ResourceFile != null)
906                                                 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
907
908                                         settings.Win32IconFile = value;
909                                         return ParseResult.Success;
910                                 }
911                         case "/doc": {
912                                         if (value.Length == 0) {
913                                                 Error_RequiresFileName (option);
914                                                 return ParseResult.Error;
915                                         }
916
917                                         settings.DocumentationFile = value;
918                                         return ParseResult.Success;
919                                 }
920                         case "/lib": {
921                                         string[] libdirs;
922
923                                         if (value.Length == 0) {
924                                                 return ParseResult.Error;
925                                         }
926
927                                         libdirs = value.Split (argument_value_separator);
928                                         foreach (string dir in libdirs)
929                                                 settings.ReferencesLookupPaths.Add (dir);
930                                         return ParseResult.Success;
931                                 }
932
933                         case "/debug-":
934                                 settings.GenerateDebugInfo = false;
935                                 return ParseResult.Success;
936
937                         case "/debug":
938                                 if (value.Equals ("full", StringComparison.OrdinalIgnoreCase) || value.Equals ("pdbonly", StringComparison.OrdinalIgnoreCase) || value.Equals ("portable", StringComparison.OrdinalIgnoreCase) || idx < 0) {
939                                         settings.GenerateDebugInfo = true;
940                                         return ParseResult.Success;
941                                 }
942
943                                 if (value.Length > 0) {
944                                         report.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
945                                 } else {
946                                         Error_RequiresArgument (option);
947                                 }
948
949                                 return ParseResult.Error;
950
951                         case "/debug+":
952                                 settings.GenerateDebugInfo = true;
953                                 return ParseResult.Success;
954
955                         case "/checked":
956                         case "/checked+":
957                                 settings.Checked = true;
958                                 return ParseResult.Success;
959
960                         case "/checked-":
961                                 settings.Checked = false;
962                                 return ParseResult.Success;
963
964                         case "/clscheck":
965                         case "/clscheck+":
966                                 settings.VerifyClsCompliance = true;
967                                 return ParseResult.Success;
968
969                         case "/clscheck-":
970                                 settings.VerifyClsCompliance = false;
971                                 return ParseResult.Success;
972
973                         case "/unsafe":
974                         case "/unsafe+":
975                                 settings.Unsafe = true;
976                                 return ParseResult.Success;
977
978                         case "/unsafe-":
979                                 settings.Unsafe = false;
980                                 return ParseResult.Success;
981
982                         case "/warnaserror":
983                         case "/warnaserror+":
984                                 if (value.Length == 0) {
985                                         settings.WarningsAreErrors = true;
986                                         parser_settings.WarningsAreErrors = true;
987                                 } else {
988                                         if (!ProcessWarningsList (value, settings.AddWarningAsError))
989                                                 return ParseResult.Error;
990                                 }
991                                 return ParseResult.Success;
992
993                         case "/warnaserror-":
994                                 if (value.Length == 0) {
995                                         settings.WarningsAreErrors = false;
996                                 } else {
997                                         if (!ProcessWarningsList (value, settings.AddWarningOnly))
998                                                 return ParseResult.Error;
999                                 }
1000                                 return ParseResult.Success;
1001
1002                         case "/warn":
1003                         case "/w":
1004                                 if (value.Length == 0) {
1005                                         Error_RequiresArgument (option);
1006                                         return ParseResult.Error;
1007                                 }
1008
1009                                 SetWarningLevel (value, settings);
1010                                 return ParseResult.Success;
1011
1012                         case "/nowarn":
1013                                 if (value.Length == 0) {
1014                                         Error_RequiresArgument (option);
1015                                         return ParseResult.Error;
1016                                 }
1017
1018                                 if (!ProcessWarningsList (value, settings.SetIgnoreWarning))
1019                                         return ParseResult.Error;
1020
1021                                 return ParseResult.Success;
1022
1023                         case "/noconfig":
1024                                 settings.LoadDefaultReferences = false;
1025                                 return ParseResult.Success;
1026
1027                         case "/platform":
1028                                 if (value.Length == 0) {
1029                                         Error_RequiresArgument (option);
1030                                         return ParseResult.Error;
1031                                 }
1032
1033                                 switch (value.ToLowerInvariant ()) {
1034                                 case "arm":
1035                                         settings.Platform = Platform.Arm;
1036                                         break;
1037                                 case "anycpu":
1038                                         settings.Platform = Platform.AnyCPU;
1039                                         break;
1040                                 case "x86":
1041                                         settings.Platform = Platform.X86;
1042                                         break;
1043                                 case "x64":
1044                                         settings.Platform = Platform.X64;
1045                                         break;
1046                                 case "itanium":
1047                                         settings.Platform = Platform.IA64;
1048                                         break;
1049                                 case "anycpu32bitpreferred":
1050                                         settings.Platform = Platform.AnyCPU32Preferred;
1051                                         break;
1052                                 default:
1053                                         report.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
1054                                                 value);
1055                                         return ParseResult.Error;
1056                                 }
1057
1058                                 return ParseResult.Success;
1059
1060                         case "/sdk":
1061                                 if (value.Length == 0) {
1062                                         Error_RequiresArgument (option);
1063                                         return ParseResult.Error;
1064                                 }
1065
1066                                 settings.SdkVersion = value;
1067                                 return ParseResult.Success;
1068
1069                         // We just ignore this.
1070                         case "/errorreport":
1071                         case "/filealign":
1072                                 if (value.Length == 0) {
1073                                         Error_RequiresArgument (option);
1074                                         return ParseResult.Error;
1075                                 }
1076
1077                                 return ParseResult.Success;
1078
1079                         case "/helpinternal":
1080                                 OtherFlags ();
1081                                 return ParseResult.Stop;
1082
1083                         case "/help":
1084                         case "/?":
1085                                 Usage ();
1086                                 return ParseResult.Stop;
1087
1088                         case "/main":
1089                         case "/m":
1090                                 if (value.Length == 0) {
1091                                         Error_RequiresArgument (option);
1092                                         return ParseResult.Error;
1093                                 }
1094                                 settings.MainClass = value;
1095                                 return ParseResult.Success;
1096
1097                         case "/nostdlib":
1098                         case "/nostdlib+":
1099                                 settings.StdLib = false;
1100                                 return ParseResult.Success;
1101
1102                         case "/nostdlib-":
1103                                 settings.StdLib = true;
1104                                 return ParseResult.Success;
1105
1106                         case "/fullpaths":
1107                                 settings.ShowFullPaths = true;
1108                                 return ParseResult.Success;
1109
1110                         case "/keyfile":
1111                                 if (value.Length == 0) {
1112                                         Error_RequiresFileName (option);
1113                                         return ParseResult.Error;
1114                                 }
1115
1116                                 settings.StrongNameKeyFile = value;
1117                                 return ParseResult.Success;
1118
1119                         case "/keycontainer":
1120                                 if (value.Length == 0) {
1121                                         Error_RequiresArgument (option);
1122                                         return ParseResult.Error;
1123                                 }
1124
1125                                 settings.StrongNameKeyContainer = value;
1126                                 return ParseResult.Success;
1127
1128                         case "/delaysign+":
1129                         case "/delaysign":
1130                                 settings.StrongNameDelaySign = true;
1131                                 return ParseResult.Success;
1132
1133                         case "/delaysign-":
1134                                 settings.StrongNameDelaySign = false;
1135                                 return ParseResult.Success;
1136
1137                         case "/langversion":
1138                                 if (value.Length == 0) {
1139                                         Error_RequiresArgument (option);
1140                                         return ParseResult.Error;
1141                                 }
1142
1143                                 switch (value.ToLowerInvariant ()) {
1144                                 case "iso-1":
1145                                 case "1":
1146                                         settings.Version = LanguageVersion.ISO_1;
1147                                         return ParseResult.Success;
1148                                 case "default":
1149                                         settings.Version = LanguageVersion.Default;
1150                                         return ParseResult.Success;
1151                                 case "2":
1152                                 case "iso-2":
1153                                         settings.Version = LanguageVersion.ISO_2;
1154                                         return ParseResult.Success;
1155                                 case "3":
1156                                         settings.Version = LanguageVersion.V_3;
1157                                         return ParseResult.Success;
1158                                 case "4":
1159                                         settings.Version = LanguageVersion.V_4;
1160                                         return ParseResult.Success;
1161                                 case "5":
1162                                         settings.Version = LanguageVersion.V_5;
1163                                         return ParseResult.Success;
1164                                 case "6":
1165                                         settings.Version = LanguageVersion.V_6;
1166                                         return ParseResult.Success;
1167                                 case "7":
1168                                         settings.Version = LanguageVersion.V_7;
1169                                         return ParseResult.Success;
1170                                 case "experimental":
1171                                         settings.Version = LanguageVersion.Experimental;
1172                                         return ParseResult.Success;
1173                                 }
1174
1175                                 report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 7", value);
1176                                 return ParseResult.Error;
1177
1178                         case "/codepage":
1179                                 if (value.Length == 0) {
1180                                         Error_RequiresArgument (option);
1181                                         return ParseResult.Error;
1182                                 }
1183
1184                                 switch (value) {
1185                                 case "utf8":
1186                                         settings.Encoding = Encoding.UTF8;
1187                                         break;
1188                                 case "reset":
1189                                         settings.Encoding = Encoding.Default;
1190                                         break;
1191                                 default:
1192                                         try {
1193                                                 settings.Encoding = Encoding.GetEncoding (int.Parse (value));
1194                                         } catch {
1195                                                 report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1196                                         }
1197                                         return ParseResult.Error;
1198                                 }
1199                                 return ParseResult.Success;
1200
1201                         case "/runtimemetadataversion":
1202                                 if (value.Length == 0) {
1203                                         Error_RequiresArgument (option);
1204                                         return ParseResult.Error;
1205                                 }
1206
1207                                 settings.RuntimeMetadataVersion = value;
1208                                 return ParseResult.Success;
1209
1210                         case "/pathmap":
1211                                 if (value.Length == 0) {
1212                                         return ParseResult.Success;
1213                                 }
1214
1215                                 foreach (var pair in value.Split (',')) {
1216                                         var kv = pair.Split ('=');
1217                                         if (kv.Length != 2) {
1218                                                 report.Error (8101, "The pathmap option was incorrectly formatted");
1219                                                 return ParseResult.Error;
1220                                         }
1221
1222                                         if (settings.PathMap == null)
1223                                                 settings.PathMap = new List<KeyValuePair<string, string>> ();
1224
1225                                         var key = kv [0].TrimEnd (Path.DirectorySeparatorChar);
1226                                         var path = kv [1].TrimEnd (Path.DirectorySeparatorChar);
1227                                         if (key.Length == 0 || path.Length == 0)
1228                                                 report.Error (8101, "The pathmap option was incorrectly formatted");
1229
1230                                         settings.PathMap.Add (new KeyValuePair<string, string> (key, path));
1231                                 }
1232
1233                                 return ParseResult.Success;
1234
1235                         // csc options that we don't support
1236                         case "/analyzer":
1237                         case "/appconfig":
1238                         case "/baseaddress":
1239                         case "/deterministic":
1240                         case "/deterministic+":
1241                         case "/deterministic-":
1242                         case "/errorendlocation":
1243                         case "/errorlog":
1244                         case "/features":
1245                         case "/highentropyva":
1246                         case "/highentropyva+":
1247                         case "/highentropyva-":
1248                         case "/link":
1249                         case "/moduleassemblyname":
1250                         case "/nowin32manifest":
1251                         case "/pdb":
1252                         case "/preferreduilang":
1253                         case "/publicsign":
1254                         case "/publicsign+":
1255                         case "/publicsign-":
1256                         case "/reportanalyzer":
1257                         case "/ruleset":
1258                         case "/sqmsessionguid":
1259                         case "/subsystemversion":
1260                         case "/utf8output":
1261                         case "/win32manifest":
1262                                 return ParseResult.Success;
1263
1264                         default:
1265                                 return ParseResult.UnknownOption;
1266                         }
1267                 }
1268
1269                 //
1270                 // Currently handles the Unix-like command line options, but will be
1271                 // deprecated in favor of the CSCParseOption, which will also handle the
1272                 // options that start with a dash in the future.
1273                 //
1274                 ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings)
1275                 {
1276                         switch (arg){
1277                         case "-v":
1278                                 settings.VerboseParserFlag++;
1279                                 return ParseResult.Success;
1280
1281                         case "--version":
1282                                 Version ();
1283                                 return ParseResult.Stop;
1284                                 
1285                         case "--parse":
1286                                 settings.ParseOnly = true;
1287                                 return ParseResult.Success;
1288                                 
1289                         case "--main": case "-m":
1290                                 report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1291                                 if ((i + 1) >= args.Length){
1292                                         Error_RequiresArgument (arg);
1293                                         return ParseResult.Error;
1294                                 }
1295                                 settings.MainClass = args[++i];
1296                                 return ParseResult.Success;
1297                                 
1298                         case "--unsafe":
1299                                 report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1300                                 settings.Unsafe = true;
1301                                 return ParseResult.Success;
1302                                 
1303                         case "/?": case "/h": case "/help":
1304                         case "--help":
1305                                 Usage ();
1306                                 return ParseResult.Stop;
1307
1308                         case "--define":
1309                                 report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1310                                 if ((i + 1) >= args.Length){
1311                                         Error_RequiresArgument (arg);
1312                                         return ParseResult.Error;
1313                                 }
1314
1315                                 settings.AddConditionalSymbol (args [++i]);
1316                                 return ParseResult.Success;
1317
1318                         case "--tokenize":
1319                                 settings.TokenizeOnly = true;
1320                                 return ParseResult.Success;
1321                                 
1322                         case "-o": 
1323                         case "--output":
1324                                 report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1325                                 if ((i + 1) >= args.Length){
1326                                         Error_RequiresArgument (arg);
1327                                         return ParseResult.Error;
1328                                 }
1329                                 settings.OutputFile = args[++i];
1330                                 return ParseResult.Success;
1331
1332                         case "--checked":
1333                                 report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1334                                 settings.Checked = true;
1335                                 return ParseResult.Success;
1336                                 
1337                         case "--stacktrace":
1338                                 settings.Stacktrace = true;
1339                                 return ParseResult.Success;
1340                                 
1341                         case "--linkresource":
1342                         case "--linkres":
1343                                 report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1344                                 if ((i + 1) >= args.Length){
1345                                         Error_RequiresArgument (arg);
1346                                         return ParseResult.Error;
1347                                 }
1348
1349                                 AddResource (new AssemblyResource (args[++i], args[i]), settings);
1350                                 return ParseResult.Success;
1351                                 
1352                         case "--resource":
1353                         case "--res":
1354                                 report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1355                                 if ((i + 1) >= args.Length){
1356                                         Error_RequiresArgument (arg);
1357                                         return ParseResult.Error;
1358                                 }
1359
1360                                 AddResource (new AssemblyResource (args[++i], args[i], true), settings);
1361                                 return ParseResult.Success;
1362                                 
1363                         case "--target":
1364                                 report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1365                                 if ((i + 1) >= args.Length){
1366                                         Error_RequiresArgument (arg);
1367                                         return ParseResult.Error;
1368                                 }
1369                                 
1370                                 string type = args [++i];
1371                                 switch (type){
1372                                 case "library":
1373                                         settings.Target = Target.Library;
1374                                         settings.TargetExt = ".dll";
1375                                         break;
1376                                         
1377                                 case "exe":
1378                                         settings.Target = Target.Exe;
1379                                         break;
1380                                         
1381                                 case "winexe":
1382                                         settings.Target = Target.WinExe;
1383                                         break;
1384                                         
1385                                 case "module":
1386                                         settings.Target = Target.Module;
1387                                         settings.TargetExt = ".dll";
1388                                         break;
1389                                 default:
1390                                         report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1391                                         break;
1392                                 }
1393                                 return ParseResult.Success;
1394                                 
1395                         case "-r":
1396                                 report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1397                                 if ((i + 1) >= args.Length){
1398                                         Error_RequiresArgument (arg);
1399                                         return ParseResult.Error;
1400                                 }
1401                                 
1402                                 string val = args [++i];
1403                                 int idx = val.IndexOf ('=');
1404                                 if (idx > -1) {
1405                                         string alias = val.Substring (0, idx);
1406                                         string assembly = val.Substring (idx + 1);
1407                                         AddAssemblyReference (alias, assembly, settings);
1408                                         return ParseResult.Success;
1409                                 }
1410
1411                                 settings.AssemblyReferences.Add (val);
1412                                 return ParseResult.Success;
1413                                 
1414                         case "-L":
1415                                 report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1416                                 if ((i + 1) >= args.Length){
1417                                         Error_RequiresArgument (arg);
1418                                         return ParseResult.Error;
1419                                 }
1420                                 settings.ReferencesLookupPaths.Add (args [++i]);
1421                                 return ParseResult.Success;
1422
1423                         case "--lint":
1424                                 settings.EnhancedWarnings = true;
1425                                 return ParseResult.Success;
1426                                 
1427                         case "--nostdlib":
1428                                 report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1429                                 settings.StdLib = false;
1430                                 return ParseResult.Success;
1431                                 
1432                         case "--nowarn":
1433                                 report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1434                                 if ((i + 1) >= args.Length){
1435                                         Error_RequiresArgument (arg);
1436                                         return ParseResult.Error;
1437                                 }
1438                                 int warn = 0;
1439                                 
1440                                 try {
1441                                         warn = int.Parse (args [++i]);
1442                                 } catch {
1443                                         Usage ();
1444                                         Environment.Exit (1);
1445                                 }
1446                                 settings.SetIgnoreWarning (warn);
1447                                 return ParseResult.Success;
1448
1449                         case "--wlevel":
1450                                 report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1451                                 if ((i + 1) >= args.Length){
1452                                         Error_RequiresArgument (arg);
1453                                         return ParseResult.Error;
1454                                 }
1455
1456                                 SetWarningLevel (args [++i], settings);
1457                                 return ParseResult.Success;
1458
1459                         case "--mcs-debug":
1460                                 if ((i + 1) >= args.Length){
1461                                         Error_RequiresArgument (arg);
1462                                         return ParseResult.Error;
1463                                 }
1464
1465                                 try {
1466                                         settings.DebugFlags = int.Parse (args [++i]);
1467                                 } catch {
1468                                         Error_RequiresArgument (arg);
1469                                         return ParseResult.Error;
1470                                 }
1471
1472                                 return ParseResult.Success;
1473                                 
1474                         case "--about":
1475                                 About ();
1476                                 return ParseResult.Stop;
1477                                 
1478                         case "--recurse":
1479                                 report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1480                                 if ((i + 1) >= args.Length){
1481                                         Error_RequiresArgument (arg);
1482                                         return ParseResult.Error;
1483                                 }
1484                                 ProcessSourceFiles (args [++i], true, settings.SourceFiles);
1485                                 return ParseResult.Success;
1486                                 
1487                         case "--timestamp":
1488                                 settings.Timestamps = true;
1489                                 return ParseResult.Success;
1490
1491                         case "--debug": case "-g":
1492                                 report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1493                                 settings.GenerateDebugInfo = true;
1494                                 return ParseResult.Success;
1495                                 
1496                         case "--noconfig":
1497                                 report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1498                                 settings.LoadDefaultReferences = false;
1499                                 return ParseResult.Success;
1500
1501                         case "--metadata-only":
1502                                 settings.WriteMetadataOnly = true;
1503                                 return ParseResult.Success;
1504
1505                         case "--break-on-ice":
1506                                 settings.BreakOnInternalError = true;
1507                                 return ParseResult.Success;
1508
1509                         default:
1510                                 if (arg.StartsWith ("--fatal", StringComparison.Ordinal)) {
1511                                         int fatal = 1;
1512                                         if (arg.StartsWith ("--fatal=", StringComparison.Ordinal))
1513                                                 int.TryParse (arg.Substring (8), out fatal);
1514
1515                                         settings.FatalCounter = fatal;
1516                                         return ParseResult.Success;
1517                                 }
1518                                 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
1519                                         string version = arg.Substring (10);
1520
1521                                         switch (version) {
1522                                         case "v1":
1523                                         case "V1":
1524                                                 settings.StdLibRuntimeVersion = RuntimeVersion.v1;
1525                                                 break;
1526                                         case "v2":
1527                                         case "V2":
1528                                                 settings.StdLibRuntimeVersion = RuntimeVersion.v2;
1529                                                 break;
1530                                         case "v4":
1531                                         case "V4":
1532                                                 settings.StdLibRuntimeVersion = RuntimeVersion.v4;
1533                                                 break;
1534                                         }
1535                                         return ParseResult.Success;
1536                                 }
1537
1538                                 if (arg.StartsWith ("--getresourcestrings:", StringComparison.Ordinal)) {
1539                                         string file = arg.Substring (21).Trim ();
1540                                         if (file.Length < 1) {
1541                                                 Error_RequiresArgument (arg);
1542                                                 return ParseResult.Error;
1543                                         }
1544
1545                                         if (settings.GetResourceStrings == null)
1546                                                 settings.GetResourceStrings = new List<string> ();
1547
1548                                         settings.GetResourceStrings.Add (file);
1549                                         return ParseResult.Success;
1550                                 }
1551
1552                                 return ParseResult.UnknownOption;
1553                         }
1554                 }
1555
1556                 void SetWarningLevel (string s, CompilerSettings settings)
1557                 {
1558                         int level = -1;
1559
1560                         try {
1561                                 level = int.Parse (s);
1562                         } catch {
1563                         }
1564                         if (level < 0 || level > 4) {
1565                                 report.Error (1900, "Warning level must be in the range 0-4");
1566                                 return;
1567                         }
1568                         settings.WarningLevel = level;
1569                 }
1570
1571                 //
1572                 // Given a path specification, splits the path from the file/pattern
1573                 //
1574                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
1575                 {
1576                         int p = spec.LastIndexOf ('/');
1577                         if (p != -1) {
1578                                 //
1579                                 // Windows does not like /file.cs, switch that to:
1580                                 // "\", "file.cs"
1581                                 //
1582                                 if (p == 0) {
1583                                         path = "\\";
1584                                         pattern = spec.Substring (1);
1585                                 } else {
1586                                         path = spec.Substring (0, p);
1587                                         pattern = spec.Substring (p + 1);
1588                                 }
1589                                 return;
1590                         }
1591
1592                         p = spec.LastIndexOf ('\\');
1593                         if (p != -1) {
1594                                 path = spec.Substring (0, p);
1595                                 pattern = spec.Substring (p + 1);
1596                                 return;
1597                         }
1598
1599                         path = ".";
1600                         pattern = spec;
1601                 }
1602
1603                 void Usage ()
1604                 {
1605                         output.WriteLine (
1606                                 "Turbo C# compiler, Copyright 2001-2011 Novell, Inc., 2011-2016 Xamarin, Inc, 2016-2017 Microsoft Corp\n" +
1607                                 "mcs [options] source-files\n" +
1608                                 "   --about              About the Mono C# compiler\n" +
1609                                 "   -addmodule:M1[,Mn]   Adds the module to the generated assembly\n" +
1610                                 "   -checked[+|-]        Sets default aritmetic overflow context\n" +
1611                                 "   -clscheck[+|-]       Disables CLS Compliance verifications\n" +
1612                                 "   -codepage:ID         Sets code page to the one in ID (number, utf8, reset)\n" +
1613                                 "   -define:S1[;S2]      Defines one or more conditional symbols (short: -d)\n" +
1614                                 "   -debug[+|-], -g      Generate debugging information\n" +
1615                                 "   -delaysign[+|-]      Only insert the public key into the assembly (no signing)\n" +
1616                                 "   -doc:FILE            Process documentation comments to XML file\n" +
1617                                 "   -fullpaths           Any issued error or warning uses absolute file path\n" +
1618                                 "   -help                Lists all compiler options (short: -?)\n" +
1619                                 "   -keycontainer:NAME   The key pair container used to sign the output assembly\n" +
1620                                 "   -keyfile:FILE        The key file used to strongname the ouput assembly\n" +
1621                                 "   -langversion:TEXT    Specifies language version: ISO-1, ISO-2, 3, 4, 5, 6, Default or Experimental\n" +
1622                                 "   -lib:PATH1[,PATHn]   Specifies the location of referenced assemblies\n" +
1623                                 "   -main:CLASS          Specifies the class with the Main method (short: -m)\n" +
1624                                 "   -noconfig            Disables implicitly referenced assemblies\n" +
1625                                 "   -nostdlib[+|-]       Does not reference mscorlib.dll library\n" +
1626                                 "   -nowarn:W1[,Wn]      Suppress one or more compiler warnings\n" +
1627                                 "   -optimize[+|-]       Enables advanced compiler optimizations (short: -o)\n" +
1628                                 "   -out:FILE            Specifies output assembly name\n" +
1629                                 "   -pathmap:K=V[,Kn=Vn] Sets a mapping for source path names used in generated output\n" +
1630                                 "   -pkg:P1[,Pn]         References packages P1..Pn\n" +
1631                                 "   -platform:ARCH       Specifies the target platform of the output assembly\n" +
1632                                 "                        ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
1633                                 "                        x86, x64 or itanium. The default is anycpu.\n" +
1634                                 "   -recurse:SPEC        Recursively compiles files according to SPEC pattern\n" +
1635                                 "   -reference:A1[,An]   Imports metadata from the specified assembly (short: -r)\n" +
1636                                 "   -reference:ALIAS=A   Imports metadata using specified extern alias (short: -r)\n" +
1637                                 "   -sdk:VERSION         Specifies SDK version of referenced assemblies\n" +
1638                                 "                        VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
1639                                 "   -target:KIND         Specifies the format of the output assembly (short: -t)\n" +
1640                                 "                        KIND can be one of: exe, winexe, library, module\n" +
1641                                 "   -unsafe[+|-]         Allows to compile code which uses unsafe keyword\n" +
1642                                 "   -warnaserror[+|-]    Treats all warnings as errors\n" +
1643                                 "   -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1644                                 "   -warn:0-4            Sets warning level, the default is 4 (short -w:)\n" +
1645                                 "   -helpinternal        Shows internal and advanced compiler options\n" +
1646                                 "\n" +
1647                                 "Resources:\n" +
1648                                 "   -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1649                                 "   -resource:FILE[,ID]     Embed FILE as a resource (short: -res)\n" +
1650                                 "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
1651                                 "   -win32icon:FILE         Use this icon for the output\n" +
1652                                                                 "   @file                   Read response file for more options\n\n" +
1653                                 "Options can be of the form -option or /option");
1654                 }
1655
1656                 void Version ()
1657                 {
1658                         string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString ();
1659                         output.WriteLine ("Mono C# compiler version {0}", version);
1660                 }
1661         }
1662
1663         public class RootContext
1664         {
1665                 //
1666                 // Contains the parsed tree
1667                 //
1668                 static ModuleContainer root;
1669
1670                 static public ModuleContainer ToplevelTypes {
1671                         get { return root; }
1672                         set { root = value; }
1673                 }
1674         }
1675 }