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