Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/settings.cs @ 12515

Last change on this file since 12515 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

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