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