[PATCH 2/2] msxml3: XSLPattern support (basic)
Adam Martinson
amartinson at codeweavers.com
Wed Sep 22 10:50:13 CDT 2010
---
dlls/msxml3/Makefile.in | 4 +
dlls/msxml3/domdoc.c | 2 +-
dlls/msxml3/queryresult.c | 147 ++++++++++-
dlls/msxml3/tests/domdoc.c | 172 ++++++++++++-
dlls/msxml3/xslpattern.h | 55 ++++
dlls/msxml3/xslpattern.l | 172 ++++++++++++
dlls/msxml3/xslpattern.y | 640 ++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 1186 insertions(+), 6 deletions(-)
create mode 100644 dlls/msxml3/xslpattern.h
create mode 100644 dlls/msxml3/xslpattern.l
create mode 100644 dlls/msxml3/xslpattern.y
diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in
index 7f9d0bb..629e7c8 100644
--- a/dlls/msxml3/Makefile.in
+++ b/dlls/msxml3/Makefile.in
@@ -32,6 +32,10 @@ C_SRCS = \
xmldoc.c \
xmlelem.c
+LEX_SRCS = xslpattern.l
+
+BISON_SRCS = xslpattern.y
+
RC_SRCS = version.rc
IDL_TLB_SRCS = msxml3_v1.idl
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index dbc71c4..89a7178 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -182,7 +182,7 @@ static inline void clear_selectNsList(struct list* pNsList)
list_init(pNsList);
}
-static inline BOOL is_xpathmode(const xmlDocPtr doc)
+inline BOOL is_xpathmode(const xmlDocPtr doc)
{
return properties_from_xmlDocPtr(doc)->XPath;
}
diff --git a/dlls/msxml3/queryresult.c b/dlls/msxml3/queryresult.c
index efaeb4b..766ad73 100644
--- a/dlls/msxml3/queryresult.c
+++ b/dlls/msxml3/queryresult.c
@@ -1,5 +1,5 @@
/*
- * XPath query result node list implementation (TODO: XSLPattern support)
+ * XPath/XSLPattern query result node list implementation
*
* Copyright 2005 Mike McCormack
* Copyright 2007 Mikolaj Zalewski
@@ -42,7 +42,6 @@
* execution of the query
* - supports IXMLDOMSelection (TODO)
*
- * TODO: XSLPattern support
*/
WINE_DEFAULT_DEBUG_CHANNEL(msxml);
@@ -50,6 +49,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2
#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+int registerNamespaces(xmlXPathContextPtr ctxt);
+inline BOOL is_xpathmode(const xmlDocPtr doc);
+xmlChar* XSLPattern_to_XPath(xmlChar const* xslpat_str);
typedef struct _queryresult
{
@@ -373,6 +377,120 @@ static dispex_static_data_t queryresult_dispex = {
queryresult_iface_tids
};
+void XSLPattern_invalid(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlXPathObjectPtr obj;
+ for (; nargs > 0; --nargs)
+ {
+ obj = valuePop(pctx);
+ xmlXPathFreeObject(obj);
+ }
+
+ obj = xmlMalloc(sizeof(xmlXPathObject));
+ obj->type = XPATH_UNDEFINED;
+ valuePush(pctx,obj);
+}
+
+#define XSLPATTERN_CHECK_ARGS(n) \
+ if (nargs != n) { \
+ FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
+ XSLPattern_invalid(pctx, nargs); \
+ return; \
+ }
+
+
+void XSLPattern_index(xmlXPathParserContextPtr pctx, int nargs)
+{
+ XSLPATTERN_CHECK_ARGS(0);
+
+ xmlXPathPositionFunction(pctx, 0);
+ valuePush(pctx, xmlXPathNewFloat(xmlXPathPopNumber(pctx) - 1.0));
+}
+
+void XSLPattern_end(xmlXPathParserContextPtr pctx, int nargs)
+{
+ double pos, last;
+ XSLPATTERN_CHECK_ARGS(0);
+
+ xmlXPathPositionFunction(pctx, 0);
+ pos = xmlXPathPopNumber(pctx);
+ xmlXPathLastFunction(pctx, 0);
+ last = xmlXPathPopNumber(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(pos == last));
+}
+
+void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) == 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
+void XSLPattern_OP_INEq(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) != 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
+void XSLPattern_OP_ILt(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) < 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
+void XSLPattern_OP_ILEq(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) <= 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
+void XSLPattern_OP_IGt(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) > 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
+void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs)
+{
+ xmlChar *arg1, *arg2;
+ XSLPATTERN_CHECK_ARGS(2);
+
+ arg2 = xmlXPathPopString(pctx);
+ arg1 = xmlXPathPopString(pctx);
+ valuePush(pctx, xmlXPathNewBoolean(xmlStrcasecmp(arg1, arg2) >= 0));
+ xmlFree(arg1);
+ xmlFree(arg2);
+}
+
HRESULT queryresult_create(xmlNodePtr node, LPCWSTR szQuery, IXMLDOMNodeList **out)
{
queryresult *This = heap_alloc_zero(sizeof(queryresult));
@@ -398,6 +516,31 @@ HRESULT queryresult_create(xmlNodePtr node, LPCWSTR szQuery, IXMLDOMNodeList **o
ctxt->node = node;
registerNamespaces(ctxt);
+ if (is_xpathmode(This->node->doc))
+ {
+ xmlXPathRegisterAllFunctions(ctxt);
+ }
+ else
+ {
+ xmlChar* tmp = str;
+ WARN("Attempting XSLPattern emulation (experimental).\n");
+ str = XSLPattern_to_XPath(str);
+ heap_free(tmp);
+
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"not", xmlXPathNotFunction);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"boolean", xmlXPathBooleanFunction);
+
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"index", XSLPattern_index);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"end", XSLPattern_end);
+
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IEq", XSLPattern_OP_IEq);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_INEq", XSLPattern_OP_INEq);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILt", XSLPattern_OP_ILt);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILEq", XSLPattern_OP_ILEq);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGt", XSLPattern_OP_IGt);
+ xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGEq", XSLPattern_OP_IGEq);
+ }
+
This->result = xmlXPathEval(str, ctxt);
if (!This->result || This->result->type != XPATH_NODESET)
{
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 5ec0bc1..b9dd41f 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -5476,16 +5476,182 @@ static void test_XSLPattern(void)
len = 0;
ole_check(IXMLDOMNodeList_get_length(list, &len));
/* should select <elem><c> and <elem xmlns='...'><c> but not <elem><foo:c> */
- todo_wine ok(len == 3, "expected 3 entries in list, got %d\n", len);
+ ok(len == 3, "expected 3 entries in list, got %d\n", len);
IXMLDOMNodeList_Release(list);
/* for XSLPattern start index is 0, for XPath it's 1 */
ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[0]"), &list));
len = 0;
ole_check(IXMLDOMNodeList_get_length(list, &len));
- todo_wine ok(len != 0, "expected filled list\n");
+ ok(len != 0, "expected filled list\n");
if (len)
- todo_wine expect_list_and_release(list, "E1.E2.D1");
+ expect_list_and_release(list, "E1.E2.D1");
+
+ /* index() */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index()=1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1");
+
+ /* $eq$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $eq$ 1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1");
+
+ /* end() */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[end()]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E4.E2.D1");
+
+ /* $not$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[$not$ end()]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1");
+
+ /* !=/$ne$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() != 0]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1 E3.E2.D1 E4.E2.D1");
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $ne$ 0]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1 E3.E2.D1 E4.E2.D1");
+
+ /* </$lt$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() < 2]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $lt$ 2]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+
+ /* <=/$le$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() <= 1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $le$ 1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+
+ /* >/$gt$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() > 1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $gt$ 1]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+
+ /* >=/$ge$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() >= 2]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[index() $ge$ 2]"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+
+ /* $ieq$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $ieq$ 'a2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1");
+
+ /* $ine$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $ine$ 'a2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E3.E2.D1 E4.E2.D1");
+
+ /* $ilt$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $ilt$ 'a3 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+
+ /* $ile$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $ile$ 'a2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E2.E2.D1");
+
+ /* $igt$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $igt$ 'a2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+
+ /* $ige$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[a $ige$ 'a3 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E3.E2.D1 E4.E2.D1");
+
+ /* $any$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[$any$ *='B2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E2.E2.D1");
+
+ /* $all$ */
+ ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[$all$ *!='B2 field']"), &list));
+ len = 0;
+ ole_check(IXMLDOMNodeList_get_length(list, &len));
+ ok(len != 0, "expected filled list\n");
+ if (len)
+ expect_list_and_release(list, "E1.E2.D1 E3.E2.D1 E4.E2.D1");
IXMLDOMDocument2_Release(doc);
free_bstrs();
diff --git a/dlls/msxml3/xslpattern.h b/dlls/msxml3/xslpattern.h
new file mode 100644
index 0000000..7b7cd7f
--- /dev/null
+++ b/dlls/msxml3/xslpattern.h
@@ -0,0 +1,55 @@
+/*
+ * XSLPattern lexer/parser shared internals
+ *
+ * Copyright 2010 Adam Martinson for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __XSLPATTERN__
+#define __XSLPATTERN__
+
+#ifndef __WINE_CONFIG_H
+ #error You must include config.h to use this header
+#endif
+
+#include "wine/debug.h"
+
+#ifndef HAVE_LIBXML2
+ #error You must have libxml2 to use this header
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xmlstring.h>
+
+typedef struct _parser_param {
+ void* yyscanner;
+ xmlChar const* in;
+ int pos;
+ int len;
+ xmlChar* out;
+} parser_param;
+
+#define YYSTYPE xmlChar*
+#define YY_EXTRA_TYPE parser_param*
+
+int xslpattern_lex(xmlChar**, void*);
+int xslpattern_lex_init(void**);
+int xslpattern_lex_destroy(void*);
+void xslpattern_set_extra(parser_param*, void*);
+int xslpattern_parse(parser_param*, void*);
+inline void xslpattern_error(parser_param const* param, void const* scanner, char const* msg);
+
+#endif /* __XSLPATTERN__ */
diff --git a/dlls/msxml3/xslpattern.l b/dlls/msxml3/xslpattern.l
new file mode 100644
index 0000000..951de5e
--- /dev/null
+++ b/dlls/msxml3/xslpattern.l
@@ -0,0 +1,172 @@
+/*
+ * XSLPattern lexer
+ *
+ * Copyright 2010 Adam Martinson for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+#include "config.h"
+#include "wine/port.h"
+
+#ifdef HAVE_LIBXML2
+
+#include "xslpattern.h"
+#include "xslpattern.tab.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msxml);
+
+#define SCAN xslpattern_get_extra(yyscanner)
+
+#define YY_INPUT(tok_buf, tok_len, max) \
+ do { \
+ if (SCAN->pos <= SCAN->len) \
+ { \
+ tok_len = SCAN->len - SCAN->pos; \
+ if (tok_len > max) tok_len = max; \
+ memcpy(tok_buf, SCAN->in + SCAN->pos, tok_len); \
+ SCAN->pos += tok_len; \
+ } \
+ else \
+ { \
+ tok_len = YY_NULL; \
+ } \
+ } while (0);
+
+#define TOK(tok) TRACE("token: %s : %s\n", #tok, yytext); return tok
+#define OP(tok) *yylval=NULL; TOK(tok)
+#define SYM(tok) *yylval=NULL; TOK(tok)
+#define STR(tok) *yylval=xmlStrdup(BAD_CAST yytext); TOK(tok)
+
+
+%}
+
+%option reentrant bison-bridge
+%option noyywrap
+%option prefix="xslpattern_"
+%option nounput
+
+/* From the w3c XML standard
+ * <http://www.w3.org/TR/REC-xml/> */
+
+ /* [2.3] Common Syntactic Constructs */
+WSpace ([[:space:]])
+
+NCNameStartChar ([A-Za-z_]|[\xc0-\xd6\xd8-\xf6\xf8-\xff])
+
+NameCharEx ([0-9]|[-._\xb7])
+
+NCNameChar ({NCNameStartChar}|{NameCharEx})
+
+/* From the w3c XML Namespace standard
+ * <http://www.w3.org/TR/REC-xml-names/> */
+
+ /* [3] Declaring Namespaces*/
+NCName ({NCNameStartChar}{NCNameChar}*)
+
+/* Mostly verbatim from the w3c XPath standard.
+ * <http://www.w3.org/TR/xpath/> */
+
+
+ /* [3.4] Booleans
+ * ||, &&, $foo$ are XSLPattern only */
+
+OP_Or ("or"|"||"|"$or$")
+OP_And ("and"|"&&"|"$and$")
+OP_Eq ("="|"$eq$")
+OP_IEq ("$ieq$")
+OP_NEq ("!="|"$ne$")
+OP_INEq ("$ine$")
+OP_Lt ("<"|"$lt$")
+OP_ILt ("$ilt$")
+OP_Gt (">"|"$gt$")
+OP_IGt ("$igt$")
+OP_LEq ("<="|"$le$")
+OP_ILEq ("$ile$")
+OP_GEq (">="|"$ge$")
+OP_IGEq ("$ige$")
+OP_Not ("$not$")
+OP_All ("$all$")
+OP_Any ("$any$")
+
+ /* [3.7] Lexical Structure */
+Literal (([\x22]([^\x22]*)[\x22])|([\x27]([^\x27]*)[\x27]))
+Number ({Digits}("."{Digits}?)?|"."{Digits})
+Digits ([0-9]+)
+
+ANY (.)
+
+%%
+
+{WSpace}+ { /* ignored */ }
+{Literal} { STR(TOK_Literal); }
+"//" { SYM(TOK_DblFSlash); }
+"/" { SYM(TOK_FSlash); }
+".." { SYM(TOK_Parent); }
+"." { SYM(TOK_Self); }
+"::" { SYM(TOK_Axis); }
+":" { SYM(TOK_Colon); }
+"(" { SYM('('); }
+")" { SYM(')'); }
+"[" { SYM('['); }
+"]" { SYM(']'); }
+"@" { SYM('@'); }
+"," { SYM(','); }
+"*" { SYM('*'); }
+{OP_And} { OP(TOK_OpAnd); }
+{OP_Or} { OP(TOK_OpOr); }
+{OP_Not} { OP(TOK_OpNot); }
+{OP_Eq} { OP(TOK_OpEq); }
+{OP_IEq} { OP(TOK_OpIEq); }
+{OP_NEq} { OP(TOK_OpNEq); }
+{OP_INEq} { OP(TOK_OpINEq); }
+{OP_Lt} { OP(TOK_OpLt); }
+{OP_ILt} { OP(TOK_OpILt); }
+{OP_Gt} { OP(TOK_OpGt); }
+{OP_IGt} { OP(TOK_OpIGt); }
+{OP_LEq} { OP(TOK_OpLEq); }
+{OP_ILEq} { OP(TOK_OpILEq); }
+{OP_GEq} { OP(TOK_OpGEq); }
+{OP_IGEq} { OP(TOK_OpIGEq); }
+{OP_All} { OP(TOK_OpAll); }
+{OP_Any} { OP(TOK_OpAny); }
+"|" { SYM('|'); }
+"!" { SYM('!'); }
+{NCName} { STR(TOK_NCName); }
+{Number} { STR(TOK_Number); }
+{ANY} { FIXME("Unexpected character '%s'.",yytext); }
+
+%%
+
+xmlChar* XSLPattern_to_XPath(xmlChar const* xslpat_str)
+{
+ parser_param p;
+ TRACE("(%s)\n", wine_dbgstr_a((char const*)xslpat_str));
+ memset(&p, 0, sizeof(parser_param));
+ p.in = xslpat_str;
+ p.len = xmlStrlen(xslpat_str);
+
+ xslpattern_lex_init(&p.yyscanner);
+ xslpattern_set_extra(&p, p.yyscanner);
+
+ xslpattern_parse(&p, p.yyscanner);
+
+ TRACE("=> %s\n", wine_dbgstr_a((char const*)p.out));
+ xslpattern_lex_destroy(p.yyscanner);
+ return p.out;
+}
+
+#endif /* HAVE_LIBXML2 */
diff --git a/dlls/msxml3/xslpattern.y b/dlls/msxml3/xslpattern.y
new file mode 100644
index 0000000..f46e991
--- /dev/null
+++ b/dlls/msxml3/xslpattern.y
@@ -0,0 +1,640 @@
+/*
+ * XSLPattern parser (XSLPattern => XPath)
+ *
+ * Copyright 2010 Adam Martinson for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+#include "config.h"
+#include "wine/port.h"
+
+#ifdef HAVE_LIBXML2
+#include "xslpattern.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msxml);
+
+
+static const xmlChar NameTest_mod_pre[] = "*[namespace-uri()=namespace::*[local-name()=''] or namespace-uri()=''][local-name()='";
+static const xmlChar NameTest_mod_post[] = "']";
+
+#define U(str) BAD_CAST str
+#define DBG(str) wine_dbgstr_a((char const*)str)
+%}
+
+%token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
+%token TOK_OpAnd TOK_OpOr TOK_OpNot
+%token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
+%token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
+%token TOK_OpAll TOK_OpAny
+%token TOK_NCName TOK_Literal TOK_Number
+
+%start XSLPattern
+
+%pure_parser
+%parse-param {parser_param* p}
+%parse-param {void* scanner}
+%lex-param {yyscan_t* scanner}
+//%glr-parser
+//%expect-rr 23
+
+%left TOK_OpAnd TOK_OpOr
+%left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
+%left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
+
+%%
+
+ XSLPattern : Expr
+ {
+ p->out = $1;
+ }
+ ;
+
+/* Mostly verbatim from the w3c XML Namespaces standard.
+ * <http://www.w3.org/TR/REC-xml-names/> */
+
+ /* [4] Qualified Names */
+ QName : PrefixedName
+ | UnprefixedName
+ ;
+ PrefixedName : TOK_NCName TOK_Colon TOK_NCName
+ {
+ TRACE("Got PrefixedName: %s:%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$, U(":"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ ;
+ UnprefixedName : TOK_NCName
+ {
+ TRACE("Got UnprefixedName: %s\n", DBG($1));
+ $$=$1;
+ }
+ ;
+/* Based on the w3c XPath standard, adapted where needed.
+ * <http://www.w3.org/TR/xpath/> */
+
+ /* [2] Location Paths */
+ LocationPath : RelativeLocationPath
+ | AbsoluteLocationPath
+ ;
+ AbsoluteLocationPath : TOK_FSlash RelativeLocationPath
+ {
+ TRACE("Got AbsoluteLocationPath: /%s\n", DBG($1));
+ $$=xmlStrdup(U("/"));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ | TOK_FSlash
+ {
+ TRACE("Got AbsoluteLocationPath: /\n");
+ $$=xmlStrdup(U("/"));
+ }
+ | AbbreviatedAbsoluteLocationPath
+ ;
+ RelativeLocationPath : Step
+ | RelativeLocationPath TOK_FSlash Step
+ {
+ TRACE("Got RelativeLocationPath: %s/%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("/"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | AbbreviatedRelativeLocationPath
+ ;
+ /* [2.1] Location Steps */
+ Step : AxisSpecifier NameTest Predicates
+ {
+ TRACE("Got Step: %s%s%s\n", DBG($1), DBG($2), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | NameTest Predicates
+ {
+ TRACE("Got Step: %s%s\n", DBG($1), DBG($2));
+ $$=$1;
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ | AxisSpecifier NameTest
+ {
+ TRACE("Got Step: %s%s\n", DBG($1), DBG($2));
+ $$=$1;
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ | NameTest
+ | AbbreviatedStep
+ ;
+ AxisSpecifier : TOK_NCName TOK_Axis
+ {
+ TRACE("Got AxisSpecifier: %s::\n", DBG($1));
+ $$=$1;
+ $$=xmlStrcat($$,U("::"));
+ }
+ | AbbreviatedAxisSpecifier
+ ;
+
+ /* [2.3] Node Tests */
+ NameTest : '*'
+ {
+ TRACE("Got NameTest: *\n");
+ $$=xmlStrdup(U("*"));
+ }
+ | TOK_NCName TOK_Colon '*'
+ {
+ TRACE("Got NameTest: %s:*\n", DBG($1));
+ $$=$1;
+ $$=xmlStrcat($$,U(":*"));
+ }
+ | PrefixedName
+ | UnprefixedName
+ {
+ $$=xmlStrdup(NameTest_mod_pre);
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,NameTest_mod_post);
+ }
+ /* [2.4] Predicates */
+ Predicates : Predicates Predicate
+ {
+ $$=$1;
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ | Predicate
+ ;
+ Predicate : '[' PredicateExpr ']'
+ {
+ TRACE("Got Predicate: [%s]\n", DBG($1));
+ $$=xmlStrdup(U("["));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,U("]"));
+ }
+ ;
+ PredicateExpr : TOK_Number
+ {
+ $$=xmlStrdup(U("index()="));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ }
+ | BoolExpr
+ ;
+ /* [2.5] Abbreviated Syntax */
+ AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
+ {
+ TRACE("Got AbbreviatedAbsoluteLocationPath: //%s\n", DBG($2));
+ $$=xmlStrdup(U("//"));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ ;
+ AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
+ {
+ TRACE("Got AbbreviatedRelativeLocationPath: %s//%s\n", DBG($1), DBG($2));
+ $$=$1;
+ $$=xmlStrcat($$,U("//"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ ;
+ AbbreviatedStep : TOK_Parent
+ {
+ TRACE("Got AbbreviatedStep: ..\n");
+ $$=xmlStrdup(U(".."));
+ }
+ | TOK_Self
+ {
+ TRACE("Got AbbreviatedStep: .\n");
+ $$=xmlStrdup(U("."));
+ }
+ ;
+ AbbreviatedAxisSpecifier: '@'
+ {
+ TRACE("Got AbbreviatedAxisSpecifier: @\n");
+ $$=xmlStrdup(U("@"));
+ }
+ ;
+
+ /* [3] Expressions */
+ /* [3.1] Basics */
+ Expr : OrExpr
+ ;
+ BoolExpr : FunctionCall
+ | BoolUnaryExpr
+ | BoolRelationalExpr
+ | BoolEqualityExpr
+ | BoolAndExpr
+ | BoolOrExpr
+ ;
+ PrimaryExpr : '(' Expr ')'
+ {
+ TRACE("Got PrimaryExpr: (%s)\n", DBG($1));
+ $$=xmlStrdup(U("("));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr '!' FunctionCall
+ {
+ TRACE("Got PrimaryExpr: %s!%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("/"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | TOK_Literal
+ | TOK_Number
+ | FunctionCall
+ ;
+ /* [3.2] Function Calls */
+ FunctionCall : QName '(' Arguments ')'
+ {
+ TRACE("Got FunctionCall: %s(%s)\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("("));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | QName '(' ')'
+ {
+ TRACE("Got FunctionCall: %s()\n", DBG($1));
+ $$=$1;
+ $$=xmlStrcat($$,U("()"));
+ }
+ ;
+ Arguments : Argument ',' Arguments
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | Argument
+ ;
+ Argument : Expr
+ ;
+ /* [3.3] Node-sets */
+ UnionExpr : PathExpr
+ | UnionExpr '|' PathExpr
+ {
+ TRACE("Got UnionExpr: %s|%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("|"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ ;
+ PathExpr : LocationPath
+ | FilterExpr TOK_FSlash RelativeLocationPath
+ {
+ TRACE("Got PathExpr: %s/%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("/"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | FilterExpr TOK_DblFSlash RelativeLocationPath
+ {
+ TRACE("Got PathExpr: %s//%s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("//"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | FilterExpr
+ ;
+ FilterExpr : PrimaryExpr
+ | FilterExpr Predicate
+ {
+ TRACE("Got FilterExpr: %s%s\n", DBG($1), DBG($2));
+ $$=$1;
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ }
+ ;
+ /* [3.4] Booleans */
+ OrExpr : AndExpr
+ | BoolOrExpr
+ ;
+ BoolOrExpr : OrExpr TOK_OpOr AndExpr
+ {
+ TRACE("Got OrExpr: %s or %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U(" or "));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ ;
+ AndExpr : EqualityExpr
+ | BoolAndExpr
+ ;
+ BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr
+ {
+ TRACE("Got AndExpr: %s and %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U(" and "));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ ;
+ EqualityExpr : RelationalExpr
+ | BoolEqualityExpr
+ ;
+ BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr
+ {
+ TRACE("Got EqualityExpr: %s $eq$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | EqualityExpr TOK_OpIEq RelationalExpr
+ {
+ TRACE("Got EqualityExpr: %s $ieq$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_IEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | EqualityExpr TOK_OpNEq RelationalExpr
+ {
+ TRACE("Got EqualityExpr: %s $ne$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("!="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | EqualityExpr TOK_OpINEq RelationalExpr
+ {
+ TRACE("Got EqualityExpr: %s $ine$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_INEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+
+ ;
+ RelationalExpr : UnaryExpr
+ | BoolRelationalExpr
+ ;
+ BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $lt$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("<"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | RelationalExpr TOK_OpILt UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $ilt$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_ILt("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | RelationalExpr TOK_OpGt UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $gt$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U(">"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | RelationalExpr TOK_OpIGt UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $igt$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_IGt("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | RelationalExpr TOK_OpLEq UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $le$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U("<="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | RelationalExpr TOK_OpILEq UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $ile$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_ILEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | RelationalExpr TOK_OpGEq UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $ge$ %s\n", DBG($1), DBG($3));
+ $$=$1;
+ $$=xmlStrcat($$,U(">="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | RelationalExpr TOK_OpIGEq UnaryExpr
+ {
+ TRACE("Got RelationalExpr: %s $ige$ %s\n", DBG($1), DBG($3));
+ $$=xmlStrdup(U("OP_IGEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ ;
+
+ /* [3.5] Numbers */
+ UnaryExpr : UnionExpr
+ | BoolUnaryExpr
+ ;
+ BoolUnaryExpr : TOK_OpNot UnaryExpr
+ {
+ TRACE("Got UnaryExpr: $not$ %s\n", DBG($2));
+ $$=xmlStrdup(U(" not("));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | TOK_OpAny Expr
+ {
+ TRACE("Got UnaryExpr: $any$ %s\n", DBG($2));
+ $$=xmlStrdup(U("boolean("));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | TOK_OpAll AllExpr
+ {
+ TRACE("Got UnaryExpr: $all$ %s\n", DBG($2));
+ $$=xmlStrdup(U("not("));
+ $$=xmlStrcat($$,$2);
+ xmlFree($2);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | TOK_OpAll
+ {
+ FIXME("Unrecognized $all$ expression - ignoring\n");
+ $$=xmlStrdup(U(""));
+ }
+ ;
+ AllExpr : PathExpr TOK_OpEq PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U("!="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpNEq PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U("="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpLt PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U(">="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpLEq PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U(">"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpGt PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U("<="));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpGEq PathExpr
+ {
+ $$=$1;
+ $$=xmlStrcat($$,U("<"));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ }
+ | PathExpr TOK_OpIEq PathExpr
+ {
+ $$=xmlStrdup(U("OP_INEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr TOK_OpINEq PathExpr
+ {
+ $$=xmlStrdup(U("OP_IEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr TOK_OpILt PathExpr
+ {
+ $$=xmlStrdup(U("OP_IGEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr TOK_OpILEq PathExpr
+ {
+ $$=xmlStrdup(U("OP_IGt("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr TOK_OpIGt PathExpr
+ {
+ $$=xmlStrdup(U("OP_ILEq("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ | PathExpr TOK_OpIGEq PathExpr
+ {
+ $$=xmlStrdup(U("OP_ILt("));
+ $$=xmlStrcat($$,$1);
+ xmlFree($1);
+ $$=xmlStrcat($$,U(","));
+ $$=xmlStrcat($$,$3);
+ xmlFree($3);
+ $$=xmlStrcat($$,U(")"));
+ }
+ ;
+
+%%
+
+inline void xslpattern_error(parser_param const* param, void const* scanner, char const* msg)
+{
+ FIXME("%s:\n"
+ " param {\n"
+ " yyscanner=%p\n"
+ " in=\"%s\"\n"
+ " pos=%i\n"
+ " len=%i\n"
+ " out=\"%s\"\n"
+ " }\n"
+ " scanner=%p\n",
+ msg, param->yyscanner, param->in, param->pos, param->len, param->out, scanner);
+}
+
+
+#endif /* HAVE_LIBXML2 */
--
1.7.2.3
--------------050508040601010607020001--
More information about the wine-patches
mailing list