1 //------------------------------------------------------------------------------
2 // <copyright file="Processor.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System.Xml.Xsl.XsltOld {
9 using Res = System.Xml.Utils.Res;
10 using System.Globalization;
11 using System.Diagnostics;
13 using System.Xml.XPath;
14 using MS.Internal.Xml.XPath;
16 using System.Collections;
17 using System.Collections.Generic;
18 using System.Xml.Xsl.XsltOld.Debugger;
19 using System.Reflection;
20 using System.Security;
22 internal sealed class Processor : IXsltProcessor {
27 const int StackIncrement = 10;
33 internal enum ExecResult {
34 Continue, // Continues next iteration immediately
35 Interrupt, // Returns to caller, was processed enough
36 Done // Execution finished
39 internal enum OutputResult {
47 private ExecResult execResult;
50 // Compiled stylesheet
53 private Stylesheet stylesheet; // Root of import tree of template managers
54 private RootAction rootAction;
55 private Key[] keyList;
56 private List<TheQuery> queryStore;
57 public PermissionSet permissions; // used by XsltCompiledContext in document and extension functions
60 // Document Being transformed
63 private XPathNavigator document;
66 // Execution action stack
69 private HWStack actionStack;
70 private HWStack debuggerStack;
73 // Register for returning value from calling nested action
76 private StringBuilder sharedStringBuilder;
79 // Output related member variables
83 RecordBuilder builder;
87 XmlNameTable nameTable = new NameTable();
91 #pragma warning disable 618
92 XsltArgumentList args;
93 #pragma warning restore 618
94 Hashtable scriptExtensions;
98 // Template lookup action
101 TemplateLookupAction templateLookup = new TemplateLookupAction();
103 private IXsltDebugger debugger;
106 private ArrayList sortArray;
108 private Hashtable documentCache;
110 // NOTE: ValueOf() can call Matches() through XsltCompileContext.PreserveWhitespace(),
111 // that's why we use two different contexts here, valueOfContext and matchesContext
112 private XsltCompileContext valueOfContext;
113 private XsltCompileContext matchesContext;
115 internal XPathNavigator Current {
117 ActionFrame frame = (ActionFrame) this.actionStack.Peek();
118 return frame != null ? frame.Node : null;
122 internal ExecResult ExecutionResult {
123 get { return this.execResult; }
126 Debug.Assert(this.execResult == ExecResult.Continue);
127 this.execResult = value;
131 internal Stylesheet Stylesheet {
132 get { return this.stylesheet; }
135 internal XmlResolver Resolver {
137 Debug.Assert(this.resolver != null, "Constructor should create it if null passed");
138 return this.resolver;
142 internal ArrayList SortArray {
144 Debug.Assert(this.sortArray != null, "InitSortArray() wasn't called");
145 return this.sortArray;
149 internal Key[] KeyList {
150 get { return this.keyList; }
153 internal XPathNavigator GetNavigator(Uri ruri) {
154 XPathNavigator result = null;
155 if (documentCache != null) {
156 result = documentCache[ruri] as XPathNavigator;
157 if (result != null) {
158 return result.Clone();
162 documentCache = new Hashtable();
165 Object input = resolver.GetEntity(ruri, null, null);
166 if (input is Stream) {
167 XmlTextReaderImpl tr = new XmlTextReaderImpl(ruri.ToString(), (Stream) input); {
168 tr.XmlResolver = this.resolver;
170 // reader is closed by Compiler.LoadDocument()
171 result = ((IXPathNavigable)Compiler.LoadDocument(tr)).CreateNavigator();
173 else if (input is XPathNavigator){
174 result = (XPathNavigator) input;
177 throw XsltException.Create(Res.Xslt_CantResolve, ruri.ToString());
179 documentCache[ruri] = result.Clone();
183 internal void AddSort(Sort sortinfo) {
184 Debug.Assert(this.sortArray != null, "InitSortArray() wasn't called");
185 this.sortArray.Add(sortinfo);
188 internal void InitSortArray() {
189 if (this.sortArray == null) {
190 this.sortArray = new ArrayList();
193 this.sortArray.Clear();
197 internal object GetGlobalParameter(XmlQualifiedName qname) {
198 object parameter = args.GetParam(qname.Name, qname.Namespace);
199 if (parameter == null) {
204 parameter is XPathNodeIterator ||
205 parameter is XPathNavigator ||
206 parameter is Boolean ||
207 parameter is Double ||
212 parameter is Int16 || parameter is UInt16 ||
213 parameter is Int32 || parameter is UInt32 ||
214 parameter is Int64 || parameter is UInt64 ||
215 parameter is Single || parameter is Decimal
217 parameter = XmlConvert.ToXPathDouble(parameter);
219 parameter = parameter.ToString();
224 internal object GetExtensionObject(string nsUri) {
225 return args.GetExtensionObject(nsUri);
228 internal object GetScriptObject(string nsUri) {
229 return scriptExtensions[nsUri];
232 internal RootAction RootAction {
233 get { return this.rootAction; }
236 internal XPathNavigator Document {
237 get { return this.document; }
241 private bool stringBuilderLocked = false;
244 internal StringBuilder GetSharedStringBuilder() {
246 Debug.Assert(! stringBuilderLocked);
248 if (sharedStringBuilder == null) {
249 sharedStringBuilder = new StringBuilder();
252 sharedStringBuilder.Length = 0;
255 stringBuilderLocked = true;
257 return sharedStringBuilder;
260 internal void ReleaseSharedStringBuilder() {
261 // don't clean stringBuilderLocked here. ToString() will happen after this call
263 stringBuilderLocked = false;
267 internal ArrayList NumberList {
269 if (this.numberList == null) {
270 this.numberList = new ArrayList();
272 return this.numberList;
276 internal IXsltDebugger Debugger {
277 get { return this.debugger; }
280 internal HWStack ActionStack {
281 get { return this.actionStack; }
284 internal RecordBuilder Builder {
285 get { return this.builder; }
288 internal XsltOutput Output {
289 get { return this.output; }
296 XPathNavigator doc, XsltArgumentList args, XmlResolver resolver,
297 Stylesheet stylesheet, List<TheQuery> queryStore, RootAction rootAction,
298 IXsltDebugger debugger
300 this.stylesheet = stylesheet;
301 this.queryStore = queryStore;
302 this.rootAction = rootAction;
303 this.queryList = new Query[queryStore.Count]; {
304 for(int i = 0; i < queryStore.Count; i ++) {
305 queryList[i] = Query.Clone(queryStore[i].CompiledQuery.QueryTree);
309 this.xsm = new StateMachine();
312 this.actionStack = new HWStack(StackIncrement);
313 this.output = this.rootAction.Output;
314 this.permissions = this.rootAction.permissions;
315 this.resolver = resolver ?? XmlNullResolver.Singleton;
316 this.args = args ?? new XsltArgumentList();
317 this.debugger = debugger;
318 if (this.debugger != null) {
319 this.debuggerStack = new HWStack(StackIncrement, /*limit:*/1000);
320 templateLookup = new TemplateLookupActionDbg();
323 // Clone the compile-time KeyList
324 if (this.rootAction.KeyList != null) {
325 this.keyList = new Key[this.rootAction.KeyList.Count];
326 for (int i = 0; i < this.keyList.Length; i ++) {
327 this.keyList[i] = this.rootAction.KeyList[i].Clone();
331 this.scriptExtensions = new Hashtable(this.stylesheet.ScriptObjectTypes.Count); {
332 foreach(DictionaryEntry entry in this.stylesheet.ScriptObjectTypes) {
333 string namespaceUri = (string)entry.Key;
334 if (GetExtensionObject(namespaceUri) != null) {
335 throw XsltException.Create(Res.Xslt_ScriptDub, namespaceUri);
337 scriptExtensions.Add(namespaceUri, Activator.CreateInstance((Type)entry.Value,
338 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null));
342 this.PushActionFrame(this.rootAction, /*nodeSet:*/null);
345 public ReaderOutput StartReader() {
346 ReaderOutput output = new ReaderOutput(this);
347 this.builder = new RecordBuilder(output, this.nameTable);
351 public void Execute(Stream stream) {
352 RecordOutput recOutput = null;
354 switch (this.output.Method) {
355 case XsltOutput.OutputMethod.Text:
356 recOutput = new TextOnlyOutput(this, stream);
358 case XsltOutput.OutputMethod.Xml:
359 case XsltOutput.OutputMethod.Html:
360 case XsltOutput.OutputMethod.Other:
361 case XsltOutput.OutputMethod.Unknown:
362 recOutput = new TextOutput(this, stream);
365 this.builder = new RecordBuilder(recOutput, this.nameTable);
369 public void Execute(TextWriter writer) {
370 RecordOutput recOutput = null;
372 switch (this.output.Method) {
373 case XsltOutput.OutputMethod.Text:
374 recOutput = new TextOnlyOutput(this, writer);
376 case XsltOutput.OutputMethod.Xml:
377 case XsltOutput.OutputMethod.Html:
378 case XsltOutput.OutputMethod.Other:
379 case XsltOutput.OutputMethod.Unknown:
380 recOutput = new TextOutput(this, writer);
383 this.builder = new RecordBuilder(recOutput, this.nameTable);
387 public void Execute(XmlWriter writer) {
388 this.builder = new RecordBuilder(new WriterOutput(this, writer), this.nameTable);
393 // Execution part of processor
395 internal void Execute() {
396 Debug.Assert(this.actionStack != null);
398 while (this.execResult == ExecResult.Continue) {
399 ActionFrame frame = (ActionFrame) this.actionStack.Peek();
402 Debug.Assert(this.builder != null);
403 this.builder.TheEnd();
404 ExecutionResult = ExecResult.Done;
408 // Execute the action which was on the top of the stack
409 if (frame.Execute(this)) {
410 this.actionStack.Pop();
414 if (this.execResult == ExecResult.Interrupt) {
415 this.execResult = ExecResult.Continue;
420 // Action frame support
423 internal ActionFrame PushNewFrame() {
424 ActionFrame prent = (ActionFrame) this.actionStack.Peek();
425 ActionFrame frame = (ActionFrame) this.actionStack.Push();
427 frame = new ActionFrame();
428 this.actionStack.AddToTop(frame);
430 Debug.Assert(frame != null);
433 frame.Inherit(prent);
439 internal void PushActionFrame(Action action, XPathNodeIterator nodeSet) {
440 ActionFrame frame = PushNewFrame();
441 frame.Init(action, nodeSet);
444 internal void PushActionFrame(ActionFrame container) {
445 this.PushActionFrame(container, container.NodeSet);
448 internal void PushActionFrame(ActionFrame container, XPathNodeIterator nodeSet) {
449 ActionFrame frame = PushNewFrame();
450 frame.Init(container, nodeSet);
453 internal void PushTemplateLookup(XPathNodeIterator nodeSet, XmlQualifiedName mode, Stylesheet importsOf) {
454 Debug.Assert(this.templateLookup != null);
455 this.templateLookup.Initialize(mode, importsOf);
456 PushActionFrame(this.templateLookup, nodeSet);
459 internal string GetQueryExpression(int key) {
460 Debug.Assert(key != Compiler.InvalidQueryKey);
461 return this.queryStore[key].CompiledQuery.Expression;
464 internal Query GetCompiledQuery(int key) {
465 Debug.Assert(key != Compiler.InvalidQueryKey);
466 TheQuery theQuery = this.queryStore[key];
467 theQuery.CompiledQuery.CheckErrors();
468 Query expr = Query.Clone(this.queryList[key]);
469 expr.SetXsltContext(new XsltCompileContext(theQuery._ScopeManager, this));
473 internal Query GetValueQuery(int key) {
474 return GetValueQuery(key, null);
477 internal Query GetValueQuery(int key, XsltCompileContext context) {
478 Debug.Assert(key != Compiler.InvalidQueryKey);
479 TheQuery theQuery = this.queryStore[key];
480 theQuery.CompiledQuery.CheckErrors();
481 Query expr = this.queryList[key];
483 if (context == null) {
484 context = new XsltCompileContext(theQuery._ScopeManager, this);
486 context.Reinitialize(theQuery._ScopeManager, this);
489 expr.SetXsltContext(context);
493 private XsltCompileContext GetValueOfContext() {
494 if (this.valueOfContext == null) {
495 this.valueOfContext = new XsltCompileContext();
497 return this.valueOfContext;
500 [Conditional("DEBUG")]
501 private void RecycleValueOfContext() {
502 if (this.valueOfContext != null) {
503 this.valueOfContext.Recycle();
507 private XsltCompileContext GetMatchesContext() {
508 if (this.matchesContext == null) {
509 this.matchesContext = new XsltCompileContext();
511 return this.matchesContext;
514 [Conditional("DEBUG")]
515 private void RecycleMatchesContext() {
516 if (this.matchesContext != null) {
517 this.matchesContext.Recycle();
521 internal String ValueOf(ActionFrame context, int key) {
524 Query query = this.GetValueQuery(key, GetValueOfContext());
525 object value = query.Evaluate(context.NodeSet);
526 if (value is XPathNodeIterator) {
527 XPathNavigator n = query.Advance();
528 result = n != null ? ValueOf(n) : string.Empty;
530 result = XmlConvert.ToXPathString(value);
533 RecycleValueOfContext();
537 internal String ValueOf(XPathNavigator n) {
538 if (this.stylesheet.Whitespace && n.NodeType == XPathNodeType.Element) {
539 StringBuilder builder = this.GetSharedStringBuilder();
540 ElementValueWithoutWS(n, builder);
541 this.ReleaseSharedStringBuilder();
542 return builder.ToString();
547 private void ElementValueWithoutWS(XPathNavigator nav, StringBuilder builder) {
548 Debug.Assert(nav.NodeType == XPathNodeType.Element);
549 bool preserve = this.Stylesheet.PreserveWhiteSpace(this, nav);
550 if (nav.MoveToFirstChild()) {
552 switch (nav.NodeType) {
553 case XPathNodeType.Text :
554 case XPathNodeType.SignificantWhitespace :
555 builder.Append(nav.Value);
557 case XPathNodeType.Whitespace :
559 builder.Append(nav.Value);
562 case XPathNodeType.Element :
563 ElementValueWithoutWS(nav, builder);
566 }while (nav.MoveToNext());
571 internal XPathNodeIterator StartQuery(XPathNodeIterator context, int key) {
572 Query query = GetCompiledQuery(key);
573 object result = query.Evaluate(context);
574 if (result is XPathNodeIterator) {
575 // ToDo: We create XPathSelectionIterator to count positions, but it's better create special query in this case at compile time.
576 return new XPathSelectionIterator(context.Current, query);
578 throw XsltException.Create(Res.XPath_NodeSetExpected);
581 internal object Evaluate(ActionFrame context, int key) {
582 return GetValueQuery(key).Evaluate(context.NodeSet);
585 internal object RunQuery(ActionFrame context, int key) {
586 Query query = GetCompiledQuery(key);
587 object value = query.Evaluate(context.NodeSet);
588 XPathNodeIterator it = value as XPathNodeIterator;
590 return new XPathArrayIterator(it);
596 internal string EvaluateString(ActionFrame context, int key) {
597 object objValue = Evaluate(context, key);
599 if (objValue != null)
600 value = XmlConvert.ToXPathString(objValue);
602 value = string.Empty;
606 internal bool EvaluateBoolean(ActionFrame context, int key) {
607 object objValue = Evaluate(context, key);
609 if (objValue != null) {
610 XPathNavigator nav = objValue as XPathNavigator;
611 return nav != null ? Convert.ToBoolean(nav.Value, CultureInfo.InvariantCulture) : Convert.ToBoolean(objValue, CultureInfo.InvariantCulture);
618 internal bool Matches(XPathNavigator context, int key) {
619 // We don't use XPathNavigator.Matches() to avoid cloning of Query on each call
620 Query query = this.GetValueQuery(key, GetMatchesContext());
623 bool result = query.MatchNode(context) != null;
625 RecycleMatchesContext();
627 } catch(XPathException) {
628 throw XsltException.Create(Res.Xslt_InvalidPattern, this.GetQueryExpression(key));
633 // Outputting part of processor
636 internal XmlNameTable NameTable {
637 get { return this.nameTable; }
640 internal bool CanContinue {
641 get { return this.execResult == ExecResult.Continue; }
644 internal bool ExecutionDone {
645 get { return this.execResult == ExecResult.Done; }
648 internal void ResetOutput() {
649 Debug.Assert(this.builder != null);
650 this.builder.Reset();
652 internal bool BeginEvent(XPathNodeType nodeType, string prefix, string name, string nspace, bool empty) {
653 return BeginEvent(nodeType, prefix, name, nspace, empty, null, true);
656 internal bool BeginEvent(XPathNodeType nodeType, string prefix, string name, string nspace, bool empty, Object htmlProps, bool search) {
657 Debug.Assert(this.xsm != null);
659 int stateOutlook = this.xsm.BeginOutlook(nodeType);
661 if (this.ignoreLevel > 0 || stateOutlook == StateMachine.Error) {
663 return true; // We consumed the event, so pretend it was output.
666 switch (this.builder.BeginEvent(stateOutlook, nodeType, prefix, name, nspace, empty, htmlProps, search)) {
667 case OutputResult.Continue:
668 this.xsm.Begin(nodeType);
669 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
670 Debug.Assert(ExecutionResult == ExecResult.Continue);
672 case OutputResult.Interrupt:
673 this.xsm.Begin(nodeType);
674 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
675 ExecutionResult = ExecResult.Interrupt;
677 case OutputResult.Overflow:
678 ExecutionResult = ExecResult.Interrupt;
680 case OutputResult.Error:
683 case OutputResult.Ignore:
686 Debug.Fail("Unexpected result of RecordBuilder.BeginEvent()");
691 internal bool TextEvent(string text) {
692 return this.TextEvent(text, false);
695 internal bool TextEvent(string text, bool disableOutputEscaping) {
696 Debug.Assert(this.xsm != null);
698 if (this.ignoreLevel > 0) {
702 int stateOutlook = this.xsm.BeginOutlook(XPathNodeType.Text);
704 switch (this.builder.TextEvent(stateOutlook, text, disableOutputEscaping)) {
705 case OutputResult.Continue:
706 this.xsm.Begin(XPathNodeType.Text);
707 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
708 Debug.Assert(ExecutionResult == ExecResult.Continue);
710 case OutputResult.Interrupt:
711 this.xsm.Begin(XPathNodeType.Text);
712 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
713 ExecutionResult = ExecResult.Interrupt;
715 case OutputResult.Overflow:
716 ExecutionResult = ExecResult.Interrupt;
718 case OutputResult.Error:
719 case OutputResult.Ignore:
722 Debug.Fail("Unexpected result of RecordBuilder.TextEvent()");
727 internal bool EndEvent(XPathNodeType nodeType) {
728 Debug.Assert(this.xsm != null);
730 if (this.ignoreLevel > 0) {
735 int stateOutlook = this.xsm.EndOutlook(nodeType);
737 switch (this.builder.EndEvent(stateOutlook, nodeType)) {
738 case OutputResult.Continue:
739 this.xsm.End(nodeType);
740 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
742 case OutputResult.Interrupt:
743 this.xsm.End(nodeType);
744 Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State,
745 "StateMachine.StateOnly(stateOutlook) == this.xsm.State");
746 ExecutionResult = ExecResult.Interrupt;
748 case OutputResult.Overflow:
749 ExecutionResult = ExecResult.Interrupt;
751 case OutputResult.Error:
752 case OutputResult.Ignore:
754 Debug.Fail("Unexpected result of RecordBuilder.TextEvent()");
759 internal bool CopyBeginEvent(XPathNavigator node, bool emptyflag) {
760 switch (node.NodeType) {
761 case XPathNodeType.Element:
762 case XPathNodeType.Attribute:
763 case XPathNodeType.ProcessingInstruction:
764 case XPathNodeType.Comment:
765 return BeginEvent(node.NodeType, node.Prefix, node.LocalName, node.NamespaceURI, emptyflag);
766 case XPathNodeType.Namespace:
767 // value instead of namespace here!
768 return BeginEvent(XPathNodeType.Namespace, null, node.LocalName, node.Value, false);
769 case XPathNodeType.Text:
770 // Text will be copied in CopyContents();
773 case XPathNodeType.Root:
774 case XPathNodeType.Whitespace:
775 case XPathNodeType.SignificantWhitespace:
776 case XPathNodeType.All:
780 Debug.Fail("Invalid XPathNodeType in CopyBeginEvent");
787 internal bool CopyTextEvent(XPathNavigator node) {
788 switch (node.NodeType) {
789 case XPathNodeType.Element:
790 case XPathNodeType.Namespace:
793 case XPathNodeType.Attribute:
794 case XPathNodeType.ProcessingInstruction:
795 case XPathNodeType.Comment:
796 case XPathNodeType.Text:
797 case XPathNodeType.Whitespace:
798 case XPathNodeType.SignificantWhitespace:
799 string text = node.Value;
800 return TextEvent(text);
802 case XPathNodeType.Root:
803 case XPathNodeType.All:
807 Debug.Fail("Invalid XPathNodeType in CopyTextEvent");
814 internal bool CopyEndEvent(XPathNavigator node) {
815 switch (node.NodeType) {
816 case XPathNodeType.Element:
817 case XPathNodeType.Attribute:
818 case XPathNodeType.ProcessingInstruction:
819 case XPathNodeType.Comment:
820 case XPathNodeType.Namespace:
821 return EndEvent(node.NodeType);
823 case XPathNodeType.Text:
824 // Text was copied in CopyContents();
828 case XPathNodeType.Root:
829 case XPathNodeType.Whitespace:
830 case XPathNodeType.SignificantWhitespace:
831 case XPathNodeType.All:
835 Debug.Fail("Invalid XPathNodeType in CopyEndEvent");
842 internal static bool IsRoot(XPathNavigator navigator) {
843 Debug.Assert(navigator != null);
845 if (navigator.NodeType == XPathNodeType.Root) {
848 else if (navigator.NodeType == XPathNodeType.Element) {
849 XPathNavigator clone = navigator.Clone();
851 return clone.IsSamePosition(navigator);
861 internal void PushOutput(RecordOutput output) {
862 Debug.Assert(output != null);
863 this.builder.OutputState = this.xsm.State;
864 RecordBuilder lastBuilder = this.builder;
865 this.builder = new RecordBuilder(output, this.nameTable);
866 this.builder.Next = lastBuilder;
871 internal RecordOutput PopOutput() {
872 Debug.Assert(this.builder != null);
874 RecordBuilder topBuilder = this.builder;
875 this.builder = topBuilder.Next;
876 this.xsm.State = this.builder.OutputState;
880 return topBuilder.Output;
883 internal bool SetDefaultOutput(XsltOutput.OutputMethod method) {
884 if(Output.Method != method) {
885 this.output = this.output.CreateDerivedOutput(method);
891 internal object GetVariableValue(VariableAction variable) {
892 int variablekey = variable.VarKey;
893 if (variable.IsGlobal) {
894 ActionFrame rootFrame = (ActionFrame) this.actionStack[0];
895 object result = rootFrame.GetVariable(variablekey);
896 if (result == VariableAction.BeingComputedMark) {
897 throw XsltException.Create(Res.Xslt_CircularReference, variable.NameStr);
899 if (result != null) {
902 // Variable wasn't evaluated yet
903 int saveStackSize = this.actionStack.Length;
904 ActionFrame varFrame = PushNewFrame();
905 varFrame.Inherit(rootFrame);
906 varFrame.Init(variable, rootFrame.NodeSet);
908 bool endOfFrame = ((ActionFrame) this.actionStack.Peek()).Execute(this);
910 this.actionStack.Pop();
912 } while (saveStackSize < this.actionStack.Length);
913 Debug.Assert(saveStackSize == this.actionStack.Length);
914 result = rootFrame.GetVariable(variablekey);
915 Debug.Assert(result != null, "Variable was just calculated and result can't be null");
918 return ((ActionFrame) this.actionStack.Peek()).GetVariable(variablekey);
922 internal void SetParameter(XmlQualifiedName name, object value) {
923 Debug.Assert(1 < actionStack.Length);
924 ActionFrame parentFrame = (ActionFrame) this.actionStack[actionStack.Length - 2];
925 parentFrame.SetParameter(name, value);
928 internal void ResetParams() {
929 ActionFrame frame = (ActionFrame) this.actionStack[actionStack.Length - 1];
933 internal object GetParameter(XmlQualifiedName name) {
934 Debug.Assert(2 < actionStack.Length);
935 ActionFrame parentFrame = (ActionFrame) this.actionStack[actionStack.Length - 3];
936 return parentFrame.GetParameter(name);
939 // ---------------------- Debugger stack -----------------------
941 internal class DebuggerFrame {
942 internal ActionFrame actionFrame;
943 internal XmlQualifiedName currentMode;
946 internal void PushDebuggerStack() {
947 Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
948 DebuggerFrame dbgFrame = (DebuggerFrame) this.debuggerStack.Push();
949 if (dbgFrame == null) {
950 dbgFrame = new DebuggerFrame();
951 this.debuggerStack.AddToTop(dbgFrame);
953 dbgFrame.actionFrame = (ActionFrame) this.actionStack.Peek(); // In a case of next builtIn action.
956 internal void PopDebuggerStack() {
957 Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
958 this.debuggerStack.Pop();
961 internal void OnInstructionExecute() {
962 Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
963 DebuggerFrame dbgFrame = (DebuggerFrame) this.debuggerStack.Peek();
964 Debug.Assert(dbgFrame != null, "PushDebuggerStack() wasn't ever called");
965 dbgFrame.actionFrame = (ActionFrame) this.actionStack.Peek();
966 this.Debugger.OnInstructionExecute((IXsltProcessor) this);
969 internal XmlQualifiedName GetPrevioseMode() {
970 Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
971 Debug.Assert(2 <= this.debuggerStack.Length);
972 return ((DebuggerFrame) this.debuggerStack[this.debuggerStack.Length - 2]).currentMode;
975 internal void SetCurrentMode(XmlQualifiedName mode) {
976 Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
977 ((DebuggerFrame) this.debuggerStack[this.debuggerStack.Length - 1]).currentMode = mode;
980 // ----------------------- IXsltProcessor : --------------------
981 int IXsltProcessor.StackDepth {
982 get {return this.debuggerStack.Length;}
985 IStackFrame IXsltProcessor.GetStackFrame(int depth) {
986 return ((DebuggerFrame) this.debuggerStack[depth]).actionFrame;