2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
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
14 using System.Collections.Generic;
17 using System.Globalization;
20 namespace Mono.CSharp {
22 public enum LanguageVersion
30 Default = LanguageVersion.V_4,
33 public enum RuntimeVersion
42 Library, Exe, Module, WinExe
47 AnyCPU, X86, X64, IA64
50 public class CompilerSettings
53 public Platform Platform;
54 public string TargetExt;
55 public bool VerifyClsCompliance;
57 public LanguageVersion Version;
58 public bool EnhancedWarnings;
59 public bool LoadDefaultReferences;
60 public string SdkVersion;
62 public string StrongNameKeyFile;
63 public string StrongNameKeyContainer;
64 public bool StrongNameDelaySign;
67 // Assemblies references to be loaded
69 public List<string> AssemblyReferences;
72 // External aliases for assemblies
74 public List<Tuple<string, string>> AssemblyReferencesAliases;
77 // Modules to be embedded
79 public List<string> Modules;
82 // Lookup paths for referenced assemblies
84 public List<string> ReferencesLookupPaths;
89 public Encoding Encoding;
92 // If set, enable XML documentation generation
94 public Documentation Documentation;
96 public string MainClass;
101 public string OutputFile;
104 // The default compiler checked state
109 // If true, the compiler is operating in statement mode,
110 // this currently turns local variable declaration into
111 // static variables of a class
113 public bool StatementMode; // TODO: SUPER UGLY
116 // Whether to allow Unsafe code
120 public string Win32ResourceFile;
121 public string Win32IconFile;
124 // A list of resource files for embedding
126 public List<AssemblyResource> Resources;
128 public bool GenerateDebugInfo;
130 // Compiler debug flags only
131 public bool ParseOnly, TokenizeOnly, Timestamps;
134 // Whether we are being linked against the standard libraries.
135 // This is only used to tell whether `System.Object' should
136 // have a base class or not.
140 public RuntimeVersion StdLibRuntimeVersion;
142 public CompilerSettings ()
147 Platform = Platform.AnyCPU;
148 Version = LanguageVersion.Default;
149 VerifyClsCompliance = true;
151 Encoding = Encoding.Default;
152 LoadDefaultReferences = true;
153 StdLibRuntimeVersion = RuntimeVersion.v4;
155 AssemblyReferences = new List<string> ();
156 AssemblyReferencesAliases = new List<Tuple<string, string>> ();
157 Modules = new List<string> ();
158 ReferencesLookupPaths = new List<string> ();
161 public bool HasKeyFileOrContainer {
163 return StrongNameKeyFile != null || StrongNameKeyContainer != null;
167 public bool NeedsEntryPoint {
169 return Target == Target.Exe || Target == Target.WinExe;
174 class CommandLineParser
184 static readonly char[] argument_value_separator = new char[] { ';', ',' };
186 readonly Report report;
187 readonly TextWriter output;
189 public event Func<string[], int, int> UnknownOptionHandler;
191 public CommandLineParser (Report report)
192 : this (report, Console.Out)
196 public CommandLineParser (Report report, TextWriter messagesOutput)
198 this.report = report;
199 this.output = messagesOutput;
205 "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" +
206 "The compiler source code is released under the terms of the \n" +
207 "MIT X11 or GNU GPL licenses\n\n" +
209 "For more information on Mono, visit the project Web site\n" +
210 " http://www.mono-project.com\n\n" +
212 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
215 public CompilerSettings ParseArguments (string[] args)
217 CompilerSettings settings = new CompilerSettings ();
218 List<string> response_file_list = null;
219 bool parsing_options = true;
221 for (int i = 0; i < args.Length; i++) {
222 string arg = args[i];
228 string response_file = arg.Substring (1);
230 if (response_file_list == null)
231 response_file_list = new List<string> ();
233 if (response_file_list.Contains (response_file)) {
234 report.Error (1515, "Response file `{0}' specified multiple times", response_file);
238 response_file_list.Add (response_file);
240 extra_args = LoadArgs (response_file);
241 if (extra_args == null) {
242 report.Error (2011, "Unable to open response file: " + response_file);
246 args = AddArgs (args, extra_args);
250 if (parsing_options) {
252 parsing_options = false;
256 bool dash_opt = arg[0] == '-';
257 bool slash_opt = arg[0] == '/';
259 switch (ParseOptionUnix (arg, ref args, ref i, settings)) {
260 case ParseResult.Error:
261 case ParseResult.Success:
263 case ParseResult.Stop:
268 if (dash_opt || slash_opt) {
270 string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg;
271 switch (ParseOption (csc_opt, ref args, settings)) {
272 case ParseResult.Error:
273 case ParseResult.Success:
275 case ParseResult.UnknownOption:
276 if (UnknownOptionHandler != null) {
277 var ret = UnknownOptionHandler (args, i);
284 Error_WrongOption (arg);
287 case ParseResult.Stop:
293 // Need to skip `/home/test.cs' however /test.cs is considered as error
294 if (arg.Length < 2 || arg.IndexOf ('/', 2) == -1) {
295 Error_WrongOption (arg);
301 ProcessSourceFiles (arg, false);
307 void ProcessSourceFiles (string spec, bool recurse)
309 string path, pattern;
311 SplitPathAndPattern (spec, out path, out pattern);
312 if (pattern.IndexOf ('*') == -1) {
313 AddSourceFile (spec);
317 string[] files = null;
319 files = Directory.GetFiles (path, pattern);
320 } catch (System.IO.DirectoryNotFoundException) {
321 report.Error (2001, "Source file `" + spec + "' could not be found");
323 } catch (System.IO.IOException) {
324 report.Error (2001, "Source file `" + spec + "' could not be found");
327 foreach (string f in files) {
334 string[] dirs = null;
337 dirs = Directory.GetDirectories (path);
341 foreach (string d in dirs) {
343 // Don't include path in this string, as each
344 // directory entry already does
345 ProcessSourceFiles (d + "/" + pattern, true);
349 static string[] AddArgs (string[] args, string[] extra_args)
352 new_args = new string[extra_args.Length + args.Length];
354 // if args contains '--' we have to take that into account
355 // split args into first half and second half based on '--'
356 // and add the extra_args before --
357 int split_position = Array.IndexOf (args, "--");
358 if (split_position != -1) {
359 Array.Copy (args, new_args, split_position);
360 extra_args.CopyTo (new_args, split_position);
361 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
363 args.CopyTo (new_args, 0);
364 extra_args.CopyTo (new_args, args.Length);
370 void AddAssemblyReference (string alias, string assembly, CompilerSettings settings)
372 if (assembly.Length == 0) {
373 report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
377 if (!IsExternAliasValid (alias)) {
378 report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
382 settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
385 void AddResource (AssemblyResource res, CompilerSettings settings)
387 if (settings.Resources == null) {
388 settings.Resources = new List<AssemblyResource> ();
389 settings.Resources.Add (res);
393 if (settings.Resources.Contains (res)) {
394 report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
398 settings.Resources.Add (res);
401 void AddSourceFile (string f)
403 Location.AddFile (report, f);
407 void Error_RequiresArgument (string option)
409 report.Error (2006, "Missing argument for `{0}' option", option);
412 void Error_RequiresFileName (string option)
414 report.Error (2005, "Missing file specification for `{0}' option", option);
417 void Error_WrongOption (string option)
419 report.Error (2007, "Unrecognized command-line option: `{0}'", option);
422 static bool IsExternAliasValid (string identifier)
424 if (identifier.Length == 0)
426 if (identifier[0] != '_' && !char.IsLetter (identifier[0]))
429 for (int i = 1; i < identifier.Length; i++) {
430 char c = identifier[i];
431 if (char.IsLetter (c) || char.IsDigit (c))
434 UnicodeCategory category = char.GetUnicodeCategory (c);
435 if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
436 category != UnicodeCategory.SpacingCombiningMark ||
437 category != UnicodeCategory.ConnectorPunctuation)
444 static string[] LoadArgs (string file)
447 var args = new List<string> ();
450 f = new StreamReader (file);
455 StringBuilder sb = new StringBuilder ();
457 while ((line = f.ReadLine ()) != null) {
460 for (int i = 0; i < t; i++) {
463 if (c == '"' || c == '\'') {
466 for (i++; i < t; i++) {
473 } else if (c == ' ') {
475 args.Add (sb.ToString ());
482 args.Add (sb.ToString ());
487 return args.ToArray ();
493 "Other flags in the compiler\n" +
494 " --fatal[=COUNT] Makes errors after COUNT fatal\n" +
495 " --lint Enhanced warnings\n" +
496 " --parse Only parses the source file\n" +
497 " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" +
498 " --stacktrace Shows stack trace at error location\n" +
499 " --timestamp Displays time stamps of various compiler events\n" +
500 " -v Verbose parsing (for debugging the parser)\n" +
501 " --mcs-debug X Sets MCS debugging level to X\n");
505 // This parses the -arg and /arg options to the compiler, even if the strings
506 // in the following text use "/arg" on the strings.
508 ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings)
510 int idx = option.IndexOf (':');
517 arg = option.Substring (0, idx);
519 value = option.Substring (idx + 1);
522 switch (arg.ToLowerInvariant ()) {
524 return ParseResult.Success;
530 settings.Target = Target.Exe;
534 settings.Target = Target.WinExe;
538 settings.Target = Target.Library;
539 settings.TargetExt = ".dll";
543 settings.Target = Target.Module;
544 settings.TargetExt = ".netmodule";
548 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
549 return ParseResult.Error;
551 return ParseResult.Success;
554 if (value.Length == 0) {
555 Error_RequiresFileName (option);
556 return ParseResult.Error;
558 settings.OutputFile = value;
559 return ParseResult.Success;
565 settings.Optimize = true;
566 return ParseResult.Success;
570 settings.Optimize = false;
571 return ParseResult.Success;
573 // TODO: Not supported by csc 3.5+
575 case "/incremental+":
576 case "/incremental-":
578 return ParseResult.Success;
582 if (value.Length == 0) {
583 Error_RequiresArgument (option);
584 return ParseResult.Error;
587 foreach (string d in value.Split (argument_value_separator)) {
588 string conditional = d.Trim ();
589 if (!Tokenizer.IsValidIdentifier (conditional)) {
590 report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
593 RootContext.AddConditional (conditional);
595 return ParseResult.Success;
600 // We should collect data, runtime, etc and store in the file specified
602 output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
603 return ParseResult.Success;
608 if (value.Length == 0) {
609 Error_RequiresArgument (option);
610 return ParseResult.Error;
612 packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' }));
613 string pkgout = Driver.GetPackageFlags (packages, true, report);
615 if (pkgout != null) {
616 string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).
617 Split (new Char[] { ' ', '\t' });
618 args = AddArgs (args, xargs);
621 return ParseResult.Success;
625 case "/linkresource":
628 AssemblyResource res = null;
629 string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries);
632 if (s[0].Length == 0)
634 res = new AssemblyResource (s[0], Path.GetFileName (s[0]));
637 res = new AssemblyResource (s[0], s[1]);
640 if (s[2] != "public" && s[2] != "private") {
641 report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]);
642 return ParseResult.Error;
644 res = new AssemblyResource (s[0], s[1], s[2] == "private");
647 report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
648 return ParseResult.Error;
652 res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R';
653 AddResource (res, settings);
656 return ParseResult.Success;
659 if (value.Length == 0) {
660 Error_RequiresFileName (option);
661 return ParseResult.Error;
663 ProcessSourceFiles (value, true);
664 return ParseResult.Success;
668 if (value.Length == 0) {
669 Error_RequiresFileName (option);
670 return ParseResult.Error;
673 string[] refs = value.Split (argument_value_separator);
674 foreach (string r in refs) {
679 int index = val.IndexOf ('=');
681 string alias = r.Substring (0, index);
682 string assembly = r.Substring (index + 1);
683 AddAssemblyReference (alias, assembly, settings);
684 if (refs.Length != 1) {
685 report.Error (2034, "Cannot specify multiple aliases using single /reference option");
686 return ParseResult.Error;
689 settings.AssemblyReferences.Add (val);
692 return ParseResult.Success;
695 if (value.Length == 0) {
696 Error_RequiresFileName (option);
697 return ParseResult.Error;
700 string[] refs = value.Split (argument_value_separator);
701 foreach (string r in refs) {
702 settings.Modules.Add (r);
704 return ParseResult.Success;
707 if (value.Length == 0) {
708 Error_RequiresFileName (option);
709 return ParseResult.Error;
712 if (settings.Win32IconFile != null)
713 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
715 settings.Win32ResourceFile = value;
716 return ParseResult.Success;
719 if (value.Length == 0) {
720 Error_RequiresFileName (option);
721 return ParseResult.Error;
724 if (settings.Win32ResourceFile != null)
725 report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
727 settings.Win32IconFile = value;
728 return ParseResult.Success;
731 if (value.Length == 0) {
732 Error_RequiresFileName (option);
733 return ParseResult.Error;
736 settings.Documentation = new Documentation (value);
737 return ParseResult.Success;
742 if (value.Length == 0) {
743 return ParseResult.Error;
746 libdirs = value.Split (argument_value_separator);
747 foreach (string dir in libdirs)
748 settings.ReferencesLookupPaths.Add (dir);
749 return ParseResult.Success;
753 settings.GenerateDebugInfo = false;
754 return ParseResult.Success;
757 if (value == "full" || value == "")
758 settings.GenerateDebugInfo = true;
760 return ParseResult.Success;
763 settings.GenerateDebugInfo = true;
764 return ParseResult.Success;
768 settings.Checked = true;
769 return ParseResult.Success;
772 settings.Checked = false;
773 return ParseResult.Success;
777 settings.VerifyClsCompliance = true;
778 return ParseResult.Success;
781 settings.VerifyClsCompliance = false;
782 return ParseResult.Success;
786 settings.Unsafe = true;
787 return ParseResult.Success;
790 settings.Unsafe = false;
791 return ParseResult.Success;
794 case "/warnaserror+":
795 if (value.Length == 0) {
796 report.WarningsAreErrors = true;
798 foreach (string wid in value.Split (argument_value_separator))
799 report.AddWarningAsError (wid);
801 return ParseResult.Success;
803 case "/warnaserror-":
804 if (value.Length == 0) {
805 report.WarningsAreErrors = false;
807 foreach (string wid in value.Split (argument_value_separator))
808 report.RemoveWarningAsError (wid);
810 return ParseResult.Success;
813 if (value.Length == 0) {
814 Error_RequiresArgument (option);
815 return ParseResult.Error;
818 SetWarningLevel (value);
819 return ParseResult.Success;
822 if (value.Length == 0) {
823 Error_RequiresArgument (option);
824 return ParseResult.Error;
827 var warns = value.Split (argument_value_separator);
828 foreach (string wc in warns) {
830 if (wc.Trim ().Length == 0)
833 int warn = Int32.Parse (wc);
835 throw new ArgumentOutOfRangeException ("warn");
837 report.SetIgnoreWarning (warn);
839 report.Error (1904, "`{0}' is not a valid warning number", wc);
840 return ParseResult.Error;
843 return ParseResult.Success;
846 settings.LoadDefaultReferences = false;
847 return ParseResult.Success;
850 if (value.Length == 0) {
851 Error_RequiresArgument (option);
852 return ParseResult.Error;
855 switch (value.ToLower (CultureInfo.InvariantCulture)) {
857 settings.Platform = Platform.AnyCPU;
860 settings.Platform = Platform.X86;
863 settings.Platform = Platform.X64;
866 settings.Platform = Platform.IA64;
869 report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'");
870 return ParseResult.Error;
873 return ParseResult.Success;
876 if (value.Length == 0) {
877 Error_RequiresArgument (option);
878 return ParseResult.Error;
881 settings.SdkVersion = value;
882 return ParseResult.Success;
884 // We just ignore this.
887 if (value.Length == 0) {
888 Error_RequiresArgument (option);
889 return ParseResult.Error;
892 return ParseResult.Success;
894 case "/helpinternal":
896 return ParseResult.Stop;
901 return ParseResult.Stop;
905 if (value.Length == 0) {
906 Error_RequiresArgument (option);
907 return ParseResult.Error;
909 settings.MainClass = value;
910 return ParseResult.Success;
914 settings.StdLib = false;
915 return ParseResult.Success;
918 settings.StdLib = true;
919 return ParseResult.Success;
922 report.Printer.ShowFullPaths = true;
923 return ParseResult.Success;
926 if (value.Length == 0) {
927 Error_RequiresFileName (option);
928 return ParseResult.Error;
931 settings.StrongNameKeyFile = value;
932 return ParseResult.Success;
934 case "/keycontainer":
935 if (value.Length == 0) {
936 Error_RequiresArgument (option);
937 return ParseResult.Error;
940 settings.StrongNameKeyContainer = value;
941 return ParseResult.Success;
945 settings.StrongNameDelaySign = true;
946 return ParseResult.Success;
949 settings.StrongNameDelaySign = false;
950 return ParseResult.Success;
953 if (value.Length == 0) {
954 Error_RequiresArgument (option);
955 return ParseResult.Error;
958 switch (value.ToLowerInvariant ()) {
960 settings.Version = LanguageVersion.ISO_1;
961 return ParseResult.Success;
963 settings.Version = LanguageVersion.Default;
964 RootContext.AddConditional ("__V2__");
965 return ParseResult.Success;
967 settings.Version = LanguageVersion.ISO_2;
968 return ParseResult.Success;
970 settings.Version = LanguageVersion.V_3;
971 return ParseResult.Success;
973 settings.Version = LanguageVersion.Future;
974 return ParseResult.Success;
977 report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value);
978 return ParseResult.Error;
981 if (value.Length == 0) {
982 Error_RequiresArgument (option);
983 return ParseResult.Error;
988 settings.Encoding = new UTF8Encoding ();
991 settings.Encoding = Encoding.Default;
995 settings.Encoding = Encoding.GetEncoding (int.Parse (value));
997 report.Error (2016, "Code page `{0}' is invalid or not installed", value);
999 return ParseResult.Error;
1001 return ParseResult.Success;
1004 return ParseResult.UnknownOption;
1009 // Currently handles the Unix-like command line options, but will be
1010 // deprecated in favor of the CSCParseOption, which will also handle the
1011 // options that start with a dash in the future.
1013 ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings)
1017 CSharpParser.yacc_verbose_flag++;
1018 return ParseResult.Success;
1022 return ParseResult.Stop;
1025 settings.ParseOnly = true;
1026 return ParseResult.Success;
1028 case "--main": case "-m":
1029 report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
1030 if ((i + 1) >= args.Length){
1031 Error_RequiresArgument (arg);
1032 return ParseResult.Error;
1034 settings.MainClass = args[++i];
1035 return ParseResult.Success;
1038 report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
1039 settings.Unsafe = true;
1040 return ParseResult.Success;
1042 case "/?": case "/h": case "/help":
1045 return ParseResult.Stop;
1048 report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
1049 if ((i + 1) >= args.Length){
1050 Error_RequiresArgument (arg);
1051 return ParseResult.Error;
1053 RootContext.AddConditional (args [++i]);
1054 return ParseResult.Success;
1057 settings.TokenizeOnly = true;
1058 return ParseResult.Success;
1062 report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
1063 if ((i + 1) >= args.Length){
1064 Error_RequiresArgument (arg);
1065 return ParseResult.Error;
1067 settings.OutputFile = args[++i];
1068 return ParseResult.Success;
1071 report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
1072 settings.Checked = true;
1073 return ParseResult.Success;
1075 case "--stacktrace":
1076 report.Printer.Stacktrace = true;
1077 return ParseResult.Success;
1079 case "--linkresource":
1081 report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
1082 if ((i + 1) >= args.Length){
1083 Error_RequiresArgument (arg);
1084 return ParseResult.Error;
1087 AddResource (new AssemblyResource (args[++i], args[i]), settings);
1088 return ParseResult.Success;
1092 report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
1093 if ((i + 1) >= args.Length){
1094 Error_RequiresArgument (arg);
1095 return ParseResult.Error;
1098 AddResource (new AssemblyResource (args[++i], args[i], true), settings);
1099 return ParseResult.Success;
1102 report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
1103 if ((i + 1) >= args.Length){
1104 Error_RequiresArgument (arg);
1105 return ParseResult.Error;
1108 string type = args [++i];
1111 settings.Target = Target.Library;
1112 settings.TargetExt = ".dll";
1116 settings.Target = Target.Exe;
1120 settings.Target = Target.WinExe;
1124 settings.Target = Target.Module;
1125 settings.TargetExt = ".dll";
1128 report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
1131 return ParseResult.Success;
1134 report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
1135 if ((i + 1) >= args.Length){
1136 Error_RequiresArgument (arg);
1137 return ParseResult.Error;
1140 string val = args [++i];
1141 int idx = val.IndexOf ('=');
1143 string alias = val.Substring (0, idx);
1144 string assembly = val.Substring (idx + 1);
1145 AddAssemblyReference (alias, assembly, settings);
1146 return ParseResult.Success;
1149 settings.AssemblyReferences.Add (val);
1150 return ParseResult.Success;
1153 report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
1154 if ((i + 1) >= args.Length){
1155 Error_RequiresArgument (arg);
1156 return ParseResult.Error;
1158 settings.ReferencesLookupPaths.Add (args [++i]);
1159 return ParseResult.Success;
1162 settings.EnhancedWarnings = true;
1163 return ParseResult.Success;
1166 report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
1167 settings.StdLib = false;
1168 return ParseResult.Success;
1171 report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
1172 if ((i + 1) >= args.Length){
1173 Error_RequiresArgument (arg);
1174 return ParseResult.Error;
1179 warn = int.Parse (args [++i]);
1182 Environment.Exit (1);
1184 report.SetIgnoreWarning (warn);
1185 return ParseResult.Success;
1188 report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
1189 if ((i + 1) >= args.Length){
1190 Error_RequiresArgument (arg);
1191 return ParseResult.Error;
1194 SetWarningLevel (args [++i]);
1195 return ParseResult.Success;
1198 if ((i + 1) >= args.Length){
1199 Error_RequiresArgument (arg);
1200 return ParseResult.Error;
1204 Report.DebugFlags = int.Parse (args [++i]);
1206 Error_RequiresArgument (arg);
1207 return ParseResult.Error;
1210 return ParseResult.Success;
1214 return ParseResult.Stop;
1217 report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
1218 if ((i + 1) >= args.Length){
1219 Error_RequiresArgument (arg);
1220 return ParseResult.Error;
1222 ProcessSourceFiles (args [++i], true);
1223 return ParseResult.Success;
1226 settings.Timestamps = true;
1227 return ParseResult.Success;
1229 case "--debug": case "-g":
1230 report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
1231 settings.GenerateDebugInfo = true;
1232 return ParseResult.Success;
1235 report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
1236 settings.LoadDefaultReferences = false;
1237 return ParseResult.Success;
1240 if (arg.StartsWith ("--fatal")){
1242 if (arg.StartsWith ("--fatal="))
1243 int.TryParse (arg.Substring (8), out fatal);
1245 report.Printer.FatalCounter = fatal;
1246 return ParseResult.Success;
1248 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
1249 string version = arg.Substring (10);
1254 settings.StdLibRuntimeVersion = RuntimeVersion.v1;
1258 settings.StdLibRuntimeVersion = RuntimeVersion.v2;
1262 settings.StdLibRuntimeVersion = RuntimeVersion.v4;
1265 return ParseResult.Success;
1268 return ParseResult.UnknownOption;
1272 void SetWarningLevel (string s)
1277 level = int.Parse (s);
1280 if (level < 0 || level > 4) {
1281 report.Error (1900, "Warning level must be in the range 0-4");
1284 report.WarningLevel = level;
1288 // Given a path specification, splits the path from the file/pattern
1290 static void SplitPathAndPattern (string spec, out string path, out string pattern)
1292 int p = spec.LastIndexOf ('/');
1295 // Windows does not like /file.cs, switch that to:
1300 pattern = spec.Substring (1);
1302 path = spec.Substring (0, p);
1303 pattern = spec.Substring (p + 1);
1308 p = spec.LastIndexOf ('\\');
1310 path = spec.Substring (0, p);
1311 pattern = spec.Substring (p + 1);
1322 "Mono C# compiler, Copyright 2001 - 2011 Novell, Inc.\n" +
1323 "mcs [options] source-files\n" +
1324 " --about About the Mono C# compiler\n" +
1325 " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
1326 " -checked[+|-] Sets default aritmetic overflow context\n" +
1327 " -clscheck[+|-] Disables CLS Compliance verifications\n" +
1328 " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" +
1329 " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" +
1330 " -debug[+|-], -g Generate debugging information\n" +
1331 " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
1332 " -doc:FILE Process documentation comments to XML file\n" +
1333 " -fullpaths Any issued error or warning uses absolute file path\n" +
1334 " -help Lists all compiler options (short: -?)\n" +
1335 " -keycontainer:NAME The key pair container used to sign the output assembly\n" +
1336 " -keyfile:FILE The key file used to strongname the ouput assembly\n" +
1337 " -langversion:TEXT Specifies language version: ISO-1, ISO-2, 3, Default or Future\n" +
1338 " -lib:PATH1[,PATHn] Specifies the location of referenced assemblies\n" +
1339 " -main:CLASS Specifies the class with the Main method (short: -m)\n" +
1340 " -noconfig Disables implicitly referenced assemblies\n" +
1341 " -nostdlib[+|-] Does not reference mscorlib.dll library\n" +
1342 " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" +
1343 " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" +
1344 " -out:FILE Specifies output assembly name\n" +
1345 " -pkg:P1[,Pn] References packages P1..Pn\n" +
1346 " -platform:ARCH Specifies the target platform of the output assembly\n" +
1347 " ARCH can be one of: anycpu, x86, x64 or itanium\n" +
1348 " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
1349 " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
1350 " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
1351 " -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
1352 " VERSION can be one of: 2, 4 (default) or custom value\n" +
1353 " -target:KIND Specifies the format of the output assembly (short: -t)\n" +
1354 " KIND can be one of: exe, winexe, library, module\n" +
1355 " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +
1356 " -warnaserror[+|-] Treats all warnings as errors\n" +
1357 " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
1358 " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" +
1359 " -helpinternal Shows internal and advanced compiler options\n" +
1362 " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
1363 " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" +
1364 " -win32res:FILE Specifies Win32 resource file (.res)\n" +
1365 " -win32icon:FILE Use this icon for the output\n" +
1366 " @file Read response file for more options\n\n" +
1367 "Options can be of the form -option or /option");
1372 string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString ();
1373 output.WriteLine ("Mono C# compiler version {0}", version);
1377 public class RootContext
1380 // Contains the parsed tree
1382 static ModuleContainer root;
1385 // This hashtable contains all of the #definitions across the source code
1386 // it is used by the ConditionalAttribute handler.
1388 static List<string> AllDefines;
1393 static RootContext ()
1398 public static void PartialReset ()
1403 public static void Reset (bool full)
1409 // Setup default defines
1411 AllDefines = new List<string> ();
1412 AddConditional ("__MonoCS__");
1415 public static void AddConditional (string p)
1417 if (AllDefines.Contains (p))
1422 public static bool IsConditionalDefined (string value)
1424 return AllDefines.Contains (value);
1427 static public ModuleContainer ToplevelTypes {
1428 get { return root; }
1429 set { root = value; }