summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Mike Barnett <mbarnett@microsoft.com>2011-07-27 17:51:53 -0700
committerGravatar Mike Barnett <mbarnett@microsoft.com>2011-07-27 17:51:53 -0700
commit055d639ad02d7ff9a1f6707d9f13fb4f7eeca880 (patch)
tree059ae0bb1fb48fcc3279d614d2f0a11deae2f3f4
parent75e8481cdb9244c7bcee82e9f67679f43feb6619 (diff)
Implemented a whitelist/blacklist so translator can ignore certain parts of an
assembly.
-rw-r--r--BCT/BytecodeTranslator/MetadataTraverser.cs4
-rw-r--r--BCT/BytecodeTranslator/Program.cs66
-rw-r--r--BCT/BytecodeTranslator/Sink.cs38
-rw-r--r--BCT/RegressionTests/TranslationTest/UnitTest0.cs2
4 files changed, 101 insertions, 9 deletions
diff --git a/BCT/BytecodeTranslator/MetadataTraverser.cs b/BCT/BytecodeTranslator/MetadataTraverser.cs
index 35561528..e7ec2ff2 100644
--- a/BCT/BytecodeTranslator/MetadataTraverser.cs
+++ b/BCT/BytecodeTranslator/MetadataTraverser.cs
@@ -64,6 +64,9 @@ namespace BytecodeTranslator {
/// </summary>
///
public override void Visit(ITypeDefinition typeDefinition) {
+
+ if (!this.sink.TranslateType(typeDefinition)) return;
+
var savedPrivateTypes = this.privateTypes;
this.privateTypes = new List<ITypeDefinition>();
@@ -591,6 +594,7 @@ namespace BytecodeTranslator {
base.Visit(methodCall);
}
}
+
#endregion
}
diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs
index 14bf89e7..f6483eac 100644
--- a/BCT/BytecodeTranslator/Program.cs
+++ b/BCT/BytecodeTranslator/Program.cs
@@ -19,10 +19,11 @@ using System.Diagnostics.Contracts;
using Microsoft.Cci.MutableCodeModel.Contracts;
using TranslationPlugins;
using BytecodeTranslator.Phone;
+using System.Text.RegularExpressions;
namespace BytecodeTranslator {
- class Options : OptionParsing {
+ public class Options : OptionParsing {
[OptionDescription("The names of the assemblies to use as input", ShortForm = "a")]
public List<string> assemblies = null;
@@ -52,6 +53,9 @@ namespace BytecodeTranslator {
[OptionDescription("Add phone feedback code on translation. Requires /phoneControls. Default false", ShortForm = "wpfb")]
public bool phoneFeedbackCode = false;
+ [OptionDescription("File containing white/black list (optionally end file name with + for white list, - for black list, default is white list", ShortForm = "exempt")]
+ public string exemptionFile = "";
+
}
public class BCT {
@@ -63,7 +67,7 @@ namespace BytecodeTranslator {
int result = 0;
int errorReturnValue = -1;
- #region Parse options
+ #region Parse options and check for errors
var options = new Options();
options.Parse(args);
if (options.HelpRequested) {
@@ -73,10 +77,19 @@ namespace BytecodeTranslator {
if (options.HasErrors) {
options.PrintErrorsAndExit(Console.Out);
}
+ if (String.IsNullOrWhiteSpace(options.exemptionFile)) {
+ string fileName = options.exemptionFile;
+ var c = fileName[fileName.Length - 1];
+ if (c == '+' || c == '-') fileName = options.exemptionFile.Remove(fileName.Length - 1);
+ if (!File.Exists(fileName)) {
+ Console.WriteLine("Specified exemption file '{0}' not found.", fileName);
+ }
+ }
if (options.breakIntoDebugger) {
System.Diagnostics.Debugger.Break();
}
+
#endregion
var assemblyNames = options.assemblies;
@@ -87,6 +100,40 @@ namespace BytecodeTranslator {
}
}
+ #region If an exclusion file has been specified, read in each line as a regular expression
+ List<Regex> exemptionList = null;
+ bool whiteList = true;
+ if (!String.IsNullOrWhiteSpace(options.exemptionFile)) {
+ int i = 0;
+ exemptionList = new List<Regex>();
+ string fileName = options.exemptionFile;
+ var c = fileName[fileName.Length - 1];
+ if (c == '+' || c == '-') {
+ fileName = options.exemptionFile.Remove(fileName.Length - 1);
+ if (c == '-') whiteList = false;
+ }
+ try {
+ // Create an instance of StreamReader to read from a file.
+ // The using statement also closes the StreamReader.
+ using (StreamReader sr = new StreamReader(fileName)) {
+ String line;
+ // Read and display lines from the file until the end of
+ // the file is reached.
+ while ((line = sr.ReadLine()) != null) {
+ exemptionList.Add(new Regex(line));
+ i++;
+ }
+ Console.WriteLine("Read {0} lines from the exclusion file '{1}'.",
+ i, options.exemptionFile);
+ }
+ } catch (Exception e) {
+ Console.WriteLine("Something went wrong reading the exclusion file '{0}'; read in {1} lines, continuing processing.",
+ fileName, i);
+ Console.WriteLine(e.Message);
+ }
+ }
+ #endregion
+
try {
HeapFactory heap;
@@ -107,8 +154,7 @@ namespace BytecodeTranslator {
return 1;
}
- result = TranslateAssembly(assemblyNames, heap, options.libpaths, options.wholeProgram, options.stub,
- options.phoneControls, options.phoneNavigationCode, options.phoneFeedbackCode);
+ result = TranslateAssembly(assemblyNames, heap, options, exemptionList, whiteList);
} catch (Exception e) { // swallow everything and just return an error code
Console.WriteLine("The byte-code translator failed: {0}", e.Message);
@@ -118,11 +164,17 @@ namespace BytecodeTranslator {
return result;
}
- public static int TranslateAssembly(List<string> assemblyNames, HeapFactory heapFactory, List<string>/*?*/ libPaths, bool wholeProgram, List<string>/*?*/ stubAssemblies,
- string phoneControlsConfigFile, bool doPhoneNav, bool doPhoneFeedback) {
+ public static int TranslateAssembly(List<string> assemblyNames, HeapFactory heapFactory, Options/*?*/ options, List<Regex> exemptionList, bool whiteList) {
Contract.Requires(assemblyNames != null);
Contract.Requires(heapFactory != null);
+ var libPaths = options == null ? null : options.libpaths;
+ var wholeProgram = options == null ? false : options.wholeProgram;
+ var/*?*/ stubAssemblies = options == null ? null : options.stub;
+ var phoneControlsConfigFile = options == null ? null : options.phoneControls;
+ var doPhoneNav = options == null ? false : options.phoneNavigationCode;
+ var doPhoneFeedback = options == null ? false : options.phoneFeedbackCode;
+
var host = new CodeContractAwareHostEnvironment(libPaths != null ? libPaths : Enumerable<string>.Empty, true, true);
Host = host;
@@ -195,7 +247,7 @@ namespace BytecodeTranslator {
else
traverserFactory = new CLRSemantics();
- Sink sink= new Sink(host, traverserFactory, heapFactory);
+ Sink sink= new Sink(host, traverserFactory, heapFactory, exemptionList, whiteList);
TranslationHelper.tmpVarCounter = 0;
MetadataTraverser translator;
translator= traverserFactory.MakeMetadataTraverser(sink, contractExtractors, pdbReaders);
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index ae56e916..e641f7cb 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using Microsoft.Cci;
using Microsoft.Cci.MetadataReader;
@@ -26,8 +27,10 @@ namespace BytecodeTranslator {
get { return this.factory; }
}
readonly TraverserFactory factory;
+ readonly bool whiteList;
+ readonly List<Regex> exemptionList;
- public Sink(IContractAwareHost host, TraverserFactory factory, HeapFactory heapFactory) {
+ public Sink(IContractAwareHost host, TraverserFactory factory, HeapFactory heapFactory, List<Regex> exemptionList, bool whiteList) {
Contract.Requires(host != null);
Contract.Requires(factory != null);
Contract.Requires(heapFactory != null);
@@ -35,6 +38,8 @@ namespace BytecodeTranslator {
this.host = host;
this.factory = factory;
var b = heapFactory.MakeHeap(this, out this.heap, out this.TranslatedProgram); // TODO: what if it returns false?
+ this.exemptionList = exemptionList;
+ this.whiteList = whiteList;
if (this.TranslatedProgram == null) {
this.TranslatedProgram = new Bpl.Program();
} else {
@@ -1105,6 +1110,37 @@ namespace BytecodeTranslator {
delegateMethods[defn] = constant;
return constant;
}
+
+ public bool TranslateType(ITypeReference t) {
+ if (this.exemptionList == null)
+ return !this.whiteList;
+ var fullName = TypeHelper.GetTypeName(t);
+ var fullerName = "[" + TypeHelper.GetDefiningUnitReference(t).Name.Value + "]" + fullName;
+ foreach (Regex r in this.exemptionList) {
+ Match m = r.Match(fullName);
+ if (m.Success)
+ return this.whiteList;
+ m = r.Match(fullerName);
+ if (m.Success)
+ return this.whiteList;
+ }
+ return !this.whiteList;
+ }
+
+ // TODO: get full namespace name from a namespace definition
+ //public bool TranslateNamespace(INamespaceDefinition nameSpace) {
+ // if (this.exemptionList == null)
+ // return !this.whiteList;
+ // var fullName = TypeHelper.GetNamespaceName(nameSpace, NameFormattingOptions.None);
+ // foreach (Regex r in this.exemptionList) {
+ // Match m = r.Match(fullName);
+ // if (m.Success)
+ // return this.whiteList;
+ // }
+ // return !this.whiteList;
+ //}
+
+
}
} \ No newline at end of file
diff --git a/BCT/RegressionTests/TranslationTest/UnitTest0.cs b/BCT/RegressionTests/TranslationTest/UnitTest0.cs
index 558730d1..e3da57b5 100644
--- a/BCT/RegressionTests/TranslationTest/UnitTest0.cs
+++ b/BCT/RegressionTests/TranslationTest/UnitTest0.cs
@@ -61,7 +61,7 @@ namespace TranslationTest {
#endregion
private string ExecuteTest(string assemblyName, HeapFactory heapFactory) {
- BCT.TranslateAssembly(new List<string>{assemblyName}, heapFactory, null, false, null, null, false, false);
+ BCT.TranslateAssembly(new List<string>{assemblyName}, heapFactory, null, null, false);
var fileName = Path.ChangeExtension(assemblyName, "bpl");
var s = File.ReadAllText(fileName);
return s;