public enum Platform
{
- AnyCPU, X86, X64, IA64
+ AnyCPU,
+ AnyCPU32Preferred,
+ Arm,
+ X86,
+ X64,
+ IA64
}
public class CompilerSettings
public bool GenerateDebugInfo;
- // Compiler debug flags only
+ #region Compiler debug flags only
public bool ParseOnly, TokenizeOnly, Timestamps;
public int DebugFlags;
public int VerboseParserFlag;
+ public int FatalCounter;
+ public bool Stacktrace;
+ public bool BreakOnInternalError;
+ #endregion
+
+ public bool ShowFullPaths;
//
// Whether we are being linked against the standard libraries.
public RuntimeVersion StdLibRuntimeVersion;
+ public string RuntimeMetadataVersion;
+
+ public bool WriteMetadataOnly;
+
readonly List<string> conditional_symbols;
- readonly List<CompilationSourceFile> source_files;
+ readonly List<SourceFile> source_files;
List<int> warnings_as_error;
List<int> warnings_only;
Platform = Platform.AnyCPU;
Version = LanguageVersion.Default;
VerifyClsCompliance = true;
- Optimize = true;
Encoding = Encoding.UTF8;
LoadDefaultReferences = true;
StdLibRuntimeVersion = RuntimeVersion.v4;
WarningLevel = 4;
- if (Environment.OSVersion.Platform == PlatformID.Win32NT)
- TabSize = 4;
- else
- TabSize = 8;
+ // Default to 1 or mdb files would be platform speficic
+ TabSize = 1;
AssemblyReferences = new List<string> ();
AssemblyReferencesAliases = new List<Tuple<string, string>> ();
//
conditional_symbols.Add ("__MonoCS__");
- source_files = new List<CompilationSourceFile> ();
+ source_files = new List<SourceFile> ();
}
#region Properties
- public CompilationSourceFile FirstSourceFile {
+ public SourceFile FirstSourceFile {
get {
return source_files.Count > 0 ? source_files [0] : null;
}
}
}
- public List<CompilationSourceFile> SourceFiles {
+ public List<SourceFile> SourceFiles {
get {
return source_files;
}
UnknownOption
}
- static readonly char[] argument_value_separator = new char[] { ';', ',' };
- static readonly char[] numeric_value_separator = new char[] { ';', ',', ' ' };
+ static readonly char[] argument_value_separator = { ';', ',' };
+ static readonly char[] numeric_value_separator = { ';', ',', ' ' };
readonly TextWriter output;
readonly Report report;
public CompilerSettings ParseArguments (string[] args)
{
CompilerSettings settings = new CompilerSettings ();
+ if (!ParseArguments (settings, args))
+ return null;
+
+ return settings;
+ }
+
+ public bool ParseArguments (CompilerSettings settings, string[] args)
+ {
+ if (settings == null)
+ throw new ArgumentNullException ("settings");
+
List<string> response_file_list = null;
bool parsing_options = true;
stop_argument = false;
if (response_file_list.Contains (response_file)) {
report.Error (1515, "Response file `{0}' specified multiple times", response_file);
- return null;
+ return false;
}
response_file_list.Add (response_file);
extra_args = LoadArgs (response_file);
if (extra_args == null) {
report.Error (2011, "Unable to open response file: " + response_file);
- return null;
+ return false;
}
args = AddArgs (args, extra_args);
continue;
case ParseResult.Stop:
stop_argument = true;
- return settings;
+ return true;
case ParseResult.UnknownOption:
if (UnknownOptionHandler != null) {
var ret = UnknownOptionHandler (args, i);
}
Error_WrongOption (arg);
- return null;
+ return false;
case ParseResult.Stop:
stop_argument = true;
- return settings;
+ return true;
}
}
}
ProcessSourceFiles (arg, false, settings.SourceFiles);
}
- if (report.Errors > 0)
- return null;
-
- return settings;
+ return report.Errors == 0;
}
- void ProcessSourceFiles (string spec, bool recurse, List<CompilationSourceFile> sourceFiles)
+ void ProcessSourceFiles (string spec, bool recurse, List<SourceFile> sourceFiles)
{
string path, pattern;
return;
}
- string[] files = null;
+ string[] files;
try {
files = Directory.GetFiles (path, pattern);
} catch (System.IO.DirectoryNotFoundException) {
settings.Resources.Add (res);
}
- void AddSourceFile (string fileName, List<CompilationSourceFile> sourceFiles)
+ void AddSourceFile (string fileName, List<SourceFile> sourceFiles)
{
string path = Path.GetFullPath (fileName);
return;
}
- var unit = new CompilationSourceFile (fileName, path, sourceFiles.Count + 1);
+ var unit = new SourceFile (fileName, path, sourceFiles.Count + 1);
sourceFiles.Add (unit);
source_file_index.Add (path, unit.Index);
}
- void AddWarningAsError (string warningId, CompilerSettings settings)
+ public bool ProcessWarningsList (string text, Action<int> action)
{
- int id;
- try {
- id = int.Parse (warningId);
- } catch {
- report.CheckWarningCode (warningId, Location.Null);
- return;
- }
-
- if (!report.CheckWarningCode (id, Location.Null))
- return;
-
- settings.AddWarningAsError (id);
- }
+ bool valid = true;
+ foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
+ int id;
+ if (!int.TryParse (wid, NumberStyles.AllowLeadingWhite, CultureInfo.InvariantCulture, out id)) {
+ report.Error (1904, "`{0}' is not a valid warning number", wid);
+ valid = false;
+ continue;
+ }
- void RemoveWarningAsError (string warningId, CompilerSettings settings)
- {
- int id;
- try {
- id = int.Parse (warningId);
- } catch {
- report.CheckWarningCode (warningId, Location.Null);
- return;
+ if (report.CheckWarningCode (id, Location.Null))
+ action (id);
}
- if (!report.CheckWarningCode (id, Location.Null))
- return;
-
- settings.AddWarningOnly (id);
+ return valid;
}
void Error_RequiresArgument (string option)
static bool IsExternAliasValid (string identifier)
{
- if (identifier.Length == 0)
- return false;
- if (identifier[0] != '_' && !char.IsLetter (identifier[0]))
- return false;
-
- for (int i = 1; i < identifier.Length; i++) {
- char c = identifier[i];
- if (char.IsLetter (c) || char.IsDigit (c))
- continue;
-
- UnicodeCategory category = char.GetUnicodeCategory (c);
- if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
- category != UnicodeCategory.SpacingCombiningMark ||
- category != UnicodeCategory.ConnectorPunctuation)
- return false;
- }
-
- return true;
+ return Tokenizer.IsValidIdentifier (identifier);
}
static string[] LoadArgs (string file)
{
output.WriteLine (
"Other flags in the compiler\n" +
- " --fatal[=COUNT] Makes errors after COUNT fatal\n" +
+ " --fatal[=COUNT] Makes error after COUNT fatal\n" +
" --lint Enhanced warnings\n" +
+ " --metadata-only Produced assembly will contain metadata only\n" +
" --parse Only parses the source file\n" +
" --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" +
" --stacktrace Shows stack trace at error location\n" +
" --timestamp Displays time stamps of various compiler events\n" +
" -v Verbose parsing (for debugging the parser)\n" +
- " --mcs-debug X Sets MCS debugging level to X\n");
+ " --mcs-debug X Sets MCS debugging level to X\n" +
+ " --break-on-ice Breaks compilation on internal compiler error");
}
//
return ParseResult.Success;
case "/debug":
- if (value == "full" || value == "")
+ if (value.Equals ("full", StringComparison.OrdinalIgnoreCase) || value.Equals ("pdbonly", StringComparison.OrdinalIgnoreCase) || idx < 0) {
settings.GenerateDebugInfo = true;
+ return ParseResult.Success;
+ }
- return ParseResult.Success;
+ if (value.Length > 0) {
+ report.Error (1902, "Invalid debug option `{0}'. Valid options are `full' or `pdbonly'", value);
+ } else {
+ Error_RequiresArgument (option);
+ }
+
+ return ParseResult.Error;
case "/debug+":
settings.GenerateDebugInfo = true;
settings.WarningsAreErrors = true;
parser_settings.WarningsAreErrors = true;
} else {
- foreach (string wid in value.Split (numeric_value_separator))
- AddWarningAsError (wid, settings);
+ if (!ProcessWarningsList (value, settings.AddWarningAsError))
+ return ParseResult.Error;
}
return ParseResult.Success;
if (value.Length == 0) {
settings.WarningsAreErrors = false;
} else {
- foreach (string wid in value.Split (numeric_value_separator))
- RemoveWarningAsError (wid, settings);
+ if (!ProcessWarningsList (value, settings.AddWarningOnly))
+ return ParseResult.Error;
}
return ParseResult.Success;
case "/warn":
+ case "/w":
if (value.Length == 0) {
Error_RequiresArgument (option);
return ParseResult.Error;
return ParseResult.Success;
case "/nowarn":
- if (value.Length == 0) {
- Error_RequiresArgument (option);
- return ParseResult.Error;
- }
+ if (value.Length == 0) {
+ Error_RequiresArgument (option);
+ return ParseResult.Error;
+ }
- var warns = value.Split (numeric_value_separator);
- foreach (string wc in warns) {
- try {
- if (wc.Trim ().Length == 0)
- continue;
+ if (!ProcessWarningsList (value, settings.SetIgnoreWarning))
+ return ParseResult.Error;
- int warn = Int32.Parse (wc);
- if (warn < 1) {
- throw new ArgumentOutOfRangeException ("warn");
- }
- settings.SetIgnoreWarning (warn);
- } catch {
- report.Error (1904, "`{0}' is not a valid warning number", wc);
- return ParseResult.Error;
- }
- }
- return ParseResult.Success;
+ return ParseResult.Success;
case "/noconfig":
settings.LoadDefaultReferences = false;
return ParseResult.Error;
}
- switch (value.ToLower (CultureInfo.InvariantCulture)) {
+ switch (value.ToLowerInvariant ()) {
+ case "arm":
+ settings.Platform = Platform.Arm;
+ break;
case "anycpu":
settings.Platform = Platform.AnyCPU;
break;
case "itanium":
settings.Platform = Platform.IA64;
break;
+ case "anycpu32bitpreferred":
+ settings.Platform = Platform.AnyCPU32Preferred;
+ break;
default:
- report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'");
+ report.Error (1672, "Invalid -platform option `{0}'. Valid options are `anycpu', `anycpu32bitpreferred', `arm', `x86', `x64' or `itanium'",
+ value);
return ParseResult.Error;
}
return ParseResult.Success;
case "/fullpaths":
- report.Printer.ShowFullPaths = true;
+ settings.ShowFullPaths = true;
return ParseResult.Success;
case "/keyfile":
}
return ParseResult.Success;
+ case "runtimemetadataversion":
+ if (value.Length == 0) {
+ Error_RequiresArgument (option);
+ return ParseResult.Error;
+ }
+
+ settings.RuntimeMetadataVersion = value;
+ return ParseResult.Success;
+
default:
return ParseResult.UnknownOption;
}
return ParseResult.Success;
case "--stacktrace":
- report.Printer.Stacktrace = true;
+ settings.Stacktrace = true;
return ParseResult.Success;
case "--linkresource":
settings.LoadDefaultReferences = false;
return ParseResult.Success;
+ case "--metadata-only":
+ settings.WriteMetadataOnly = true;
+ return ParseResult.Success;
+
+ case "--break-on-ice":
+ settings.BreakOnInternalError = true;
+ return ParseResult.Success;
+
default:
- if (arg.StartsWith ("--fatal")){
+ if (arg.StartsWith ("--fatal", StringComparison.Ordinal)){
int fatal = 1;
- if (arg.StartsWith ("--fatal="))
+ if (arg.StartsWith ("--fatal=", StringComparison.Ordinal))
int.TryParse (arg.Substring (8), out fatal);
- report.Printer.FatalCounter = fatal;
+ settings.FatalCounter = fatal;
return ParseResult.Success;
}
if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
void Usage ()
{
output.WriteLine (
- "Mono C# compiler, Copyright 2001 - 2011 Novell, Inc.\n" +
+ "Mono C# compiler, Copyright 2001-2011 Novell, Inc., Copyright 2011-2012 Xamarin, Inc\n" +
"mcs [options] source-files\n" +
" --about About the Mono C# compiler\n" +
" -addmodule:M1[,Mn] Adds the module to the generated assembly\n" +
" -out:FILE Specifies output assembly name\n" +
" -pkg:P1[,Pn] References packages P1..Pn\n" +
" -platform:ARCH Specifies the target platform of the output assembly\n" +
- " ARCH can be one of: anycpu, x86, x64 or itanium\n" +
+ " ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
+ " x86, x64 or itanium. The default is anycpu.\n" +
" -recurse:SPEC Recursively compiles files according to SPEC pattern\n" +
" -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" +
" -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" +
" -sdk:VERSION Specifies SDK version of referenced assemblies\n" +
- " VERSION can be one of: 2, 4 (default) or custom value\n" +
+ " VERSION can be one of: 2, 4, 4.5 (default) or a custom value\n" +
" -target:KIND Specifies the format of the output assembly (short: -t)\n" +
" KIND can be one of: exe, winexe, library, module\n" +
" -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" +