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