summaryrefslogtreecommitdiffstats
path: root/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xslt/xslt/txStylesheetCompileHandlers.cpp')
-rw-r--r--dom/xslt/xslt/txStylesheetCompileHandlers.cpp2944
1 files changed, 2944 insertions, 0 deletions
diff --git a/dom/xslt/xslt/txStylesheetCompileHandlers.cpp b/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
new file mode 100644
index 000000000..4d451e3c3
--- /dev/null
+++ b/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
@@ -0,0 +1,2944 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/FloatingPoint.h"
+#include "mozilla/Move.h"
+
+#include "txStylesheetCompiler.h"
+#include "txStylesheetCompileHandlers.h"
+#include "nsWhitespaceTokenizer.h"
+#include "txInstructions.h"
+#include "nsGkAtoms.h"
+#include "txCore.h"
+#include "txStringUtils.h"
+#include "txStylesheet.h"
+#include "txToplevelItems.h"
+#include "txPatternParser.h"
+#include "txNamespaceMap.h"
+#include "txURIUtils.h"
+#include "txXSLTFunctions.h"
+
+using namespace mozilla;
+
+txHandlerTable* gTxIgnoreHandler = 0;
+txHandlerTable* gTxRootHandler = 0;
+txHandlerTable* gTxEmbedHandler = 0;
+txHandlerTable* gTxTopHandler = 0;
+txHandlerTable* gTxTemplateHandler = 0;
+txHandlerTable* gTxTextHandler = 0;
+txHandlerTable* gTxApplyTemplatesHandler = 0;
+txHandlerTable* gTxCallTemplateHandler = 0;
+txHandlerTable* gTxVariableHandler = 0;
+txHandlerTable* gTxForEachHandler = 0;
+txHandlerTable* gTxTopVariableHandler = 0;
+txHandlerTable* gTxChooseHandler = 0;
+txHandlerTable* gTxParamHandler = 0;
+txHandlerTable* gTxImportHandler = 0;
+txHandlerTable* gTxAttributeSetHandler = 0;
+txHandlerTable* gTxFallbackHandler = 0;
+
+static nsresult
+txFnStartLRE(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState);
+static nsresult
+txFnEndLRE(txStylesheetCompilerState& aState);
+
+
+#define TX_RETURN_IF_WHITESPACE(_str, _state) \
+ do { \
+ if (!_state.mElementContext->mPreserveWhitespace && \
+ XMLUtils::isWhitespace(PromiseFlatString(_str))) { \
+ return NS_OK; \
+ } \
+ } while(0)
+
+
+static nsresult
+getStyleAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ int32_t aNamespace,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetAttr** aAttr)
+{
+ int32_t i;
+ for (i = 0; i < aAttrCount; ++i) {
+ txStylesheetAttr* attr = aAttributes + i;
+ if (attr->mNamespaceID == aNamespace &&
+ attr->mLocalName == aName) {
+ attr->mLocalName = nullptr;
+ *aAttr = attr;
+
+ return NS_OK;
+ }
+ }
+ *aAttr = nullptr;
+
+ if (aRequired) {
+ // XXX ErrorReport: missing required attribute
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+parseUseAttrSets(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ bool aInXSLTNS,
+ txStylesheetCompilerState& aState)
+{
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount,
+ aInXSLTNS ? kNameSpaceID_XSLT
+ : kNameSpaceID_None,
+ nsGkAtoms::useAttributeSets, false,
+ &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ nsWhitespaceTokenizer tok(attr->mValue);
+ while (tok.hasMoreTokens()) {
+ txExpandedName name;
+ rv = name.init(tok.nextToken(), aState.mElementContext->mMappings,
+ false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(new txInsertAttrSet(name));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ return NS_OK;
+}
+
+static nsresult
+parseExcludeResultPrefixes(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ int32_t aNamespaceID)
+{
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, aNamespaceID,
+ nsGkAtoms::excludeResultPrefixes, false,
+ &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ // XXX Needs to be implemented.
+
+ return NS_OK;
+}
+
+static nsresult
+getQNameAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ txExpandedName& aExpName)
+{
+ aExpName.reset();
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ rv = aExpName.init(attr->mValue, aState.mElementContext->mMappings,
+ false);
+ if (!aRequired && NS_FAILED(rv) && aState.fcp()) {
+ aExpName.reset();
+ rv = NS_OK;
+ }
+
+ return rv;
+}
+
+static nsresult
+getExprAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ nsAutoPtr<Expr>& aExpr)
+{
+ aExpr = nullptr;
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ rv = txExprParser::createExpr(attr->mValue, &aState,
+ getter_Transfers(aExpr));
+ if (NS_FAILED(rv) && aState.ignoreError(rv)) {
+ // use default value in fcp for not required exprs
+ if (aRequired) {
+ aExpr = new txErrorExpr(
+#ifdef TX_TO_STRING
+ attr->mValue
+#endif
+ );
+ }
+ else {
+ aExpr = nullptr;
+ }
+ return NS_OK;
+ }
+
+ return rv;
+}
+
+static nsresult
+getAVTAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ nsAutoPtr<Expr>& aAVT)
+{
+ aAVT = nullptr;
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ rv = txExprParser::createAVT(attr->mValue, &aState,
+ getter_Transfers(aAVT));
+ if (NS_FAILED(rv) && aState.fcp()) {
+ // use default value in fcp for not required exprs
+ if (aRequired) {
+ aAVT = new txErrorExpr(
+#ifdef TX_TO_STRING
+ attr->mValue
+#endif
+ );
+ }
+ else {
+ aAVT = nullptr;
+ }
+ return NS_OK;
+ }
+
+ return rv;
+}
+
+static nsresult
+getPatternAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ nsAutoPtr<txPattern>& aPattern)
+{
+ aPattern = nullptr;
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ rv = txPatternParser::createPattern(attr->mValue, &aState,
+ getter_Transfers(aPattern));
+ if (NS_FAILED(rv) && (aRequired || !aState.ignoreError(rv))) {
+ // XXX ErrorReport: XSLT-Pattern parse failure
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+getNumberAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ double& aNumber)
+{
+ aNumber = UnspecifiedNaN<double>();
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ aNumber = txDouble::toDouble(attr->mValue);
+ if (mozilla::IsNaN(aNumber) && (aRequired || !aState.fcp())) {
+ // XXX ErrorReport: number parse failure
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+getAtomAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ nsIAtom** aAtom)
+{
+ *aAtom = nullptr;
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ *aAtom = NS_Atomize(attr->mValue).take();
+ NS_ENSURE_TRUE(*aAtom, NS_ERROR_OUT_OF_MEMORY);
+
+ return NS_OK;
+}
+
+static nsresult
+getYesNoAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ txThreeState& aRes)
+{
+ aRes = eNotSet;
+ nsCOMPtr<nsIAtom> atom;
+ nsresult rv = getAtomAttr(aAttributes, aAttrCount, aName, aRequired,
+ aState, getter_AddRefs(atom));
+ if (!atom) {
+ return rv;
+ }
+
+ if (atom == nsGkAtoms::yes) {
+ aRes = eTrue;
+ }
+ else if (atom == nsGkAtoms::no) {
+ aRes = eFalse;
+ }
+ else if (aRequired || !aState.fcp()) {
+ // XXX ErrorReport: unknown values
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+getCharAttr(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ nsIAtom* aName,
+ bool aRequired,
+ txStylesheetCompilerState& aState,
+ char16_t& aChar)
+{
+ // Don't reset aChar since it contains the default value
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ aName, aRequired, &attr);
+ if (!attr) {
+ return rv;
+ }
+
+ if (attr->mValue.Length() == 1) {
+ aChar = attr->mValue.CharAt(0);
+ }
+ else if (aRequired || !aState.fcp()) {
+ // XXX ErrorReport: not a character
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+
+/**
+ * Ignore and error handlers
+ */
+static nsresult
+txFnTextIgnore(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ return NS_OK;
+}
+
+static nsresult
+txFnTextError(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ TX_RETURN_IF_WHITESPACE(aStr, aState);
+
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+}
+
+void
+clearAttributes(txStylesheetAttr* aAttributes,
+ int32_t aAttrCount)
+{
+ int32_t i;
+ for (i = 0; i < aAttrCount; ++i) {
+ aAttributes[i].mLocalName = nullptr;
+ }
+}
+
+static nsresult
+txFnStartElementIgnore(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ if (!aState.fcp()) {
+ clearAttributes(aAttributes, aAttrCount);
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndElementIgnore(txStylesheetCompilerState& aState)
+{
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementSetIgnore(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ if (!aState.fcp()) {
+ clearAttributes(aAttributes, aAttrCount);
+ }
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndElementSetIgnore(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementError(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+}
+
+static nsresult
+txFnEndElementError(txStylesheetCompilerState& aState)
+{
+ NS_ERROR("txFnEndElementError shouldn't be called");
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+}
+
+
+/**
+ * Root handlers
+ */
+static nsresult
+txFnStartStylesheet(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ // extension-element-prefixes is handled in
+ // txStylesheetCompiler::startElementInternal
+
+ txStylesheetAttr* attr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::id, false, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_None);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::version, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxImportHandler);
+}
+
+static nsresult
+txFnEndStylesheet(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementContinueTopLevel(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ aState.mHandlerTable = gTxTopHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+static nsresult
+txFnStartLREStylesheet(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ txStylesheetAttr* attr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_XSLT,
+ nsGkAtoms::version, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txExpandedName nullExpr;
+ double prio = UnspecifiedNaN<double>();
+
+ nsAutoPtr<txPattern> match(new txRootPattern());
+ nsAutoPtr<txTemplateItem> templ(new txTemplateItem(Move(match), nullExpr,
+ nullExpr, prio));
+ aState.openInstructionContainer(templ);
+ rv = aState.addToplevelItem(templ);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ templ.forget();
+
+ rv = aState.pushHandlerTable(gTxTemplateHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return txFnStartLRE(aNamespaceID, aLocalName, aPrefix, aAttributes,
+ aAttrCount, aState);
+}
+
+static nsresult
+txFnEndLREStylesheet(txStylesheetCompilerState& aState)
+{
+ nsresult rv = txFnEndLRE(aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.popHandlerTable();
+
+ nsAutoPtr<txInstruction> instr(new txReturn());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.closeInstructionContainer();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnStartEmbed(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ if (!aState.handleEmbeddedSheet()) {
+ return NS_OK;
+ }
+ if (aNamespaceID != kNameSpaceID_XSLT ||
+ (aLocalName != nsGkAtoms::stylesheet &&
+ aLocalName != nsGkAtoms::transform)) {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+ return txFnStartStylesheet(aNamespaceID, aLocalName, aPrefix,
+ aAttributes, aAttrCount, aState);
+}
+
+static nsresult
+txFnEndEmbed(txStylesheetCompilerState& aState)
+{
+ if (!aState.handleEmbeddedSheet()) {
+ return NS_OK;
+ }
+ nsresult rv = txFnEndStylesheet(aState);
+ aState.doneEmbedding();
+ return rv;
+}
+
+
+/**
+ * Top handlers
+ */
+static nsresult
+txFnStartOtherTop(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ if (aNamespaceID == kNameSpaceID_None ||
+ (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp())) {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndOtherTop(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+
+// xsl:attribute-set
+static nsresult
+txFnStartAttributeSet(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txAttributeSetItem> attrSet(new txAttributeSetItem(name));
+ aState.openInstructionContainer(attrSet);
+
+ rv = aState.addToplevelItem(attrSet);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ attrSet.forget();
+
+ rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxAttributeSetHandler);
+}
+
+static nsresult
+txFnEndAttributeSet(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ nsAutoPtr<txInstruction> instr(new txReturn());
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.closeInstructionContainer();
+
+ return NS_OK;
+}
+
+
+// xsl:decimal-format
+static nsresult
+txFnStartDecimalFormat(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txDecimalFormat> format(new txDecimalFormat);
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::decimalSeparator,
+ false, aState, format->mDecimalSeparator);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator,
+ false, aState, format->mGroupingSeparator);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txStylesheetAttr* attr = nullptr;
+ rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::infinity, false, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (attr) {
+ format->mInfinity = attr->mValue;
+ }
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::minusSign,
+ false, aState, format->mMinusSign);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::NaN, false, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (attr) {
+ format->mNaN = attr->mValue;
+ }
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::percent,
+ false, aState, format->mPercent);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::perMille,
+ false, aState, format->mPerMille);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::zeroDigit,
+ false, aState, format->mZeroDigit);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::digit,
+ false, aState, format->mDigit);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getCharAttr(aAttributes, aAttrCount, nsGkAtoms::patternSeparator,
+ false, aState, format->mPatternSeparator);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.mStylesheet->addDecimalFormat(name, Move(format));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndDecimalFormat(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:import
+static nsresult
+txFnStartImport(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txImportItem> import(new txImportItem);
+ import->mFrame = new txStylesheet::ImportFrame;
+ nsresult rv = aState.addToplevelItem(import);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txImportItem* importPtr = import.forget();
+
+ txStylesheetAttr* attr = nullptr;
+ rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::href, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString absUri;
+ URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI,
+ absUri);
+ rv = aState.loadImportedStylesheet(absUri, importPtr->mFrame);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndImport(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:include
+static nsresult
+txFnStartInclude(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::href, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString absUri;
+ URIUtils::resolveHref(attr->mValue, aState.mElementContext->mBaseURI,
+ absUri);
+ rv = aState.loadIncludedStylesheet(absUri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndInclude(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:key
+static nsresult
+txFnStartKey(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.mDisAllowed = txIParseContext::KEY_FUNCTION;
+
+ nsAutoPtr<txPattern> match;
+ rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match, true,
+ aState, match);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> use;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::use, true,
+ aState, use);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.mDisAllowed = 0;
+
+ rv = aState.mStylesheet->addKey(name, Move(match), Move(use));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndKey(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:namespace-alias
+static nsresult
+txFnStartNamespaceAlias(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::stylesheetPrefix, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::resultPrefix, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // XXX Needs to be implemented.
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndNamespaceAlias(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:output
+static nsresult
+txFnStartOutput(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txOutputItem> item(new txOutputItem);
+
+ txExpandedName methodExpName;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::method, false,
+ aState, methodExpName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!methodExpName.isNull()) {
+ if (methodExpName.mNamespaceID != kNameSpaceID_None) {
+ // The spec doesn't say what to do here so we'll just ignore the
+ // value. We could possibly warn.
+ }
+ else if (methodExpName.mLocalName == nsGkAtoms::html) {
+ item->mFormat.mMethod = eHTMLOutput;
+ }
+ else if (methodExpName.mLocalName == nsGkAtoms::text) {
+ item->mFormat.mMethod = eTextOutput;
+ }
+ else if (methodExpName.mLocalName == nsGkAtoms::xml) {
+ item->mFormat.mMethod = eXMLOutput;
+ }
+ else {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+ }
+
+ txStylesheetAttr* attr = nullptr;
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::version, false, &attr);
+ if (attr) {
+ item->mFormat.mVersion = attr->mValue;
+ }
+
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::encoding, false, &attr);
+ if (attr) {
+ item->mFormat.mEncoding = attr->mValue;
+ }
+
+ rv = getYesNoAttr(aAttributes, aAttrCount,
+ nsGkAtoms::omitXmlDeclaration, false, aState,
+ item->mFormat.mOmitXMLDeclaration);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = getYesNoAttr(aAttributes, aAttrCount,
+ nsGkAtoms::standalone, false, aState,
+ item->mFormat.mStandalone);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::doctypePublic, false, &attr);
+ if (attr) {
+ item->mFormat.mPublicId = attr->mValue;
+ }
+
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::doctypeSystem, false, &attr);
+ if (attr) {
+ item->mFormat.mSystemId = attr->mValue;
+ }
+
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::cdataSectionElements, false, &attr);
+ if (attr) {
+ nsWhitespaceTokenizer tokens(attr->mValue);
+ while (tokens.hasMoreTokens()) {
+ nsAutoPtr<txExpandedName> qname(new txExpandedName());
+ rv = qname->init(tokens.nextToken(),
+ aState.mElementContext->mMappings, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = item->mFormat.mCDATASectionElements.add(qname);
+ NS_ENSURE_SUCCESS(rv, rv);
+ qname.forget();
+ }
+ }
+
+ rv = getYesNoAttr(aAttributes, aAttrCount,
+ nsGkAtoms::indent, false, aState,
+ item->mFormat.mIndent);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::mediaType, false, &attr);
+ if (attr) {
+ item->mFormat.mMediaType = attr->mValue;
+ }
+
+ rv = aState.addToplevelItem(item);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ item.forget();
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndOutput(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:strip-space/xsl:preserve-space
+static nsresult
+txFnStartStripSpace(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ txStylesheetAttr* attr = nullptr;
+ nsresult rv = getStyleAttr(aAttributes, aAttrCount, kNameSpaceID_None,
+ nsGkAtoms::elements, true, &attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool strip = aLocalName == nsGkAtoms::stripSpace;
+
+ nsAutoPtr<txStripSpaceItem> stripItem(new txStripSpaceItem);
+ nsWhitespaceTokenizer tokenizer(attr->mValue);
+ while (tokenizer.hasMoreTokens()) {
+ const nsASingleFragmentString& name = tokenizer.nextToken();
+ int32_t ns = kNameSpaceID_None;
+ nsCOMPtr<nsIAtom> prefix, localName;
+ rv = XMLUtils::splitQName(name, getter_AddRefs(prefix),
+ getter_AddRefs(localName));
+ if (NS_FAILED(rv)) {
+ // check for "*" or "prefix:*"
+ uint32_t length = name.Length();
+ const char16_t* c;
+ name.BeginReading(c);
+ if (length == 2 || c[length-1] != '*') {
+ // these can't work
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+ if (length > 1) {
+ // Check for a valid prefix, that is, the returned prefix
+ // should be empty and the real prefix is returned in
+ // localName.
+ if (c[length-2] != ':') {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+ rv = XMLUtils::splitQName(StringHead(name, length - 2),
+ getter_AddRefs(prefix),
+ getter_AddRefs(localName));
+ if (NS_FAILED(rv) || prefix) {
+ // bad chars or two ':'
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+ prefix = localName;
+ }
+ localName = nsGkAtoms::_asterisk;
+ }
+ if (prefix) {
+ ns = aState.mElementContext->mMappings->lookupNamespace(prefix);
+ NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, NS_ERROR_FAILURE);
+ }
+ nsAutoPtr<txStripSpaceTest> sst(new txStripSpaceTest(prefix, localName,
+ ns, strip));
+ rv = stripItem->addStripSpaceTest(sst);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ sst.forget();
+ }
+
+ rv = aState.addToplevelItem(stripItem);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ stripItem.forget();
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndStripSpace(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+// xsl:template
+static nsresult
+txFnStartTemplate(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, false,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txExpandedName mode;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false,
+ aState, mode);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ double prio = UnspecifiedNaN<double>();
+ rv = getNumberAttr(aAttributes, aAttrCount, nsGkAtoms::priority,
+ false, aState, prio);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txPattern> match;
+ rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::match,
+ name.isNull(), aState, match);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txTemplateItem> templ(new txTemplateItem(Move(match), name, mode,
+ prio));
+ aState.openInstructionContainer(templ);
+ rv = aState.addToplevelItem(templ);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ templ.forget();
+
+ return aState.pushHandlerTable(gTxParamHandler);
+}
+
+static nsresult
+txFnEndTemplate(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ nsAutoPtr<txInstruction> instr(new txReturn());
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.closeInstructionContainer();
+
+ return NS_OK;
+}
+
+// xsl:variable, xsl:param
+static nsresult
+txFnStartTopVariable(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txVariableItem> var(
+ new txVariableItem(name, Move(select),
+ aLocalName == nsGkAtoms::param));
+ aState.openInstructionContainer(var);
+ rv = aState.pushPtr(var, aState.eVariableItem);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (var->mValue) {
+ // XXX should be gTxErrorHandler?
+ rv = aState.pushHandlerTable(gTxIgnoreHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ rv = aState.pushHandlerTable(gTxTopVariableHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = aState.addToplevelItem(var);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ var.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndTopVariable(txStylesheetCompilerState& aState)
+{
+ txHandlerTable* prev = aState.mHandlerTable;
+ aState.popHandlerTable();
+ txVariableItem* var =
+ static_cast<txVariableItem*>(aState.popPtr(aState.eVariableItem));
+
+ if (prev == gTxTopVariableHandler) {
+ // No children were found.
+ NS_ASSERTION(!var->mValue,
+ "There shouldn't be a select-expression here");
+ var->mValue = new txLiteralExpr(EmptyString());
+ }
+ else if (!var->mValue) {
+ // If we don't have a select-expression there mush be children.
+ nsAutoPtr<txInstruction> instr(new txReturn());
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ aState.closeInstructionContainer();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementStartTopVar(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+static nsresult
+txFnTextStartTopVar(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ TX_RETURN_IF_WHITESPACE(aStr, aState);
+
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+/**
+ * Template Handlers
+ */
+
+/*
+ LRE
+
+ txStartLREElement
+ txInsertAttrSet one for each qname in xsl:use-attribute-sets
+ txLREAttribute one for each attribute
+ [children]
+ txEndElement
+*/
+static nsresult
+txFnStartLRE(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txInstruction> instr(new txStartLREElement(aNamespaceID,
+ aLocalName, aPrefix));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = parseExcludeResultPrefixes(aAttributes, aAttrCount, kNameSpaceID_XSLT);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = parseUseAttrSets(aAttributes, aAttrCount, true, aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txStylesheetAttr* attr = nullptr;
+ int32_t i;
+ for (i = 0; i < aAttrCount; ++i) {
+ attr = aAttributes + i;
+
+ if (attr->mNamespaceID == kNameSpaceID_XSLT) {
+ if (attr->mLocalName == nsGkAtoms::version) {
+ attr->mLocalName = nullptr;
+ }
+
+ continue;
+ }
+
+ nsAutoPtr<Expr> avt;
+ rv = txExprParser::createAVT(attr->mValue, &aState,
+ getter_Transfers(avt));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txLREAttribute(attr->mNamespaceID, attr->mLocalName,
+ attr->mPrefix, Move(avt));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndLRE(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txEndElement);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ "LRE text"
+
+ txText
+*/
+static nsresult
+txFnText(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ TX_RETURN_IF_WHITESPACE(aStr, aState);
+
+ nsAutoPtr<txInstruction> instr(new txText(aStr, false));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:apply-imports
+
+ txApplyImports
+*/
+static nsresult
+txFnStartApplyImports(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txInstruction> instr(new txApplyImports);
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndApplyImports(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+/*
+ xsl:apply-templates
+
+ txPushParams
+ [params]
+ txPushNewContext -+ (holds <xsl:sort>s)
+ txApplyTemplate <-+ |
+ txLoopNodeSet -+ |
+ txPopParams <-+
+*/
+static nsresult
+txFnStartApplyTemplates(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txInstruction> instr(new txPushParams);
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txExpandedName mode;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::mode, false,
+ aState, mode);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txApplyTemplates(mode);
+ rv = aState.pushObject(instr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr.forget();
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!select) {
+ nsAutoPtr<txNodeTest> nt(
+ new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
+ select = new LocationStep(nt, LocationStep::CHILD_AXIS);
+ nt.forget();
+ }
+
+ nsAutoPtr<txPushNewContext> pushcontext( new txPushNewContext(Move(select)));
+ rv = aState.pushSorter(pushcontext);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.pushObject(pushcontext);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ pushcontext.forget();
+
+ return aState.pushHandlerTable(gTxApplyTemplatesHandler);
+}
+
+static nsresult
+txFnEndApplyTemplates(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ txPushNewContext* pushcontext =
+ static_cast<txPushNewContext*>(aState.popObject());
+ nsAutoPtr<txInstruction> instr(pushcontext); // txPushNewContext
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.popSorter();
+
+ instr = static_cast<txInstruction*>(aState.popObject()); // txApplyTemplates
+ nsAutoPtr<txLoopNodeSet> loop(new txLoopNodeSet(instr));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = loop.forget();
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txPopParams;
+ pushcontext->mBailTarget = instr;
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:attribute
+
+ txPushStringHandler
+ [children]
+ txAttribute
+*/
+static nsresult
+txFnStartAttribute(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txInstruction> instr(new txPushStringHandler(true));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> name;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> nspace;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false,
+ aState, nspace);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txAttribute(Move(name), Move(nspace),
+ aState.mElementContext->mMappings);
+ rv = aState.pushObject(instr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr.forget();
+
+ // We need to push the template-handler since the current might be
+ // the attributeset-handler
+ return aState.pushHandlerTable(gTxTemplateHandler);
+}
+
+static nsresult
+txFnEndAttribute(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ nsAutoPtr<txInstruction> instr(static_cast<txInstruction*>
+ (aState.popObject()));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:call-template
+
+ txPushParams
+ [params]
+ txCallTemplate
+ txPopParams
+*/
+static nsresult
+txFnStartCallTemplate(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<txInstruction> instr(new txPushParams);
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txCallTemplate(name);
+ rv = aState.pushObject(instr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr.forget();
+
+ return aState.pushHandlerTable(gTxCallTemplateHandler);
+}
+
+static nsresult
+txFnEndCallTemplate(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ // txCallTemplate
+ nsAutoPtr<txInstruction> instr(static_cast<txInstruction*>(aState.popObject()));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txPopParams;
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:choose
+
+ txCondotionalGoto --+ \
+ [children] | | one for each xsl:when
+ txGoTo --+ | /
+ | |
+ txCondotionalGoto | <-+ --+
+ [children] | |
+ txGoTo --+ |
+ | |
+ [children] | <-+ for the xsl:otherwise, if there is one
+ <-+
+*/
+static nsresult
+txFnStartChoose(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = aState.pushChooseGotoList();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxChooseHandler);
+}
+
+static nsresult
+txFnEndChoose(txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+ aState.popHandlerTable();
+ txListIterator iter(aState.mChooseGotoList);
+ txGoTo* gotoinstr;
+ while ((gotoinstr = static_cast<txGoTo*>(iter.next()))) {
+ rv = aState.addGotoTarget(&gotoinstr->mTarget);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ aState.popChooseGotoList();
+
+ return NS_OK;
+}
+
+/*
+ xsl:comment
+
+ txPushStringHandler
+ [children]
+ txComment
+*/
+static nsresult
+txFnStartComment(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txPushStringHandler(true));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndComment(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txComment);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:copy
+
+ txCopy -+
+ txInsertAttrSet | one for each qname in use-attribute-sets
+ [children] |
+ txEndElement |
+ <-+
+*/
+static nsresult
+txFnStartCopy(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txCopy> copy(new txCopy);
+ nsresult rv = aState.pushPtr(copy, aState.eCopy);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(copy.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndCopy(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txEndElement);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txCopy* copy = static_cast<txCopy*>(aState.popPtr(aState.eCopy));
+ rv = aState.addGotoTarget(&copy->mBailTarget);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:copy-of
+
+ txCopyOf
+*/
+static nsresult
+txFnStartCopyOf(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(new txCopyOf(Move(select)));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndCopyOf(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+/*
+ xsl:element
+
+ txStartElement
+ txInsertAttrSet one for each qname in use-attribute-sets
+ [children]
+ txEndElement
+*/
+static nsresult
+txFnStartElement(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> name;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> nspace;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::_namespace, false,
+ aState, nspace);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(
+ new txStartElement(Move(name), Move(nspace),
+ aState.mElementContext->mMappings));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = parseUseAttrSets(aAttributes, aAttrCount, false, aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndElement(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txEndElement);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:fallback
+
+ [children]
+*/
+static nsresult
+txFnStartFallback(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ aState.mSearchingForFallback = false;
+
+ return aState.pushHandlerTable(gTxTemplateHandler);
+}
+
+static nsresult
+txFnEndFallback(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ NS_ASSERTION(!aState.mSearchingForFallback,
+ "bad nesting of unknown-instruction and fallback handlers");
+ return NS_OK;
+}
+
+/*
+ xsl:for-each
+
+ txPushNewContext -+ (holds <xsl:sort>s)
+ txPushNullTemplateRule <-+ |
+ [children] | |
+ txLoopNodeSet -+ |
+ <-+
+*/
+static nsresult
+txFnStartForEach(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txPushNewContext> pushcontext(new txPushNewContext(Move(select)));
+ rv = aState.pushPtr(pushcontext, aState.ePushNewContext);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.pushSorter(pushcontext);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(pushcontext.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txPushNullTemplateRule;
+ rv = aState.pushPtr(instr, aState.ePushNullTemplateRule);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxForEachHandler);
+}
+
+static nsresult
+txFnEndForEach(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ // This is a txPushNullTemplateRule
+ txInstruction* pnullrule =
+ static_cast<txInstruction*>(aState.popPtr(aState.ePushNullTemplateRule));
+
+ nsAutoPtr<txInstruction> instr(new txLoopNodeSet(pnullrule));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.popSorter();
+ txPushNewContext* pushcontext =
+ static_cast<txPushNewContext*>(aState.popPtr(aState.ePushNewContext));
+ aState.addGotoTarget(&pushcontext->mBailTarget);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementContinueTemplate(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+static nsresult
+txFnTextContinueTemplate(const nsAString& aStr,
+ txStylesheetCompilerState& aState)
+{
+ TX_RETURN_IF_WHITESPACE(aStr, aState);
+
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+/*
+ xsl:if
+
+ txConditionalGoto -+
+ [children] |
+ <-+
+*/
+static nsresult
+txFnStartIf(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> test;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true,
+ aState, test);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txConditionalGoto> condGoto(new txConditionalGoto(Move(test),
+ nullptr));
+ rv = aState.pushPtr(condGoto, aState.eConditionalGoto);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(condGoto.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndIf(txStylesheetCompilerState& aState)
+{
+ txConditionalGoto* condGoto =
+ static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
+ return aState.addGotoTarget(&condGoto->mTarget);
+}
+
+/*
+ xsl:message
+
+ txPushStringHandler
+ [children]
+ txMessage
+*/
+static nsresult
+txFnStartMessage(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txPushStringHandler(false));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txThreeState term;
+ rv = getYesNoAttr(aAttributes, aAttrCount, nsGkAtoms::terminate,
+ false, aState, term);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txMessage(term == eTrue);
+ rv = aState.pushObject(instr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndMessage(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(static_cast<txInstruction*>(aState.popObject()));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:number
+
+ txNumber
+*/
+static nsresult
+txFnStartNumber(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsCOMPtr<nsIAtom> levelAtom;
+ rv = getAtomAttr(aAttributes, aAttrCount, nsGkAtoms::level, false,
+ aState, getter_AddRefs(levelAtom));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txXSLTNumber::LevelType level = txXSLTNumber::eLevelSingle;
+ if (levelAtom == nsGkAtoms::multiple) {
+ level = txXSLTNumber::eLevelMultiple;
+ }
+ else if (levelAtom == nsGkAtoms::any) {
+ level = txXSLTNumber::eLevelAny;
+ }
+ else if (levelAtom && levelAtom != nsGkAtoms::single && !aState.fcp()) {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ nsAutoPtr<txPattern> count;
+ rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::count, false,
+ aState, count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txPattern> from;
+ rv = getPatternAttr(aAttributes, aAttrCount, nsGkAtoms::from, false,
+ aState, from);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> value;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::value, false,
+ aState, value);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> format;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::format, false,
+ aState, format);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> lang;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false,
+ aState, lang);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> letterValue;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::letterValue, false,
+ aState, letterValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> groupingSeparator;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSeparator,
+ false, aState, groupingSeparator);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> groupingSize;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::groupingSize,
+ false, aState, groupingSize);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(new txNumber(level, Move(count), Move(from),
+ Move(value), Move(format),
+ Move(groupingSeparator),
+ Move(groupingSize)));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndNumber(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+/*
+ xsl:otherwise
+
+ (see xsl:choose)
+*/
+static nsresult
+txFnStartOtherwise(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ return aState.pushHandlerTable(gTxTemplateHandler);
+}
+
+static nsresult
+txFnEndOtherwise(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ aState.mHandlerTable = gTxIgnoreHandler; // XXX should be gTxErrorHandler
+
+ return NS_OK;
+}
+
+/*
+ xsl:param
+
+ txCheckParam --+
+ txPushRTFHandler | --- (for RTF-parameters)
+ [children] | /
+ txSetVariable |
+ <-+
+*/
+static nsresult
+txFnStartParam(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txCheckParam> checkParam(new txCheckParam(name));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.pushPtr(checkParam, aState.eCheckParam);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(checkParam.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txSetVariable> var(new txSetVariable(name, Move(select)));
+ if (var->mValue) {
+ // XXX should be gTxErrorHandler?
+ rv = aState.pushHandlerTable(gTxIgnoreHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ rv = aState.pushHandlerTable(gTxVariableHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = aState.pushObject(var);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ var.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndParam(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txSetVariable> var(static_cast<txSetVariable*>
+ (aState.popObject()));
+ txHandlerTable* prev = aState.mHandlerTable;
+ aState.popHandlerTable();
+
+ if (prev == gTxVariableHandler) {
+ // No children were found.
+ NS_ASSERTION(!var->mValue,
+ "There shouldn't be a select-expression here");
+ var->mValue = new txLiteralExpr(EmptyString());
+ }
+
+ nsresult rv = aState.addVariable(var->mName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(var.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txCheckParam* checkParam =
+ static_cast<txCheckParam*>(aState.popPtr(aState.eCheckParam));
+ aState.addGotoTarget(&checkParam->mBailTarget);
+
+ return NS_OK;
+}
+
+/*
+ xsl:processing-instruction
+
+ txPushStringHandler
+ [children]
+ txProcessingInstruction
+*/
+static nsresult
+txFnStartPI(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txPushStringHandler(true));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> name;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr = new txProcessingInstruction(Move(name));
+ rv = aState.pushObject(instr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ instr.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndPI(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(static_cast<txInstruction*>
+ (aState.popObject()));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:sort
+
+ (no instructions)
+*/
+static nsresult
+txFnStartSort(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!select) {
+ nsAutoPtr<txNodeTest> nt(
+ new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
+
+ select = new LocationStep(nt, LocationStep::SELF_AXIS);
+
+ nt.forget();
+ }
+
+ nsAutoPtr<Expr> lang;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::lang, false,
+ aState, lang);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> dataType;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::dataType, false,
+ aState, dataType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> order;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::order, false,
+ aState, order);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> caseOrder;
+ rv = getAVTAttr(aAttributes, aAttrCount, nsGkAtoms::caseOrder, false,
+ aState, caseOrder);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aState.mSorter->addSort(Move(select), Move(lang), Move(dataType),
+ Move(order), Move(caseOrder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndSort(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ return NS_OK;
+}
+
+/*
+ xsl:text
+
+ [children] (only txText)
+*/
+static nsresult
+txFnStartText(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ NS_ASSERTION(!aState.mDOE, "nested d-o-e elements should not happen");
+
+ nsresult rv = NS_OK;
+ txThreeState doe;
+ rv = getYesNoAttr(aAttributes, aAttrCount,
+ nsGkAtoms::disableOutputEscaping, false, aState,
+ doe);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.mDOE = doe == eTrue;
+
+ return aState.pushHandlerTable(gTxTextHandler);
+}
+
+static nsresult
+txFnEndText(txStylesheetCompilerState& aState)
+{
+ aState.mDOE = false;
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+static nsresult
+txFnTextText(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txText(aStr, aState.mDOE));
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:value-of
+
+ txValueOf
+*/
+static nsresult
+txFnStartValueOf(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ txThreeState doe;
+ rv = getYesNoAttr(aAttributes, aAttrCount,
+ nsGkAtoms::disableOutputEscaping, false, aState,
+ doe);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, true,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(new txValueOf(Move(select), doe == eTrue));
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxIgnoreHandler);
+}
+
+static nsresult
+txFnEndValueOf(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ return NS_OK;
+}
+
+/*
+ xsl:variable
+
+ txPushRTFHandler --- (for RTF-parameters)
+ [children] /
+ txSetVariable
+*/
+static nsresult
+txFnStartVariable(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txSetVariable> var(new txSetVariable(name, Move(select)));
+ if (var->mValue) {
+ // XXX should be gTxErrorHandler?
+ rv = aState.pushHandlerTable(gTxIgnoreHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ rv = aState.pushHandlerTable(gTxVariableHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = aState.pushObject(var);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ var.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndVariable(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txSetVariable> var(static_cast<txSetVariable*>
+ (aState.popObject()));
+
+ txHandlerTable* prev = aState.mHandlerTable;
+ aState.popHandlerTable();
+
+ if (prev == gTxVariableHandler) {
+ // No children were found.
+ NS_ASSERTION(!var->mValue,
+ "There shouldn't be a select-expression here");
+ var->mValue = new txLiteralExpr(EmptyString());
+ }
+
+ nsresult rv = aState.addVariable(var->mName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(var.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+static nsresult
+txFnStartElementStartRTF(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txInstruction> instr(new txPushRTFHandler);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+static nsresult
+txFnTextStartRTF(const nsAString& aStr, txStylesheetCompilerState& aState)
+{
+ TX_RETURN_IF_WHITESPACE(aStr, aState);
+
+ nsAutoPtr<txInstruction> instr(new txPushRTFHandler);
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aState.mHandlerTable = gTxTemplateHandler;
+
+ return NS_XSLT_GET_NEW_HANDLER;
+}
+
+/*
+ xsl:when
+
+ (see xsl:choose)
+*/
+static nsresult
+txFnStartWhen(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoPtr<Expr> test;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::test, true,
+ aState, test);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txConditionalGoto> condGoto(new txConditionalGoto(Move(test),
+ nullptr));
+ rv = aState.pushPtr(condGoto, aState.eConditionalGoto);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(condGoto.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aState.pushHandlerTable(gTxTemplateHandler);
+}
+
+static nsresult
+txFnEndWhen(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+ nsAutoPtr<txGoTo> gotoinstr(new txGoTo(nullptr));
+ nsresult rv = aState.mChooseGotoList->add(gotoinstr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txInstruction> instr(gotoinstr.forget());
+ rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txConditionalGoto* condGoto =
+ static_cast<txConditionalGoto*>(aState.popPtr(aState.eConditionalGoto));
+ rv = aState.addGotoTarget(&condGoto->mTarget);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ xsl:with-param
+
+ txPushRTFHandler -- for RTF-parameters
+ [children] /
+ txSetParam
+*/
+static nsresult
+txFnStartWithParam(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ nsresult rv = NS_OK;
+
+ txExpandedName name;
+ rv = getQNameAttr(aAttributes, aAttrCount, nsGkAtoms::name, true,
+ aState, name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<Expr> select;
+ rv = getExprAttr(aAttributes, aAttrCount, nsGkAtoms::select, false,
+ aState, select);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoPtr<txSetParam> var(new txSetParam(name, Move(select)));
+ if (var->mValue) {
+ // XXX should be gTxErrorHandler?
+ rv = aState.pushHandlerTable(gTxIgnoreHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ rv = aState.pushHandlerTable(gTxVariableHandler);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = aState.pushObject(var);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ var.forget();
+
+ return NS_OK;
+}
+
+static nsresult
+txFnEndWithParam(txStylesheetCompilerState& aState)
+{
+ nsAutoPtr<txSetParam> var(static_cast<txSetParam*>(aState.popObject()));
+ txHandlerTable* prev = aState.mHandlerTable;
+ aState.popHandlerTable();
+
+ if (prev == gTxVariableHandler) {
+ // No children were found.
+ NS_ASSERTION(!var->mValue,
+ "There shouldn't be a select-expression here");
+ var->mValue = new txLiteralExpr(EmptyString());
+ }
+
+ nsAutoPtr<txInstruction> instr(var.forget());
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+/*
+ Unknown instruction
+
+ [fallbacks] if one or more xsl:fallbacks are found
+ or
+ txErrorInstruction otherwise
+*/
+static nsresult
+txFnStartUnknownInstruction(int32_t aNamespaceID,
+ nsIAtom* aLocalName,
+ nsIAtom* aPrefix,
+ txStylesheetAttr* aAttributes,
+ int32_t aAttrCount,
+ txStylesheetCompilerState& aState)
+{
+ NS_ASSERTION(!aState.mSearchingForFallback,
+ "bad nesting of unknown-instruction and fallback handlers");
+
+ if (aNamespaceID == kNameSpaceID_XSLT && !aState.fcp()) {
+ return NS_ERROR_XSLT_PARSE_FAILURE;
+ }
+
+ aState.mSearchingForFallback = true;
+
+ return aState.pushHandlerTable(gTxFallbackHandler);
+}
+
+static nsresult
+txFnEndUnknownInstruction(txStylesheetCompilerState& aState)
+{
+ aState.popHandlerTable();
+
+ if (aState.mSearchingForFallback) {
+ nsAutoPtr<txInstruction> instr(new txErrorInstruction());
+ nsresult rv = aState.addInstruction(Move(instr));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ aState.mSearchingForFallback = false;
+
+ return NS_OK;
+}
+
+/**
+ * Table Datas
+ */
+
+struct txHandlerTableData {
+ txElementHandler mOtherHandler;
+ txElementHandler mLREHandler;
+ HandleTextFn mTextHandler;
+};
+
+const txHandlerTableData gTxIgnoreTableData = {
+ // Other
+ { 0, 0, txFnStartElementIgnore, txFnEndElementIgnore },
+ // LRE
+ { 0, 0, txFnStartElementIgnore, txFnEndElementIgnore },
+ // Text
+ txFnTextIgnore
+};
+
+const txElementHandler gTxRootElementHandlers[] = {
+ { kNameSpaceID_XSLT, "stylesheet", txFnStartStylesheet, txFnEndStylesheet },
+ { kNameSpaceID_XSLT, "transform", txFnStartStylesheet, txFnEndStylesheet }
+};
+
+const txHandlerTableData gTxRootTableData = {
+ // Other
+ { 0, 0, txFnStartElementError, txFnEndElementError },
+ // LRE
+ { 0, 0, txFnStartLREStylesheet, txFnEndLREStylesheet },
+ // Text
+ txFnTextError
+};
+
+const txHandlerTableData gTxEmbedTableData = {
+ // Other
+ { 0, 0, txFnStartEmbed, txFnEndEmbed },
+ // LRE
+ { 0, 0, txFnStartEmbed, txFnEndEmbed },
+ // Text
+ txFnTextIgnore
+};
+
+const txElementHandler gTxTopElementHandlers[] = {
+ { kNameSpaceID_XSLT, "attribute-set", txFnStartAttributeSet, txFnEndAttributeSet },
+ { kNameSpaceID_XSLT, "decimal-format", txFnStartDecimalFormat, txFnEndDecimalFormat },
+ { kNameSpaceID_XSLT, "include", txFnStartInclude, txFnEndInclude },
+ { kNameSpaceID_XSLT, "key", txFnStartKey, txFnEndKey },
+ { kNameSpaceID_XSLT, "namespace-alias", txFnStartNamespaceAlias,
+ txFnEndNamespaceAlias },
+ { kNameSpaceID_XSLT, "output", txFnStartOutput, txFnEndOutput },
+ { kNameSpaceID_XSLT, "param", txFnStartTopVariable, txFnEndTopVariable },
+ { kNameSpaceID_XSLT, "preserve-space", txFnStartStripSpace, txFnEndStripSpace },
+ { kNameSpaceID_XSLT, "strip-space", txFnStartStripSpace, txFnEndStripSpace },
+ { kNameSpaceID_XSLT, "template", txFnStartTemplate, txFnEndTemplate },
+ { kNameSpaceID_XSLT, "variable", txFnStartTopVariable, txFnEndTopVariable }
+};
+
+const txHandlerTableData gTxTopTableData = {
+ // Other
+ { 0, 0, txFnStartOtherTop, txFnEndOtherTop },
+ // LRE
+ { 0, 0, txFnStartOtherTop, txFnEndOtherTop },
+ // Text
+ txFnTextIgnore
+};
+
+const txElementHandler gTxTemplateElementHandlers[] = {
+ { kNameSpaceID_XSLT, "apply-imports", txFnStartApplyImports, txFnEndApplyImports },
+ { kNameSpaceID_XSLT, "apply-templates", txFnStartApplyTemplates, txFnEndApplyTemplates },
+ { kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute },
+ { kNameSpaceID_XSLT, "call-template", txFnStartCallTemplate, txFnEndCallTemplate },
+ { kNameSpaceID_XSLT, "choose", txFnStartChoose, txFnEndChoose },
+ { kNameSpaceID_XSLT, "comment", txFnStartComment, txFnEndComment },
+ { kNameSpaceID_XSLT, "copy", txFnStartCopy, txFnEndCopy },
+ { kNameSpaceID_XSLT, "copy-of", txFnStartCopyOf, txFnEndCopyOf },
+ { kNameSpaceID_XSLT, "element", txFnStartElement, txFnEndElement },
+ { kNameSpaceID_XSLT, "fallback", txFnStartElementSetIgnore, txFnEndElementSetIgnore },
+ { kNameSpaceID_XSLT, "for-each", txFnStartForEach, txFnEndForEach },
+ { kNameSpaceID_XSLT, "if", txFnStartIf, txFnEndIf },
+ { kNameSpaceID_XSLT, "message", txFnStartMessage, txFnEndMessage },
+ { kNameSpaceID_XSLT, "number", txFnStartNumber, txFnEndNumber },
+ { kNameSpaceID_XSLT, "processing-instruction", txFnStartPI, txFnEndPI },
+ { kNameSpaceID_XSLT, "text", txFnStartText, txFnEndText },
+ { kNameSpaceID_XSLT, "value-of", txFnStartValueOf, txFnEndValueOf },
+ { kNameSpaceID_XSLT, "variable", txFnStartVariable, txFnEndVariable }
+};
+
+const txHandlerTableData gTxTemplateTableData = {
+ // Other
+ { 0, 0, txFnStartUnknownInstruction, txFnEndUnknownInstruction },
+ // LRE
+ { 0, 0, txFnStartLRE, txFnEndLRE },
+ // Text
+ txFnText
+};
+
+const txHandlerTableData gTxTextTableData = {
+ // Other
+ { 0, 0, txFnStartElementError, txFnEndElementError },
+ // LRE
+ { 0, 0, txFnStartElementError, txFnEndElementError },
+ // Text
+ txFnTextText
+};
+
+const txElementHandler gTxApplyTemplatesElementHandlers[] = {
+ { kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort },
+ { kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam }
+};
+
+const txHandlerTableData gTxApplyTemplatesTableData = {
+ // Other
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, // should this be error?
+ // LRE
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore },
+ // Text
+ txFnTextIgnore
+};
+
+const txElementHandler gTxCallTemplateElementHandlers[] = {
+ { kNameSpaceID_XSLT, "with-param", txFnStartWithParam, txFnEndWithParam }
+};
+
+const txHandlerTableData gTxCallTemplateTableData = {
+ // Other
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore }, // should this be error?
+ // LRE
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore },
+ // Text
+ txFnTextIgnore
+};
+
+const txHandlerTableData gTxVariableTableData = {
+ // Other
+ { 0, 0, txFnStartElementStartRTF, 0 },
+ // LRE
+ { 0, 0, txFnStartElementStartRTF, 0 },
+ // Text
+ txFnTextStartRTF
+};
+
+const txElementHandler gTxForEachElementHandlers[] = {
+ { kNameSpaceID_XSLT, "sort", txFnStartSort, txFnEndSort }
+};
+
+const txHandlerTableData gTxForEachTableData = {
+ // Other
+ { 0, 0, txFnStartElementContinueTemplate, 0 },
+ // LRE
+ { 0, 0, txFnStartElementContinueTemplate, 0 },
+ // Text
+ txFnTextContinueTemplate
+};
+
+const txHandlerTableData gTxTopVariableTableData = {
+ // Other
+ { 0, 0, txFnStartElementStartTopVar, 0 },
+ // LRE
+ { 0, 0, txFnStartElementStartTopVar, 0 },
+ // Text
+ txFnTextStartTopVar
+};
+
+const txElementHandler gTxChooseElementHandlers[] = {
+ { kNameSpaceID_XSLT, "otherwise", txFnStartOtherwise, txFnEndOtherwise },
+ { kNameSpaceID_XSLT, "when", txFnStartWhen, txFnEndWhen }
+};
+
+const txHandlerTableData gTxChooseTableData = {
+ // Other
+ { 0, 0, txFnStartElementError, 0 },
+ // LRE
+ { 0, 0, txFnStartElementError, 0 },
+ // Text
+ txFnTextError
+};
+
+const txElementHandler gTxParamElementHandlers[] = {
+ { kNameSpaceID_XSLT, "param", txFnStartParam, txFnEndParam }
+};
+
+const txHandlerTableData gTxParamTableData = {
+ // Other
+ { 0, 0, txFnStartElementContinueTemplate, 0 },
+ // LRE
+ { 0, 0, txFnStartElementContinueTemplate, 0 },
+ // Text
+ txFnTextContinueTemplate
+};
+
+const txElementHandler gTxImportElementHandlers[] = {
+ { kNameSpaceID_XSLT, "import", txFnStartImport, txFnEndImport }
+};
+
+const txHandlerTableData gTxImportTableData = {
+ // Other
+ { 0, 0, txFnStartElementContinueTopLevel, 0 },
+ // LRE
+ { 0, 0, txFnStartOtherTop, txFnEndOtherTop }, // XXX what should we do here?
+ // Text
+ txFnTextIgnore // XXX what should we do here?
+};
+
+const txElementHandler gTxAttributeSetElementHandlers[] = {
+ { kNameSpaceID_XSLT, "attribute", txFnStartAttribute, txFnEndAttribute }
+};
+
+const txHandlerTableData gTxAttributeSetTableData = {
+ // Other
+ { 0, 0, txFnStartElementError, 0 },
+ // LRE
+ { 0, 0, txFnStartElementError, 0 },
+ // Text
+ txFnTextError
+};
+
+const txElementHandler gTxFallbackElementHandlers[] = {
+ { kNameSpaceID_XSLT, "fallback", txFnStartFallback, txFnEndFallback }
+};
+
+const txHandlerTableData gTxFallbackTableData = {
+ // Other
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore },
+ // LRE
+ { 0, 0, txFnStartElementSetIgnore, txFnEndElementSetIgnore },
+ // Text
+ txFnTextIgnore
+};
+
+
+
+/**
+ * txHandlerTable
+ */
+txHandlerTable::txHandlerTable(const HandleTextFn aTextHandler,
+ const txElementHandler* aLREHandler,
+ const txElementHandler* aOtherHandler)
+ : mTextHandler(aTextHandler),
+ mLREHandler(aLREHandler),
+ mOtherHandler(aOtherHandler)
+{
+}
+
+nsresult
+txHandlerTable::init(const txElementHandler* aHandlers, uint32_t aCount)
+{
+ nsresult rv = NS_OK;
+
+ uint32_t i;
+ for (i = 0; i < aCount; ++i) {
+ nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aHandlers->mLocalName);
+ txExpandedName name(aHandlers->mNamespaceID, nameAtom);
+ rv = mHandlers.add(name, aHandlers);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ++aHandlers;
+ }
+ return NS_OK;
+}
+
+const txElementHandler*
+txHandlerTable::find(int32_t aNamespaceID, nsIAtom* aLocalName)
+{
+ txExpandedName name(aNamespaceID, aLocalName);
+ const txElementHandler* handler = mHandlers.get(name);
+ if (!handler) {
+ handler = mOtherHandler;
+ }
+ return handler;
+}
+
+#define INIT_HANDLER(_name) \
+ gTx##_name##Handler = \
+ new txHandlerTable(gTx##_name##TableData.mTextHandler, \
+ &gTx##_name##TableData.mLREHandler, \
+ &gTx##_name##TableData.mOtherHandler); \
+ if (!gTx##_name##Handler) \
+ return false
+
+#define INIT_HANDLER_WITH_ELEMENT_HANDLERS(_name) \
+ INIT_HANDLER(_name); \
+ \
+ rv = gTx##_name##Handler->init(gTx##_name##ElementHandlers, \
+ ArrayLength(gTx##_name##ElementHandlers)); \
+ if (NS_FAILED(rv)) \
+ return false
+
+#define SHUTDOWN_HANDLER(_name) \
+ delete gTx##_name##Handler; \
+ gTx##_name##Handler = nullptr
+
+// static
+bool
+txHandlerTable::init()
+{
+ nsresult rv = NS_OK;
+
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Root);
+ INIT_HANDLER(Embed);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Top);
+ INIT_HANDLER(Ignore);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Template);
+ INIT_HANDLER(Text);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(ApplyTemplates);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(CallTemplate);
+ INIT_HANDLER(Variable);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(ForEach);
+ INIT_HANDLER(TopVariable);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Choose);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Param);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Import);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(AttributeSet);
+ INIT_HANDLER_WITH_ELEMENT_HANDLERS(Fallback);
+
+ return true;
+}
+
+// static
+void
+txHandlerTable::shutdown()
+{
+ SHUTDOWN_HANDLER(Root);
+ SHUTDOWN_HANDLER(Embed);
+ SHUTDOWN_HANDLER(Top);
+ SHUTDOWN_HANDLER(Ignore);
+ SHUTDOWN_HANDLER(Template);
+ SHUTDOWN_HANDLER(Text);
+ SHUTDOWN_HANDLER(ApplyTemplates);
+ SHUTDOWN_HANDLER(CallTemplate);
+ SHUTDOWN_HANDLER(Variable);
+ SHUTDOWN_HANDLER(ForEach);
+ SHUTDOWN_HANDLER(TopVariable);
+ SHUTDOWN_HANDLER(Choose);
+ SHUTDOWN_HANDLER(Param);
+ SHUTDOWN_HANDLER(Import);
+ SHUTDOWN_HANDLER(AttributeSet);
+ SHUTDOWN_HANDLER(Fallback);
+}