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