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