2 // settings.cs: All compiler settings
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2004-2008 Novell, Inc
13 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
16 using System
.Collections
.Generic
;
19 using System
.Globalization
;
22 namespace Mono
.CSharp
{
24 public enum LanguageVersion
34 Default
= LanguageVersion
.V_6
,
37 public enum RuntimeVersion
46 Library
, Exe
, Module
, WinExe
59 public class CompilerSettings
62 public Platform Platform
;
63 public string TargetExt
;
64 public bool VerifyClsCompliance
;
66 public LanguageVersion Version
;
67 public bool EnhancedWarnings
;
68 public bool LoadDefaultReferences
;
69 public string SdkVersion
;
71 public string StrongNameKeyFile
;
72 public string StrongNameKeyContainer
;
73 public bool StrongNameDelaySign
;
77 public bool WarningsAreErrors
;
78 public int WarningLevel
;
81 // Assemblies references to be loaded
83 public List
<string> AssemblyReferences
;
86 // External aliases for assemblies
88 public List
<Tuple
<string, string>> AssemblyReferencesAliases
;
91 // Modules to be embedded
93 public List
<string> Modules
;
96 // Lookup paths for referenced assemblies
98 public List
<string> ReferencesLookupPaths
;
103 public Encoding Encoding
;
106 // If set, enable XML documentation generation
108 public string DocumentationFile
;
110 public string MainClass
;
115 public string OutputFile
;
118 // The default compiler checked state
123 // If true, the compiler is operating in statement mode,
124 // this currently turns local variable declaration into
125 // static variables of a class
127 public bool StatementMode
; // TODO: SUPER UGLY
130 // Whether to allow Unsafe code
134 public string Win32ResourceFile
;
135 public string Win32IconFile
;
138 // A list of resource files for embedding
140 public List
<AssemblyResource
> Resources
;
142 public bool GenerateDebugInfo
;
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
;
153 public List
<string> GetResourceStrings
;
155 public bool ShowFullPaths
;
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.
164 public RuntimeVersion StdLibRuntimeVersion
;
166 public string RuntimeMetadataVersion
;
168 public bool WriteMetadataOnly
;
170 readonly List
<string> conditional_symbols
;
172 readonly List
<SourceFile
> source_files
;
174 List
<int> warnings_as_error
;
175 List
<int> warnings_only
;
176 HashSet
<int> warning_ignore_table
;
178 public CompilerSettings ()
183 Platform
= Platform
.AnyCPU
;
184 Version
= LanguageVersion
.Default
;
185 VerifyClsCompliance
= true;
186 Encoding
= Encoding
.UTF8
;
187 LoadDefaultReferences
= true;
188 StdLibRuntimeVersion
= RuntimeVersion
.v4
;
191 // Default to 1 or mdb files would be platform speficic
194 AssemblyReferences
= new List
<string> ();
195 AssemblyReferencesAliases
= new List
<Tuple
<string, string>> ();
196 Modules
= new List
<string> ();
197 ReferencesLookupPaths
= new List
<string> ();
199 conditional_symbols
= new List
<string> ();
201 // Add default mcs define
203 conditional_symbols
.Add ("__MonoCS__");
205 source_files
= new List
<SourceFile
> ();
210 public SourceFile FirstSourceFile
{
212 return source_files
.Count
> 0 ? source_files
[0] : null;
216 public bool HasKeyFileOrContainer
{
218 return StrongNameKeyFile
!= null || StrongNameKeyContainer
!= null;
222 public bool NeedsEntryPoint
{
224 return Target
== Target
.Exe
|| Target
== Target
.WinExe
;
228 public List
<SourceFile
> SourceFiles
{
236 public void AddConditionalSymbol (string symbol
)
238 if (!conditional_symbols
.Contains (symbol
))
239 conditional_symbols
.Add (symbol
);
242 public void AddWarningAsError (int id
)
244 if (warnings_as_error
== null)
245 warnings_as_error
= new List
<int> ();
247 warnings_as_error
.Add (id
);
250 public void AddWarningOnly (int id
)
252 if (warnings_only
== null)
253 warnings_only
= new List
<int> ();
255 warnings_only
.Add (id
);
258 public bool IsConditionalSymbolDefined (string symbol
)
260 return conditional_symbols
.Contains (symbol
);
263 public bool IsWarningAsError (int code
)
265 bool is_error
= WarningsAreErrors
;
267 // Check specific list
268 if (warnings_as_error
!= null)
269 is_error
|= warnings_as_error
.Contains (code
);
271 // Ignore excluded warnings
272 if (warnings_only
!= null && warnings_only
.Contains (code
))
278 public bool IsWarningEnabled (int code
, int level
)
280 if (WarningLevel
< level
)
283 return !IsWarningDisabledGlobally (code
);
286 public bool IsWarningDisabledGlobally (int code
)
288 return warning_ignore_table
!= null && warning_ignore_table
.Contains (code
);
291 public void SetIgnoreWarning (int code
)
293 if (warning_ignore_table
== null)
294 warning_ignore_table
= new HashSet
<int> ();
296 warning_ignore_table
.Add (code
);
300 public class CommandLineParser
310 static readonly char[] argument_value_separator
= { ';', ',' }
;
311 static readonly char[] numeric_value_separator
= { ';', ',', ' ' }
;
313 readonly TextWriter output
;
314 readonly Report report
;
317 Dictionary
<string, int> source_file_index
;
319 public event Func
<string[], int, int> UnknownOptionHandler
;
321 CompilerSettings parser_settings
;
323 public CommandLineParser (TextWriter errorOutput
)
324 : this (errorOutput
, Console
.Out
)
328 public CommandLineParser (TextWriter errorOutput
, TextWriter messagesOutput
)
330 var rp
= new StreamReportPrinter (errorOutput
);
332 parser_settings
= new CompilerSettings ();
333 report
= new Report (new CompilerContext (parser_settings
, rp
), rp
);
334 this.output
= messagesOutput
;
337 public bool HasBeenStopped
{
339 return stop_argument
;
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" +
350 "For more information on Mono, visit the project Web site\n" +
351 " http://www.mono-project.com\n\n" +
353 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
356 public CompilerSettings
ParseArguments (string[] args
)
358 CompilerSettings settings
= new CompilerSettings ();
359 if (!ParseArguments (settings
, args
))
365 public bool ParseArguments (CompilerSettings settings
, string[] args
)
367 if (settings
== null)
368 throw new ArgumentNullException ("settings");
370 List
<string> response_file_list
= null;
371 bool parsing_options
= true;
372 stop_argument
= false;
373 source_file_index
= new Dictionary
<string, int> ();
375 for (int i
= 0; i
< args
.Length
; i
++) {
376 string arg
= args
[i
];
382 string response_file
= arg
.Substring (1);
384 if (response_file_list
== null)
385 response_file_list
= new List
<string> ();
387 if (response_file_list
.Contains (response_file
)) {
388 report
.Error (1515, "Response file `{0}' specified multiple times", response_file
);
392 response_file_list
.Add (response_file
);
394 extra_args
= LoadArgs (response_file
);
395 if (extra_args
== null) {
396 report
.Error (2011, "Unable to open response file: " + response_file
);
400 args
= AddArgs (args
, extra_args
);
404 if (parsing_options
) {
406 parsing_options
= false;
410 bool dash_opt
= arg
[0] == '-';
411 bool slash_opt
= arg
[0] == '/';
413 switch (ParseOptionUnix (arg
, ref args
, ref i
, settings
)) {
414 case ParseResult
.Error
:
415 case ParseResult
.Success
:
417 case ParseResult
.Stop
:
418 stop_argument
= true;
420 case ParseResult
.UnknownOption
:
421 if (UnknownOptionHandler
!= null) {
422 var ret
= UnknownOptionHandler (args
, i
);
432 if (dash_opt
|| slash_opt
) {
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
:
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))
444 if (UnknownOptionHandler
!= null) {
445 var ret
= UnknownOptionHandler (args
, i
);
452 Error_WrongOption (arg
);
455 case ParseResult
.Stop
:
456 stop_argument
= true;
462 ProcessSourceFiles (arg
, false, settings
.SourceFiles
);
465 return report
.Errors
== 0;
468 void ProcessSourceFiles (string spec
, bool recurse
, List
<SourceFile
> sourceFiles
)
470 string path
, pattern
;
472 SplitPathAndPattern (spec
, out path
, out pattern
);
473 if (pattern
.IndexOf ('*') == -1) {
474 AddSourceFile (spec
, sourceFiles
);
480 files
= Directory
.GetFiles (path
, pattern
);
481 } catch (System
.IO
.DirectoryNotFoundException
) {
482 report
.Error (2001, "Source file `" + spec
+ "' could not be found");
484 } catch (System
.IO
.IOException
) {
485 report
.Error (2001, "Source file `" + spec
+ "' could not be found");
488 foreach (string f
in files
) {
489 AddSourceFile (f
, sourceFiles
);
495 string[] dirs
= null;
498 dirs
= Directory
.GetDirectories (path
);
502 foreach (string d
in dirs
) {
504 // Don't include path in this string, as each
505 // directory entry already does
506 ProcessSourceFiles (d
+ "/" + pattern
, true, sourceFiles
);
510 static string[] AddArgs (string[] args
, string[] extra_args
)
513 new_args
= new string[extra_args
.Length
+ args
.Length
];
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
);
524 args
.CopyTo (new_args
, 0);
525 extra_args
.CopyTo (new_args
, args
.Length
);
531 void AddAssemblyReference (string alias, string assembly
, CompilerSettings settings
)
533 if (assembly
.Length
== 0) {
534 report
.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
538 if (!IsExternAliasValid (alias)) {
539 report
.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
543 settings
.AssemblyReferencesAliases
.Add (Tuple
.Create (alias, assembly
));
546 void AddResource (AssemblyResource res
, CompilerSettings settings
)
548 if (settings
.Resources
== null) {
549 settings
.Resources
= new List
<AssemblyResource
> ();
550 settings
.Resources
.Add (res
);
554 if (settings
.Resources
.Contains (res
)) {
555 report
.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res
.Name
);
559 settings
.Resources
.Add (res
);
562 void AddSourceFile (string fileName
, List
<SourceFile
> sourceFiles
)
564 string path
= Path
.GetFullPath (fileName
);
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
);
572 report
.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName
, other_name
, path
);
577 var unit
= new SourceFile (fileName
, path
, sourceFiles
.Count
+ 1);
578 sourceFiles
.Add (unit
);
579 source_file_index
.Add (path
, unit
.Index
);
582 public bool ProcessWarningsList (string text
, Action
<int> action
)
584 foreach (string wid
in text
.Split (numeric_value_separator
, StringSplitOptions
.RemoveEmptyEntries
)) {
586 if (warning
.Length
== 6 && warning
[0] == 'C' && warning
[1] == 'S')
587 warning
= warning
.Substring (2);
590 if (!int.TryParse (warning
, NumberStyles
.AllowLeadingWhite
, CultureInfo
.InvariantCulture
, out id
)) {
600 void Error_RequiresArgument (string option
)
602 report
.Error (2006, "Missing argument for `{0}' option", option
);
605 void Error_RequiresFileName (string option
)
607 report
.Error (2005, "Missing file specification for `{0}' option", option
);
610 void Error_WrongOption (string option
)
612 report
.Error (2007, "Unrecognized command-line option: `{0}'", option
);
615 static bool IsExternAliasValid (string identifier
)
617 return Tokenizer
.IsValidIdentifier (identifier
);
620 static string[] LoadArgs (string file
)
623 var args
= new List
<string> ();
626 f
= new StreamReader (file
);
631 StringBuilder sb
= new StringBuilder ();
633 while ((line
= f
.ReadLine ()) != null) {
636 for (int i
= 0; i
< t
; i
++) {
639 if (c
== '"' || c
== '\'') {
642 for (i
++; i
< t
; i
++) {
649 } else if (c
== ' ') {
651 args
.Add (sb
.ToString ());
658 args
.Add (sb
.ToString ());
663 return args
.ToArray ();
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");
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.
686 ParseResult
ParseOption (string option
, ref string[] args
, CompilerSettings settings
)
688 int idx
= option
.IndexOf (':');
695 arg
= option
.Substring (0, idx
);
697 value = option
.Substring (idx
+ 1);
700 switch (arg
.ToLowerInvariant ()) {
702 return ParseResult
.Success
;
708 settings
.Target
= Target
.Exe
;
712 settings
.Target
= Target
.WinExe
;
716 settings
.Target
= Target
.Library
;
717 settings
.TargetExt
= ".dll";
721 settings
.Target
= Target
.Module
;
722 settings
.TargetExt
= ".netmodule";
726 report
.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
727 return ParseResult
.Error
;
729 return ParseResult
.Success
;
732 if (value.Length
== 0) {
733 Error_RequiresFileName (option
);
734 return ParseResult
.Error
;
736 settings
.OutputFile
= value;
737 return ParseResult
.Success
;
743 settings
.Optimize
= true;
744 return ParseResult
.Success
;
748 settings
.Optimize
= false;
749 return ParseResult
.Success
;
751 // TODO: Not supported by csc 3.5+
753 case "/incremental+":
754 case "/incremental-":
756 return ParseResult
.Success
;
760 if (value.Length
== 0) {
761 Error_RequiresArgument (option
);
762 return ParseResult
.Error
;
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
);
772 settings
.AddConditionalSymbol (conditional
);
774 return ParseResult
.Success
;
779 // We should collect data, runtime, etc and store in the file specified
781 output
.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
782 return ParseResult
.Success
;
787 if (value.Length
== 0) {
788 Error_RequiresArgument (option
);
789 return ParseResult
.Error
;
791 packages
= String
.Join (" ", value.Split (new Char
[] { ';', ',', '\n', '\r' }
));
792 string pkgout
= Driver
.GetPackageFlags (packages
, report
);
795 return ParseResult
.Error
;
797 string[] xargs
= pkgout
.Trim (new Char
[] { ' ', '\n', '\r', '\t' }
).Split (new Char
[] { ' ', '\t' }
);
798 args
= AddArgs (args
, xargs
);
799 return ParseResult
.Success
;
803 case "/linkresource":
806 AssemblyResource res
= null;
807 string[] s
= value.Split (argument_value_separator
, StringSplitOptions
.RemoveEmptyEntries
);
810 if (s
[0].Length
== 0)
812 res
= new AssemblyResource (s
[0], Path
.GetFileName (s
[0]));
815 res
= new AssemblyResource (s
[0], s
[1]);
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
;
822 res
= new AssemblyResource (s
[0], s
[1], s
[2] == "private");
825 report
.Error (-2005, "Wrong number of arguments for option `{0}'", option
);
826 return ParseResult
.Error
;
830 res
.IsEmbeded
= arg
[1] == 'r' || arg
[1] == 'R';
831 AddResource (res
, settings
);
834 return ParseResult
.Success
;
837 if (value.Length
== 0) {
838 Error_RequiresFileName (option
);
839 return ParseResult
.Error
;
841 ProcessSourceFiles (value, true, settings
.SourceFiles
);
842 return ParseResult
.Success
;
846 if (value.Length
== 0) {
847 Error_RequiresFileName (option
);
848 return ParseResult
.Error
;
851 string[] refs
= value.Split (argument_value_separator
);
852 foreach (string r
in refs
) {
857 int index
= val
.IndexOf ('=');
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
;
867 settings
.AssemblyReferences
.Add (val
);
870 return ParseResult
.Success
;
873 if (value.Length
== 0) {
874 Error_RequiresFileName (option
);
875 return ParseResult
.Error
;
878 string[] refs
= value.Split (argument_value_separator
);
879 foreach (string r
in refs
) {
880 settings
.Modules
.Add (r
);
882 return ParseResult
.Success
;
885 if (value.Length
== 0) {
886 Error_RequiresFileName (option
);
887 return ParseResult
.Error
;
890 if (settings
.Win32IconFile
!= null)
891 report
.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
893 settings
.Win32ResourceFile
= value;
894 return ParseResult
.Success
;
897 if (value.Length
== 0) {
898 Error_RequiresFileName (option
);
899 return ParseResult
.Error
;
902 if (settings
.Win32ResourceFile
!= null)
903 report
.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
905 settings
.Win32IconFile
= value;
906 return ParseResult
.Success
;
909 if (value.Length
== 0) {
910 Error_RequiresFileName (option
);
911 return ParseResult
.Error
;
914 settings
.DocumentationFile
= value;
915 return ParseResult
.Success
;
920 if (value.Length
== 0) {
921 return ParseResult
.Error
;
924 libdirs
= value.Split (argument_value_separator
);
925 foreach (string dir
in libdirs
)
926 settings
.ReferencesLookupPaths
.Add (dir
);
927 return ParseResult
.Success
;
931 settings
.GenerateDebugInfo
= false;
932 return ParseResult
.Success
;
935 if (value.Equals ("full", StringComparison
.OrdinalIgnoreCase
) || value.Equals ("pdbonly", StringComparison
.OrdinalIgnoreCase
) || idx
< 0) {
936 settings
.GenerateDebugInfo
= true;
937 return ParseResult
.Success
;
940 if (value.Length
> 0) {
941 report
.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
943 Error_RequiresArgument (option
);
946 return ParseResult
.Error
;
949 settings
.GenerateDebugInfo
= true;
950 return ParseResult
.Success
;
954 settings
.Checked
= true;
955 return ParseResult
.Success
;
958 settings
.Checked
= false;
959 return ParseResult
.Success
;
963 settings
.VerifyClsCompliance
= true;
964 return ParseResult
.Success
;
967 settings
.VerifyClsCompliance
= false;
968 return ParseResult
.Success
;
972 settings
.Unsafe
= true;
973 return ParseResult
.Success
;
976 settings
.Unsafe
= false;
977 return ParseResult
.Success
;
980 case "/warnaserror+":
981 if (value.Length
== 0) {
982 settings
.WarningsAreErrors
= true;
983 parser_settings
.WarningsAreErrors
= true;
985 if (!ProcessWarningsList (value, settings
.AddWarningAsError
))
986 return ParseResult
.Error
;
988 return ParseResult
.Success
;
990 case "/warnaserror-":
991 if (value.Length
== 0) {
992 settings
.WarningsAreErrors
= false;
994 if (!ProcessWarningsList (value, settings
.AddWarningOnly
))
995 return ParseResult
.Error
;
997 return ParseResult
.Success
;
1001 if (value.Length
== 0) {
1002 Error_RequiresArgument (option
);
1003 return ParseResult
.Error
;
1006 SetWarningLevel (value, settings
);
1007 return ParseResult
.Success
;
1010 if (value.Length
== 0) {
1011 Error_RequiresArgument (option
);
1012 return ParseResult
.Error
;
1015 if (!ProcessWarningsList (value, settings
.SetIgnoreWarning
))
1016 return ParseResult
.Error
;
1018 return ParseResult
.Success
;
1021 settings
.LoadDefaultReferences
= false;
1022 return ParseResult
.Success
;
1025 if (value.Length
== 0) {
1026 Error_RequiresArgument (option
);
1027 return ParseResult
.Error
;
1030 switch (value.ToLowerInvariant ()) {
1032 settings
.Platform
= Platform
.Arm
;
1035 settings
.Platform
= Platform
.AnyCPU
;
1038 settings
.Platform
= Platform
.X86
;
1041 settings
.Platform
= Platform
.X64
;
1044 settings
.Platform
= Platform
.IA64
;
1046 case "anycpu32bitpreferred":
1047 settings
.Platform
= Platform
.AnyCPU32Preferred
;
1050 report
.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
1052 return ParseResult
.Error
;
1055 return ParseResult
.Success
;
1058 if (value.Length
== 0) {
1059 Error_RequiresArgument (option
);
1060 return ParseResult
.Error
;
1063 settings
.SdkVersion
= value;
1064 return ParseResult
.Success
;
1066 // We just ignore this.
1067 case "/errorreport":
1069 if (value.Length
== 0) {
1070 Error_RequiresArgument (option
);
1071 return ParseResult
.Error
;
1074 return ParseResult
.Success
;
1076 case "/helpinternal":
1078 return ParseResult
.Stop
;
1083 return ParseResult
.Stop
;
1087 if (value.Length
== 0) {
1088 Error_RequiresArgument (option
);
1089 return ParseResult
.Error
;
1091 settings
.MainClass
= value;
1092 return ParseResult
.Success
;
1096 settings
.StdLib
= false;
1097 return ParseResult
.Success
;
1100 settings
.StdLib
= true;
1101 return ParseResult
.Success
;
1104 settings
.ShowFullPaths
= true;
1105 return ParseResult
.Success
;
1108 if (value.Length
== 0) {
1109 Error_RequiresFileName (option
);
1110 return ParseResult
.Error
;
1113 settings
.StrongNameKeyFile
= value;
1114 return ParseResult
.Success
;
1116 case "/keycontainer":
1117 if (value.Length
== 0) {
1118 Error_RequiresArgument (option
);
1119 return ParseResult
.Error
;
1122 settings
.StrongNameKeyContainer
= value;
1123 return ParseResult
.Success
;
1127 settings
.StrongNameDelaySign
= true;
1128 return ParseResult
.Success
;
1131 settings
.StrongNameDelaySign
= false;
1132 return ParseResult
.Success
;
1134 case "/langversion":
1135 if (value.Length
== 0) {
1136 Error_RequiresArgument (option
);
1137 return ParseResult
.Error
;
1140 switch (value.ToLowerInvariant ()) {
1143 settings
.Version
= LanguageVersion
.ISO_1
;
1144 return ParseResult
.Success
;
1146 settings
.Version
= LanguageVersion
.Default
;
1147 return ParseResult
.Success
;
1150 settings
.Version
= LanguageVersion
.ISO_2
;
1151 return ParseResult
.Success
;
1153 settings
.Version
= LanguageVersion
.V_3
;
1154 return ParseResult
.Success
;
1156 settings
.Version
= LanguageVersion
.V_4
;
1157 return ParseResult
.Success
;
1159 settings
.Version
= LanguageVersion
.V_5
;
1160 return ParseResult
.Success
;
1162 settings
.Version
= LanguageVersion
.V_6
;
1163 return ParseResult
.Success
;
1164 case "experimental":
1165 settings
.Version
= LanguageVersion
.Experimental
;
1166 return ParseResult
.Success
;
1168 report
.Warning (8000, 1, "Language version `future' is no longer supported");
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
;
1176 if (value.Length
== 0) {
1177 Error_RequiresArgument (option
);
1178 return ParseResult
.Error
;
1183 settings
.Encoding
= Encoding
.UTF8
;
1186 settings
.Encoding
= Encoding
.Default
;
1190 settings
.Encoding
= Encoding
.GetEncoding (int.Parse (value));
1192 report
.Error (2016, "Code page `{0}' is invalid or not installed", value);
1194 return ParseResult
.Error
;
1196 return ParseResult
.Success
;
1198 case "/runtimemetadataversion":
1199 if (value.Length
== 0) {
1200 Error_RequiresArgument (option
);
1201 return ParseResult
.Error
;
1204 settings
.RuntimeMetadataVersion
= value;
1205 return ParseResult
.Success
;
1207 // csc options that we don't support
1210 case "/baseaddress":
1211 case "/deterministic":
1212 case "/deterministic+":
1213 case "/deterministic-":
1214 case "/errorendlocation":
1217 case "/highentropyva":
1218 case "/highentropyva+":
1219 case "/highentropyva-":
1221 case "/moduleassemblyname":
1222 case "/nowin32manifest":
1225 case "/preferreduilang":
1227 case "/publicsign+":
1228 case "/publicsign-":
1229 case "/reportanalyzer":
1231 case "/sqmsessionguid":
1232 case "/subsystemversion":
1234 case "/win32manifest":
1235 return ParseResult
.Success
;
1238 return ParseResult
.UnknownOption
;
1243 // Currently handles the Unix-like command line options, but will be
1244 // deprecated in favor of the CSCParseOption, which will also handle the
1245 // options that start with a dash in the future.
1247 ParseResult
ParseOptionUnix (string arg
, ref string[] args
, ref int i
, CompilerSettings settings
)
1251 settings
.VerboseParserFlag
++;
1252 return ParseResult
.Success
;
1256 return ParseResult
.Stop
;
1259 settings
.ParseOnly
= true;
1260 return ParseResult
.Success
;
1262 case "--main": case "-m":
1263 report
.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1264 if ((i
+ 1) >= args
.Length
){
1265 Error_RequiresArgument (arg
);
1266 return ParseResult
.Error
;
1268 settings
.MainClass
= args
[++i
];
1269 return ParseResult
.Success
;
1272 report
.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1273 settings
.Unsafe
= true;
1274 return ParseResult
.Success
;
1276 case "/?": case "/h": case "/help":
1279 return ParseResult
.Stop
;
1282 report
.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1283 if ((i
+ 1) >= args
.Length
){
1284 Error_RequiresArgument (arg
);
1285 return ParseResult
.Error
;
1288 settings
.AddConditionalSymbol (args
[++i
]);
1289 return ParseResult
.Success
;
1292 settings
.TokenizeOnly
= true;
1293 return ParseResult
.Success
;
1297 report
.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1298 if ((i
+ 1) >= args
.Length
){
1299 Error_RequiresArgument (arg
);
1300 return ParseResult
.Error
;
1302 settings
.OutputFile
= args
[++i
];
1303 return ParseResult
.Success
;
1306 report
.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1307 settings
.Checked
= true;
1308 return ParseResult
.Success
;
1310 case "--stacktrace":
1311 settings
.Stacktrace
= true;
1312 return ParseResult
.Success
;
1314 case "--linkresource":
1316 report
.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1317 if ((i
+ 1) >= args
.Length
){
1318 Error_RequiresArgument (arg
);
1319 return ParseResult
.Error
;
1322 AddResource (new AssemblyResource (args
[++i
], args
[i
]), settings
);
1323 return ParseResult
.Success
;
1327 report
.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1328 if ((i
+ 1) >= args
.Length
){
1329 Error_RequiresArgument (arg
);
1330 return ParseResult
.Error
;
1333 AddResource (new AssemblyResource (args
[++i
], args
[i
], true), settings
);
1334 return ParseResult
.Success
;
1337 report
.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1338 if ((i
+ 1) >= args
.Length
){
1339 Error_RequiresArgument (arg
);
1340 return ParseResult
.Error
;
1343 string type
= args
[++i
];
1346 settings
.Target
= Target
.Library
;
1347 settings
.TargetExt
= ".dll";
1351 settings
.Target
= Target
.Exe
;
1355 settings
.Target
= Target
.WinExe
;
1359 settings
.Target
= Target
.Module
;
1360 settings
.TargetExt
= ".dll";
1363 report
.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1366 return ParseResult
.Success
;
1369 report
.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1370 if ((i
+ 1) >= args
.Length
){
1371 Error_RequiresArgument (arg
);
1372 return ParseResult
.Error
;
1375 string val
= args
[++i
];
1376 int idx
= val
.IndexOf ('=');
1378 string alias = val
.Substring (0, idx
);
1379 string assembly
= val
.Substring (idx
+ 1);
1380 AddAssemblyReference (alias, assembly
, settings
);
1381 return ParseResult
.Success
;
1384 settings
.AssemblyReferences
.Add (val
);
1385 return ParseResult
.Success
;
1388 report
.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1389 if ((i
+ 1) >= args
.Length
){
1390 Error_RequiresArgument (arg
);
1391 return ParseResult
.Error
;
1393 settings
.ReferencesLookupPaths
.Add (args
[++i
]);
1394 return ParseResult
.Success
;
1397 settings
.EnhancedWarnings
= true;
1398 return ParseResult
.Success
;
1401 report
.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1402 settings
.StdLib
= false;
1403 return ParseResult
.Success
;
1406 report
.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1407 if ((i
+ 1) >= args
.Length
){
1408 Error_RequiresArgument (arg
);
1409 return ParseResult
.Error
;
1414 warn
= int.Parse (args
[++i
]);
1417 Environment
.Exit (1);
1419 settings
.SetIgnoreWarning (warn
);
1420 return ParseResult
.Success
;
1423 report
.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1424 if ((i
+ 1) >= args
.Length
){
1425 Error_RequiresArgument (arg
);
1426 return ParseResult
.Error
;
1429 SetWarningLevel (args
[++i
], settings
);
1430 return ParseResult
.Success
;
1433 if ((i
+ 1) >= args
.Length
){
1434 Error_RequiresArgument (arg
);
1435 return ParseResult
.Error
;
1439 settings
.DebugFlags
= int.Parse (args
[++i
]);
1441 Error_RequiresArgument (arg
);
1442 return ParseResult
.Error
;
1445 return ParseResult
.Success
;
1449 return ParseResult
.Stop
;
1452 report
.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1453 if ((i
+ 1) >= args
.Length
){
1454 Error_RequiresArgument (arg
);
1455 return ParseResult
.Error
;
1457 ProcessSourceFiles (args
[++i
], true, settings
.SourceFiles
);
1458 return ParseResult
.Success
;
1461 settings
.Timestamps
= true;
1462 return ParseResult
.Success
;
1464 case "--debug": case "-g":
1465 report
.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1466 settings
.GenerateDebugInfo
= true;
1467 return ParseResult
.Success
;
1470 report
.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1471 settings
.LoadDefaultReferences
= false;
1472 return ParseResult
.Success
;
1474 case "--metadata-only":
1475 settings
.WriteMetadataOnly
= true;
1476 return ParseResult
.Success
;
1478 case "--break-on-ice":
1479 settings
.BreakOnInternalError
= true;
1480 return ParseResult
.Success
;
1483 if (arg
.StartsWith ("--fatal", StringComparison
.Ordinal
)) {
1485 if (arg
.StartsWith ("--fatal=", StringComparison
.Ordinal
))
1486 int.TryParse (arg
.Substring (8), out fatal
);
1488 settings
.FatalCounter
= fatal
;
1489 return ParseResult
.Success
;
1491 if (arg
.StartsWith ("--runtime:", StringComparison
.Ordinal
)) {
1492 string version
= arg
.Substring (10);
1497 settings
.StdLibRuntimeVersion
= RuntimeVersion
.v1
;
1501 settings
.StdLibRuntimeVersion
= RuntimeVersion
.v2
;
1505 settings
.StdLibRuntimeVersion
= RuntimeVersion
.v4
;
1508 return ParseResult
.Success
;
1511 if (arg
.StartsWith ("--getresourcestrings:", StringComparison
.Ordinal
)) {
1512 string file
= arg
.Substring (21).Trim ();
1513 if (file
.Length
< 1) {
1514 Error_RequiresArgument (arg
);
1515 return ParseResult
.Error
;
1518 if (settings
.GetResourceStrings
== null)
1519 settings
.GetResourceStrings
= new List
<string> ();
1521 settings
.GetResourceStrings
.Add (file
);
1522 return ParseResult
.Success
;
1525 return ParseResult
.UnknownOption
;
1529 void SetWarningLevel (string s
, CompilerSettings settings
)
1534 level
= int.Parse (s
);
1537 if (level
< 0 || level
> 4) {
1538 report
.Error (1900, "Warning level must be in the range 0-4");
1541 settings
.WarningLevel
= level
;
1545 // Given a path specification, splits the path from the file/pattern
1547 static void SplitPathAndPattern (string spec
, out string path
, out string pattern
)
1549 int p
= spec
.LastIndexOf ('/');
1552 // Windows does not like /file.cs, switch that to:
1557 pattern
= spec
.Substring (1);
1559 path
= spec
.Substring (0, p
);
1560 pattern
= spec
.Substring (p
+ 1);
1565 p
= spec
.LastIndexOf ('\\');
1567 path
= spec
.Substring (0, p
);
1568 pattern
= spec
.Substring (p
+ 1);
1579 "Mono C# compiler, Copyright 2001-2011 Novell, Inc., Copyright 2011-2012 Xamarin, Inc\n" +
1580 "mcs [options] source-files\n" +
1581 " --about About the Mono C# compiler\n" +
1582 " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
1583 " -checked[+|-] Sets default aritmetic overflow context\n" +
1584 " -clscheck[+|-] Disables CLS Compliance verifications\n" +
1585 " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" +
1586 " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" +
1587 " -debug[+|-], -g Generate debugging information\n" +
1588 " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
1589 " -doc:FILE Process documentation comments to XML file\n" +
1590 " -fullpaths Any issued error or warning uses absolute file path\n" +
1591 " -help Lists all compiler options (short: -?)\n" +
1592 " -keycontainer:NAME The key pair container used to sign the output assembly\n" +
1593 " -keyfile:FILE The key file used to strongname the ouput assembly\n" +
1594 " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Experimental\n" +
1595 " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
1596 " -main:CLASS Specifies the class with the Main method (short: -m)\n" +
1597 " -noconfig Disables implicitly referenced assemblies\n" +
1598 " -nostdlib[+|-] Does not reference mscorlib.dll library\n" +
1599 " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" +
1600 " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" +
1601 " -out:FILE Specifies output assembly name\n" +
1602 " -pkg:P1[,Pn] References packages P1..Pn\n" +
1603 " -platform:ARCH Specifies the target platform of the output assembly\n" +
1604 " ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
1605 " x86, x64 or itanium. The default is anycpu.\n" +
1606 " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
1607 " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
1608 " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
1609 " -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
1610 " VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
1611 " -target:KIND Specifies the format of the output assembly (short: -t)\n" +
1612 " KIND can be one of: exe, winexe, library, module\n" +
1613 " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +
1614 " -warnaserror[+|-] Treats all warnings as errors\n" +
1615 " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1616 " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" +
1617 " -helpinternal Shows internal and advanced compiler options\n" +
1620 " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1621 " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" +
1622 " -win32res:FILE Specifies Win32 resource file (.res)\n" +
1623 " -win32icon:FILE Use this icon for the output\n" +
1624 " @file Read response file for more options\n\n" +
1625 "Options can be of the form -option or /option");
1630 string version
= System
.Reflection
.MethodBase
.GetCurrentMethod ().DeclaringType
.Assembly
.GetName ().Version
.ToString ();
1631 output
.WriteLine ("Mono C# compiler version {0}", version
);
1635 public class RootContext
1638 // Contains the parsed tree
1640 static ModuleContainer root
;
1642 static public ModuleContainer ToplevelTypes
{
1643 get { return root; }
1644 set { root = value; }