|
//------------------------------------------------------------------------------
// <copyright file="Compiler.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
namespace System.Xml.Xsl.XsltOld {
using Res = System.Xml.Utils.Res;
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl.Runtime;
using MS.Internal.Xml.XPath;
using System.Xml.Xsl.XsltOld.Debugger;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using Keywords = System.Xml.Xsl.Xslt.KeywordsTable;
using System.Runtime.Versioning;
internal class Sort {
internal int select;
internal string lang;
internal XmlDataType dataType;
internal XmlSortOrder order;
internal XmlCaseOrder caseOrder;
public Sort(int sortkey, String xmllang, XmlDataType datatype, XmlSortOrder xmlorder, XmlCaseOrder xmlcaseorder) {
select = sortkey;
lang = xmllang;
dataType = datatype;
order = xmlorder;
caseOrder = xmlcaseorder;
}
}
internal enum ScriptingLanguage {
JScript,
#if !FEATURE_PAL // visualbasic
VisualBasic,
#endif // !FEATURE_PAL
CSharp
}
internal class Compiler {
internal const int InvalidQueryKey = -1;
internal const double RootPriority = 0.5;
// cached StringBuilder for AVT parseing
internal StringBuilder AvtStringBuilder = new StringBuilder();
private int stylesheetid; // Root stylesheet has id=0. We are using this in CompileImports to compile BuiltIns
private InputScope rootScope;
//
// Object members
private XmlResolver xmlResolver;
//
// Template being currently compiled
private TemplateBaseAction currentTemplate;
private XmlQualifiedName currentMode;
private Hashtable globalNamespaceAliasTable;
//
// Current import stack
private Stack stylesheets;
private HybridDictionary documentURIs = new HybridDictionary();
// import/include documents, who is here has its URI in this.documentURIs
private NavigatorInput input;
// Atom table & InputScopeManager - cached top of the this.input stack
private Keywords atoms;
private InputScopeManager scopeManager;
//
// Compiled stylesheet state
internal Stylesheet stylesheet;
internal Stylesheet rootStylesheet;
private RootAction rootAction;
private List<TheQuery> queryStore;
private QueryBuilder queryBuilder = new QueryBuilder();
private int rtfCount = 0;
// Used to load Built In templates
public bool AllowBuiltInMode;
public static XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty);
internal Keywords Atoms {
get {
Debug.Assert(this.atoms != null);
return this.atoms;
}
}
internal int Stylesheetid {
get{ return this.stylesheetid; }
set { this.stylesheetid = value; }
}
internal NavigatorInput Document {
get { return this.input; }
}
internal NavigatorInput Input {
get { return this.input; }
}
internal bool Advance() {
Debug.Assert(Document != null);
return Document.Advance();
}
internal bool Recurse() {
Debug.Assert(Document != null);
return Document.Recurse();
}
internal bool ToParent() {
Debug.Assert(Document != null);
return Document.ToParent();
}
internal Stylesheet CompiledStylesheet {
get { return this.stylesheet; }
}
internal RootAction RootAction {
get { return this.rootAction; }
set {
Debug.Assert(this.rootAction == null);
this.rootAction = value;
Debug.Assert(this.currentTemplate == null);
this.currentTemplate = this.rootAction;
}
}
internal List<TheQuery> QueryStore {
get { return this.queryStore; }
}
public virtual IXsltDebugger Debugger { get { return null; } }
internal string GetUnicRtfId() {
this.rtfCount++;
return this.rtfCount.ToString(CultureInfo.InvariantCulture);
}
//
// The World of Compile
//
internal void Compile(NavigatorInput input, XmlResolver xmlResolver, Evidence evidence) {
Debug.Assert(input != null);
Debug.Assert(xmlResolver != null);
// Debug.Assert(evidence != null); -- default evidence is null now
Debug.Assert(this.input == null && this.atoms == null);
this.xmlResolver = xmlResolver;
PushInputDocument(input);
this.rootScope = this.scopeManager.PushScope();
this.queryStore = new List<TheQuery>();
try {
this.rootStylesheet = new Stylesheet();
PushStylesheet(this.rootStylesheet);
Debug.Assert(this.input != null && this.atoms != null);
try {
this.CreateRootAction();
}
catch (XsltCompileException) {
throw;
}
catch (Exception e) {
throw new XsltCompileException(e, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
}
this.stylesheet.ProcessTemplates();
this.rootAction.PorcessAttributeSets(this.rootStylesheet);
this.stylesheet.SortWhiteSpace();
CompileScript(evidence);
if (evidence != null) {
this.rootAction.permissions = SecurityManager.GetStandardSandbox(evidence);
}
if (this.globalNamespaceAliasTable != null) {
this.stylesheet.ReplaceNamespaceAlias(this);
this.rootAction.ReplaceNamespaceAlias(this);
}
}
finally {
PopInputDocument();
}
Debug.Assert(this.rootAction != null);
Debug.Assert(this.stylesheet != null);
Debug.Assert(this.queryStore != null);
Debug.Assert(this.input == null && this.atoms == null);
}
//
// Input scope compiler's support
//
internal bool ForwardCompatibility {
get { return this.scopeManager.CurrentScope.ForwardCompatibility; }
set { this.scopeManager.CurrentScope.ForwardCompatibility = value; }
}
internal bool CanHaveApplyImports {
get { return this.scopeManager.CurrentScope.CanHaveApplyImports; }
set { this.scopeManager.CurrentScope.CanHaveApplyImports = value; }
}
internal void InsertExtensionNamespace(string value) {
string[] nsList = ResolvePrefixes(value);
if (nsList != null) {
scopeManager.InsertExtensionNamespaces(nsList);
}
}
internal void InsertExcludedNamespace(string value) {
string[] nsList = ResolvePrefixes(value);
if (nsList != null) {
scopeManager.InsertExcludedNamespaces(nsList);
}
}
internal void InsertExtensionNamespace() {
InsertExtensionNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExtensionElementPrefixes, Input.Atoms.UriXsl));
}
internal void InsertExcludedNamespace() {
InsertExcludedNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExcludeResultPrefixes, Input.Atoms.UriXsl));
}
internal bool IsExtensionNamespace(String nspace) {
return this.scopeManager.IsExtensionNamespace(nspace);
}
internal bool IsExcludedNamespace(String nspace) {
return this.scopeManager.IsExcludedNamespace(nspace);
}
internal void PushLiteralScope() {
PushNamespaceScope();
string value = Input.Navigator.GetAttribute(Atoms.Version, Atoms.UriXsl);
if (value.Length != 0) {
ForwardCompatibility = (value != "1.0");
}
}
internal void PushNamespaceScope() {
this.scopeManager.PushScope();
NavigatorInput input = Input;
if (input.MoveToFirstNamespace()) {
do {
this.scopeManager.PushNamespace(input.LocalName, input.Value);
}
while(input.MoveToNextNamespace());
input.ToParent();
}
}
protected InputScopeManager ScopeManager {
get { return this.scopeManager; }
}
internal virtual void PopScope() {
this.currentTemplate.ReleaseVariableSlots(this.scopeManager.CurrentScope.GetVeriablesCount());
this.scopeManager.PopScope();
}
internal InputScopeManager CloneScopeManager() {
return this.scopeManager.Clone();
}
//
// Variable support
//
internal int InsertVariable(VariableAction variable) {
InputScope varScope;
if (variable.IsGlobal) {
Debug.Assert(this.rootAction != null);
varScope = this.rootScope;
}
else {
Debug.Assert(this.currentTemplate != null);
Debug.Assert(variable.VarType == VariableType.LocalVariable || variable.VarType == VariableType.LocalParameter || variable.VarType == VariableType.WithParameter);
varScope = this.scopeManager.VariableScope;
}
VariableAction oldVar = varScope.ResolveVariable(variable.Name);
if (oldVar != null) {
// Other variable with this name is visible in this scope
if (oldVar.IsGlobal) {
if (variable.IsGlobal) {
// Global Vars replace each other base on import presidens odred
if (variable.Stylesheetid == oldVar.Stylesheetid) {
// Both vars are in the same stylesheet
throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
}
else if (variable.Stylesheetid < oldVar.Stylesheetid) {
// newly defined var is more importent
varScope.InsertVariable(variable);
return oldVar.VarKey;
}
else {
// we egnore new variable
return InvalidQueryKey; // We didn't add this var, so doesn't matter what VarKey we return;
}
}
else {
// local variable can shadow global
}
}
else {
// Local variable never can be "shadowed"
throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
}
}
varScope.InsertVariable(variable);
return this.currentTemplate.AllocateVariableSlot();
}
internal void AddNamespaceAlias(String StylesheetURI, NamespaceInfo AliasInfo){
if (this.globalNamespaceAliasTable == null) {
this.globalNamespaceAliasTable = new Hashtable();
}
NamespaceInfo duplicate = this.globalNamespaceAliasTable[StylesheetURI] as NamespaceInfo;
if (duplicate == null || AliasInfo.stylesheetId <= duplicate.stylesheetId) {
this.globalNamespaceAliasTable[StylesheetURI] = AliasInfo;
}
}
internal bool IsNamespaceAlias(String StylesheetURI){
if (this.globalNamespaceAliasTable == null) {
return false;
}
return this.globalNamespaceAliasTable.Contains(StylesheetURI);
}
internal NamespaceInfo FindNamespaceAlias(String StylesheetURI) {
if (this.globalNamespaceAliasTable != null) {
return (NamespaceInfo)this.globalNamespaceAliasTable[StylesheetURI];
}
return null;
}
internal String ResolveXmlNamespace(String prefix) {
return this.scopeManager.ResolveXmlNamespace(prefix);
}
internal String ResolveXPathNamespace(String prefix) {
return this.scopeManager.ResolveXPathNamespace(prefix);
}
internal String DefaultNamespace {
get{ return this.scopeManager.DefaultNamespace; }
}
internal void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey) {
this.rootAction.InsertKey(name, MatchKey, UseKey);
}
internal void AddDecimalFormat(XmlQualifiedName name, DecimalFormat formatinfo) {
this.rootAction.AddDecimalFormat(name, formatinfo);
}
//
// Attribute parsing support
//
// This function is for processing optional attributes only. In case of error
// the value is ignored iff forwards-compatible mode is on.
private string[] ResolvePrefixes(string tokens) {
if (tokens == null || tokens.Length == 0) {
return null;
}
string[] nsList = XmlConvert.SplitString(tokens);
try {
for (int idx = 0; idx < nsList.Length; idx++) {
string prefix = nsList[idx];
nsList[idx] = scopeManager.ResolveXmlNamespace(prefix == "#default" ? string.Empty : prefix);
}
}
catch (XsltException) {
// The only exception here might be Res.Xslt_InvalidPrefix
if (!ForwardCompatibility) {
// Rethrow the exception if we're not in forwards-compatible mode
throw;
}
// Ignore the whole list in forwards-compatible mode
return null;
}
return nsList;
}
internal bool GetYesNo(string value) {
Debug.Assert(value != null);
Debug.Assert((object)value == (object)Input.Value); // this is always true. Why we passing value to this function.
if (value == "yes") {
return true;
}
if (value == "no") {
return false;
}
throw XsltException.Create(Res.Xslt_InvalidAttrValue, Input.LocalName, value);
}
internal string GetSingleAttribute(string attributeAtom) {
NavigatorInput input = Input;
string element = input.LocalName;
string value = null;
if (input.MoveToFirstAttribute()) {
do {
string nspace = input.NamespaceURI;
string name = input.LocalName;
if (nspace.Length != 0) continue;
if (Ref.Equal(name, attributeAtom)) {
value = input.Value;
}
else {
if (! this.ForwardCompatibility) {
throw XsltException.Create(Res.Xslt_InvalidAttribute, name, element);
}
}
}
while (input.MoveToNextAttribute());
input.ToParent();
}
if (value == null) {
throw XsltException.Create(Res.Xslt_MissingAttribute, attributeAtom);
}
return value;
}
internal XmlQualifiedName CreateXPathQName(string qname) {
string prefix, local;
PrefixQName.ParseQualifiedName(qname, out prefix, out local);
return new XmlQualifiedName(local, this.scopeManager.ResolveXPathNamespace(prefix));
}
internal XmlQualifiedName CreateXmlQName(string qname) {
string prefix, local;
PrefixQName.ParseQualifiedName(qname, out prefix, out local);
return new XmlQualifiedName(local, this.scopeManager.ResolveXmlNamespace(prefix));
}
//
// Input documents management
//
internal static XPathDocument LoadDocument(XmlTextReaderImpl reader) {
reader.EntityHandling = EntityHandling.ExpandEntities;
reader.XmlValidatingReaderCompatibilityMode = true;
try {
return new XPathDocument(reader, XmlSpace.Preserve);
}
finally {
reader.Close();
}
}
private void AddDocumentURI(string href) {
Debug.Assert(!this.documentURIs.Contains(href), "Circular references must be checked while processing xsl:include and xsl:import");
this.documentURIs.Add(href, null);
}
private void RemoveDocumentURI(string href) {
Debug.Assert(this.documentURIs.Contains(href), "Attempt to remove href that was not added");
this.documentURIs.Remove(href);
}
internal bool IsCircularReference(string href) {
return this.documentURIs.Contains(href);
}
[ResourceConsumption(ResourceScope.Machine)]
[ResourceExposure(ResourceScope.Machine)]
internal Uri ResolveUri(string relativeUri) {
Debug.Assert(this.xmlResolver != null);
string baseUri = this.Input.BaseURI;
Uri uri = this.xmlResolver.ResolveUri((baseUri.Length != 0) ? this.xmlResolver.ResolveUri(null, baseUri) : null, relativeUri);
if (uri == null) {
throw XsltException.Create(Res.Xslt_CantResolve, relativeUri);
}
return uri;
}
[SuppressMessage("Microsoft.Security.Xml", "CA3068:TextReaderImplNeedsSettingsAndResolver", Justification="XmlResolver is set on XmlTextReaderImpl after it is constructed. Entities have expansion limit - exception granted on Feb 6 2018")]
internal NavigatorInput ResolveDocument(Uri absoluteUri) {
Debug.Assert(this.xmlResolver != null);
object input = this.xmlResolver.GetEntity(absoluteUri, null, null);
string resolved = absoluteUri.ToString();
if (input is Stream) {
XmlTextReaderImpl tr = new XmlTextReaderImpl(resolved, (Stream) input); {
tr.XmlResolver = this.xmlResolver;
}
// reader is closed by Compiler.LoadDocument()
return new NavigatorInput(Compiler.LoadDocument(tr).CreateNavigator(), resolved, rootScope);
}
else if (input is XPathNavigator) {
return new NavigatorInput((XPathNavigator) input, resolved, rootScope);
}
else {
throw XsltException.Create(Res.Xslt_CantResolve, resolved);
}
}
internal void PushInputDocument(NavigatorInput newInput) {
Debug.Assert(newInput != null);
string inputUri = newInput.Href;
AddDocumentURI(inputUri);
newInput.Next = this.input;
this.input = newInput;
this.atoms = this.input.Atoms;
this.scopeManager = this.input.InputScopeManager;
}
internal void PopInputDocument() {
Debug.Assert(this.input != null);
Debug.Assert(this.input.Atoms == this.atoms);
NavigatorInput lastInput = this.input;
this.input = lastInput.Next;
lastInput.Next = null;
if (this.input != null) {
this.atoms = this.input.Atoms;
this.scopeManager = this.input.InputScopeManager;
}
else {
this.atoms = null;
this.scopeManager = null;
}
RemoveDocumentURI(lastInput.Href);
lastInput.Close();
}
//
// Stylesheet management
//
internal void PushStylesheet(Stylesheet stylesheet) {
if (this.stylesheets == null) {
this.stylesheets = new Stack();
}
Debug.Assert(this.stylesheets != null);
this.stylesheets.Push(stylesheet);
this.stylesheet = stylesheet;
}
internal Stylesheet PopStylesheet() {
Debug.Assert(this.stylesheet == this.stylesheets.Peek());
Stylesheet stylesheet = (Stylesheet) this.stylesheets.Pop();
this.stylesheet = (Stylesheet) this.stylesheets.Peek();
return stylesheet;
}
//
// Attribute-Set management
//
internal void AddAttributeSet(AttributeSetAction attributeSet) {
Debug.Assert(this.stylesheet == this.stylesheets.Peek());
this.stylesheet.AddAttributeSet(attributeSet);
}
//
// Template management
//
internal void AddTemplate(TemplateAction template) {
Debug.Assert(this.stylesheet == this.stylesheets.Peek());
this.stylesheet.AddTemplate(template);
}
internal void BeginTemplate(TemplateAction template) {
Debug.Assert(this.currentTemplate != null);
this.currentTemplate = template;
this.currentMode = template.Mode;
this.CanHaveApplyImports = template.MatchKey != Compiler.InvalidQueryKey;
}
internal void EndTemplate() {
Debug.Assert(this.currentTemplate != null);
this.currentTemplate = this.rootAction;
}
internal XmlQualifiedName CurrentMode {
get { return this.currentMode; }
}
//
// Query management
//
internal int AddQuery(string xpathQuery) {
return AddQuery(xpathQuery, /*allowVars:*/true, /*allowKey*/true, false);
}
internal int AddQuery(string xpathQuery, bool allowVar, bool allowKey, bool isPattern) {
Debug.Assert(this.queryStore != null);
CompiledXpathExpr expr;
try {
expr = new CompiledXpathExpr(
(isPattern
? this.queryBuilder.BuildPatternQuery(xpathQuery, allowVar, allowKey)
: this.queryBuilder.Build( xpathQuery, allowVar, allowKey)
),
xpathQuery,
false
);
} catch (XPathException e) {
if (! ForwardCompatibility) {
throw XsltException.Create(Res.Xslt_InvalidXPath, new string[] { xpathQuery }, e);
}
expr = new ErrorXPathExpression(xpathQuery, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
}
this.queryStore.Add(new TheQuery(expr, this.scopeManager));
return this.queryStore.Count - 1;
}
internal int AddStringQuery(string xpathQuery) {
string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "string(" + xpathQuery + ")";
return AddQuery(modifiedQuery);
}
internal int AddBooleanQuery(string xpathQuery) {
string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "boolean(" + xpathQuery + ")";
return AddQuery(modifiedQuery);
}
//
// Script support
//
Hashtable[] _typeDeclsByLang = new Hashtable[] { new Hashtable(), new Hashtable(), new Hashtable() };
ArrayList scriptFiles = new ArrayList();
// Namespaces we always import when compiling
private static string[] _defaultNamespaces = new string[] {
"System",
"System.Collections",
"System.Text",
"System.Text.RegularExpressions",
"System.Xml",
"System.Xml.Xsl",
"System.Xml.XPath",
};
private static int scriptClassCounter = 0;
private static string GenerateUniqueClassName() {
return "ScriptClass_" + System.Threading.Interlocked.Increment(ref scriptClassCounter);
}
internal void AddScript(string source, ScriptingLanguage lang, string ns, string fileName, int lineNumber) {
ValidateExtensionNamespace(ns);
for (ScriptingLanguage langTmp = ScriptingLanguage.JScript; langTmp <= ScriptingLanguage.CSharp; langTmp ++) {
Hashtable typeDecls = _typeDeclsByLang[(int)langTmp];
if (lang == langTmp) {
CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)typeDecls[ns];
if (scriptClass == null) {
scriptClass = new CodeTypeDeclaration(GenerateUniqueClassName());
scriptClass.TypeAttributes = TypeAttributes.Public;
typeDecls.Add(ns, scriptClass);
}
CodeSnippetTypeMember scriptSnippet = new CodeSnippetTypeMember(source);
if (lineNumber > 0) {
scriptSnippet.LinePragma = new CodeLinePragma(fileName, lineNumber);
scriptFiles.Add(fileName);
}
scriptClass.Members.Add(scriptSnippet);
}
else if (typeDecls.Contains(ns)) {
throw XsltException.Create(Res.Xslt_ScriptMixedLanguages, ns);
}
}
}
private static void ValidateExtensionNamespace(string nsUri) {
if (nsUri.Length == 0 || nsUri == XmlReservedNs.NsXslt) {
throw XsltException.Create(Res.Xslt_InvalidExtensionNamespace);
}
XmlConvert.ToUri(nsUri);
}
private void FixCompilerError(CompilerError e) {
foreach(string scriptFile in this.scriptFiles) {
if (e.FileName == scriptFile) {
return; // Yes! this error is in our code sippet.
}
}
e.FileName = string.Empty;
}
CodeDomProvider ChooseCodeDomProvider(ScriptingLanguage lang) {
return (
lang == ScriptingLanguage.JScript ? (CodeDomProvider) Activator.CreateInstance(Type.GetType("Microsoft.JScript.JScriptCodeProvider, " + AssemblyRef.MicrosoftJScript), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null) :
#if !FEATURE_PAL // visualbasic
lang == ScriptingLanguage.VisualBasic ? (CodeDomProvider) new Microsoft.VisualBasic.VBCodeProvider() :
#endif
/*CSharp | default */ (CodeDomProvider) new Microsoft.CSharp.CSharpCodeProvider()
);
}
private void CompileScript(Evidence evidence) {
for (ScriptingLanguage lang = ScriptingLanguage.JScript; lang <= ScriptingLanguage.CSharp; lang ++) {
int idx = (int)lang;
if (_typeDeclsByLang[idx].Count > 0) {
CompileAssembly(lang, _typeDeclsByLang[idx], lang.ToString(), evidence);
}
}
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
// SxS: This method does not take any resource name and does not expose any resources to the caller.
// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
private void CompileAssembly(ScriptingLanguage lang, Hashtable typeDecls, string nsName, Evidence evidence) {
nsName = "Microsoft.Xslt.CompiledScripts." + nsName;
CodeNamespace msXslt = new CodeNamespace(nsName);
// Add all the default namespaces
foreach(string ns in _defaultNamespaces) {
msXslt.Imports.Add(new CodeNamespaceImport(ns));
}
#if !FEATURE_PAL // visualbasic
if (lang == ScriptingLanguage.VisualBasic) {
msXslt.Imports.Add(new CodeNamespaceImport("Microsoft.VisualBasic"));
}
#endif //!FEATURE_PAL
foreach(CodeTypeDeclaration scriptClass in typeDecls.Values) {
msXslt.Types.Add(scriptClass);
}
CodeCompileUnit unit = new CodeCompileUnit(); {
unit.Namespaces.Add(msXslt);
// This settings have sense for Visual Basic only.
// We can consider in future to allow user set them in <xsl:script option="???"> attribute.
unit.UserData["AllowLateBound"] = true; // Allow variables to be undeclared
unit.UserData["RequireVariableDeclaration"] = false; // Allow variables to be declared untyped
}
// We want the assemblies generated for scripts to stick to the old security model
unit.AssemblyCustomAttributes.Add(
new CodeAttributeDeclaration(
new CodeTypeReference(typeof(System.Security.SecurityRulesAttribute)),
new CodeAttributeArgument(
new CodeFieldReferenceExpression(
new CodeTypeReferenceExpression(typeof(System.Security.SecurityRuleSet)), "Level1"))));
CompilerParameters compilParams = new CompilerParameters(); {
try {
new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Assert();
try {
compilParams.GenerateInMemory = true;
#pragma warning disable 618
compilParams.Evidence = evidence;
#pragma warning restore 618
compilParams.ReferencedAssemblies.Add(typeof(XPathNavigator).Module.FullyQualifiedName);
compilParams.ReferencedAssemblies.Add("system.dll");
#if !FEATURE_PAL // visualbasic
if (lang == ScriptingLanguage.VisualBasic) {
compilParams.ReferencedAssemblies.Add("microsoft.visualbasic.dll");
}
#endif // !FEATURE_PAL
}
finally {
CodeAccessPermission.RevertAssert();
}
} catch { throw; }
}
CompilerResults results = ChooseCodeDomProvider(lang).CompileAssemblyFromDom(compilParams, unit);
if (results.Errors.HasErrors) {
StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
foreach (CompilerError e in results.Errors) {
FixCompilerError(e);
stringWriter.WriteLine(e.ToString());
}
throw XsltException.Create(Res.Xslt_ScriptCompileErrors, stringWriter.ToString());
}
Assembly assembly = results.CompiledAssembly;
foreach(DictionaryEntry entry in typeDecls) {
string ns = (string)entry.Key;
CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)entry.Value;
this.stylesheet.ScriptObjectTypes.Add(ns, assembly.GetType(nsName + "." + scriptClass.Name));
}
}
public string GetNsAlias(ref string prefix) {
Debug.Assert(
Ref.Equal(this.input.LocalName, this.input.Atoms.StylesheetPrefix) ||
Ref.Equal(this.input.LocalName, this.input.Atoms.ResultPrefix)
);
if (prefix == "#default") {
prefix = string.Empty;
return this.DefaultNamespace;
}
else {
if (! PrefixQName.ValidatePrefix(prefix)) {
throw XsltException.Create(Res.Xslt_InvalidAttrValue, this.input.LocalName, prefix);
}
return this.ResolveXPathNamespace(prefix);
}
}
// AVT's compilation.
// CompileAvt() returns ArrayList of TextEvent & AvtEvent
private static void getTextLex(string avt, ref int start, StringBuilder lex) {
Debug.Assert(avt.Length != start, "Empty string not supposed here");
Debug.Assert(lex.Length == 0 , "Builder shoud to be reset here");
int avtLength = avt.Length;
int i;
for (i = start; i < avtLength; i ++) {
char ch = avt[i];
if (ch == '{') {
if (i + 1 < avtLength && avt[i + 1] == '{') { // "{{"
i ++;
}
else {
break;
}
}
else if (ch == '}') {
if (i + 1 < avtLength && avt[i + 1] == '}') { // "}}"
i ++;
}
else {
throw XsltException.Create(Res.Xslt_SingleRightAvt, avt);
}
}
lex.Append(ch);
}
start = i;
}
private static void getXPathLex(string avt, ref int start, StringBuilder lex) {
// AVT parser states
const int InExp = 0; // Inside AVT expression
const int InLiteralA = 1; // Inside literal in expression, apostrophe delimited
const int InLiteralQ = 2; // Inside literal in expression, quote delimited
Debug.Assert(avt.Length != start, "Empty string not supposed here");
Debug.Assert(lex.Length == 0 , "Builder shoud to be reset here");
Debug.Assert(avt[start] == '{' , "We calling getXPathLex() only after we realy meet {");
int avtLength = avt.Length;
int state = InExp;
for (int i = start + 1; i < avtLength; i ++) {
char ch = avt[i];
switch(state) {
case InExp :
switch (ch) {
case '{' :
throw XsltException.Create(Res.Xslt_NestedAvt, avt);
case '}' :
i ++; // include '}'
if (i == start + 2) { // empty XPathExpresion
throw XsltException.Create(Res.Xslt_EmptyAvtExpr, avt);
}
lex.Append(avt, start + 1, i - start - 2); // avt without {}
start = i;
return;
case '\'' :
state = InLiteralA;
break;
case '"' :
state = InLiteralQ;
break;
}
break;
case InLiteralA :
if (ch == '\'') {
state = InExp;
}
break;
case InLiteralQ :
if (ch == '"') {
state = InExp;
}
break;
}
}
// if we meet end of string before } we have an error
throw XsltException.Create(state == InExp ? Res.Xslt_OpenBracesAvt : Res.Xslt_OpenLiteralAvt, avt);
}
private static bool GetNextAvtLex(string avt, ref int start, StringBuilder lex, out bool isAvt) {
Debug.Assert(start <= avt.Length);
#if DEBUG
int saveStart = start;
#endif
isAvt = false;
if (start == avt.Length) {
return false;
}
lex.Length = 0;
getTextLex(avt, ref start, lex);
if (lex.Length == 0) {
isAvt = true;
getXPathLex(avt, ref start, lex);
}
#if DEBUG
Debug.Assert(saveStart < start, "We have to read something. Otherwise it's dead loop.");
#endif
return true;
}
internal ArrayList CompileAvt(string avtText, out bool constant) {
Debug.Assert(avtText != null);
ArrayList list = new ArrayList();
constant = true;
/* Parse input.Value as AVT */ {
int pos = 0;
bool isAvt;
while (GetNextAvtLex(avtText, ref pos, this.AvtStringBuilder, out isAvt)) {
string lex = this.AvtStringBuilder.ToString();
if (isAvt) {
list.Add(new AvtEvent(this.AddStringQuery(lex)));
constant = false;
}
else {
list.Add(new TextEvent(lex));
}
}
}
Debug.Assert(!constant || list.Count <= 1, "We can't have more then 1 text event if now {avt} found");
return list;
}
internal ArrayList CompileAvt(string avtText) {
bool constant;
return CompileAvt(avtText, out constant);
}
// Compiler is a class factory for some actions:
// CompilerDbg override all this methods:
public virtual ApplyImportsAction CreateApplyImportsAction() {
ApplyImportsAction action = new ApplyImportsAction();
action.Compile(this);
return action;
}
public virtual ApplyTemplatesAction CreateApplyTemplatesAction() {
ApplyTemplatesAction action = new ApplyTemplatesAction();
action.Compile(this);
return action;
}
public virtual AttributeAction CreateAttributeAction() {
AttributeAction action = new AttributeAction();
action.Compile(this);
return action;
}
public virtual AttributeSetAction CreateAttributeSetAction() {
AttributeSetAction action = new AttributeSetAction();
action.Compile(this);
return action;
}
public virtual CallTemplateAction CreateCallTemplateAction() {
CallTemplateAction action = new CallTemplateAction();
action.Compile(this);
return action;
}
public virtual ChooseAction CreateChooseAction() {//!!! don't need to be here
ChooseAction action = new ChooseAction();
action.Compile(this);
return action;
}
public virtual CommentAction CreateCommentAction() {
CommentAction action = new CommentAction();
action.Compile(this);
return action;
}
public virtual CopyAction CreateCopyAction() {
CopyAction action = new CopyAction();
action.Compile(this);
return action;
}
public virtual CopyOfAction CreateCopyOfAction() {
CopyOfAction action = new CopyOfAction();
action.Compile(this);
return action;
}
public virtual ElementAction CreateElementAction() {
ElementAction action = new ElementAction();
action.Compile(this);
return action;
}
public virtual ForEachAction CreateForEachAction() {
ForEachAction action = new ForEachAction();
action.Compile(this);
return action;
}
public virtual IfAction CreateIfAction(IfAction.ConditionType type) {
IfAction action = new IfAction(type);
action.Compile(this);
return action;
}
public virtual MessageAction CreateMessageAction() {
MessageAction action = new MessageAction();
action.Compile(this);
return action;
}
public virtual NewInstructionAction CreateNewInstructionAction() {
NewInstructionAction action = new NewInstructionAction();
action.Compile(this);
return action;
}
public virtual NumberAction CreateNumberAction() {
NumberAction action = new NumberAction();
action.Compile(this);
return action;
}
public virtual ProcessingInstructionAction CreateProcessingInstructionAction() {
ProcessingInstructionAction action = new ProcessingInstructionAction();
action.Compile(this);
return action;
}
public virtual void CreateRootAction() {
this.RootAction = new RootAction();
this.RootAction.Compile(this);
}
public virtual SortAction CreateSortAction() {
SortAction action = new SortAction();
action.Compile(this);
return action;
}
public virtual TemplateAction CreateTemplateAction() {
TemplateAction action = new TemplateAction();
action.Compile(this);
return action;
}
public virtual TemplateAction CreateSingleTemplateAction() {
TemplateAction action = new TemplateAction();
action.CompileSingle(this);
return action;
}
public virtual TextAction CreateTextAction() {
TextAction action = new TextAction();
action.Compile(this);
return action;
}
public virtual UseAttributeSetsAction CreateUseAttributeSetsAction() {
UseAttributeSetsAction action = new UseAttributeSetsAction();
action.Compile(this);
return action;
}
public virtual ValueOfAction CreateValueOfAction() {
ValueOfAction action = new ValueOfAction();
action.Compile(this);
return action;
}
public virtual VariableAction CreateVariableAction(VariableType type) {
VariableAction action = new VariableAction(type);
action.Compile(this);
if (action.VarKey != InvalidQueryKey) {
return action;
}
else {
return null;
}
}
public virtual WithParamAction CreateWithParamAction() {
WithParamAction action = new WithParamAction();
action.Compile(this);
return action;
}
// Compiler is a class factory for some events:
// CompilerDbg override all this methods:
public virtual BeginEvent CreateBeginEvent() {
return new BeginEvent(this);
}
public virtual TextEvent CreateTextEvent() {
return new TextEvent(this);
}
public XsltException UnexpectedKeyword() {
XPathNavigator nav = this.Input.Navigator.Clone();
string thisName = nav.Name;
nav.MoveToParent();
string parentName = nav.Name;
return XsltException.Create(Res.Xslt_UnexpectedKeyword, thisName, parentName);
}
internal class ErrorXPathExpression : CompiledXpathExpr {
private string baseUri;
private int lineNumber, linePosition;
public ErrorXPathExpression(string expression, string baseUri, int lineNumber, int linePosition)
: base(null, expression, false)
{
this.baseUri = baseUri;
this.lineNumber = lineNumber;
this.linePosition = linePosition;
}
public override XPathExpression Clone() { return this; }
public override void CheckErrors() {
throw new XsltException(Res.Xslt_InvalidXPath, new string[] { Expression }, baseUri, linePosition, lineNumber, null);
}
}
}
}
|