xpath.c revision 692092b5886073a8cd1c97bb7d57579e4a9cfc3f
13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
23473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xpath.c: XML Path Language implementation
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          XPath is a language for addressing parts of an XML document,
43473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          designed to be used by both XSLT and XPointer
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Reference: W3C Recommendation 16 November 1999
73473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/1999/REC-xpath-19991116
83473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Public reference:
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/xpath
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * See Copyright for the status of this software
123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * Author: daniel@veillard.com
143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 14 Nov 2000 ht - truncated declaration of xmlXPathEvalRelativeLocationPath
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * for VMS
173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1934ce8bece2f22cc99d25221b77315cd008f4866bDaniel Veillard#define IN_LIBXML
2070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPATH_ENABLED
223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h>
243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_TYPES_H
263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/types.h>
273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_MATH_H
293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <math.h>
303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_FLOAT_H
323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <float.h>
333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_CTYPE_H
353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <ctype.h>
363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
375792e16f0562d206e1ef4e611f7b43ec53c92149Daniel Veillard#ifdef HAVE_SIGNAL_H
38b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#include <signal.h>
39b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#endif
403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/tree.h>
433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/valid.h>
443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpath.h>
453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpathInternals.h>
463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/parserInternals.h>
473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/hash.h>
483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpointer.h>
503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/debugXML.h>
533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlerror.h>
558146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#include <libxml/threads.h>
563c01b1d81b696fe8624b6d7e26ec0ebffcc7c06bDaniel Veillard#include <libxml/globals.h>
573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* #define DEBUG */
593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* #define DEBUG_STEP */
60f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/* #define DEBUG_STEP_NTH */
613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* #define DEBUG_EXPR */
62f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/* #define DEBUG_EVAL_COUNTS */
633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
645792e16f0562d206e1ef4e611f7b43ec53c92149Daniel Veillarddouble xmlXPathDivideBy(double f, double fzero);
653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6620ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic xmlNs xmlXPathXMLNamespaceStruct = {
6720ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    NULL,
6820ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    XML_NAMESPACE_DECL,
6920ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    XML_XML_NAMESPACE,
7020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    BAD_CAST "xml"
7120ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard};
7220ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
73da423da207ec877ed93a7b165c5ef6d6785e8940Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
748146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard/*
758146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard * Optimizer is disabled only when threaded apps are detected while
768146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard * the library ain't compiled for thread safety.
778146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard */
788146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillardstatic int xmlXPathDisableOptimizer = 0;
798146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
8020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard
819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Floating point stuff				*
849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
87c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#ifndef TRIO_REPLACE_STDIO
88cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#define TRIO_PUBLIC static
89c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#endif
90cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#include "trionan.c"
91cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lack of portability of this section of the libc is annoying !
943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNAN = 0;
963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathPINF = 1;
973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNINF = -1;
985fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillarddouble xmlXPathNZERO = 0;
9920ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic int xmlXPathInitialized = 0;
1003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathInit:
1033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initialize the XPath environment
1053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathInit(void) {
10820ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    if (xmlXPathInitialized) return;
1093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
110450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathPINF = trio_pinf();
111450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNINF = trio_ninf();
112450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNAN = trio_nan();
1135fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    xmlXPathNZERO = trio_nzero();
1143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11520ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    xmlXPathInitialized = 1;
1163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
118cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
119cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsNaN:
120cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
121cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
122cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isnan() function to detect whether a double
123cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a NotaNumber. Based on trio code
124cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
125cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
126cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 if the value is a NaN, 0 otherwise
127cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
128cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
129cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsNaN(double val) {
130cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isnan(val));
131cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
132cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
133cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
134cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsInf:
135cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
136cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
137cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isinf() function to detect whether a double
138cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a +Infinite or -Infinite. Based on trio code
139cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
140cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
141cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
142cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
143cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
144cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsInf(double val) {
145cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isinf(val));
146cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
147cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
1485fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard/**
1495fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * xmlXPathGetSign:
1505fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * @val:  a double value
1515fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1525fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Provides a portable function to detect the sign of a double
1535fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Modified from trio code
1545fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * http://sourceforge.net/projects/ctrio/
1555fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1565fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Returns 1 if the value is Negative, 0 if positive
1575fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard */
15821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillardstatic int
1595fc1f0893af6ffe76453ac16817204a866bdeab2Daniel VeillardxmlXPathGetSign(double val) {
16021458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    return(trio_signbit(val));
1615fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard}
1625fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
1635fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
1643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
1659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
1669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Types					*
1679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
1689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
1699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/*
1719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Types are private:
1729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
1739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
1759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_END=0,
1769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_AND,
1779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_OR,
1789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_EQUAL,
1799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_CMP,
1809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PLUS,
1819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_MULT,
1829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_UNION,
1839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ROOT,
1849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_NODE,
1859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_RESET,
1869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_COLLECT,
1879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VALUE,
1889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VARIABLE,
1899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_FUNCTION,
1909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ARG,
1919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PREDICATE,
192d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    XPATH_OP_FILTER,
1939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_SORT
1949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
1959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ,XPATH_OP_RANGETO
1969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif
1979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathOp;
1989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR = 1,
2019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR_OR_SELF,
2029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ATTRIBUTE,
2039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_CHILD,
2049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT,
2059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT_OR_SELF,
2069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING,
2079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING_SIBLING,
2089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_NAMESPACE,
2099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PARENT,
2109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING,
2119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING_SIBLING,
2129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_SELF
2139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathAxisVal;
2149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NONE = 0,
2179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_TYPE = 1,
2189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_PI = 2,
2199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_ALL = 3,
2209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NS = 4,
2219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NAME = 5
2229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTestVal;
2239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_NODE = 0,
2269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_COMMENT = XML_COMMENT_NODE,
2279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_TEXT = XML_TEXT_NODE,
2289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_PI = XML_PI_NODE
2299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTypeVal;
2309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef struct _xmlXPathStepOp xmlXPathStepOp;
2339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef xmlXPathStepOp *xmlXPathStepOpPtr;
2349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathStepOp {
2359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathOp op;
2369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int ch1;
2379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int ch2;
2389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value;
2399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value2;
2409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value3;
2419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value4;
2429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value5;
243e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    void *cache;
24442596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    void *cacheURI;
2459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
2469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathCompExpr {
2489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int nbStep;
2499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int maxStep;
2509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOp *steps;        /* ops for computation */
2519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int last;
252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int nb;
254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlChar *string;
255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
2569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
2579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
2599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
2609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Type functions 				*
2619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
2629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
2639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
2659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathNewCompExpr:
2669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
2679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new Xpath component
2689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
2699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
2709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
27156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathCompExprPtr
2729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathNewCompExpr(void) {
2739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr cur;
2749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
2769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur == NULL) {
2779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
2789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		"xmlXPathNewCompExpr : malloc failed\n");
2799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
2809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
2819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur, 0, sizeof(xmlXPathCompExpr));
2829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->maxStep = 10;
2839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->nbStep = 0;
2849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
2859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                                   sizeof(xmlXPathStepOp));
2869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur->steps == NULL) {
2879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
2889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		"xmlXPathNewCompExpr : malloc failed\n");
2899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(cur);
2909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
2919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
2929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
2939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->last = -1;
294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur->nb = 0;
296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
2979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(cur);
2989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
2999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
3019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathFreeCompExpr:
3029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  an XPATH comp
3039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Free up the memory allocated by @comp
3059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
3069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardvoid
307f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
3099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOpPtr op;
3109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
3119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL)
313f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return;
314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < comp->nbStep; i++) {
315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        op = &comp->steps[i];
316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (op->value4 != NULL) {
317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->op == XPATH_OP_VALUE)
318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(op->value4);
319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else
320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(op->value4);
321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (op->value5 != NULL)
323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlFree(op->value5);
3249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
3259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->steps != NULL) {
326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->steps);
3279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
328f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp->string != NULL) {
330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->string);
331f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlFree(comp);
3359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
3369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
3389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompExprAdd:
3399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled expression
3409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch1: first child index
3419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch2: second child index
3429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @op:  an op
3439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value:  the first int value
3449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value2:  the second int value
3459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value3:  the third int value
3469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value4:  the first string value
3479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value5:  the second string value
3489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Add an step to an XPath Compiled Expression
3509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns -1 in case of failure, the index otherwise
3529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
35356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
3549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
3559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   xmlXPathOp op, int value,
3569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   int value2, int value3, void *value4, void *value5) {
3579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->nbStep >= comp->maxStep) {
3589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathStepOp *real;
3599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->maxStep *= 2;
3619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
3629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		                      comp->maxStep * sizeof(xmlXPathStepOp));
3639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (real == NULL) {
3649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->maxStep /= 2;
3659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
3669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    "xmlXPathCompExprAdd : realloc failed\n");
3679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    return(-1);
3689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
3699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->steps = real;
3709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
3719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->last = comp->nbStep;
3729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch1 = ch1;
3739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch2 = ch2;
3749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].op = op;
3759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value = value;
3769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value2 = value2;
3779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value3 = value3;
3789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value4 = value4;
3799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value5 = value5;
380e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    comp->steps[comp->nbStep].cache = NULL;
3819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(comp->nbStep++);
3829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
3839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompSwap:
386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @comp:  the compiled expression
387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op: operation index
388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Swaps 2 operations in the compiled expression
390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic void
392f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompSwap(xmlXPathStepOpPtr op) {
393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int tmp;
394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
395bc6f759ac9b41773e3643ad288b5214732051c98Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
3968146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    /*
3978146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * Since this manipulates possibly shared variables, this is
3988146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * disable if one detects that the library is used in a multithreaded
3998146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * application
4008146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     */
4018146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (xmlXPathDisableOptimizer)
4028146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	return;
4038146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
4048146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = op->ch1;
406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch1 = op->ch2;
407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch2 = tmp;
408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
410d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5)	\
411d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprAdd(ctxt->comp, (op1), (op2),			\
412d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
4139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5)			\
4149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1,		\
4159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
4169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LEAVE_EXPR(op, val, val2) 					\
4189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
4199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_UNARY_EXPR(op, ch, val, val2) 				\
4219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
4229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) 			\
4249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), (val), (val2), 0 ,NULL ,NULL)
4259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
4273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
4283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Debugging related functions				*
4293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
4303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
4313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define TODO 								\
4333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
4343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Unimplemented block at %s:%d\n",				\
4353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
4363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define STRANGE 							\
4383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
4393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Internal error at %s:%d\n",				\
4403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
4413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
44356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
44456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
4453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
4463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
4473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
4493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
4503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
4513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
4523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
4533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "Node is NULL !\n");
4543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
4553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
4593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     (cur->type == XML_HTML_DOCUMENT_NODE)) {
4603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
4613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " /\n");
4623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->type == XML_ATTRIBUTE_NODE)
4633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
4643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
4653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpOneNode(output, cur, depth);
4663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
46756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
46856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
469f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlNodePtr tmp;
470f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
471f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
472f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
473f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
474f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
475f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
476f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if (cur == NULL) {
477f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
478f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Node is NULL !\n");
479f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
480f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
481f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
482f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
483f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    while (cur != NULL) {
484f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	tmp = cur;
485f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	cur = cur->next;
486f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	xmlDebugDumpOneNode(output, tmp, depth);
487f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
488f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
4893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
49156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
4923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
4933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
4943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
4963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
4973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
4983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "NodeSet is NULL !\n");
5023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
506911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (cur != NULL) {
507911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
508911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < cur->nodeNr;i++) {
509911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, shift);
510911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, "%d", i + 1);
511911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
512911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
5133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
5153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
51756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
518f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
519f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
520f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
521f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
522f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
523f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
524f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
525f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
526f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
527f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Value Tree is NULL !\n");
528f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
529f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
530f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
531f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
532f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, shift);
533f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, "%d", i + 1);
534f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
535f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
5363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
53756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
53856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
5393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
5403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
5413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
5433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
5443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
5453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "LocationSet is NULL !\n");
5493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->locNr;i++) {
5543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "%d : ", i + 1);
5563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
5573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
559017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
5603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
561afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
562afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathDebugDumpObject:
563afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @output:  the FILE * to dump the output
564afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @cur:  the object to inspect
565afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @depth:  indentation level
566afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
567afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Dump the content of the object for debugging purposes
568afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
569afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
570afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
5713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
5723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
5733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
5753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
5763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
5773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, shift);
5793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "Object is empty (NULL)\n");
5823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(cur->type) {
5853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
5863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is uninitialized\n");
5873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
5883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
5893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Node Set :\n");
5903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
5913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
5923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
5933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is an XSLT value tree :\n");
594f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	    xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
5953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
5963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
5973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Boolean : ");
5983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->boolval) fprintf(output, "true\n");
5993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else fprintf(output, "false\n");
6003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
602cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    switch (xmlXPathIsInf(cur->floatval)) {
603357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case 1:
6045fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard		fprintf(output, "Object is a number : Infinity\n");
605357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
606357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case -1:
607357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		fprintf(output, "Object is a number : -Infinity\n");
608357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
609357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    default:
610cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard		if (xmlXPathIsNaN(cur->floatval)) {
611357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : NaN\n");
612d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		} else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
613d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    fprintf(output, "Object is a number : 0\n");
614357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		} else {
615357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
616357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		}
617357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    }
6183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
6203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a string : ");
6213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlDebugDumpString(output, cur->stringval);
6223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
6233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
6253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a point : index %d in node", cur->index);
6263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
6273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
6283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
6303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((cur->user2 == NULL) ||
6313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		((cur->user2 == cur->user) && (cur->index == cur->index2))) {
6323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a collapsed range :\n");
6333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
6353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
6363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
6383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else  {
6403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a range :\n");
6413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "From ");
6433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
6443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
6453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
6473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "To ");
6503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index2 >= 0)
6513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index2);
6523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
6543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "\n");
6563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
6573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
6593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
6603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Location Set:\n");
6613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpLocationSet(output,
6623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    (xmlLocationSetPtr) cur->user, depth);
6633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_USERS:
6663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is user defined\n");
6673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
6709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
67156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
67256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
6739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                     xmlXPathStepOpPtr op, int depth) {
6749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
6759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
6769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
6789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
6799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
6809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
6829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op == NULL) {
6839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Step is NULL\n");
6849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
6859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
6869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    switch (op->op) {
6879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_END:
6889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "END"); break;
6899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_AND:
6909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "AND"); break;
6919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_OR:
6929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "OR"); break;
6939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_EQUAL:
6949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
6959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL =");
6969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
6979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL !=");
6989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
6999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_CMP:
7009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
7019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP <");
7029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
7039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP >");
7049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (!op->value2)
7059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "=");
7069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PLUS:
7089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
7099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS -");
7109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
7119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS +");
7129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 2)
7139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary -");
7149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 3)
7159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary - -");
7169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_MULT:
7189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
7199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT *");
7209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
7219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT div");
7229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
7239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT mod");
7249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_UNION:
7269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "UNION"); break;
7279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ROOT:
7289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "ROOT"); break;
7299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_NODE:
7309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "NODE"); break;
7319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_RESET:
7329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "RESET"); break;
7339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_SORT:
7349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "SORT"); break;
7359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_COLLECT: {
7369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathAxisVal axis = op->value;
7379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathTestVal test = op->value2;
7389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathTypeVal type = op->value3;
7399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value4;
7409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value5;
7419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
7429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "COLLECT ");
7439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (axis) {
7449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR:
7459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors' "); break;
7469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR_OR_SELF:
7479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors-or-self' "); break;
7489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ATTRIBUTE:
7499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'attributes' "); break;
7509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_CHILD:
7519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'child' "); break;
7529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT:
7539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant' "); break;
7549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT_OR_SELF:
7559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant-or-self' "); break;
7569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING:
7579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following' "); break;
7589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING_SIBLING:
7599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following-siblings' "); break;
7609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_NAMESPACE:
7619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'namespace' "); break;
7629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PARENT:
7639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'parent' "); break;
7649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING:
7659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding' "); break;
7669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING_SIBLING:
7679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding-sibling' "); break;
7689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_SELF:
7699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'self' "); break;
7709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
7719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (test) {
7729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NONE:
7739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'none' "); break;
7749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_TYPE:
7759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'type' "); break;
7769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_PI:
7779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
7789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_ALL:
7799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'all' "); break;
7809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NS:
7819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'namespace' "); break;
7829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NAME:
7839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'name' "); break;
7849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
7859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (type) {
7869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_NODE:
7879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'node' "); break;
7889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_COMMENT:
7899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'comment' "); break;
7909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_TEXT:
7919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'text' "); break;
7929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_PI:
7939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
7949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
7959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
7969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "%s:", prefix);
7979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (name != NULL)
7989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "%s", name);
7999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
8029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VALUE: {
8039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
8049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "ELEM ");
8069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathDebugDumpObject(output, object, 0);
8079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    goto finish;
8089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VARIABLE: {
8109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
8119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
8129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
8149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s:%s", prefix, name);
8159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
8169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s", name);
8179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_FUNCTION: {
8209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    int nbargs = op->value;
8219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
8229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
8239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
8259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s:%s(%d args)",
8269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			prefix, name, nbargs);
8279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
8289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
8299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ARG: fprintf(output, "ARG"); break;
8329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
833d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
834fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
835fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard        case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
836fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	default:
8389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        fprintf(output, "UNKNOWN %d\n", op->op); return;
8399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
8409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "\n");
8419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardfinish:
8429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch1 >= 0)
8439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
8449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch2 >= 0)
8459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
8469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
84756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard
8485e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
8495e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathDebugDumpCompExpr:
8505e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @output:  the FILE * for the output
8515e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @comp:  the precompiled XPath expression
8525e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @depth:  the indentation level.
8535e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
8545e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Dumps the tree of the compiled XPath expression.
8555e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
85656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardvoid
85756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
85856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	                  int depth) {
8599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
8609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
8619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
8639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
8649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
8659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
8679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL) {
8699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Compiled Expression is NULL\n");
8709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
8719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
8729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "Compiled Expression : %d elements\n",
8739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->nbStep);
8749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    i = comp->last;
8759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
8769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
877017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_DEBUG_ENABLED */
8783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
8803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
8813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Parser stacks related functions and macros		*
8823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
8833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
8843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
8863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Generic function for accessing stacks in the Parser Context
8873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define PUSH_AND_POP(type, name)					\
8903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorextern int name##Push(xmlXPathParserContextPtr ctxt, type value) {	\
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->name##Nr >= ctxt->name##Max) {				\
8923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->name##Max *= 2;						\
8933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ctxt->name##Tab = (type *) xmlRealloc(ctxt->name##Tab,		\
8943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	             ctxt->name##Max * sizeof(ctxt->name##Tab[0]));	\
8953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->name##Tab == NULL) {					\
8963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,			\
8973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "realloc failed !\n");				\
8983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(0);							\
8993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}								\
9003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
9013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->name##Tab[ctxt->name##Nr] = value;				\
9023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->name = value;							\
9033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ctxt->name##Nr++);						\
9043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}									\
9053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorextern type name##Pop(xmlXPathParserContextPtr ctxt) {			\
9063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    type ret;								\
9073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->name##Nr <= 0) return(0);					\
9083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->name##Nr--;							\
9093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->name##Nr > 0)						\
9103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];		\
9113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else								\
9123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ctxt->name = NULL;						\
9133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = ctxt->name##Tab[ctxt->name##Nr];				\
9143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->name##Tab[ctxt->name##Nr] = 0;				\
9153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);							\
9163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}									\
9173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9185e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
9195e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePop:
9205e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt: an XPath evaluation context
9215e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
9225e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pops the top XPath object from the value stack
9235e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
9245e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Returns the XPath object just removed
9255e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
9265e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
9275e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePush:
9285e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt:  an XPath evaluation context
9295e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @value:  the XPath object
9305e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
9315e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pushes a new XPath object on top of the value stack
932cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *
933cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * returns the number of items on the value stack
9345e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
9353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorPUSH_AND_POP(xmlXPathObjectPtr, value)
9363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
937f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
938f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopBoolean:
939f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
940f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
941f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a boolean from the stack, handling conversion if needed.
942f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
943f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
944f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the boolean
945f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
946f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
947f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
948f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
949f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int ret;
950f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
951f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
952f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
953f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
954f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
955f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
956f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToBoolean(obj);
957f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
958f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
959f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
960f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
961f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
962f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNumber:
963f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
964f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
965f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a number from the stack, handling conversion if needed.
966f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
967f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
968f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the number
969f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
970f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerdouble
971f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
972f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
973f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    double ret;
974f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
975f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
976f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
977f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
978f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
979f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
980f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToNumber(obj);
981f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
982f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
983f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
984f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
985f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
986f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopString:
987f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
988f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
989f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a string from the stack, handling conversion if needed.
990f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
991f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
992f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the string
993f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
994f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlChar *
995f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopString (xmlXPathParserContextPtr ctxt) {
996f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
997f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * ret;
998f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
999f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1000f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1001f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1002f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1003f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1004f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToString(obj);
1005f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    /* TODO: needs refactoring somewhere else */
1006f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj->stringval == ret)
1007f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	obj->stringval = NULL;
1008f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1009f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1010f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1011f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1012f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1013f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNodeSet:
1014f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1015f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1016f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a node-set from the stack, handling conversion if needed.
1017f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1018f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1019f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the node-set
1020f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1021f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
1022f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
1023f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1024f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
1025f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1026f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1027f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1028f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1029f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1030f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (!xmlXPathStackIsNodeSet(ctxt)) {
1031f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1032f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1033f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1034f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1035f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->nodesetval;
1036f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeNodeSetList(obj);
1037f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1038f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1039f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1040f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1041f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopExternal:
1042f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1043f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1044cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Pops an external object from the stack, handling conversion if needed.
1045f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1046f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1047f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the object
1048f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1049f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyervoid *
1050f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
1051f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1052f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    void * ret;
1053f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1054f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1055f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1056f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1057f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1058f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value->type != XPATH_USERS) {
1059f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1060f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1061f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1062f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1063f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->user;
1064f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1065f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1066f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1067f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
10683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
10693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Macros for accessing the content. Those should be used only by the parser,
10703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and not exported.
10713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Dirty macros, i.e. one need to make assumption on the context to use them
10733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR_PTR return the current pointer to the xmlChar to be parsed.
10753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR     returns the current xmlChar value, i.e. a 8 bit value
10763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in ISO-Latin or UTF-8.
10773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           This should be used internally by the parser
10783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           only to compare to ASCII values otherwise it would break when
10793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           running with UTF-8 encoding.
10803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
10813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           to compare on ASCII based substring.
10823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
10833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           strings within the parser.
10843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CURRENT Returns the current char value, with the full decoding of
10853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           UTF-8 if we are using this mode. It returns an int.
10863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NEXT    Skip to the next character, this does the proper decoding
10873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
10883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           It returns the pointer to the current xmlChar.
10893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
10903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR (*ctxt->cur)
10923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP(val) ctxt->cur += (val)
10933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NXT(val) ctxt->cur[(val)]
10943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR_PTR ctxt->cur
109561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
109661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
109761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define COPY_BUF(l,b,i,v)                                              \
109861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (l == 1) b[i++] = (xmlChar) v;                                  \
109961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    else i += xmlCopyChar(l,&b[i],v)
110061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
110161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define NEXTL(l)  ctxt->cur += l
11023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP_BLANKS 							\
11043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*(ctxt->cur))) NEXT
11053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CURRENT (*ctxt->cur)
11073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
11083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1109e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1110e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_DIG
1111e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_DIG 16
1112e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1113e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_EPSILON
1114e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_EPSILON 1E-9
1115e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1116e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1117e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define UPPER_DOUBLE 1E9
1118e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define LOWER_DOUBLE 1E-5
1119e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1120e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define INTEGER_DIGITS DBL_DIG
1121e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define FRACTION_DIGITS (DBL_DIG + 1)
1122e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define EXPONENT_DIGITS (3 + 2)
1123e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1124e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese/**
1125e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * xmlXPathFormatNumber:
1126e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @number:     number to format
1127e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffer:     output buffer
1128e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffersize: size of output buffer
1129e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese *
1130e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * Convert the number into a string representation.
1131e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese */
1132e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reesestatic void
1133e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn ReesexmlXPathFormatNumber(double number, char buffer[], int buffersize)
1134e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese{
1135cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(number)) {
1136e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case 1:
11375fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (buffersize > (int)sizeof("Infinity"))
113849cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "Infinity");
1139e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1140e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case -1:
1141e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	if (buffersize > (int)sizeof("-Infinity"))
114249cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "-Infinity");
1143e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1144e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    default:
1145cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(number)) {
1146e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    if (buffersize > (int)sizeof("NaN"))
114749cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin		snprintf(buffer, buffersize, "NaN");
1148d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (number == 0 && xmlXPathGetSign(number) != 0) {
114949cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "0");
115028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	} else if (number == ((int) number)) {
115128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char work[30];
115228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char *ptr, *cur;
115328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    int res, value = (int) number;
115428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard
115528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard            ptr = &buffer[0];
115628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value < 0) {
115728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '-';
115828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		value = -value;
115928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
116028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value == 0) {
116128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '0';
116228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else {
116328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur = &work[0];
116428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while (value != 0) {
116528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    res = value % 10;
116628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    value = value / 10;
116728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *cur++ = '0' + res;
116828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
116928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur--;
117028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while ((cur >= &work[0]) && (ptr - buffer < buffersize)) {
117128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *ptr++ = *cur--;
117228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
117328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
117428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (ptr - buffer < buffersize) {
117528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
117628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else if (buffersize > 0) {
117728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		ptr--;
117828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
117928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
1180e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	} else {
118170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* 3 is sign, decimal point, and terminating zero */
118270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
118370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int integer_place, fraction_place;
118470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *ptr;
118570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *after_fraction;
118670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    double absolute_value;
118770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int size;
118870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
118970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    absolute_value = fabs(number);
119070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
119170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /*
119270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * First choose format - scientific or regular floating point.
119370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * In either case, result is in work, and after_fraction points
119470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * just past the fractional part.
119570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    */
119670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if ( ((absolute_value > UPPER_DOUBLE) ||
119770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		  (absolute_value < LOWER_DOUBLE)) &&
119870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		 (absolute_value != 0.0) ) {
119970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use scientific notation */
120070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
120170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = DBL_DIG - 1;
120270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		snprintf(work, sizeof(work),"%*.*e",
120370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese			 integer_place, fraction_place, number);
120470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = strchr(work + DBL_DIG, 'e');
1205e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
120670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    else {
120770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use regular notation */
120856f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		if (absolute_value > 0.0)
120956f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		    integer_place = 1 + (int)log10(absolute_value);
121056f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		else
1211a3067d19ec3a96fd6e7997753e27a5422a2856f7Daniel Veillard		    integer_place = 0;
121270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = (integer_place > 0)
121370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    ? DBL_DIG - integer_place
121470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    : DBL_DIG;
121570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = snprintf(work, sizeof(work), "%0.*f",
121670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese				fraction_place, number);
121770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = work + size;
1218e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
1219e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
122070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Remove fractional trailing zeroes */
122170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    ptr = after_fraction;
122270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    while (*(--ptr) == '0')
122370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		;
122470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (*ptr != '.')
122570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	        ptr++;
122670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    strcpy(ptr, after_fraction);
122770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
122870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Finally copy result back to caller */
122970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    size = strlen(work) + 1;
123070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (size > buffersize) {
123170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		work[buffersize - 1] = 0;
123270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = buffersize;
123370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    }
123470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    memcpy(buffer, work, size);
1235e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	}
1236e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1237e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    }
1238e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese}
1239e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
12403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
12413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
12423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Error handling routines				*
12433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
12443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
12453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1247b44025c72b7472971a061b022cfe422adc42715dDaniel Veillardstatic const char *xmlXPathErrorMessages[] = {
12483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Ok",
12493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Number encoding",
1250cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard    "Unfinished literal",
1251cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard    "Start of literal",
12523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Expected $ for variable reference",
12533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Undefined variable",
12543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid predicate",
12553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid expression",
12563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Missing closing curly brace",
12573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Unregistered function",
12583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid operand",
12593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid type",
12603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid number of arguments",
12613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid context size",
12623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid context position",
12633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Memory allocation error",
12643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Syntax error",
12653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Resource error",
12663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Sub resource error",
126761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Undefined namespace prefix",
126861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Encoding error",
126961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Char out of XML range"
12703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor};
12713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
12735e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPatherror:
12743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
12753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @file:  the file name
12763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @line:  the line number
12773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @no:  the error number
12783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1279f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Formats an error message.
12803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
12813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
128221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel VeillardxmlXPatherror(xmlXPathParserContextPtr ctxt, ATTRIBUTE_UNUSED const char *file,
128321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard              ATTRIBUTE_UNUSED int line, int no) {
12843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
12853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur;
12863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *base;
12873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12885fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard/*    xmlGenericError(xmlGenericErrorContext,
12893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Error %s:%d: %s\n", file, line,
12903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            xmlXPathErrorMessages[no]);
12915fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard*/
12925fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
12935fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    "Error %s\n", xmlXPathErrorMessages[no]);
12943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = ctxt->cur;
12963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    base = ctxt->base;
1297d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((cur == NULL) || (base == NULL))
1298d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	return;
1299d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
13003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
13013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur--;
13023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
13053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur--;
13063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur == '\n') || (*cur == '\r')) cur++;
13073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    base = cur;
13083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
13103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext, "%c", (unsigned char) *cur++);
13113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	n++;
13123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "\n");
13143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = ctxt->cur;
13153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur == '\n') || (*cur == '\r'))
13163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur--;
13173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((cur != base) && (n++ < 80)) {
13193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext, " ");
13203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        base++;
13213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,"^\n");
13233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
13273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
13283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle NodeSets			*
13293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
13303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
13313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
13333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCmpNodes:
13343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node1:  the first node
13353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node2:  the second node
13363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Compare two nodes w.r.t document order
13383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -2 in case of error 1 if first point < second point, 0 if
13403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         that's the same node, -1 otherwise
13413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
13433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int depth1, depth2;
13453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr cur, root;
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((node1 == NULL) || (node2 == NULL))
13483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
13493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
13503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * a couple of optimizations which will avoid computations in most cases
13513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
13523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2)
13533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
1354b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard    if ((node1->type == XML_NAMESPACE_DECL) ||
1355b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard        (node2->type == XML_NAMESPACE_DECL))
1356b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard	return(1);
13573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->prev)
13583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
13593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
13603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
13613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
13633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * compute depth to root
13643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
13653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
13663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node1)
13673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
13683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2++;
13693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    root = cur;
13713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
13723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
13733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
13743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1++;
13753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
13773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Distinct document (or distinct entities :-( ) case.
13783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
13793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (root != cur) {
13803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
13813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
13833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * get the nearest common ancestor.
13843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
13853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth1 > depth2) {
13863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1--;
13873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
13883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth2 > depth1) {
13903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2--;
13913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
13923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node1->parent != node2->parent) {
13943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
13953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
13963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* should not happen but just in case ... */
13973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((node1 == NULL) || (node2 == NULL))
13983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-2);
13993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
14013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Find who's first.
14023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
14033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
14043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
14053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (cur = node1->next;cur != NULL;cur = cur->next)
14063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
14073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
14083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(-1); /* assume there is no sibling list corruption */
14093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
14103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
14123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetSort:
14133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @set:  the node set
14143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
14153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Sort the node set in document order
14163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
14173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
14183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetSort(xmlNodeSetPtr set) {
1419e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    int i, j, incr, len;
14203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr tmp;
14213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (set == NULL)
14233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
14243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use Shell's sort to sort the node-set */
14263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    len = set->nodeNr;
14273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (incr = len / 2; incr > 0; incr /= 2) {
14283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (i = incr; i < len; i++) {
14293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    j = i - incr;
14303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (j >= 0) {
1431e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese		if (xmlXPathCmpNodes(set->nodeTab[j],
1432e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese				     set->nodeTab[j + incr]) == -1) {
14333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    tmp = set->nodeTab[j];
14343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j] = set->nodeTab[j + incr];
14353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j + incr] = tmp;
14363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    j -= incr;
14373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else
14383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
14393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
14403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
14413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
14433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NODESET_DEFAULT	10
14453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1446044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetDupNs:
1447044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the parent node of the namespace XPath node
1448044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the libxml namespace declaration node.
1449044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1450044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
1451044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1452044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic.
1453044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1454044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Returns the newly created object.
1455044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1456044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillardstatic xmlNodePtr
1457044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
1458044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    xmlNsPtr cur;
1459044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1460044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1461044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1462044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1463044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return((xmlNodePtr) ns);
1464044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1465044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1466044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * Allocate a new Namespace and fill the fields.
1467044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1468044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1469044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur == NULL) {
1470044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
1471044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		"xmlXPathNodeSetDupNs : malloc failed\n");
1472044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1473044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1474044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    memset(cur, 0, sizeof(xmlNs));
1475044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->type = XML_NAMESPACE_DECL;
1476044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->href != NULL)
1477044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->href = xmlStrdup(ns->href);
1478044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->prefix != NULL)
1479044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->prefix = xmlStrdup(ns->prefix);
1480044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->next = (xmlNsPtr) node;
1481044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return((xmlNodePtr) cur);
1482044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1483044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1484044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
1485044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetFreeNs:
1486044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the XPath namespace node found in a nodeset.
1487044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1488044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
1489044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1490044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic. Check if such a node need to be freed
1491044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1492f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Saninvoid
1493044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetFreeNs(xmlNsPtr ns) {
1494044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1495044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1496044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1497044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
1498044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->href != NULL)
1499044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->href);
1500044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->prefix != NULL)
1501044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->prefix);
1502044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlFree(ns);
1503044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1504044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1505044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1506044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
15073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetCreate:
15083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an initial xmlNodePtr, or NULL
15093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlNodeSetPtr of type double and of value @val
15113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
15133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
15143473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
15153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetCreate(xmlNodePtr val) {
15163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ret;
15173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
15193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
15203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
1521cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathNodeSetCreate: out of memory\n");
15223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
15233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
15243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
15253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL) {
15263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
15273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
15283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret->nodeTab == NULL) {
15293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
1530cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		    "xmlXPathNodeSetCreate: out of memory\n");
15313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
15323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
15333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(ret->nodeTab, 0 ,
15343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
15353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeMax = XML_NODESET_DEFAULT;
1536044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val->type == XML_NAMESPACE_DECL) {
1537044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val;
1538044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1539044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] =
1540044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1541044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
1542044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] = val;
15433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
15443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
15453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
15463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1548f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeSetContains:
1549f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @cur:  the node-set
1550f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the node
1551f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1552f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * checks whether @cur contains @val
1553f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1554f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @cur contains @val, false (0) otherwise
1555f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1556f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
1557f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
1558f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i;
1559f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1560044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1561044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1562044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1563044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
1564044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1565044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val;
1566044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) cur->nodeTab[i];
1567044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (ns1 == ns2)
1568044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1569044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
1570044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	            (xmlStrEqual(ns1->prefix, ns2->prefix)))
1571044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1572044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
1573044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1574044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else {
1575044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1576044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i] == val)
1577044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		return(1);
1578044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1579f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1580f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
1581f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1582f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1583f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1584044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetAddNs:
1585044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @cur:  the initial node set
1586044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the hosting node
1587044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  a the namespace node
1588044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1589044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * add a new namespace node to an existing NodeSet
1590044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
159179376ba94845db7096c3917f4f40baeb450eb0e9Aleksey Saninvoid
1592044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
1593044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    int i;
1594044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1595044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (node == NULL) || (ns->type != XML_NAMESPACE_DECL) ||
1596044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(node->type != XML_ELEMENT_NODE))
1597044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1598044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1599044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
1600044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1601044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * check against doublons
1602044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1603044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    for (i = 0;i < cur->nodeNr;i++) {
1604044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        if ((cur->nodeTab[i] != NULL) &&
1605044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
1606c62a147963b5839fc815267706eaec381f90ca16Daniel Veillard	    (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
1607044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
1608044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1609044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1610044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1611044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1612044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * grow the nodeTab if needed
1613044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1614044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur->nodeMax == 0) {
1615044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
1616044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					     sizeof(xmlNodePtr));
1617044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (cur->nodeTab == NULL) {
1618044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1619044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    "xmlXPathNodeSetAdd: out of memory\n");
1620044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1621044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1622044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	memset(cur->nodeTab, 0 ,
1623044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
1624044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax = XML_NODESET_DEFAULT;
1625044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else if (cur->nodeNr == cur->nodeMax) {
1626044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlNodePtr *temp;
1627044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1628044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax *= 2;
1629044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
1630044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				      sizeof(xmlNodePtr));
1631044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (temp == NULL) {
1632044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1633044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    "xmlXPathNodeSetAdd: out of memory\n");
1634044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1635044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1636044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab = temp;
1637044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1638044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
1639044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1640044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1641044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
16423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAdd:
16433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
16443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
16453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1646cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet
16473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
16483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
16493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
16503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
16513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
16533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1654044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
16553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * check against doublons
16573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
16593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) return;
16603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
16633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
16653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
16663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
16673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
16683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
16693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAdd: out of memory\n");
16703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
16713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
16723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
16733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
16743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
16753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
16763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
16773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
16793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
16803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
16813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
16823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
16833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAdd: out of memory\n");
16843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
16853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
16863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
16873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1688044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1689044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
1690044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1691044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
1692044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1693044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
1694044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
16953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
16963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
16983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAddUnique:
16993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
17003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
17013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1702cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet, optimized version
17033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * when we are sure the node is not already in the set.
17043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
17053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
17063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
17073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
17083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1709044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
17103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
17113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
17123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
17133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
17143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
17153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
17163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
17173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
17183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAddUnique: out of memory\n");
17193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
17203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
17213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
17223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
17233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
17243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
17253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
17263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
17283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
17293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
17303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
17313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
17323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAddUnique: out of memory\n");
17333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
17343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
17353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
17363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1737044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1738044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
1739044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1740044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
1741044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1742044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
1743044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
17443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
17453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
17473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetMerge:
17483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val1:  the first NodeSet or NULL
17493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val2:  the second NodeSet
17503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
17513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Merges two nodesets, all nodes from @val2 are added to @val1
17523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if @val1 is NULL, a new set is created and copied from @val2
17533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1754cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns @val1 once extended or NULL in case of error.
17553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
17563473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
17573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
1758d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    int i, j, initNr, skip;
17593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val2 == NULL) return(val1);
17613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val1 == NULL) {
17623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val1 = xmlXPathNodeSetCreate(NULL);
17633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
17643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1765044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
17663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initNr = val1->nodeNr;
17673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < val2->nodeNr;i++) {
17693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
17703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * check against doublons
17713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
1772d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	skip = 0;
1773d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	for (j = 0; j < initNr; j++) {
1774d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (val1->nodeTab[j] == val2->nodeTab[i]) {
1775d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		skip = 1;
1776d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		break;
1777044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    } else if ((val1->nodeTab[j]->type == XML_NAMESPACE_DECL) &&
1778044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		       (val2->nodeTab[i]->type == XML_NAMESPACE_DECL)) {
1779044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
1780044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val1->nodeTab[j];
1781044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) val2->nodeTab[i];
1782044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next == ns2->next) &&
1783044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (xmlStrEqual(ns1->prefix, ns2->prefix))) {
1784044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    skip = 1;
1785044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    break;
1786044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
1787d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    }
1788d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	}
1789d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	if (skip)
1790d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    continue;
17913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
17933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * grow the nodeTab if needed
17943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
17953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (val1->nodeMax == 0) {
17963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
17973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor						    sizeof(xmlNodePtr));
17983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (val1->nodeTab == NULL) {
17993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
18003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"xmlXPathNodeSetMerge: out of memory\n");
18013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
18023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
18033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memset(val1->nodeTab, 0 ,
18043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
18053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax = XML_NODESET_DEFAULT;
18063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (val1->nodeNr == val1->nodeMax) {
18073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNodePtr *temp;
18083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax *= 2;
18103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
18113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
18123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (temp == NULL) {
18133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
18143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"xmlXPathNodeSetMerge: out of memory\n");
18153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
18163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
18173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = temp;
18183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1819044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1820044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
1821044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1822044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] =
1823044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1824044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
1825044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
18263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
18273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(val1);
18293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
18303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
183275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * xmlXPathNodeSetMergeUnique:
183375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val1:  the first NodeSet or NULL
183475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val2:  the second NodeSet
183575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
183675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Merges two nodesets, all nodes from @val2 are added to @val1
183775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * if @val1 is NULL, a new set is created and copied from @val2
183875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
183975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Returns @val1 once extended or NULL in case of error.
184075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard */
184175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillardstatic xmlNodeSetPtr
184275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel VeillardxmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
184375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    int i, initNr;
184475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
184575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val2 == NULL) return(val1);
184675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val1 == NULL) {
184775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	val1 = xmlXPathNodeSetCreate(NULL);
184875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
184975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
185075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
185175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    initNr = val1->nodeNr;
185275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
185375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    for (i = 0;i < val2->nodeNr;i++) {
185475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	/*
185575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 * grow the nodeTab if needed
185675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 */
185775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val1->nodeMax == 0) {
185875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
185975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard						    sizeof(xmlNodePtr));
186075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (val1->nodeTab == NULL) {
186175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlGenericError(xmlGenericErrorContext,
186275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard				"xmlXPathNodeSetMerge: out of memory\n");
186375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
186475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
186575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    memset(val1->nodeTab, 0 ,
186675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
186775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax = XML_NODESET_DEFAULT;
186875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else if (val1->nodeNr == val1->nodeMax) {
186975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNodePtr *temp;
187075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
187175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax *= 2;
187275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
187375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard					     sizeof(xmlNodePtr));
187475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (temp == NULL) {
187575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlGenericError(xmlGenericErrorContext,
187675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard				"xmlXPathNodeSetMerge: out of memory\n");
187775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
187875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
187975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = temp;
188075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	}
188175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
188275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
188375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
188475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] =
188575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
188675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else
188775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
188875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
188975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
189075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    return(val1);
189175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard}
189275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
189375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard/**
18943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetDel:
18953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
18963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an xmlNodePtr
18973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
18983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an xmlNodePtr from an existing NodeSet
18993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
19023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
19033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
19053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
19063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
19083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * check against doublons
19093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
19113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) break;
19123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (i >= cur->nodeNr) {
19143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG
19153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
19163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
19173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		val->name);
19183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
19193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return;
19203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1921044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[i] != NULL) &&
1922044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
1923044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
19243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
19253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;i < cur->nodeNr;i++)
19263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[i] = cur->nodeTab[i + 1];
19273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
19283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
19313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetRemove:
19323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
19333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the index to remove
19343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
19353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an entry from an existing NodeSet list.
19363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
19393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
19403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val >= cur->nodeNr) return;
1941044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[val] != NULL) &&
1942044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
1943044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
19443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
19453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;val < cur->nodeNr;val++)
19463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[val] = cur->nodeTab[val + 1];
19473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
19483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
19513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSet:
19523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
19533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
19543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound (not the actual nodes !).
19553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
19583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
19593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
1960044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	int i;
1961044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1962044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	/* @@ with_ns to check wether namespace nodes should be looked at @@ */
1963044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++)
1964044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if ((obj->nodeTab[i] != NULL) &&
1965044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
1966044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
19673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
19683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
19703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
19733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeValueTree:
19743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
19753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
19763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound and the actual tree, this is different
19773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * from xmlXPathFreeNodeSet()
19783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
197956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
19803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeValueTree(xmlNodeSetPtr obj) {
19813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
19823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
19843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
1986044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++) {
1987044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (obj->nodeTab[i] != NULL) {
1988044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1989044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
1990044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		} else {
1991044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlFreeNodeList(obj->nodeTab[i]);
1992044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
1993044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
1994044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
19953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
19963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
19983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(DEBUG) || defined(DEBUG_STEP)
20013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlGenericErrorContextNodeSet:
20033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @output:  a FILE * for the output
20043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
20053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Quick display of a NodeSet
20073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
20093473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
20103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
20113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (output == NULL) output = xmlGenericErrorContext;
20133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL)  {
20143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet == NULL !\n");
20153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
20163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeNr == 0) {
20183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet is empty\n");
20193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
20203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab == NULL) {
20223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " nodeTab == NULL !\n");
20233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
20243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0; i < obj->nodeNr; i++) {
20263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (obj->nodeTab[i] == NULL) {
20273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " NULL !\n");
20283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
20293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
20303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
20313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
20323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " /");
20333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (obj->nodeTab[i]->name == NULL)
20343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " noname!");
20353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else fprintf(output, " %s", obj->nodeTab[i]->name);
20363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, "\n");
20383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
20403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSet:
20433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
20443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
20463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the single Node @val
20473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
20493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
20513473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewNodeSet(xmlNodePtr val) {
20523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
20533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
20553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
20563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
20573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewNodeSet: out of memory\n");
20583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
20593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
20613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
206277851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard    ret->boolval = 0;
20633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
2064044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
20653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
20663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewValueTree:
20703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
20713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
20733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the tree root @val
20743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
20763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20773473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
20783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewValueTree(xmlNodePtr val) {
20793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
20803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
20823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
20833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
20843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewNodeSet: out of memory\n");
20853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
20863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
20883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_XSLT_TREE;
20890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->boolval = 1;
20900ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->user = (void *) val;
20913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
20923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
20933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSetList:
20973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an existing NodeSet
20983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
21003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the Nodeset @val
21013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
21033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
2105044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNewNodeSetList(xmlNodeSetPtr val)
2106044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard{
21073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
21083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
21093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
2111044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = NULL;
21123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (val->nodeTab == NULL)
2113044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(NULL);
2114044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    else {
2115044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(val->nodeTab[0]);
2116044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        for (i = 1; i < val->nodeNr; ++i)
2117044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard            xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
2118044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
21193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2120044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return (ret);
21213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
21243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathWrapNodeSet:
21253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
21263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Wrap the Nodeset @val in a new xmlXPathObjectPtr
21283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
21303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21313473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
21323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathWrapNodeSet(xmlNodeSetPtr val) {
21333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
21343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
21363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
21373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
21383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathWrapNodeSet: out of memory\n");
21393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
21403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
21423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
21433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = val;
21443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
21453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
21483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSetList:
21493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  an existing NodeSetList object
21503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
21523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the list contrary to xmlXPathFreeObject().
21533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
21553473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
21563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
21573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
21583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2160f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2161f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDifference:
2162f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2163f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2164f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2165f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets difference() function:
2166f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:difference (node-set, node-set)
2167f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2168f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the difference between the two node sets, or nodes1 if
2169f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         nodes2 is empty
2170f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2171f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2172f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2173f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2174f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2175f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2176f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2177f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2178f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2179f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2180f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2181f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2182f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2183f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2184f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2185f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2186f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2187f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2188f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (!xmlXPathNodeSetContains(nodes2, cur))
2189f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2190f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2191f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2192f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2193f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2194f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2195f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathIntersection:
2196f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2197f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2198f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2199f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets intersection() function:
2200f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:intersection (node-set, node-set)
2201f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2202f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a node set comprising the nodes that are within both the
2203f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         node sets passed as arguments
2204f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2205f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2206f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2207f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
2208f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2209f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2210f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2211f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2212f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2213f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2214f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2215f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2216f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2217f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2218f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2219f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2220f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2221f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2222f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2223f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2224f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2225f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2226f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2227f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinctSorted:
2228f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set, sorted by document order
2229f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2230f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2231f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2232f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2233f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2234f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2235f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2236f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2237f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
2238f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2239f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashTablePtr hash;
2240f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2241f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * strval;
2242f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2243f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2244f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2245f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2246f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2247f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2248f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2249f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    hash = xmlHashCreate (l);
2250f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2251f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2252f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	strval = xmlXPathCastNodeToString(cur);
2253f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlHashLookup(hash, strval) == NULL) {
2254f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlHashAddEntry(hash, strval, strval);
2255f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2256f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	} else {
2257f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlFree(strval);
2258f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	}
2259f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2260f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
2261f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2262f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2263f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2264f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2265f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinct:
2266f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2267f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2268f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2269f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2270f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsDistinctSorted
2271f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called with the sorted node-set
2272f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2273f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2274f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2275f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2276f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2277f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinct (xmlNodeSetPtr nodes) {
2278f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2279f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2280f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2281f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2282f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathDistinctSorted(nodes));
2283f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2284f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2285f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2286f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathHasSameNodes:
2287f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2288f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2289f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2290f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets has-same-nodes function:
2291f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    boolean set:has-same-node(node-set, node-set)
2292f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2293f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
2294f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         otherwise
2295f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2296f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
2297f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2298f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2299f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2300f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2301f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1) ||
2302f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetIsEmpty(nodes2))
2303f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
2304f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2305f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes1);
2306f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2307f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2308f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2309f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    return(1);
2310f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2311f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
2312f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2313f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2314f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2315f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeadingSorted:
2316f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2317f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2318f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2319f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2320f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2321f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2322f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2323f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2324f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2325f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2326f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2327f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2328f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2329f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2330f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2331f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2332f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2333f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2334f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2335f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2336f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2337f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2338f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2339f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2340f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2341f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2342f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2343f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2344f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2345f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2346f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2347f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2348f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2349f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2350f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2351f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeading:
2352f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2353f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2354f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2355f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2356f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2357f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
2358f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2359f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2360f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2361f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2362f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2363f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2364f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2365f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
2366f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2367f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes, node));
2368f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2369f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2370f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2371f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeadingSorted:
2372f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2373f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2374f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2375f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2376f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2377f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2378f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2379f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2380f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2381f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2382f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2383f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2384f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2385f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2386f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2387f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2388f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2389f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2390f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2391f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeading:
2392f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2393f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2394f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2395f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2396f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2397f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2398f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #exslSetsLeadingSorted is called.
2399f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2400f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2401f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2402f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2403f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2404f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2405f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2406f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2407f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2408f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2409f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2410f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2411f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2412f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2413f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2414f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2415f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2416f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2417f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailingSorted:
2418f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2419f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2420f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2421f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2422f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2423f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2424f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2425f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2426f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2427f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2428f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2429f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2430f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2431f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2432f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2433f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2434f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2435f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2436f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2437f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2438f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2439f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2440f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2441f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2442f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2443f186c8259ae985cd56b3e14c1def484ab127fd14Thomas Broyer    for (i = l; i > 0; i--) {
2444f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2445f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2446f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2447f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2448f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2449f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2450f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2451f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2452f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2453f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailing:
2454f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2455f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2456f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2457f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2458f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2459f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
2460f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2461f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2462f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2463f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2464f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2465f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2466f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2467f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
2468f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2469f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes, node));
2470f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2471f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2472f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2473f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailingSorted:
2474f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2475f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2476f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2477f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2478f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2479f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2480f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2481f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2482f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2483f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2484f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2485f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2486f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2487f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2488f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2489f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2490f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2491f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2492f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2493f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailing:
2494f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2495f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2496f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2497f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2498f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2499f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2500f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #xmlXPathTrailingSorted is called.
2501f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2502f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2503f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2504f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2505f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2506f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2507f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2508f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2509f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2510f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2511f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2512f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2513f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2514f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2515f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2516f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2517f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
25183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
25193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
25203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle extra functions			*
25213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
25223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
25233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFunc:
25263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
25273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
25283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
25293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
25313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
25333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
25353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
25363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		     xmlXPathFunction f) {
25373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
25383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFuncNS:
25423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
25433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
25443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
25453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
25463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
25483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
25503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
25523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
25533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		       const xmlChar *ns_uri, xmlXPathFunction f) {
25543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
25553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
25563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
25573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
25583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
25603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->funcHash = xmlHashCreate(0);
25613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
25623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
25633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f));
25643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2567ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * xmlXPathRegisterFuncLookup:
2568ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @ctxt:  the XPath context
2569ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @f:  the lookup function
2570cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @funcCtxt:  the lookup data
2571ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer *
2572cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Registers an external mechanism to do function lookup.
2573ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer */
2574ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyervoid
2575ba4ad3263bf7f5625329f115367e0c7018521a16Thomas BroyerxmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
2576ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    xmlXPathFuncLookupFunc f,
2577ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    void *funcCtxt) {
2578ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2579ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return;
2580ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupFunc = (void *) f;
2581ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupData = funcCtxt;
2582ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer}
2583ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2584ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer/**
25853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookup:
25863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
25873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
25883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
25903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
25913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
25933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
25953473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
2596ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2597ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return (NULL);
2598ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2599ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
2600ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
260199e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2602ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
260399e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	f = (xmlXPathFuncLookupFunc) ctxt->funcLookupFunc;
2604963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, NULL);
2605ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2606ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2607ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
26083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
26093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookupNS:
26133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
26153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
26163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
26183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
26193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
26213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
26233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
26243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
26253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
26263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
26273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
26283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
26293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2630ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
2631ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
263299e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2633ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
263499e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	f = (xmlXPathFuncLookupFunc) ctxt->funcLookupFunc;
2635963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, ns_uri);
2636ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2637ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2638ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
2639ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2640ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcHash == NULL)
2641ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return(NULL);
2642ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
26433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri));
26443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredFuncsCleanup:
26483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered functions
26513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
26533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
26543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
26553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
26563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlHashFree(ctxt->funcHash, NULL);
26583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->funcHash = NULL;
26593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
26623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
26633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Variable			*
26643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
26653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
26663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariable:
26693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
26713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
26723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
26743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
26753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
26773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
26793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
26803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 xmlXPathObjectPtr value) {
26813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
26823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableNS:
26863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
26883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
26893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
26903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
26923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
26933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
26953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
26973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
26983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri,
26993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   xmlXPathObjectPtr value) {
27003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
27023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
27033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
27043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
27063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->varHash = xmlHashCreate(0);
27073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
27083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
27093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
27103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (void *) value,
27113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (xmlHashDeallocator)xmlXPathFreeObject));
27123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableLookup:
27163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the lookup function
27183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @data:  the lookup data
27193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * register an external mechanism to do variable lookup
27213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
27233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
27243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 xmlXPathVariableLookupFunc f, void *data) {
27253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
27273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupFunc = (void *) f;
27283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupData = data;
27293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookup:
27333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
27353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
27373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * variable value.
27383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
273973c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns a copy of the value or NULL if not found
27403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27413473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
27423473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
27433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
27473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
27483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
27503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, NULL);
2751556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	return(ret);
27523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
27533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathVariableLookupNS(ctxt, name, NULL));
27543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookupNS:
27583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
27603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
27613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
276373c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * variable value.
27643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
276573c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns the a copy of the value or NULL if not found
27663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27673473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
27683473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
27693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
27703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
27743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
27753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
27773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, ns_uri);
27783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret != NULL) return(ret);
27793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
27803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
27823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
27843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27868c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard    return(xmlXPathObjectCopy((xmlXPathObjectPtr)
27878c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard		xmlHashLookup2(ctxt->varHash, name, ns_uri)));
27883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredVariablesCleanup:
27923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
27953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
27973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
27983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
28003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
280176d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard    xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
28023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varHash = NULL;
28033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterNs:
28073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix
28093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the namespace name
28103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new namespace. If @ns_uri is NULL it unregisters
28123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace
28133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
28153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
28173473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
28183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri) {
28193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
28223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
28253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->nsHash = xmlHashCreate(10);
28263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
28273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) ns_uri,
28293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			      (xmlHashDeallocator)xmlFree));
28303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNsLookup:
28343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix value
28363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the namespace declaration array of the context for the given
28383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace name associated to the given prefix
28393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the value or NULL if not found
28413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorconst xmlChar *
28433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
28443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
28473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef XML_XML_NAMESPACE
28503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
28513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(XML_XML_NAMESPACE);
28523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
28533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2854c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    if (ctxt->namespaces != NULL) {
2855c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	int i;
2856c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard
2857c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	for (i = 0;i < ctxt->nsNr;i++) {
2858c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	    if ((ctxt->namespaces[i] != NULL) &&
2859c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		(xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
2860c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		return(ctxt->namespaces[i]->href);
2861c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	}
2862c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    }
28633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
28653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28685e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathRegisteredNsCleanup:
28693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
28723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
28743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
28753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
28773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlHashFree(ctxt->nsHash, NULL);
28793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->nsHash = NULL;
28803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
28833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
28843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Values			*
28853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
28863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
28873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* Allocations are terrible, one need to optimize all this !!! */
28893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewFloat:
28923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the double value
28933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type double and of value @val
28953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
28973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28983473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
28993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewFloat(double val) {
29003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
29013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
29033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
29043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
29053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewFloat: out of memory\n");
29063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
29083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
29093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NUMBER;
29103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->floatval = val;
29113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
29123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewBoolean:
29163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the boolean value
29173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type boolean and of value @val
29193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
29213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
29233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewBoolean(int val) {
29243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
29253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
29273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
29283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
29293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewBoolean: out of memory\n");
29303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
29323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
29333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_BOOLEAN;
29343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->boolval = (val != 0);
29353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
29363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewString:
29403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the xmlChar * value
29413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
29433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
29453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
29473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewString(const xmlChar *val) {
29483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
29493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
29513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
29523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
29533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewString: out of memory\n");
29543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
29563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
29573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
29583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL)
29593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup(val);
29603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
29613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup((const xmlChar *)"");
29623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
29633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2966ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapString:
2967ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the xmlChar * value
2968ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
2969ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps the @val string into an XPath object.
2970ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
2971ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
2972ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
2973ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
2974ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapString (xmlChar *val) {
2975ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
2976ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
2977ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
2978ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ret == NULL) {
2979ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        xmlGenericError(xmlGenericErrorContext,
2980ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		"xmlXPathWrapString: out of memory\n");
2981ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(NULL);
2982ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
2983ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
2984ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->type = XPATH_STRING;
2985ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->stringval = val;
2986ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
2987ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
2988ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
2989ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
29903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewCString:
29913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the char * value
29923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
29943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
29963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
29983473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewCString(const char *val) {
29993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
30003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
30023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
30033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
30043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewCString: out of memory\n");
30053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
30083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
30093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->stringval = xmlStrdup(BAD_CAST val);
30103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
30113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3014ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapCString:
3015ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the char * value
3016ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3017ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps a string into an XPath object.
3018ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3019ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3020ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3021ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3022ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapCString (char * val) {
3023ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString((xmlChar *)(val)));
3024ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3025ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3026ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3027f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathWrapExternal:
3028f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the user data
3029f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3030f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Wraps the @val data into an XPath object.
3031f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3032f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the newly created object.
3033f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3034f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathObjectPtr
3035f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathWrapExternal (void *val) {
3036f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr ret;
3037f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3038f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3039f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ret == NULL) {
3040f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer        xmlGenericError(xmlGenericErrorContext,
3041cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathWrapExternal: out of memory\n");
3042f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
3043f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
3044f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3045f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->type = XPATH_USERS;
3046f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->user = val;
3047f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
3048f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3049f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3050f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
30513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathObjectCopy:
30523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the original object
30533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * allocate a new copy of a given object
30553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
30573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectCopy(xmlXPathObjectPtr val) {
30603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
30613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
30633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
30663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
30673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
30683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathObjectCopy: out of memory\n");
30693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
30723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (val->type) {
30733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_BOOLEAN:
30743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NUMBER:
30753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
30763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
30773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
30783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_STRING:
30793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->stringval = xmlStrdup(val->stringval);
30803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
30813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
30823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((val->nodesetval != NULL) &&
30830ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		(val->nodesetval->nodeTab != NULL)) {
30840ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		ret->boolval = 1;
30856ab38386cc16642626d944b357580657e751d8baDaniel Veillard		ret->user = xmlDocCopyNode(val->nodesetval->nodeTab[0],
30866ab38386cc16642626d944b357580657e751d8baDaniel Veillard				       val->nodesetval->nodeTab[0]->doc, 1);
30873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret->nodesetval = xmlXPathNodeSetCreate(
30880ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard					  (xmlNodePtr) ret->user);
30890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else
30903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret->nodesetval = xmlXPathNodeSetCreate(NULL);
30910ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Deallocate the copied tree value */
30923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
30933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NODESET:
30943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
30950ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Do not deallocate the copied tree value */
30960ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    ret->boolval = 0;
30973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
30983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
30993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
31003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	{
31013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlLocationSetPtr loc = val->user;
31023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
31033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
31043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
31053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
310647334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_USERS:
310747334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    ret->user = val->user;
310847334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    break;
310947334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_UNDEFINED:
31103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
31113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathObjectCopy: unsupported type %d\n",
31123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    val->type);
31133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
31143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
31153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
31163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeObject:
31203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the object to free
31213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathObjectPtr object.
31233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
31253473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeObject(xmlXPathObjectPtr obj) {
31263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
31270ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
312877851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	if (obj->boolval) {
31290ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    if (obj->user != NULL) {
31300ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard                xmlXPathFreeNodeSet(obj->nodesetval);
313138bf6f042507c6051bfa2db5cc9b6666cfc35c2aDaniel Veillard		xmlFreeNodeList((xmlNodePtr) obj->user);
31320ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else if (obj->nodesetval != NULL)
313377851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeValueTree(obj->nodesetval);
313477851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	} else {
313577851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	    if (obj->nodesetval != NULL)
313677851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeNodeSet(obj->nodesetval);
313777851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	}
31383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
31393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_LOCATIONSET) {
31403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->user != NULL)
31413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPtrFreeLocationSet(obj->user);
31423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
31433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_STRING) {
31443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->stringval != NULL)
31453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(obj->stringval);
31463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
31473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
31493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3151ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3152ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/************************************************************************
3153ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3154ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *			Type Casting Routines				*
3155ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3156ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard ************************************************************************/
3157ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3158ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3159ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToString:
3160ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3161ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3162ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its string value.
3163ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3164ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3165ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3166ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3167ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToString (int val) {
3168ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3169ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3170ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "true");
3171ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    else
3172ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "false");
3173ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3174ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3175ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3176ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3177ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToString:
3178ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3179ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3180ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its string value.
3181ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3182ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3183ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3184ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3185ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToString (double val) {
3186ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3187cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(val)) {
3188ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case 1:
31895fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	ret = xmlStrdup((const xmlChar *) "Infinity");
3190ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3191ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case -1:
3192ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "-Infinity");
3193ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3194ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    default:
3195cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val)) {
3196ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "NaN");
3197d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (val == 0 && xmlXPathGetSign(val) != 0) {
3198d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "0");
3199ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	} else {
3200ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    /* could be improved */
3201ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    char buf[100];
3202ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlXPathFormatNumber(val, buf, 100);
3203ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) buf);
3204ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3205ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3206ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3207ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3208ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3209ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3210ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToString:
3211ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3212ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3213ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its string value.
3214ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3215ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3216ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3217ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3218ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToString (xmlNodePtr node) {
321923b1f37bf53e07d2a36a86c9efa173af533c0266Daniel Veillard    if ((node != NULL) && (node->type == XML_DOCUMENT_NODE))
322023b1f37bf53e07d2a36a86c9efa173af533c0266Daniel Veillard	node = xmlDocGetRootElement((xmlDocPtr) node);
3221ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlNodeGetContent(node));
3222ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3223ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3224ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3225ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToString:
3226ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3227ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3228ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its string value.
3229ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3230ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3231ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3232ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3233ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
3234ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
3235ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3236ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3237ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathNodeSetSort(ns);
3238ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathCastNodeToString(ns->nodeTab[0]));
3239ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3240ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3241ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3242ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToString:
3243ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3244ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3245ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3246ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3247ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the string value of the object, NULL in case of error.
3248cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *         A new string is allocated only if needed (@val isn't a
3249ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         string object).
3250ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3251ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3252ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToString(xmlXPathObjectPtr val) {
3253ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret = NULL;
3254ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3255ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3256ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3257ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3258ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_UNDEFINED:
3259ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3260ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
3261ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3262ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3263ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3264ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_XSLT_TREE:
3265ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_NODESET:
3266ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNodeSetToString(val->nodesetval);
3267ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3268ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_STRING:
32694e2df54bb17645ef0d3f28b9665b2d2dde4b47a3Daniel Veillard	    return(xmlStrdup(val->stringval));
3270ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_BOOLEAN:
3271ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastBooleanToString(val->boolval);
3272ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3273ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_NUMBER: {
3274ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNumberToString(val->floatval);
3275ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3276ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3277ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_USERS:
3278ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_POINT:
3279ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_RANGE:
3280ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_LOCATIONSET:
3281ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    TODO
3282ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3283ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3284ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3285ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3286ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3287ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3288ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3289ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertString:
3290ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3291ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3292ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3293ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3294ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3295ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3296ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3297ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3298ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertString(xmlXPathObjectPtr val) {
3299ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *res = NULL;
3300ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3301ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3302ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3303ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3304ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3305ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3306ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3307ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
3308ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3309ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3310ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_XSLT_TREE:
3311ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
3312ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNodeSetToString(val->nodesetval);
3313ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3314ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3315ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3316ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3317ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastBooleanToString(val->boolval);
3318ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3319ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3320ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNumberToString(val->floatval);
3321ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3322ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3323ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3324ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3325ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3326ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3327ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3328ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3329ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3330ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (res == NULL)
3331ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3332ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString(res));
3333ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3334ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3335ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3336ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToNumber:
3337ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3338ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3339ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its number value
3340ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3341ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3342ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3343ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3344ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToNumber(int val) {
3345ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3346ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(1.0);
3347ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(0.0);
3348ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3349ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3350ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3351ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToNumber:
3352ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3353ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3354ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its number value
3355ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3356ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3357ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3358ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3359ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToNumber(const xmlChar * val) {
3360ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathStringEvalNumber(val));
3361ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3362ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3363ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3364ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToNumber:
3365ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3366ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3367ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its number value
3368ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3369ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3370ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3371ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3372ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToNumber (xmlNodePtr node) {
3373ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *strval;
3374ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3375ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3376ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (node == NULL)
3377ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3378ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    strval = xmlXPathCastNodeToString(node);
3379ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (strval == NULL)
3380ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3381ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(strval);
3382ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(strval);
3383ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3384ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3385ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3386ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3387ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3388ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToNumber:
3389ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3390ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3391ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its number value
3392ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3393ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3394ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3395ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3396ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
3397ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *str;
3398ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3399ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3400ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ns == NULL)
3401ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3402ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    str = xmlXPathCastNodeSetToString(ns);
3403ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(str);
3404ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(str);
3405ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3406ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3407ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3408ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3409ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToNumber:
3410ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3411ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3412ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its number value
3413ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3414ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3415ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3416ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3417ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToNumber(xmlXPathObjectPtr val) {
3418ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret = 0.0;
3419ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3420ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3421ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3422ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3423ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3424ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEGUB_EXPR
3425ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
3426ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3427ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3428ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3429ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_XSLT_TREE:
3430ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
3431ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
3432ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3433ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3434ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToNumber(val->stringval);
3435ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3436ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3437ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->floatval;
3438ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3439ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3440ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastBooleanToNumber(val->boolval);
3441ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3442ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3443ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3444ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3445ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3446ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3447ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3448ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3449ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3450ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3451ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3452ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3453ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3454ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertNumber:
3455ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3456ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3457ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its number() equivalent
3458ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3459ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3460ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3461ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3462ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3463ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertNumber(xmlXPathObjectPtr val) {
3464ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3465ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3466ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3467ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewFloat(0.0));
3468ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_NUMBER)
3469ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3470ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
3471ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3472ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3473ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3474ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3475ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3476ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToBoolean:
3477ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3478ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3479ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its boolean value
3480ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3481ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3482ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3483ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3484ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToBoolean (double val) {
3485cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard     if (xmlXPathIsNaN(val) || (val == 0.0))
3486ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	 return(0);
3487ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard     return(1);
3488ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3489ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3490ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3491ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToBoolean:
3492ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3493ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3494ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its boolean value
3495ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3496ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3497ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3498ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3499ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToBoolean (const xmlChar *val) {
3500ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((val == NULL) || (xmlStrlen(val) == 0))
3501ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3502ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3503ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3504ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3505ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3506ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToBoolean:
3507ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3508ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3509ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its boolean value
3510ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3511ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3512ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3513ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3514ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
3515ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0))
3516ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3517ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3518ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3519ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3520ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
35215e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathCastToBoolean:
3522ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3523ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3524ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its boolean value
3525ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3526ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3527ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3528ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3529ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToBoolean (xmlXPathObjectPtr val) {
3530ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    int ret = 0;
3531ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3532ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3533ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3534ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3535ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3536ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3537ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
3538ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3539ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3540ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3541ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_XSLT_TREE:
3542ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
3543ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
3544ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3545ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3546ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToBoolean(val->stringval);
3547ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3548ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3549ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNumberToBoolean(val->floatval);
3550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->boolval;
3553ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3554ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3555ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3556ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3558ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3559ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3560ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3561ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3562ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3563ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3564ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3565ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3566ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3567ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertBoolean:
3568ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3569ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3570ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its boolean() equivalent
3571ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3572ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3573ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3574ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3575ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3576ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertBoolean(xmlXPathObjectPtr val) {
3577ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3578ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3579ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3580ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewBoolean(0));
3581ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_BOOLEAN)
3582ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3583ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
3584ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3585ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3586ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3587ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
35883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
35893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
35903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath contexts			*
35913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
35923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
35933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
35953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewContext:
35963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @doc:  the XML document
35973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathContext
35993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3600af43f63aaabf0dc4b4a070773875d0927da3d8a2Daniel Veillard * Returns the xmlXPathContext just allocated. The caller will need to free it.
36013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
36023473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContextPtr
36033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewContext(xmlDocPtr doc) {
36043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathContextPtr ret;
36053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
36073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
36083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
36093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewContext: out of memory\n");
36103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
36113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
36123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
36133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->doc = doc;
36143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->node = NULL;
36153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->varHash = NULL;
36173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_types = 0;
36193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_types = 0;
36203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->types = NULL;
36213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->funcHash = xmlHashCreate(0);
36233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_axis = 0;
36253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_axis = 0;
36263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->axis = NULL;
36273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nsHash = NULL;
36293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->user = NULL;
36303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->contextSize = -1;
36323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->proximityPosition = -1;
36333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterAllFunctions(ret);
36353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
36373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
36383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
36403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeContext:
36413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
36423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
36433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathContext
36443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
36453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
36463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeContext(xmlXPathContextPtr ctxt) {
36473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredNsCleanup(ctxt);
36483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredFuncsCleanup(ctxt);
36493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredVariablesCleanup(ctxt);
36503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
36513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
36523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
36543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
36553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath parser contexts		*
36563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
36573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
36583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CTXT(ctxt)						\
36603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
36613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
36623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: ctxt == NULL\n",			\
36633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
36643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
36653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CONTEXT(ctxt)						\
36683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
36693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
36703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: no context\n",			\
36713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
36723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
36733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (ctxt->doc == NULL) { 					\
36743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
36753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: no document\n",			\
36763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
36773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
36783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (ctxt->doc->children == NULL) { 				\
36793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
36803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "%s:%d Internal error: document without root\n",	\
36813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
36823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
36833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
36863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewParserContext:
36873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
36883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
36893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
36903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathParserContext
36913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
36923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathParserContext just allocated.
36933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
36943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParserContextPtr
36953473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
36963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ret;
36973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
36993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
37003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
37013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewParserContext: out of memory\n");
37023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
37033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
37043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
37053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->cur = ret->base = str;
37063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->context = ctxt;
37073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = xmlXPathNewCompExpr();
37099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->comp == NULL) {
37109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret->valueTab);
37119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
37129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
37139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
37149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
37159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(ret);
37169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
37179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
37189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
37199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompParserContext:
37209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the XPath compiled expression
37219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath context
37229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
37239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new xmlXPathParserContext when processing a compiled expression
37249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
37259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the xmlXPathParserContext just allocated.
37269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
372756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathParserContextPtr
37289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
37299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ret;
37309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
37319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
37329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret == NULL) {
37339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
3734cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompParserContext: out of memory\n");
37359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
37369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
37379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
37389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
37393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Allocate the value stack */
37403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueTab = (xmlXPathObjectPtr *)
37413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                     xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
37429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->valueTab == NULL) {
37439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
37449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
3745cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompParserContext: out of memory\n");
37469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
37479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
37483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueNr = 0;
37493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueMax = 10;
37503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->value = NULL;
37519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3752fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ret->context = ctxt;
37539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = comp;
37549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
37553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
37563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
37593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeParserContext:
37603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
37613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
37623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathParserContext
37633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
37643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
37653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
37663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->valueTab != NULL) {
37673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->valueTab);
37683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
37699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp)
37709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeCompExpr(ctxt->comp);
37713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
37723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
37753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The implicit core function library			*
37773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
37793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNodeStringHash:
3782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @node:  a node pointer
3783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
3785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
3786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
3788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
3789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
3790f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeValHash(xmlNodePtr node) {
3791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int len = 2;
3792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar * string = NULL;
3793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp = NULL;
3794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int ret = 0;
3795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (node == NULL)
3797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
3798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (node->type) {
3801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_COMMENT_NODE:
3802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_PI_NODE:
3803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_CDATA_SECTION_NODE:
3804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_TEXT_NODE:
3805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = node->content;
3806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
3807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
3811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
3812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_NAMESPACE_DECL:
3813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = ((xmlNsPtr)node)->href;
3814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
3815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
3819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
3820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ATTRIBUTE_NODE:
3821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = ((xmlAttrPtr) node)->children;
3822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ELEMENT_NODE:
3824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = node->children;
3825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3826f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	default:
3827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(0);
3828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
3829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (tmp != NULL) {
3830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	switch (tmp->type) {
3831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_COMMENT_NODE:
3832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_PI_NODE:
3833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_CDATA_SECTION_NODE:
3834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_TEXT_NODE:
3835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = tmp->content;
3836f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_NAMESPACE_DECL:
3838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = ((xmlNsPtr)tmp)->href;
3839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3840f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    default:
3841f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3842f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3843f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((string != NULL) && (string[0] != 0)) {
3844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (len == 1) {
3847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(ret + (((unsigned int) string[0]) << 8));
3848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[1] == 0) {
3850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		len = 1;
3851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		ret = (unsigned int) string[0];
3852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    } else {
3853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(((unsigned int) string[0]) +
3854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		       (((unsigned int) string[1]) << 8));
3855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	/*
3858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 * Skip to next node
3859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 */
3860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
3861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->children->type != XML_ENTITY_DECL) {
3862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->children;
3863f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		continue;
3864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp == node)
3867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp->next != NULL) {
3870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->next;
3871f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    continue;
3872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	do {
3875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->parent;
3876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == NULL)
3877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == node) {
3879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = NULL;
3880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->next != NULL) {
3883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->next;
3884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	} while (tmp != NULL);
3887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
3888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(ret);
3889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
3890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
3892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathStringHash:
3893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @string:  a string
3894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
3896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
3897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
3899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
3900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
3901f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathStringHash(const xmlChar * string) {
3902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string == NULL)
3903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return((unsigned int) 0);
3904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string[0] == 0)
3905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
3906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(((unsigned int) string[0]) +
3907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	   (((unsigned int) string[1]) << 8));
3908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
3909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
39113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetFloat:
39123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
39133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
39143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
39153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
39163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the value
39173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a number
39193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
39203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
39213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
39223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
39233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
39253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in the
39263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set such that the result of performing the comparison on the number
39273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be compared and on the result of converting the string-value of that
39283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node to a number using the number function is true.
39293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
39313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
393256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
39333473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
39343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
39353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
39363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
39373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
39383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((f == NULL) || (arg == NULL) ||
39403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
39413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
39423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(f);
39433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
39443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
39453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
3946911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
3947911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
3948ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
3949911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
3950911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
3951911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
3952911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
3953911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlXPathNumberFunction(ctxt, 1);
3954911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(f));
3955911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
3956911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
3957911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
3958911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
3959911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
39603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
39613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
39623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(f);
39633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
39643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
39653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
39673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetString:
39683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
39693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
39703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
39713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
39723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @s:  the value
39733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a string
39753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
39763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
39773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
39783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
39793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
39813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
39823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
39833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
39843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
39863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
398756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
39883473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
39893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
39903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
39913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
39923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
39933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((s == NULL) || (arg == NULL) ||
39953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
39963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
39973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(s);
39983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
39993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
40003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4001911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4002911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4003ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4004911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4005911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4006911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4007911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4008911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(s));
4009911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4010911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4011911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4012911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4013911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
40143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
40153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
40163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(s);
40173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
40183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
40193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
40213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSets:
4022ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @inf:  less than (1) or greater than (0)
40233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
4024cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @arg1:  the first node set object
40253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  the second node set object
40263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on nodesets:
40283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
40303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set
40313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a node in the second node-set such that the result of performing
40323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the string-values of the two nodes is true.
40333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
40343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator
40353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is <=, <, >= or >, then the objects are compared by converting both
40363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * objects to numbers and comparing the numbers according to IEEE 754.
40373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
40383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The number function converts its argument to a number as follows:
40393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - a string that consists of optional whitespace followed by an
40403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    optional minus sign followed by a Number followed by whitespace
40413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    is converted to the IEEE 754 number that is nearest (according
40423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    to the IEEE 754 round-to-nearest rule) to the mathematical value
40433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    represented by the string; any other string is converted to NaN
40443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Conclusion all nodes need to be converted first to their string value
40463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and then the comparison must be done when possible
40473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
404856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
404956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathCompareNodeSets(int inf, int strict,
40503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
40513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j, init = 0;
40523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val1;
40533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double *values2;
40543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
40553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
40563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
40573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
40594dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
40604dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
40613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
40624dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
40633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
40644dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
40654dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
40664dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
40673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
40684dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
40693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
40713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
40723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4073d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
40744dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
40754dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
40763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
40774dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
4078d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
40794dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
40804dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
40813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
40824dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
40833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
40853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
40864dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
40874dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
40883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
40893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
40903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4091ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
4092cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val1))
40933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    continue;
40943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
40953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (init == 0) {
4096ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
40973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
4098cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    if (xmlXPathIsNaN(values2[j]))
40993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		continue;
41003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (inf && strict)
41013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 < values2[j]);
41023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (inf && !strict)
41033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 <= values2[j]);
41043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && strict)
41053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 > values2[j]);
41063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && !strict)
41073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 >= values2[j]);
41083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ret)
41093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
41103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
41113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
41123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
41133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	init = 1;
41143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
41153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
41164dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg1);
41174dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg2);
41183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
41193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
41203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
41223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetValue:
41233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
41243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
41253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
41263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
41273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the value
41283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a value
41303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
41313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
41323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
41333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
41343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a boolean,
41363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if the result of performing
41373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the boolean and on the result of converting
41383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set to a boolean using the boolean function is true.
41393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
41413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
414256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
41433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
41443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
41453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((val == NULL) || (arg == NULL) ||
41463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
41473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
41483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(val->type) {
41503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
41513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
41523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
41533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_XSLT_TREE:
415456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    return(xmlXPathCompareNodeSets(inf, strict, arg, val));
41553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
41563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
41573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
41583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, arg);
41593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathBooleanFunction(ctxt, 1);
41603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, val);
41613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareValues(ctxt, inf, strict));
41623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
41633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
41643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
41653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
41663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
41673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
41693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEqualNodeSetString
41703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
41713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the string to compare to.
41723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
41743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
41753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
41763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
41773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
41783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
41803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
418156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
4182f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str)
4183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
41843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
41853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
41863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
4187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int hash;
41883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((str == NULL) || (arg == NULL) ||
4190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
4191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
41923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hash = xmlXPathStringHash(str);
4194d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ns == NULL)
4195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
419673c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard    if (ns->nodeNr <= 0) {
419773c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard	if (hash == 0)
419873c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard	    return(1);
419973c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard        return(0);
420073c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard    }
4201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < ns->nodeNr; i++) {
4202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
4203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            str2 = xmlNodeGetContent(ns->nodeTab[i]);
4204f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
4205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
4206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (1);
4207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
4208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (str2 != NULL)
4209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
4210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
42113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (0);
42133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEqualNodeSetFloat
42173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
42183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the float to compare to
42193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
42213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
42223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
42233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
42243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number to be compared and on the result of converting the string-value
42253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of that node to a number using the number function is true.
42263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
42283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
422956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
42303473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEqualNodeSetFloat(xmlXPathObjectPtr arg, double f) {
42313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char buf[100] = "";
42323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg == NULL) ||
42343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
42353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
42363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4237e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    xmlXPathFormatNumber(f, buf, sizeof(buf));
42383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathEqualNodeSetString(arg, BAD_CAST buf));
42393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEqualNodeSets
42443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg1:  first nodeset object argument
42453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  second nodeset object argument
42463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath nodesets: @arg1 == @arg2
42483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
42493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set and
42503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a node in the second node-set such that the result of performing the
42513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison on the string-values of the two nodes is true.
42523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (needless to say, this is a costly operation)
42543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
42563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
425756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
42583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
42593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j;
4260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs1;
4261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs2;
42623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values1;
42633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values2;
42643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
42653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
42663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
42673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
42693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
42703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
42713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
42723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
42733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
42743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
42763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
42773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4278911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0))
42793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4280911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0))
42813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
42823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
42843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * check if there is a node pertaining to both sets
42853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
42863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++)
42873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++)
42883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ns1->nodeTab[i] == ns2->nodeTab[j])
42893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(1);
42903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
42923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values1 == NULL)
42933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
4295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs1 == NULL) {
4296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
42993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
43003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
43013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
43033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(values1);
43043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
43053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
4307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs2 == NULL) {
4308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
4309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4310f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values2);
4311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
43133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
43143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
43163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
43173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (i == 0)
4318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
4319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (hashs1[i] == hashs2[j]) {
4320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values1[i] == NULL)
4321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
4322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values2[j] == NULL)
4323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
4324f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		ret = xmlStrEqual(values1[i], values2[j]);
4325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (ret)
4326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    break;
4327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
43283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
43293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
43303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
43313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++)
43333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values1[i] != NULL)
43343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values1[i]);
43353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (j = 0;j < ns2->nodeNr;j++)
43363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values2[j] != NULL)
43373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values2[j]);
43383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values1);
43393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
4340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs1);
4341f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs2);
43423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
43433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
43443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
43463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEqualValues:
43473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
43483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
43503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
43523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
43533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
43543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
43553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg1, arg2;
43563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
43573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg1 = valuePop(ctxt);
43593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1 == NULL)
43603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
43613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg2 = valuePop(ctxt);
43633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2 == NULL) {
43643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
43653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
43663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1 == arg2) {
43693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
43703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
43713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Equal: by pointer\n");
43723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
43733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(1);
43743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (arg1->type) {
43773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
43783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
43793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
43803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "Equal: undefined\n");
43813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
43823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
43833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_XSLT_TREE:
43843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
43853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
43863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
43873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
43883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
43893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
43903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
43913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
43923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_XSLT_TREE:
43933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NODESET:
43943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlXPathEqualNodeSets(arg1, arg2);
43953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
43963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
43973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg1->nodesetval == NULL) ||
43983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg1->nodesetval->nodeNr == 0)) ret = 0;
43993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
44003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
44013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (ret == arg2->boolval);
44023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
44043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlXPathEqualNodeSetFloat(arg1, arg2->floatval);
44053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
44073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval);
44083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
44103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
44113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
44123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
44133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
44143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
44163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
44173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
44183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
44193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
44203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
44213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
44223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
44233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
44243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NODESET:
44263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_XSLT_TREE:
44273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg2->nodesetval == NULL) ||
4428bd6e63122f047d519a57611a187a965c6a1c0b1cDaniel Veillard			(arg2->nodesetval->nodeNr == 0))
4429bd6e63122f047d519a57611a187a965c6a1c0b1cDaniel Veillard			ret = 0;
44303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
44313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
4432bd6e63122f047d519a57611a187a965c6a1c0b1cDaniel Veillard		    ret = (ret == arg1->boolval);
44333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
44353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
44363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
44373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: %d boolean %d \n",
44383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    arg1->boolval, arg2->boolval);
44393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
44403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == arg2->boolval);
44413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
44433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (arg2->floatval) ret = 1;
44443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else ret = 0;
44453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == ret);
44463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
44483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg2->stringval == NULL) ||
44493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg2->stringval[0] == 0)) ret = 0;
44503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
44513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
44523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == ret);
44533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
44553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
44563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
44573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
44583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
44593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
44613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
44623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
44633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
44643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
44653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
44663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
44673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
44683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
44693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NODESET:
44713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_XSLT_TREE:
44723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlXPathEqualNodeSetFloat(arg2, arg1->floatval);
44733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
44753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (arg1->floatval) ret = 1;
44763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else ret = 0;
44773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg2->boolval == ret);
44783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
44793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
44803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg2);
44813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
44823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg2 = valuePop(ctxt);
44833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* no break on purpose */
44843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
4485d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
448621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
448721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4488d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4489d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		        if (xmlXPathIsInf(arg2->floatval) == 1)
4490d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4491d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4492d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4493d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4494d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4495d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4496d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4497d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4498d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4499d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4500d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4501d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4502d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4503d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4504d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4505d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4506d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4507d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
450821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
450921458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
451021458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
45113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
45133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
45143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
45153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
45163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
45173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
45193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
45213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
45223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
45233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
45243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
45253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
45263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
45273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NODESET:
45293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_XSLT_TREE:
45303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlXPathEqualNodeSetString(arg2, arg1->stringval);
45313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
45333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg1->stringval == NULL) ||
45343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg1->stringval[0] == 0)) ret = 0;
45353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
45363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
45373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg2->boolval == ret);
45383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
45403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlStrEqual(arg1->stringval, arg2->stringval);
45413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
45433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg1);
45443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
45453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg1 = valuePop(ctxt);
4546d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
454721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
454821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4549d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4550d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == 1)
4551d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4552d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4553d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4554d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4555d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4556d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4557d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4558d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4559d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4560d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4561d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4562d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4563d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4564d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4565d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4566d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4567d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4568d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
456921458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
457021458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
457121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
45723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
45743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
45753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
45763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
45773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
45783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
45803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_USERS:
45823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
45833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
45843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
45853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
45863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
45883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
45893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
45903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
45913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
45923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
45953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareValues:
45963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
45973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
45983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
45993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on XPath objects:
46013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 < @arg2    (1, 1, ...
46023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 <= @arg2   (1, 0, ...
46033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 > @arg2    (0, 1, ...
46043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 >= @arg2   (0, 0, ...
46053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator is
46073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * <=, <, >=, >, then the objects are compared by converted both objects
46083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to numbers and comparing the numbers according to IEEE 754. The <
46093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison will be true if and only if the first number is less than the
46103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * second number. The <= comparison will be true if and only if the first
46113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number is less than or equal to the second number. The > comparison
46123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if the first number is greater than the second
46133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number. The >= comparison will be true if and only if the first number
46143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is greater than or equal to the second number.
46153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4616cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if the comparison succeeded, 0 if it failed
46173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
46183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
46193473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
4620d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    int ret = 0, arg1i = 0, arg2i = 0;
46213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg1, arg2;
46223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg2 = valuePop(ctxt);
46243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2 == NULL) {
46253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
46263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg1 = valuePop(ctxt);
46293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1 == NULL) {
46303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
46313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
46323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2->type == XPATH_NODESET) || (arg1->type == XPATH_NODESET)) {
46353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((arg2->type == XPATH_NODESET) && (arg1->type == XPATH_NODESET)) {
463656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
46373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
46383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (arg1->type == XPATH_NODESET) {
46394af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
46404af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg1, arg2);
46413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
46424af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
46434af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg2, arg1);
46443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
46453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
46463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(ret);
46473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
46503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg1);
46513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
46523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg1 = valuePop(ctxt);
46533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
46553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
46563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
46573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
46583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
46603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg2);
46613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
46623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg2 = valuePop(ctxt);
46633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
46653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
46663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
46673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
46683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
46703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Add tests for infinity and nan
46713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * => feedback on 3.4 for Inf and NaN
46723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
4673d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    /* Hand check NaN and Infinity comparisons */
467421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
4675d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	ret=0;
467621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    } else {
4677d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg1i=xmlXPathIsInf(arg1->floatval);
4678d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg2i=xmlXPathIsInf(arg2->floatval);
4679d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	if (inf && strict) {
4680d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == -1 && arg2i != -1) ||
4681d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == 1 && arg1i != 1)) {
4682d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4683d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4684d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval < arg2->floatval);
4685d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4686d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4687d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4688d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4689d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (inf && !strict) {
4690d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == -1 || arg2i == 1) {
4691d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4692d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4693d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval <= arg2->floatval);
4694d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4695d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4696d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4697d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4698d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && strict) {
4699d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == 1 && arg2i != 1) ||
4700d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == -1 && arg1i != -1)) {
4701d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4702d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4703d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval > arg2->floatval);
4704d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4705d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4706d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4707d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4708d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && !strict) {
4709d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == 1 || arg2i == -1) {
4710d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4711d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4712d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval >= arg2->floatval);
4713d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4714d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4715d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4716d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
471721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    }
47183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
47193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
47203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
47213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
47243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathValueFlipSign:
47253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
47263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the unary - operation on an XPath object
47283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
47293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
47303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
47313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
47323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
4733ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4734ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
4735eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(ctxt->value->floatval))
4736eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNAN;
4737eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
4738eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNINF;
4739eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
4740eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathPINF;
4741eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (ctxt->value->floatval == 0) {
47425fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        if (xmlXPathGetSign(ctxt->value->floatval) == 0)
47435fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
47445fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else
47455fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = 0;
47465fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
47475fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else
47485fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        ctxt->value->floatval = - ctxt->value->floatval;
47493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
47523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathAddValues:
47533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
47543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the add operation on XPath objects:
47563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
47573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
47583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
47593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
47603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
47613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
47623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
47633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4764ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
4765ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
4766ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
4767ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
47683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
47693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4770ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4771ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
4772ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval += val;
47733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
47763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubValues:
47773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
47783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4779cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Implement the subtraction operation on XPath objects:
47803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
47813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
47823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
47833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
47843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
47853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
47863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
47873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4788ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
4789ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
4790ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
4791ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
47923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
47933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4794ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4795ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
4796ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval -= val;
47973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
48003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathMultValues:
48013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
48023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the multiply operation on XPath objects:
48043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
48053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
48063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
48073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
48083473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
48093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
48103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
48113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4812ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
4813ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
4814ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
4815ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
48163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
48173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4818ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4819ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
4820ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval *= val;
48213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
48243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathDivValues:
48253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
48263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the div operation on XPath objects @arg1 / @arg2:
48283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
48293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
48303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
48313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
48323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
48333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
48343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
48353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4836ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
4837ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
4838ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
4839ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
48403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
48413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4842ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4843ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
4844eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
4845eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard	ctxt->value->floatval = xmlXPathNAN;
4846eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (val == 0 && xmlXPathGetSign(val) != 0) {
48475fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
48485fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
48495fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval > 0)
48505fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
48515fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval < 0)
48525fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
48535fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
48545fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else if (val == 0) {
48555f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	if (ctxt->value->floatval == 0)
48565f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
48575f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval > 0)
48585f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
48595f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval < 0)
48605f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
48615f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard    } else
48625f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	ctxt->value->floatval /= val;
48633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
48663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathModValues:
48673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
48683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the mod operation on XPath objects: @arg1 / @arg2
48703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
48713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
48723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
48733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
48743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathModValues(xmlXPathParserContextPtr ctxt) {
48753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
48765fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    double arg1, arg2, tmp;
48773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4878ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
4879ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
4880ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
48815fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg2 = xmlXPathCastToNumber(arg);
48823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
48833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4884ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
4885ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
48865fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg1 = ctxt->value->floatval;
4887268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard    if (arg2 == 0)
4888268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard	ctxt->value->floatval = xmlXPathNAN;
48895fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else {
48905fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	tmp=arg1/arg2;
48915fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	ctxt->value->floatval = arg2 * (tmp - (double)((int)tmp));
48925fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
48933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
48963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
48973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The traversal functions					*
48983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
48993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
49003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
49023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A traversal function enumerates nodes along an axis.
49033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initially it must be called with NULL, and it indicates
49043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * termination on the axis by returning NULL.
49053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
49063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylortypedef xmlNodePtr (*xmlXPathTraversalFunction)
49073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
49083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
49103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextSelf:
49113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
49123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
49133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "self" direction
49153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The self axis contains just the context node itself
49163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
49183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
49193473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
49203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
49213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
49223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
49233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
49243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
49253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
49273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextChild:
49283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
49293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
49303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "child" direction
49323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The child axis contains the children of the context node in document order.
49333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
49353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
49363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
49373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
49383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
49393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
49403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
49413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
49423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
49433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
49443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
49453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
49463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
49473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
49483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
49493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
49503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->children);
49513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
49523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
49533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
49543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
4955eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
4956eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
49573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
49583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(((xmlDocPtr) ctxt->context->node)->children);
49593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
49603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
49613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
49623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE:
49633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_NAMESPACE_DECL:
49643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
49653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
49663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
49673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
49683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
49693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
49713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (cur->type == XML_HTML_DOCUMENT_NODE))
49723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
49733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
49743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
49753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
49773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendant:
49783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
49793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
49803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant" direction
49823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant axis contains the descendants of the context node in document
49833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order; a descendant is a child or a child of a child and so on.
49843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
49863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
49873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
49883473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
49893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
49903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
49913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
49923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
49933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
49943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
49953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
49973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(ctxt->context->doc->children);
49983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->children);
49993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
50003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5001567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur->children != NULL) {
50023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    	if (cur->children->type != XML_ENTITY_DECL)
5003567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard	    return(cur->children);
5004567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    }
5005567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
5006567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur == ctxt->context->node) return(NULL);
5007567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
50083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->next != NULL) return(cur->next);
50093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
50113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
50123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == NULL) return(NULL);
50133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == ctxt->context->node) return(NULL);
50143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->next != NULL) {
50153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur = cur->next;
50163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur);
50173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
50183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
50193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
50203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendantOrSelf:
50243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
50263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant-or-self" direction
50283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant-or-self axis contains the context node and the descendants
50293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node in document order; thus the context node is the first
50303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis, and the first child of the context node is the second node
50313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the axis
50323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
50343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
50363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
50373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
50383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
50393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
50403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
50413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
50423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
50433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
50443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
50453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextDescendant(ctxt, cur));
50473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextParent:
50513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
50533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "parent" direction
50553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The parent axis contains the parent of the context node, if there is one.
50563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
50583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
50603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
50613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
50623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
50633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
50643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Namespace handling !!!
50653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
50663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
50673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
50683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
50693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
50703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
50713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
50723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
50733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
50743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
50753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
50763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
50773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
50783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
50793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
50803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
50813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
50823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
50833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
50843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
50853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
50863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
50873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
50883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(att->parent);
50903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
50913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
50923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
50933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
50943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5095eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5096eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
50973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
50983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5099044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5100044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5101044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5102044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5103044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5104044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
51053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5106044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
51073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
51083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
51103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
51113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
51133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestor:
51143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
51153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
51163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor" direction
51183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the ancestor axis contains the ancestors of the context node; the ancestors
51193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node consist of the parent of context node and the parent's
51203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent and so on; the nodes are ordered in reverse document order; thus the
51213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent is the first node on the axis, and the parent's parent is the second
51223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis
51233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
51253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
51263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
51273473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
51283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
51293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
51303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
51313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * !!!!!!!!!!!!!
51323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
51333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
51343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
51353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
51363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
51373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
51383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
51393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
51403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
51413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
51423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
51433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_DTD_NODE:
51443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
51453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
51463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
51473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
51483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
51493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
51503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
51513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
51523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
51533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
515456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
51553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
515656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		return(tmp->parent);
51573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
51583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
51593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
51603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
51613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5162eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5163eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
51643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
51653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5166044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5167044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5168044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5169044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5170044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5171044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
5172044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		/* Bad, how did that namespace ended-up there ? */
51733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5174044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
51753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
51763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
51773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == ctxt->context->doc->children)
51793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return((xmlNodePtr) ctxt->context->doc);
51803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
51813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
51823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (cur->type) {
51833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
51843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_TEXT_NODE:
51853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_CDATA_SECTION_NODE:
51863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_REF_NODE:
51873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_NODE:
51883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
51893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_COMMENT_NODE:
51903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NOTATION_NODE:
51913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DTD_NODE:
51923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ELEMENT_DECL:
51933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ATTRIBUTE_DECL:
51943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ENTITY_DECL:
51953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_START:
51963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_END:
51973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur->parent);
51983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE: {
51993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
52003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(att->parent);
52023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5203dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	case XML_NAMESPACE_DECL: {
5204dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5205dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin
5206dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    if ((ns->next != NULL) &&
5207dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        (ns->next->type != XML_NAMESPACE_DECL))
5208dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        return((xmlNodePtr) ns->next);
5209dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    /* Bad, how did that namespace ended-up there ? */
5210dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin            return(NULL);
5211dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	}
52123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_NODE:
52133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_TYPE_NODE:
52143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_FRAG_NODE:
52153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_HTML_DOCUMENT_NODE:
5216eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5217eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	case XML_DOCB_DOCUMENT_NODE:
52183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
52193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
52203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
52213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
52223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestorOrSelf:
52263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
52283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor-or-self" direction
52303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he ancestor-or-self axis contains the context node and ancestors of
52313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node in reverse document order; thus the context node is
52323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node on the axis, and the context node's parent the second;
52333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent here is defined the same as with the parent axis.
52343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
52363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
52383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
52393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
52403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
52413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextAncestor(ctxt, cur));
52423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowingSibling:
52463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
52483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following-sibling" direction
52503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following-sibling axis contains the following siblings of the context
52513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in document order.
52523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
52543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52553473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
52563473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
52573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
52583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
52593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
52603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
52613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
52623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
52633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->next);
52643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
52653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPrecedingSibling:
52693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
52713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding-sibling" direction
52733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The preceding-sibling axis contains the preceding siblings of the context
52743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in reverse document order; the first preceding sibling is first on the
52753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * axis; the sibling preceding that node is the second on the axis and so on.
52763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
52783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
52803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
52813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
52823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
52833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
52843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
52853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
52863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
52873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->prev);
5288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
5289f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (cur == NULL)
5291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(ctxt->context->node->prev);
5292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
52933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->prev);
52943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowing:
52983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
53003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following" direction
53023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following axis contains all nodes in the same document as the context
53033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are after the context node in document order, excluding any
53043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * descendants and excluding attribute nodes and namespace nodes; the nodes
53053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * are ordered in document order
53063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
53083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53093473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
53103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
53113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur != NULL && cur->children != NULL)
53123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return cur->children ;
53133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) cur = ctxt->context->node;
53143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return(NULL) ; /* ERROR */
53153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->next != NULL) return(cur->next) ;
53163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
53173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
53183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == NULL) return(NULL);
53193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
53203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->next != NULL) return(cur->next);
53213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
53223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
53233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
53263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAncestor:
53273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ancestor:  the ancestor node
53283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node:  the current node
53293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Check that @ancestor is a @node's ancestor
53313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
53333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
53353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
53363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ancestor == NULL) || (node == NULL)) return(0);
53373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* nodes need to be in the same document */
53383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor->doc != node->doc) return(0);
53393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* avoid searching if ancestor or node is the root node */
53403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor == (xmlNodePtr) node->doc) return(1);
53413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node == (xmlNodePtr) ancestor->doc) return(0);
53423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node->parent != NULL) {
53433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (node->parent == ancestor)
53443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            return(1);
53453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node = node->parent;
53463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
53473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
53483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPreceding:
53523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
53543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding" direction
53563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the preceding axis contains all nodes in the same document as the context
53573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are before the context node in document order, excluding any
53583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ancestors and excluding attribute nodes and namespace nodes; the nodes are
53593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ordered in reverse document order
53603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
53623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
5364f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
5365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL)
5367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
53683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
5369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return (NULL);
5370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5371f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
53723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
53733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->prev != NULL) {
5374f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
5375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
53763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
53773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
5379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
53833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (xmlXPathIsAncestor(cur, ctxt->context->node));
5384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
5385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
5386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
5387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
5388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNextPrecedingInternal:
5389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
5390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @cur:  the current node in the traversal
5391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Traversal function for the "preceding" direction
5393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * the preceding axis contains all nodes in the same document as the context
5394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * node that are before the context node in document order, excluding any
5395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ancestors and excluding attribute nodes and namespace nodes; the nodes are
5396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ordered in reverse document order
5397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is a faster implementation but internal only since it requires a
5398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * state kept in the parser context: ctxt->ancestor.
5399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the next element following that axis
5401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
5402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic xmlNodePtr
5403f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
5404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr cur)
5405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL) {
5407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
5408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->prev == NULL) {
5415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->parent;
5416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur != ctxt->ancestor)
5421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
5422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur = cur->prev;
5425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->last != NULL)
5426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->last;
5427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
54283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
54313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextNamespace:
54323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
54333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
54343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "namespace" direction
54363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace axis contains the namespace nodes of the context node;
54373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the order of nodes on this axis is implementation-defined; the axis will
54383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be empty unless the context node is an element
54393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
544020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard * We keep the XML namespace node at the end of the list.
544120ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard *
54423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
54433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
54443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
54453473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
54467d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    xmlNodePtr ret;
54477d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard
54483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
544920ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    if (cur == (xmlNodePtr) xmlXPathXMLNamespace)
545020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard	return(NULL);
54517d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    if ((cur == NULL) || (ctxt->context->tmpNsList == NULL)) {
54527d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard        if (ctxt->context->tmpNsList != NULL)
54537d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
54547d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList =
54553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGetNsList(ctxt->context->doc, ctxt->context->node);
54567d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	if (ctxt->context->tmpNsList == NULL) return(NULL);
54577d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsNr = 0;
54587d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    }
54597d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    ret = (xmlNodePtr)ctxt->context->tmpNsList[ctxt->context->tmpNsNr++];
54607d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    if (ret == NULL) {
54617d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	xmlFree(ctxt->context->tmpNsList);
54627d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList = NULL;
546320ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard	return((xmlNodePtr) xmlXPathXMLNamespace);
54643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54657d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    return(ret);
54663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
54693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAttribute:
54703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
54713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
54723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "attribute" direction
54743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * TODO: support DTD inherited default attributes
54753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
54773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
54783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
54793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5480e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node == NULL)
5481e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
5482e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node->type != XML_ELEMENT_NODE)
5483e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
54843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
54853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
54863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
54873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return((xmlNodePtr)ctxt->context->node->properties);
54883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlNodePtr)cur->next);
54903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
54933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
54943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		NodeTest Functions					*
54953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
54963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
54973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_FUNCTION			200
54993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5500d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
5501d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
5502d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5503d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		Implicit tree core function library			*
5504d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5505d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
5506d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
55073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5508d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathRoot:
55093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5511d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Initialize the context to the root of the document
55123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
5513d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5514d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathRoot(xmlXPathParserContextPtr ctxt) {
5515d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
5516d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
5517d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
55183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5519d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
5520d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5521d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		The explicit core function library			*
5522d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib	*
5523d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5524d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
55253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5526d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
5527d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
5528d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathLastFunction:
5529d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
5530d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
5531d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
5532d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the last() XPath function
5533d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number last()
5534d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The last function returns the number of nodes in the context node list.
5535d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
5536d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5537d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
5538d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
5539d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->contextSize >= 0) {
5540d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) ctxt->context->contextSize));
5541d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
5542d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext,
5543d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		"last() : %d\n", ctxt->context->contextSize);
55443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
5545d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
5546d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
55473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5548d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
55493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5550d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
5551d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathPositionFunction:
5552d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
5553d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
5554d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
5555d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the position() XPath function
5556d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number position()
5557d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The position function returns the position of the context node in the
5558cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * context node list. The first position is 1, and so the last position
5559d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * will be equal to last().
5560d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
5561d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5562d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
5563d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
5564d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->proximityPosition >= 0) {
5565d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt,
5566d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	      xmlXPathNewFloat((double) ctxt->context->proximityPosition));
5567d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
5568d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
5569d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		ctxt->context->proximityPosition);
55703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
5571d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
5572d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
5573d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
5574d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
55753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCountFunction:
55783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
55803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the count() XPath function
55823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number count(node-set)
55833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
55853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
55863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
55873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
55893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
55903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
55913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
55923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
55933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
55943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5595911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur == NULL) || (cur->nodesetval == NULL))
5596911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) 0));
5597fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    else if (cur->type == XPATH_NODESET) {
5598911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) cur->nodesetval->nodeNr));
5599fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    } else {
5600fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	if ((cur->nodesetval->nodeNr != 1) ||
5601fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    (cur->nodesetval->nodeTab == NULL)) {
5602fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) 0));
5603fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	} else {
5604fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    xmlNodePtr tmp;
5605fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    int i = 0;
5606fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard
5607fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    tmp = cur->nodesetval->nodeTab[0];
5608fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    if (tmp != NULL) {
5609fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		tmp = tmp->children;
5610fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		while (tmp != NULL) {
5611fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    tmp = tmp->next;
5612fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    i++;
5613fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		}
5614fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    }
5615fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) i));
5616fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	}
5617fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    }
56183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
56193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5622ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathGetElementsByIds:
5623ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @doc:  the document
5624ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ids:  a whitespace separated list of IDs
5625ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
5626ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Selects elements by their unique ID.
5627ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
5628ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a node-set of selected elements.
5629ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
5630ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardstatic xmlNodeSetPtr
5631ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
5632ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
5633ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    const xmlChar *cur = ids;
5634ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ID;
5635ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlAttrPtr attr;
5636ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodePtr elem = NULL;
5637ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5638ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNodeSetCreate(NULL);
5639ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5640ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (IS_BLANK(*cur)) cur++;
5641ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (*cur != 0) {
5642ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
5643ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	       (*cur == '.') || (*cur == '-') ||
5644ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	       (*cur == '_') || (*cur == ':') ||
5645ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	       (IS_COMBINING(*cur)) ||
5646ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	       (IS_EXTENDER(*cur)))
5647ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	       cur++;
5648ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5649ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	if ((!IS_BLANK(*cur)) && (*cur != 0)) break;
5650ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5651ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        ID = xmlStrndup(ids, cur - ids);
5652ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	attr = xmlGetID(doc, ID);
5653ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	if (attr != NULL) {
5654ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    elem = attr->parent;
5655ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard            xmlXPathNodeSetAdd(ret, elem);
5656ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        }
5657ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	if (ID != NULL)
5658ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlFree(ID);
5659ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5660ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	while (IS_BLANK(*cur)) cur++;
5661ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ids = cur;
5662ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
5663ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
5664ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
5665ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5666ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
56673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIdFunction:
56683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
56703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the id() XPath function
56723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    node-set id(object)
56733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The id function selects elements by their unique ID
56743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
56753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the result is the union of the result of applying id to the
56763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string value of each of the nodes in the argument node-set. When the
56773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument to id is of any other type, the argument is converted to a
56783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string as if by a call to the string function; the string is split
56793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * into a whitespace-separated list of tokens (whitespace is any sequence
56803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of characters matching the production S); the result is a node-set
56813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * containing the elements in the same document as the context node that
56823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * have a unique ID equal to any of the tokens in the list.
56833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
56853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
5686ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *tokens;
5687ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
5688ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr obj;
56893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
56913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    obj = valuePop(ctxt);
56923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
56933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->type == XPATH_NODESET) {
5694ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlNodeSetPtr ns;
56953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i;
56963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5697ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNodeSetCreate(NULL);
56983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5699911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	if (obj->nodesetval != NULL) {
5700911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
5701ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		tokens =
5702ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
5703ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
5704ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ret = xmlXPathNodeSetMerge(ret, ns);
5705ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		xmlXPathFreeNodeSet(ns);
5706ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		if (tokens != NULL)
5707ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlFree(tokens);
5708911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    }
57093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
57103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(obj);
5712ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathWrapNodeSet(ret));
57133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
57143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5715ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    obj = xmlXPathConvertString(obj);
57163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5717ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
5718ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
57193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(obj);
57213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return;
57223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLocalNameFunction:
57263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
57283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the local-name() XPath function
57303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string local-name(node-set?)
57313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The local-name function returns a string containing the local part
57323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the name of the node in the argument node-set that is first in
57333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document order. If the node-set is empty or the first node has no
57343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * name, an empty string is returned. If the argument is omitted it
57353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
57363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
57383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
57393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
57403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
57423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
57433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
57443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
57473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
57483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
57493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
57503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
57513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
57523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5753911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
57543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
57553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
57563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
57573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
57583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
57593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
57603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
57613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt,
57623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		      xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
57633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
57643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NAMESPACE_DECL:
57653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewString(
57663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
57673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
57683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
57693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
57703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
57713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
57733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNamespaceURIFunction:
57773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
57793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the namespace-uri() XPath function
57813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string namespace-uri(node-set?)
57823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The namespace-uri function returns a string containing the
57833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace URI of the expanded name of the node in the argument
57843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set that is first in document order. If the node-set is empty,
57853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node has no name, or the expanded name has no namespace
57863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * URI, an empty string is returned. If the argument is omitted it
57873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
57883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
57903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
57913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
57923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
57943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
57953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
57963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
57983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
57993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
58003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
58013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
58023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
58033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5804911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
58053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
58063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
58073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
58083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
58093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
58103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
58113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
58123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewCString(""));
58133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else
58143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewString(
58153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			  cur->nodesetval->nodeTab[i]->ns->href));
58163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
58173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
58183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
58193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
58203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
58223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNameFunction:
58263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
58283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the name() XPath function
58303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string name(node-set?)
58313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The name function returns a string containing a QName representing
5832cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * the name of the node in the argument node-set that is first in document
58333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order. The QName must represent the name with respect to the namespace
58343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * declarations in effect on the node whose name is being represented.
58353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Typically, this will be the form in which the name occurred in the XML
58363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * source. This need not be the case if there are namespace declarations
58373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in effect on the node that associate multiple prefixes with the same
58383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace. However, an implementation may include information about
58393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the original prefix in its representation of nodes; in this case, an
58403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation can ensure that the returned string is always the same
58413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * as the QName used in the XML source. If the argument it omitted it
58423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
58433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Libxml keep the original prefix so the "real qualified name" used is
58443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returned.
58453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
584656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
58470438375d2e6be47d0179826271081ae64df94f8bDaniel VeillardxmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
58480438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard{
58493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
58503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
58520438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
58530438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        nargs = 1;
58543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
58570438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard    if ((ctxt->value == NULL) ||
58580438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        ((ctxt->value->type != XPATH_NODESET) &&
58590438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard         (ctxt->value->type != XPATH_XSLT_TREE)))
58600438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        XP_ERROR(XPATH_INVALID_TYPE);
58613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
58623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5863911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
58640438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewCString(""));
58653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
58660438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        int i = 0;              /* Should be first in document order !!!!! */
58673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58680438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        switch (cur->nodesetval->nodeTab[i]->type) {
58690438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ELEMENT_NODE:
58700438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ATTRIBUTE_NODE:
58710438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
58720438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    (cur->nodesetval->nodeTab[i]->ns->prefix == NULL))
58730438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    valuePush(ctxt,
58740438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                              xmlXPathNewString(cur->nodesetval->
58750438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                                                nodeTab[i]->name));
58760438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard
58770438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                else {
58780438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    char name[2000];
58790438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard
58800438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    snprintf(name, sizeof(name), "%s:%s",
58810438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                             (char *) cur->nodesetval->nodeTab[i]->ns->
58820438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                             prefix,
58830438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                             (char *) cur->nodesetval->nodeTab[i]->name);
58840438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    name[sizeof(name) - 1] = 0;
58850438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    valuePush(ctxt, xmlXPathNewCString(name));
58860438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                }
58870438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                break;
58880438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            default:
58890438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                valuePush(ctxt,
58900438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                          xmlXPathNewNodeSet(cur->nodesetval->nodeTab[i]));
58910438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                xmlXPathLocalNameFunction(ctxt, 1);
58920438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        }
58933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
58953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5897fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
5898fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
58993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringFunction:
59003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
59023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string() XPath function
59043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string string(object?)
59053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he string function converts an object to a string as follows:
59063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A node-set is converted to a string by returning the value of
59073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      the node in the node-set that is first in document order.
59083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      If the node-set is empty, an empty string is returned.
59093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A number is converted to a string as follows
59103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + NaN is converted to the string NaN
59113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive zero is converted to the string 0
59123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative zero is converted to the string 0
59133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive infinity is converted to the string Infinity
59143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative infinity is converted to the string -Infinity
59153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + if the number is an integer, the number is represented in
59163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal form as a Number with no decimal point and no leading
59173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        zeros, preceded by a minus sign (-) if the number is negative
59183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + otherwise, the number is represented in decimal form as a
59193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        Number including a decimal point with at least one digit
59203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point and at least one digit after the
59213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal point, preceded by a minus sign (-) if the number
59223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        is negative; there must be no leading zeros before the decimal
5923cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *        point apart possibly from the one required digit immediately
59243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point; beyond the one required digit
59253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        after the decimal point there must be as many, but only as
59263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        many, more digits as are needed to uniquely distinguish the
59273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        number from all other IEEE 754 numeric values.
59283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - The boolean false value is converted to the string false.
59293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      The boolean true value is converted to the string true.
59303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If the argument is omitted, it defaults to a node-set with the
59323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * context node as its only member.
59333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
59343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
59353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
59363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
59373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
5939ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt,
5940ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathWrapString(
5941ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard			xmlXPathCastNodeToString(ctxt->context->node)));
5942ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return;
59433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
59443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
59463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
59473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
5948fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertString(cur);
5949fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
59503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
59533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringLengthFunction:
59543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
59563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string-length() XPath function
59583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number string-length(string?)
59593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The string-length returns the number of characters in the string
59603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [3.6 Strings]). If the argument is omitted, it defaults to
59613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node converted to a string, in other words the value
59623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node.
59633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
59643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
59653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
59663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
59673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
59693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
59703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0));
59713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
59723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar *content;
59733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5974ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    content = xmlXPathCastNodeToString(ctxt->context->node);
5975e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(content)));
59763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
59773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
59783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
59793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
59803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
59813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
59823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
59833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
5984e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(cur->stringval)));
59853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
59863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
59893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathConcatFunction:
59903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
59923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the concat() XPath function
59943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string concat(string, string, string*)
59953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The concat function returns the concatenation of its arguments.
59963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
59973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
59983473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
59993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur, newobj;
60003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *tmp;
60013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
60033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
60043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
60073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
60083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur == NULL) || (cur->type != XPATH_STRING)) {
60093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(cur);
60103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
60113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs--;
60133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (nargs > 0) {
60153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_STRING;
60163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj = valuePop(ctxt);
60173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
60183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(newobj);
60193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(cur);
60203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_INVALID_TYPE);
60213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
60223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tmp = xmlStrcat(newobj->stringval, cur->stringval);
60233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj->stringval = cur->stringval;
60243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->stringval = tmp;
60253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(newobj);
60273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs--;
60283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, cur);
60303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathContainsFunction:
60343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
60363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the contains() XPath function
60383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean contains(string, string)
60393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The contains function returns true if the first argument string
60403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * contains the second argument string, and otherwise returns false.
60413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
60433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
60443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
60453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
60473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
60483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
60493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
60503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
60513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
60523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
60533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
60543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
60553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
60563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrstr(hay->stringval, needle->stringval))
60583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
60593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
60603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
60613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
60623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
60633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStartsWithFunction:
60673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
60693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the starts-with() XPath function
60713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean starts-with(string, string)
60723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The starts-with function returns true if the first argument string
60733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starts with the second argument string, and otherwise returns false.
60743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
60763473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
60773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
60783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
60793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
60813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
60823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
60833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
60843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
60853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
60863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
60873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
60883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
60893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
60903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = xmlStrlen(needle->stringval);
60923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrncmp(hay->stringval, needle->stringval, n))
60933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
60943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
60953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
60963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
60973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
60983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
61013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringFunction:
61023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
61033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
61043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring() XPath function
61063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring(string, number, number?)
61073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring function returns the substring of the first argument
61083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starting at the position specified in the second argument with
61093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * length specified in the third argument. For example,
61103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * substring("12345",2,3) returns "234". If the third argument is not
61113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * specified, it returns the substring starting at the position specified
61123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in the second argument and continuing to the end of the string. For
61133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * example, substring("12345",2) returns "2345".  More precisely, each
61143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character in the string (see [3.6 Strings]) is considered to have a
61153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * numeric position: the position of the first character is 1, the position
61163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the second character is 2 and so on. The returned substring contains
61173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * those characters for which the position of the character is greater than
61183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or equal to the second argument and, if the third argument is specified,
61193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * less than the sum of the second and third arguments; the comparisons
61203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and addition used for the above follow the standard IEEE 754 rules. Thus:
61213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1.5, 2.6) returns "234"
61223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0, 3) returns "12"
61233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0 div 0, 3) returns ""
61243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1, 0 div 0) returns ""
61253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -42, 1 div 0) returns "12345"
61263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -1 div 0, 1 div 0) returns ""
61273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
61293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
61303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr str, start, len;
613197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    double le=0, in;
613297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int i, l, m;
61333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret;
61343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
61363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
61373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
61383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs > 3) {
61393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(3);
61403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
614197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
614297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * take care of possible last (position) argument
614397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
61443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 3) {
61453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_NUMBER;
61463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_TYPE(XPATH_NUMBER);
61473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len = valuePop(ctxt);
61483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	le = len->floatval;
61493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(len);
61503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
615197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
61523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
61533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
61543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    start = valuePop(ctxt);
61553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    in = start->floatval;
61563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(start);
61573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
61583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
61593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    str = valuePop(ctxt);
616097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    m = xmlUTF8Strlen((const unsigned char *)str->stringval);
616197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
616297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
616397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * If last pos not present, calculate last position
616497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
61659e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (nargs != 3) {
61669e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	le = (double)m;
61679e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (in < 1.0)
61689e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    in = 1.0;
61699e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    }
617097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
61710eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    /* Need to check for the special cases where either
61720eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * the index is NaN, the length is NaN, or both
61730eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * arguments are infinity (relying on Inf + -Inf = NaN)
617497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     */
61759e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) {
61760eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /*
61779e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * To meet the requirements of the spec, the arguments
61789e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * must be converted to integer format before
61799e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * initial index calculations are done
61800eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         *
61819e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * First we go to integer form, rounding up
61829e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * and checking for special cases
61830eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         */
61840eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        i = (int) in;
61859e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (((double)i)+0.5 <= in) i++;
61869e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard
61879e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (xmlXPathIsInf(le) == 1) {
61889e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = m;
61899e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (i < 1)
61909e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard		i = 1;
61919e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
61929e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else if (xmlXPathIsInf(le) == -1 || le < 0.0)
61939e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = 0;
61949e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else {
61959e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = (int) le;
61969e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (((double)l)+0.5 <= le) l++;
61979e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
61980eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard
61999e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	/* Now we normalize inidices */
62009e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        i -= 1;
62019e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        l += i;
62029e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (i < 0)
62039e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            i = 0;
62049e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (l > m)
62059e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            l = m;
62063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62070eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /* number of chars to copy */
62080eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        l -= i;
62093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62100eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = xmlUTF8Strsub(str->stringval, i, l);
62110eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
62120eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    else {
62130eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = NULL;
62140eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
62153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL)
62173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
62183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
62193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewString(ret));
62203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(ret);
62213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
622297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
62233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(str);
62243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
62273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringBeforeFunction:
62283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-before() XPath function
62323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-before(string, string)
62333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-before function returns the substring of the first
62343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that precedes the first occurrence of the second
62353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty string
62363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
62373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-before("1999/04/01","/") returns 1999.
62383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62403473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
62413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
62423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
62433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
62443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
62453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
62463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
62483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
62493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
62503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
62513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
62523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
62543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
62553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
62563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
62573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval);
62583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, str->stringval, offset);
62593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
62603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
62613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
62623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
62633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
62653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
62663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
62693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringAfterFunction:
62703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-after() XPath function
62743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-after(string, string)
62753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-after function returns the substring of the first
62763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that follows the first occurrence of the second
62773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty stringi
62783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
62793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-after("1999/04/01","/") returns 04/01,
62803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and substring-after("1999/04/01","19") returns 99/04/01.
62813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
62843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
62853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
62863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
62873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
62883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
62893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
62913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
62923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
62933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
62943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
62953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
62973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
62983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
62993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
63003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
63013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, &str->stringval[offset],
63023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   xmlStrlen(str->stringval) - offset);
63033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
63053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
63063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
63073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
63093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
63103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNormalizeFunction:
63143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the normalize-space() XPath function
63183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string normalize-space(string?)
63193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The normalize-space function returns the argument string with white
63203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space normalized by stripping leading and trailing whitespace
63213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and replacing sequences of whitespace characters by a single
63223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space. Whitespace characters are the same allowed by the S production
63233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in XML. If the argument is omitted, it defaults to the context
63243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node converted to a string, in other words the value of the context node.
63253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63273473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
63283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr obj = NULL;
63293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar *source = NULL;
63303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
63313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar blank;
63323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (nargs == 0) {
63343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use current context node */
6335ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt,
6336ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	      xmlXPathWrapString(
6337ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathCastNodeToString(ctxt->context->node)));
63383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs = 1;
63393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
63403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(1);
63423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
63433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_TYPE(XPATH_STRING);
63443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  obj = valuePop(ctxt);
63453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  source = obj->stringval;
63463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
63483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target && source) {
63493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Skip leading whitespaces */
63513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*source))
63523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
63533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Collapse intermediate whitespaces, and skip trailing whitespaces */
63553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blank = 0;
63563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*source) {
63573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      if (IS_BLANK(*source)) {
635897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	blank = 0x20;
63593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      } else {
63603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (blank) {
63613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  xmlBufferAdd(target, &blank, 1);
63623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  blank = 0;
63633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
63643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlBufferAdd(target, source, 1);
63653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      }
63663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
63673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
63703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
63713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
63723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(obj);
63733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTranslateFunction:
63773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the translate() XPath function
63813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string translate(string, string, string)
63823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The translate function returns the first argument string with
63833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * occurrences of characters in the second argument string replaced
63843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the character at the corresponding position in the third argument
63853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, translate("bar","abc","ABC") returns the string
63863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * BAr. If there is a character in the second argument string with no
63873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character at a corresponding position in the third argument string
63883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (because the second argument string is longer than the third argument
63893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string), then occurrences of that character in the first argument
63903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string are removed. For example, translate("--aaa--","abc-","ABC")
63913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns "AAA". If a character occurs more than once in second
63923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then the first occurrence determines the replacement
63933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character. If the third argument string is longer than the second
63943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then excess characters are ignored.
63953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6398e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr str;
6399e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr from;
6400e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr to;
6401e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferPtr target;
640297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int offset, max;
6403e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlChar ch;
640497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *point;
640597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *cptr;
64063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6407e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CHECK_ARITY(3);
64083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6409e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6410e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    to = valuePop(ctxt);
6411e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6412e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    from = valuePop(ctxt);
6413e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6414e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    str = valuePop(ctxt);
64153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6416e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    target = xmlBufferCreate();
6417e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (target) {
641897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	max = xmlUTF8Strlen(to->stringval);
641997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	for (cptr = str->stringval; (ch=*cptr); ) {
642097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    offset = xmlUTF8Strloc(from->stringval, cptr);
642197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if (offset >= 0) {
642297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (offset < max) {
642397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    point = xmlUTF8Strpos(to->stringval, offset);
642497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if (point)
642597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));
642697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
642797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    } else
642897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
642997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
643097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    /* Step to next character in input */
643197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    cptr++;
643297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if ( ch & 0x80 ) {
643397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* if not simple ascii, verify proper format */
643497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if ( (ch & 0xc0) != 0xc0 ) {
643597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    xmlGenericError(xmlGenericErrorContext,
643697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			"xmlXPathTranslateFunction: Invalid UTF8 string\n");
643797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
643897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
643997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* then skip over remaining bytes for this char */
644097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		while ( (ch <<= 1) & 0x80 )
644197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if ( (*cptr++ & 0xc0) != 0x80 ) {
644297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlGenericError(xmlGenericErrorContext,
644397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			    "xmlXPathTranslateFunction: Invalid UTF8 string\n");
644497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			break;
644597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    }
644697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (ch & 0x80) /* must have had error encountered */
644797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
644897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    }
6449e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	}
64503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6451e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
6452e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferFree(target);
6453e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(str);
6454e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(from);
6455e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(to);
64563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6459fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathBooleanFunction:
6460fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
6461fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @nargs:  the number of arguments
6462fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
6463fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Implement the boolean() XPath function
6464fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    boolean boolean(object)
6465fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * he boolean function converts its argument to a boolean as follows:
6466fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a number is true if and only if it is neither positive or
6467fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *      negative zero nor NaN
6468fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a node-set is true if and only if it is non-empty
6469fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a string is true if and only if its length is non-zero
6470fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
6471fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardvoid
6472fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6473fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlXPathObjectPtr cur;
6474fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
6475fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    CHECK_ARITY(1);
6476fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = valuePop(ctxt);
6477fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
6478fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertBoolean(cur);
6479fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
64803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
64833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNotFunction:
64843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
64853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
64863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
64873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the not() XPath function
64883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean not(boolean)
64893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The not function returns true if its argument is false,
64903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and false otherwise.
64913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
64923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
64933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
64943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
64953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_BOOLEAN;
64963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_BOOLEAN);
64973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->boolval = ! ctxt->value->boolval;
64983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTrueFunction:
65023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the true() XPath function
65063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean true()
65073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65093473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
65113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(1));
65123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFalseFunction:
65163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the false() XPath function
65203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean false()
65213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
65253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(0));
65263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLangFunction:
65303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the lang() XPath function
65343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean lang(string)
65353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lang function returns true or false depending on whether the
65363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * language of the context node as specified by xml:lang attributes
65373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is the same as or is a sublanguage of the language specified by
65383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument string. The language of the context node is determined
65393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the value of the xml:lang attribute on the context node, or, if
65403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node has no xml:lang attribute, by the value of the
65413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xml:lang attribute on the nearest ancestor of the context node that
65423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * has an xml:lang attribute. If there is no such attribute, then lang
65433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns false. If there is such an attribute, then lang returns
65443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * true if the attribute value is equal to the argument ignoring case,
65453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or if there is some suffix starting with - such that the attribute
65463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value is equal to the argument ignoring that suffix of the attribute
65473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value and ignoring case.
65483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr val;
65523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *theLang;
65533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *lang;
65543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
65553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
65563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
65583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
65593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
65603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    val = valuePop(ctxt);
65613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    lang = val->stringval;
65623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    theLang = xmlNodeGetLang(ctxt->context->node);
65633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((theLang != NULL) && (lang != NULL)) {
65643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        for (i = 0;lang[i] != 0;i++)
65653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (toupper(lang[i]) != toupper(theLang[i]))
65663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        goto not_equal;
65673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret = 1;
65683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylornot_equal:
65703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(val);
65713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(ret));
65723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNumberFunction:
65763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the number() XPath function
65803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number number(object?)
65813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
65853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double res;
65863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
65883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
65893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0.0));
65903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
65913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
65923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res = xmlXPathStringEvalNumber(content);
65943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(res));
65953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
65963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
65973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
65983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
66013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
6602fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertNumber(cur);
6603fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
66043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSumFunction:
66083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the sum() XPath function
66123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number sum(node-set)
66133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The sum function returns the sum of the values of the nodes in
66143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument node-set.
66153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66173473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
66193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
6620ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double res = 0.0;
66213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
66233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
66243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
66253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
66263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
66273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
66283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6629d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
66303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewFloat(0.0));
66313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
6632ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
6633ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
66343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
6635ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat(res));
66363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
66383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFloorFunction:
66423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the floor() XPath function
66463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number floor(number)
66473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The floor function returns the largest (closest to positive infinity)
66483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not greater than the argument and that is an integer.
66493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66513473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
665256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    double f;
665356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
66543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
66553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
66563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
665756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
665856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    f = (double)((int) ctxt->value->floatval);
665956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
666056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
666156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
666256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
666356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
666456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
66653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCeilingFunction:
66693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the ceiling() XPath function
66733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number ceiling(number)
66743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The ceiling function returns the smallest (closest to negative infinity)
66753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not less than the argument and that is an integer.
66763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
66803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
66823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
66833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
66843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if 0
66863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->floatval = ceil(ctxt->value->floatval);
66873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
66883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    f = (double)((int) ctxt->value->floatval);
668956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
669056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
669156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
66925fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else {
66935fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    if (ctxt->value->floatval < 0 && f == 0)
66945fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = xmlXPathNZERO;
66955fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    else
66965fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = f;
66975fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	}
66985fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
669956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
67003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
67013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
67023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
67043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRoundFunction:
67053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
67063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
67073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
67083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the round() XPath function
67093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number round(number)
67103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The round function returns the number that is closest to the
67113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument and that is an integer. If there are two such numbers,
67123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the one that is even is returned.
67133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
67143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
67153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
67163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
67173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
67193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
67203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
67213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6722cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
6723cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == 1) ||
6724cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == -1) ||
67253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->value->floatval == 0.0))
67263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
67273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    f = (double)((int) ctxt->value->floatval);
672956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (ctxt->value->floatval < 0) {
673056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f - 0.5)
673156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
673256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
673356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
67345fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
67355fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
673656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    } else {
673756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f + 0.5)
673856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
673956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
674056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
674156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
67423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
67433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
67453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
67463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			The Parser					*
67473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
67483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
67493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
67513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a couple of forward declarations since we use a recursive call based
67523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation.
67533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
6754afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
6755d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardstatic void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
6756afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
67573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef VMS
6758afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompRelLocationPath(xmlXPathParserContextPtr ctxt);
6759afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard#define xmlXPathCompRelativeLocationPath xmlXPathCompRelLocationPath
67603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
6761afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
67623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
67632156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillardstatic xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
67642156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	                                  int qualified);
67653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
676761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * xmlXPathCurrentChar:
676861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @ctxt:  the XPath parser context
676961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @cur:  pointer to the beginning of the char
677061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @len:  pointer to the length of the char read
677161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
6772cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * The current char value, if using UTF-8 this may actually span multiple
677361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * bytes in the input buffer.
677461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
677560087f30f3b4cf21de48f39181736e7d71e7a661Daniel Veillard * Returns the current char value and its length
677661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard */
677761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
677861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic int
677961d80a2822b2678dee885ac2850295cc96277c63Daniel VeillardxmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
678061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned char c;
678161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned int val;
678261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *cur;
678361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
678461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (ctxt == NULL)
678561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(0);
678661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    cur = ctxt->cur;
678761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
678861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
678961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * We are supposed to handle UTF8, check it's valid
679061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * From rfc2044: encoding of the Unicode values on UTF-8:
679161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
679261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
679361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0000-0000 007F   0xxxxxxx
679461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
679561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
679661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
679761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Check for the 0x110000 limit too
679861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
679961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = *cur;
680061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (c & 0x80) {
680161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((cur[1] & 0xc0) != 0x80)
680261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    goto encoding_error;
680361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((c & 0xe0) == 0xe0) {
680461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
680561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((cur[2] & 0xc0) != 0x80)
680661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		goto encoding_error;
680761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((c & 0xf0) == 0xf0) {
680861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (((c & 0xf8) != 0xf0) ||
680961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    ((cur[3] & 0xc0) != 0x80))
681061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    goto encoding_error;
681161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		/* 4-byte code */
681261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 4;
681361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0x7) << 18;
681461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 12;
681561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[2] & 0x3f) << 6;
681661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[3] & 0x3f;
681761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    } else {
681861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	      /* 3-byte code */
681961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 3;
682061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0xf) << 12;
682161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 6;
682261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[2] & 0x3f;
682361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
682461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	} else {
682561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	  /* 2-byte code */
682661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    *len = 2;
682761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val = (cur[0] & 0x1f) << 6;
682861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val |= cur[1] & 0x3f;
682961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
683061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (!IS_CHAR(val)) {
683161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
683261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
683361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(val);
683461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    } else {
683561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	/* 1-byte code */
683661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	*len = 1;
683761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return((int) *cur);
683861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
683961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardencoding_error:
684061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
684161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * If we detect an UTF8 error that probably mean that the
684261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * input encoding didn't get properly advertized in the
684361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * declaration header. Report the error and switch the encoding
684461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * to ISO-Latin-1 (if you don't like this policy, just declare the
684561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * encoding !)
684661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
684742596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    *len = 0;
684861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    XP_ERROR0(XPATH_ENCODING_ERROR);
684961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
685061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
685161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard/**
68523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseNCName:
68533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML namespace non qualified name.
68563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
68583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
68603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                       CombiningChar | Extender
68613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
68633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
68663473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
68672156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    const xmlChar *in;
68682156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    xmlChar *ret;
68692156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    int count = 0;
68703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68712156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    /*
68722156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     * Accelerator for simple ASCII names
68732156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     */
68742156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    in = ctxt->cur;
68752156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
68762156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
68772156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	(*in == '_')) {
68782156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	in++;
68792156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
68802156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
68812156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
68829a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '_') || (*in == '.') ||
68839a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '-'))
68842156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    in++;
68852156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if ((*in == ' ') || (*in == '>') || (*in == '/') ||
68862156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '[') || (*in == ']') || (*in == ':') ||
68872156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '@') || (*in == '*')) {
68882156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    count = in - ctxt->cur;
68892156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (count == 0)
68902156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		return(NULL);
68912156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
68922156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ctxt->cur = in;
68932156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    return(ret);
68942156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	}
68952156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    }
68962156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 0));
68973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68992156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard
69003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseQName:
69023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  a xmlChar **
69043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML qualified name
69063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 5] QName ::= (Prefix ':')? LocalPart
69083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 6] Prefix ::= NCName
69103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 7] LocalPart ::= NCName
69123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the function returns the local part, and prefix is updated
69143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   to get the Prefix if any.
69153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
691756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
69183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
69193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
69203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
69223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = xmlXPathParseNCName(ctxt);
69233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == ':') {
69243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        *prefix = ret;
69253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
69263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlXPathParseNCName(ctxt);
69273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
69293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseName:
69333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML name
69363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
69383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
69393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
69413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
69433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69453473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
69463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseName(xmlXPathParserContextPtr ctxt) {
694761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *in;
694861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar *ret;
694961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int count = 0;
69503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
695161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
695261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Accelerator for simple ASCII names
695361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
695461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    in = ctxt->cur;
695561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
695661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
695761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(*in == '_') || (*in == ':')) {
695861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	in++;
695961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
696061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
696161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
696276d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == '_') || (*in == '-') ||
696376d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == ':') || (*in == '.'))
696461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    in++;
696576d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	if ((*in > 0) && (*in < 0x80)) {
696661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    count = in - ctxt->cur;
696761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
696861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ctxt->cur = in;
696961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(ret);
697061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
697161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
69722156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 1));
697361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
69743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
697561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic xmlChar *
69762156a56bcbf5d83fb3d694123be01beebf84d273Daniel VeillardxmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
697761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar buf[XML_MAX_NAMELEN + 5];
697861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int len = 0, l;
697961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int c;
69803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
698161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
698261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Handler for more complex cases
698361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
698461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = CUR_CHAR(l);
698561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
69862156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '[') || (c == ']') || (c == '@') || /* accelerators */
69872156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '*') || /* accelerators */
698861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
69892156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard         ((qualified) && (c != ':')))) {
699061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(NULL);
699161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
69923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
699361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
699461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
699561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard            (c == '.') || (c == '-') ||
69962156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    (c == '_') || ((qualified) && (c == ':')) ||
699761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_COMBINING(c)) ||
699861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_EXTENDER(c)))) {
699961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	COPY_BUF(l,buf,len,c);
700061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	NEXTL(l);
700161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	c = CUR_CHAR(l);
700261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (len >= XML_MAX_NAMELEN) {
700361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    /*
700461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * Okay someone managed to make a huge name, so he's ready to pay
700561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * for the processing speed.
700661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     */
700761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    xmlChar *buffer;
700861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    int max = len * 2;
700961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
701061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
701161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if (buffer == NULL) {
701261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		XP_ERROR0(XPATH_MEMORY_ERROR);
701361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
701461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    memcpy(buffer, buf, len);
701561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
701661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (c == '.') || (c == '-') ||
70172156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		   (c == '_') || ((qualified) && (c == ':')) ||
701861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_COMBINING(c)) ||
701961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_EXTENDER(c))) {
702061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (len + 10 > max) {
702161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    max *= 2;
702261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    buffer = (xmlChar *) xmlRealloc(buffer,
702361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			                            max * sizeof(xmlChar));
702461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    if (buffer == NULL) {
702561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			XP_ERROR0(XPATH_MEMORY_ERROR);
702661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    }
702761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		}
702861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		COPY_BUF(l,buffer,len,c);
702961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		NEXTL(l);
703061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		c = CUR_CHAR(l);
703161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
703261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    buffer[len] = 0;
703361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(buffer);
703461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
703561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
70362156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (len == 0)
70372156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	return(NULL);
703861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    return(xmlStrndup(buf, len));
703961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
70403cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
70413cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard#define MAX_FRAC 20
70423cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
70433cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillardstatic double my_pow10[MAX_FRAC] = {
70443cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1.0, 10.0, 100.0, 1000.0, 10000.0,
70453cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
70463cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
70473cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000000000000.0,
70483cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
70493cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000000.0, 10000000000000000000.0
70503cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard};
70513cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
70523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringEvalNumber:
70543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  A string to scan
70553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
705670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *  [30a]  Float  ::= Number ('e' Digits?)?
705770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *
70583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
70593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
70603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
70613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7062afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number in the string
70633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * In complement of the Number expression, this function also handles
70643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * negative values : '-' Number.
70653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the double value.
70673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble
70693473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringEvalNumber(const xmlChar *str) {
70703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur = str;
70717b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double ret;
7072b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    int ok = 0;
70733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int isneg = 0;
707470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
707570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
7076b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7077b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    unsigned long tmp = 0;
70787b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
7079b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7080eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (cur == NULL) return(0);
70813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*cur)) cur++;
70823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
70833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(xmlXPathNAN);
70843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
70853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '-') {
70863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	isneg = 1;
70873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
70883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7089b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard
7090b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7091d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
70927b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
70937b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7094d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
70957b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
70963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur >= '0') && (*cur <= '9')) {
70977b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
70987b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (*cur - '0');
70993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ok = 1;
71003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
71017b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
71027b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
71033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7104b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#else
71057b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
7106b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    while ((*cur >= '0') && (*cur <= '9')) {
7107b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ret = ret * 10 + (*cur - '0');
7108b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ok = 1;
7109b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	cur++;
7110b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    }
7111b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7112d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard
71133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '.') {
71143cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	int v, frac = 0;
71153cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	double fraction = 0;
71163cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
71173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur++;
71183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (((*cur < '0') || (*cur > '9')) && (!ok)) {
71193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathNAN);
71203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
71213cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
71223cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    v = (*cur - '0');
71233cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    fraction = fraction * 10 + v;
71243cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    frac = frac + 1;
71253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
71263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
71273cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	fraction /= my_pow10[frac];
71283cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	ret = ret + fraction;
71293cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while ((*cur >= '0') && (*cur <= '9'))
71303cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    cur++;
71313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
713270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((*cur == 'e') || (*cur == 'E')) {
713370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      cur++;
713470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      if (*cur == '-') {
713570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	is_exponent_negative = 1;
713670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
713770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
713870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      while ((*cur >= '0') && (*cur <= '9')) {
713970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	exponent = exponent * 10 + (*cur - '0');
714070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
714170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
714270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
71433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*cur)) cur++;
71443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur != 0) return(xmlXPathNAN);
71453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (isneg) ret = -ret;
714670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if (is_exponent_negative) exponent = -exponent;
714770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    ret *= pow(10.0, (double)exponent);
71483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
71493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7152afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNumber:
71533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
71563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
71573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
71583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7159afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number, then push it on the stack
71603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7162afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7163d79bcd1b36412a7996ace1900ab613e38a609b60Daniel VeillardxmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
7164d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard{
71653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double ret = 0.0;
71663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double mult = 1;
71677b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    int ok = 0;
716870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
716970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
71707b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
71717b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    unsigned long tmp = 0;
71727b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
71737b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
71743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
71763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
71773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        XP_ERROR(XPATH_NUMBER_ERROR);
71783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71797b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
7180d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
71817b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
71827b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7183d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
71847b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
71853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR >= '0') && (CUR <= '9')) {
71867b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
71877b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (CUR - '0');
7188d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ok = 1;
7189d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
71907b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
71917b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
71923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71937b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#else
71947b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
71957b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
71967b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10 + (CUR - '0');
71977b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ok = 1;
71987b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	NEXT;
71997b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    }
72007b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
72013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '.') {
72023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
7203d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (((CUR < '0') || (CUR > '9')) && (!ok)) {
7204d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            XP_ERROR(XPATH_NUMBER_ERROR);
7205d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7206d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7207d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            mult /= 10;
7208d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            ret = ret + (CUR - '0') * mult;
7209d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7210d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
72113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
721270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((CUR == 'e') || (CUR == 'E')) {
7213d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
7214d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (CUR == '-') {
7215d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            is_exponent_negative = 1;
7216d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7217d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7218d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7219d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = exponent * 10 + (CUR - '0');
7220d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7221d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7222d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (is_exponent_negative)
7223d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = -exponent;
7224d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ret *= pow(10.0, (double) exponent);
722570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
72269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
7227d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard                   xmlXPathNewFloat(ret), NULL);
72283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7231fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathParseLiteral:
7232fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
7233fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7234fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Parse a Literal
7235fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7236fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *  [29]   Literal ::=   '"' [^"]* '"'
7237fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *                    | "'" [^']* "'"
7238fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7239fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Returns the value found or NULL in case of error
7240fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
7241fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic xmlChar *
7242fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
7243fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    const xmlChar *q;
7244fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlChar *ret = NULL;
7245fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7246fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (CUR == '"') {
7247fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7248fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
7249fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	while ((IS_CHAR(CUR)) && (CUR != '"'))
7250fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7251fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (!IS_CHAR(CUR)) {
7252fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7253fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7254fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7255fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7256fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7257fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else if (CUR == '\'') {
7258fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7259fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
7260fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	while ((IS_CHAR(CUR)) && (CUR != '\''))
7261fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7262fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (!IS_CHAR(CUR)) {
7263fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7264fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7265fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7266fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7267fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7268fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else {
7269fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	XP_ERROR0(XPATH_START_LITERAL_ERROR);
7270fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
7271fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(ret);
7272fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
7273fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7274fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
7275afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLiteral:
72763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a Literal and push it on the stack.
72793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [29]   Literal ::=   '"' [^"]* '"'
72813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | "'" [^']* "'"
72823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7283afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * TODO: xmlXPathCompLiteral memory allocation could be improved.
72843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7285afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7286afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
72873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *q;
72883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
72893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '"') {
72913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
72923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
72933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((IS_CHAR(CUR)) && (CUR != '"'))
72943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
72953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!IS_CHAR(CUR)) {
72963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
72973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
72983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
72993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
73003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
73013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '\'') {
73023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
73033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
73043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while ((IS_CHAR(CUR)) && (CUR != '\''))
73053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
73063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!IS_CHAR(CUR)) {
73073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
73083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
73093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
73103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
73113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
73123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
73133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_START_LITERAL_ERROR);
73143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
73153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) return;
73169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
73179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           xmlXPathNewString(ret), NULL);
73183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ret);
73193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7322afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompVariableReference:
73233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a VariableReference, evaluate it and push it on the stack.
73263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings consist of a mapping from variable names
73283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to variable values. The value of a variable is an object, which
73293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of any of the types that are possible for the value of an expression,
73303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and may also be of additional types not specified here.
73313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Early evaluation is possible since:
73333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings [...] used to evaluate a subexpression are
73343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * always the same as those used to evaluate the containing expression.
73353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [36]   VariableReference ::=   '$' QName
73373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7338afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7339afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
73403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
73413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
73423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
73443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '$') {
73453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
73463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
73473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
73483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
73493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
73503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
73513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7352fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ctxt->comp->last = -1;
73539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
73549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
73553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
73563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsNodeType:
73603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a name string
73623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Is the name given a NodeType one.
73643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [38]   NodeType ::=   'comment'
73663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'text'
73673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'processing-instruction'
73683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'node'
73693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 1 if true 0 otherwise
73713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
73723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
73733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsNodeType(const xmlChar *name) {
73743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
73753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
73763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73771971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "node"))
73783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
73793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(name, BAD_CAST "text"))
73803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
73811971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "comment"))
73823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
73831971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
73843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
73853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
73863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7389afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFunctionCall:
73903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [16]   FunctionCall ::=   FunctionName '(' ( Argument ( ',' Argument)*)? ')'
73933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [17]   Argument ::=   Expr
73943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7395afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a function call, the evaluation of all arguments are
73963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * pushed on the stack
73973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7398afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7399afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
74003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
74013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
74023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int nbargs = 0;
74033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
74053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
74063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
74073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
74093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
74103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
74113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
74123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			name);
74133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
74143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
74153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			prefix, name);
74163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
74173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '(') {
74193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
74203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
74223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
74233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
74253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR != ')') {
74269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
74279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->comp->last = -1;
7428afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompileExpr(ctxt);
742950fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	CHECK_ERROR;
74309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
74313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nbargs++;
74323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR == ')') break;
74333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ',') {
74343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
74353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
74373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
74383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
74409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
74413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
74423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
74433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7446afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPrimaryExpr:
74473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [15]   PrimaryExpr ::=   VariableReference
74503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | '(' Expr ')'
74513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Literal
74523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Number
74533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | FunctionCall
74543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7455afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a primary expression.
74563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7457afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7458afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
74593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
7460afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (CUR == '$') xmlXPathCompVariableReference(ctxt);
74613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (CUR == '(') {
74623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
74633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7464afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompileExpr(ctxt);
746550fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	CHECK_ERROR;
74663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
74673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
74683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
74703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
747101917aa1cb20fb33e6fa2b1e0ca2125051e491e0Daniel Veillard    } else if (IS_DIGIT(CUR) || (CUR == '.' && IS_DIGIT(NXT(1)))) {
7472afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompNumber(ctxt);
74733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if ((CUR == '\'') || (CUR == '"')) {
7474afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLiteral(ctxt);
74753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
7476afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFunctionCall(ctxt);
74773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
74793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7482afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFilterExpr:
74833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [20]   FilterExpr ::=   PrimaryExpr
74863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr Predicate
74873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7488afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a filter expression.
74893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Square brackets are used to filter expressions in the same way that
74903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * they are used in location paths. It is an error if the expression to
74913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be filtered does not evaluate to a node-set. The context node list
74923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used for evaluating the expression in square brackets is the node-set
74933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be filtered listed in document order.
74943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7496afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7497afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
7498afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPrimaryExpr(ctxt);
74993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
75003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
75013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '[') {
7503d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlXPathCompPredicate(ctxt, 1);
75043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
75053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
75063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
75113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathScanName:
75123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Trickery: parse an XML name but without consuming the input flow
75153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Needed to avoid insanity in the parser state.
75163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
75183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
75193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
75213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] Names ::= Name (S Name)*
75233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the Name parsed or NULL
75253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
752756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
75283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathScanName(xmlXPathParserContextPtr ctxt) {
75293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar buf[XML_MAX_NAMELEN];
75303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int len = 0;
75313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
75333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!IS_LETTER(CUR) && (CUR != '_') &&
75343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (CUR != ':')) {
75353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
75363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
75373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
75393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (NXT(len) == '.') || (NXT(len) == '-') ||
75403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (NXT(len) == '_') || (NXT(len) == ':') ||
75413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (IS_COMBINING(NXT(len))) ||
75423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (IS_EXTENDER(NXT(len)))) {
75433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	buf[len] = NXT(len);
75443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len++;
75453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (len >= XML_MAX_NAMELEN) {
75463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
75473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       "xmlScanName: reached XML_MAX_NAMELEN limit\n");
75483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
75493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (NXT(len) == '.') || (NXT(len) == '-') ||
75503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (NXT(len) == '_') || (NXT(len) == ':') ||
75513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (IS_COMBINING(NXT(len))) ||
75523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (IS_EXTENDER(NXT(len))))
75533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		 len++;
75543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
75553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
75563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
75573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlStrndup(buf, len));
75583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7561afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPathExpr:
75623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [19]   PathExpr ::=   LocationPath
75653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr
75663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '/' RelativeLocationPath
75673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '//' RelativeLocationPath
75683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7569afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a path expression.
75703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator and // operators combine an arbitrary expression
75713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a relative location path. It is an error if the expression
75723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * does not evaluate to a node-set.
75733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator does composition in the same way as when / is
75743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used in a location path. As in location paths, // is short for
75753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * /descendant-or-self::node()/.
75763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7578afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7579afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
75803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int lc = 1;           /* Should we branch to LocationPath ?         */
75813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name = NULL; /* we may have to preparse a name to find out */
75823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
75843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '$') || (CUR == '(') || (IS_DIGIT(CUR)) ||
758501917aa1cb20fb33e6fa2b1e0ca2125051e491e0Daniel Veillard        (CUR == '\'') || (CUR == '"') || (CUR == '.' && IS_DIGIT(NXT(1)))) {
75863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 0;
75873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '*') {
75883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
75893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
75903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
75913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
75923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
75933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '@') {
75943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
75953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
75963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
75973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
75983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
75993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
76003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
76013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Problem is finding if we have a name here whether it's:
76023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a nodetype
76033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a function call in which case it's followed by '('
76043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - an axis in which case it's followed by ':'
76053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a element name
76063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * We do an a priori analysis here rather than having to
76073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * maintain parsed token content through the recursive function
76083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * calls. This looks uglier but makes the code quite easier to
76093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * read/write/debug.
76103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
76113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
76123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathScanName(ctxt);
76133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
76143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
76163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "PathExpr: Axis\n");
76173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    lc = 1;
76193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
76203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (name != NULL) {
76213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int len =xmlStrlen(name);
76223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int blank = 0;
76233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (NXT(len) != 0) {
76263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (NXT(len) == '/') {
76273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
76283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
76303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
76313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
76333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
76343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (IS_BLANK(NXT(len))) {
76353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* skip to next */
76363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    blank = 1;
76373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (NXT(len) == ':') {
76383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
76403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
76413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
76433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
76443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '(')) {
76453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* Note Type or Function */
76463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (xmlXPathIsNodeType(name)) {
76473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
76493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: Type search\n");
76503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 1;
76523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    } else {
76533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
76553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: function call\n");
76563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 0;
76583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    }
76593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    break;
76603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '[')) {
76613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
76623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
76643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
76653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
76673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
76683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
76693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   (NXT(len) == '=')) {
76703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
76713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
76723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
76733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
76743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
76753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
76763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		len++;
76773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
76783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (NXT(len) == 0) {
76793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
76803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
76813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			"PathExpr: AbbrRelLocation\n");
76823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
76833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		/* element name */
76843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		lc = 1;
76853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
76863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
76873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
76883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* make sure all cases are covered explicitely */
76893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
76903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
76913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
76923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (lc) {
76949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (CUR == '/') {
76959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
76969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	} else {
76979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
76983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
7699afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLocationPath(ctxt);
77003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
7701afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFilterExpr(ctxt);
77023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
77033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
77043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
77053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
77069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
77079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
77089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
77099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
77109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
7711afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
77123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
7713afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
77143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
77153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7720afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnionExpr:
77213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [18]   UnionExpr ::=   PathExpr
77243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | UnionExpr '|' PathExpr
77253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7726afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an union expression.
77273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
77283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7729afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7730afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
7731afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPathExpr(ctxt);
77323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
77333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '|') {
77359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
77369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
77373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
77393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7740afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompPathExpr(ctxt);
77413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
77439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
77443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
77453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7749afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnaryExpr:
77503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [27]   UnaryExpr ::=   UnionExpr
77533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | '-' UnaryExpr
77543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7755afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an unary expression.
77563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
77573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7758afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7759afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
77603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int minus = 0;
77619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int found = 0;
77623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
776468d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard    while (CUR == '-') {
776568d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard        minus = 1 - minus;
77669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	found = 1;
77673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
77683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
77693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
7771afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnionExpr(ctxt);
77723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
77739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (found) {
77749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (minus)
77759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
77769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	else
77779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
77783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7782afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompMultiplicativeExpr:
77833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [26]   MultiplicativeExpr ::=   UnaryExpr
77863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr MultiplyOperator UnaryExpr
77873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'div' UnaryExpr
77883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'mod' UnaryExpr
77893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [34]   MultiplyOperator ::=   '*'
77903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7791afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
77923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
77933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7794afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7795afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
7796afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnaryExpr(ctxt);
77973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
77983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '*') ||
78003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
78013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
78023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int op = -1;
78039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
78043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '*') {
78063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 0;
78073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
78083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'd') {
78093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 1;
78103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
78113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'm') {
78123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 2;
78133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
78143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
78153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7816afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompUnaryExpr(ctxt);
78173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
78189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
78193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
78203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7824afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAdditiveExpr:
78253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [25]   AdditiveExpr ::=   MultiplicativeExpr
78283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '+' MultiplicativeExpr
78293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '-' MultiplicativeExpr
78303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7831afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
78323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7834afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7835afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
78369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
7837afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompMultiplicativeExpr(ctxt);
78383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
78393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
78403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '+') || (CUR == '-')) {
78413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int plus;
78429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
78433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '+') plus = 1;
78453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else plus = 0;
78463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
78473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7848afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompMultiplicativeExpr(ctxt);
78493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
78509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
78513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
78523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7856afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelationalExpr:
78573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [24]   RelationalExpr ::=   AdditiveExpr
78603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<' AdditiveExpr
78613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>' AdditiveExpr
78623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<=' AdditiveExpr
78633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>=' AdditiveExpr
78643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A <= B > C is allowed ? Answer from James, yes with
78663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
78673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
78683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7869afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Relational expression, then push the result
78703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the stack
78713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7873afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7874afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
7875afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAdditiveExpr(ctxt);
78763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
78773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
78783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '<') ||
78793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (CUR == '>') ||
78803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '<') && (NXT(1) == '=')) ||
78813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '>') && (NXT(1) == '='))) {
78829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int inf, strict;
78839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
78843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '<') inf = 1;
78863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else inf = 0;
78873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (NXT(1) == '=') strict = 0;
78883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else strict = 1;
78893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
78903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!strict) NEXT;
78913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7892afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAdditiveExpr(ctxt);
78933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
78949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
78953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
78963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7900afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompEqualityExpr:
79013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
79023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [23]   EqualityExpr ::=   RelationalExpr
79043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '=' RelationalExpr
79053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '!=' RelationalExpr
79063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A != B != C is allowed ? Answer from James, yes with
79083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr = RelationalExpr) = RelationalExpr
79093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr != RelationalExpr) != RelationalExpr
79103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
79113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7912afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Equality expression.
79133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7915afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7916afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
7917afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompRelationalExpr(ctxt);
79183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
79193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
79219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int eq;
79229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
79233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '=') eq = 1;
79253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else eq = 0;
79263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
79273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!eq) NEXT;
79283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7929afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelationalExpr(ctxt);
79303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
79319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
79323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
79333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
79353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7937afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAndExpr:
79383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
79393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [22]   AndExpr ::=   EqualityExpr
79413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | AndExpr 'and' EqualityExpr
79423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7943afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an AND expression.
79443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7946afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7947afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
7948afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompEqualityExpr(ctxt);
79493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
79503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
79529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
79533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(3);
79543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7955afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompEqualityExpr(ctxt);
79563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
79579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
79583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
79593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
79613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7963afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompExpr:
79643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
79653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [14]   Expr ::=   OrExpr
79673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [21]   OrExpr ::=   AndExpr
79683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | OrExpr 'or' AndExpr
79693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7970afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and compile an expression
79713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7972afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7973afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompileExpr(xmlXPathParserContextPtr ctxt) {
7974afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAndExpr(ctxt);
79753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
79763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'o') && (NXT(1) == 'r')) {
79789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
79793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(2);
79803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7981afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAndExpr(ctxt);
79823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
79839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
79849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	op1 = ctxt->comp->nbStep;
79853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
79863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE) {
79889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* more ops could be optimized too */
79899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
79909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
79913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
79923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7994afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPredicate:
79953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
7996d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @filter:  act as a filter
79973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [8]   Predicate ::=   '[' PredicateExpr ']'
79993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [9]   PredicateExpr ::=   Expr
80003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8001afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a predicate expression
80029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8003afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8004d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
80059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int op1 = ctxt->comp->last;
80069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
80089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != '[') {
80099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
80109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
80119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
80129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
80139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
8015afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
80169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_ERROR;
80179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != ']') {
80199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
80209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
80219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8022d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (filter)
8023d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
8024d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    else
8025d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
80269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
80289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
80299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
80309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8032afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNodeTest:
80333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @test:  pointer to a xmlXPathTestVal
80353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @type:  pointer to a xmlXPathTypeVal
80363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  placeholder for a possible name prefix
80373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [7] NodeTest ::=   NameTest
80393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NodeType '(' ')'
80403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | 'processing-instruction' '(' Literal ')'
80413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [37] NameTest ::=  '*'
80433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NCName ':' '*'
80443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | QName
80453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [38] NodeType ::= 'comment'
80463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'text'
80473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'processing-instruction'
80483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'node'
80493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the name found and update @test, @type and @prefix appropriately
80513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
805256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
8053afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
8054afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	             xmlXPathTypeVal *type, const xmlChar **prefix,
8055afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		     xmlChar *name) {
80563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int blanks;
80573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
80593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	STRANGE;
80603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
80613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *type = 0;
80633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *test = 0;
80643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
80653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((name == NULL) && (CUR == '*')) {
80683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
80693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * All elements
80703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
80713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_ALL;
80733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
80743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
80773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
80783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
80793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_EXPR_ERROR);
80803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blanks = IS_BLANK(CUR);
80833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '(') {
80853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
80873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * NodeType or PI search
80883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
80893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (xmlStrEqual(name, BAD_CAST "comment"))
80903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_COMMENT;
80913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "node"))
80923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_NODE;
80933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
80943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_PI;
80953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "text"))
80963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_TEXT;
80973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else {
80983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
80993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
81003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
81013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_TYPE;
81043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
81063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*type == NODE_TYPE_PI) {
81073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
81083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * Specific case: search a PI by name.
81093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
81103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
81113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
811282e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    name = NULL;
811382e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    if (CUR != ')') {
811482e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		name = xmlXPathParseLiteral(ctxt);
811582e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		CHECK_ERROR 0;
8116ed23b7dc73f6c1146701ece20ed3f03d68366516Daniel Veillard		*test = NODE_TEST_PI;
811782e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		SKIP_BLANKS;
811882e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    }
81193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
81213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
81223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
81233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNCLOSED_ERROR);
81243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
81263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(name);
81273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *test = NODE_TEST_NAME;
81293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((!blanks) && (CUR == ':')) {
81303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
81313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
8133fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * Since currently the parser context don't have a
8134fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * namespace list associated:
8135fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * The namespace name for this prefix can be computed
8136fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * only at evaluation time. The compilation is done
8137fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * outside of any context.
81383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
8139fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#if 0
81403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*prefix = xmlXPathNsLookup(ctxt->context, name);
81413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name != NULL)
81423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
81433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*prefix == NULL) {
81443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
81453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8146fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#else
8147fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	*prefix = name;
8148fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#endif
81493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR == '*') {
81513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
81523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * All elements
81533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
81543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
81553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *test = NODE_TEST_ALL;
81563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
81573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
81603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name == NULL) {
81613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
81623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(name);
81653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
81663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
81683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAxisName:
81693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a preparsed name token
81703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] AxisName ::=   'ancestor'
81723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'ancestor-or-self'
81733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'attribute'
81743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'child'
81753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant'
81763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant-or-self'
81773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following'
81783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following-sibling'
81793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'namespace'
81803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'parent'
81813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding'
81823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding-sibling'
81833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'self'
81843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the axis or 0
81863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
818756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathAxisVal
81883473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAxisName(const xmlChar *name) {
81893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathAxisVal ret = 0;
81903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (name[0]) {
81913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'a':
81923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor"))
81933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR;
81943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
81953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR_OR_SELF;
81963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "attribute"))
81973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ATTRIBUTE;
81983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
81993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'c':
82003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "child"))
82013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_CHILD;
82023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'd':
82043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant"))
82053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT;
82063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
82073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT_OR_SELF;
82083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'f':
82103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following"))
82113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING;
82123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following-sibling"))
82133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING_SIBLING;
82143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'n':
82163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "namespace"))
82173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_NAMESPACE;
82183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'p':
82203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "parent"))
82213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PARENT;
82223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding"))
82233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING;
82243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
82253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING_SIBLING;
82263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 's':
82283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "self"))
82293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_SELF;
82303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
82313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
82333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8236afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompStep:
82373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] Step ::=   AxisSpecifier NodeTest Predicate*
82403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedStep
82413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [12] AbbreviatedStep ::=   '.' | '..'
82433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] AxisSpecifier ::= AxisName '::'
82453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedAxisSpecifier
82463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [13] AbbreviatedAxisSpecifier ::= '@'?
82483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Modified for XPtr range support as:
82503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
82523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedStep
82533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | 'range-to' '(' Expr ')' Predicate*
82543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8255afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile one step in a Location Path
82563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A location step of . is short for self::node(). This is
82573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * particularly useful in conjunction with //. For example, the
82583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * location path .//para is short for
82593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * self::node()/descendant-or-self::node()/child::para
82603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select all para descendant elements of the context
82613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
82623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Similarly, a location step of .. is short for parent::node().
82633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * For example, ../title is short for parent::node()/child::title
82643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select the title children of the parent of the context
82653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
82663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8267afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8268afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
8269fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8270fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int rangeto = 0;
8271fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int op2 = -1;
8272fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8273fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard
82743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '.') && (NXT(1) == '.')) {
82763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
82773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
82789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
82799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
82803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
82813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
82823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
82833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
82843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlChar *name = NULL;
82853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	const xmlChar *prefix = NULL;
82863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTestVal test;
8287d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlXPathAxisVal axis = 0;
82883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTypeVal type;
8289d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	int op1;
82903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
82923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * The modification needed for XPointer change to the production
82933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
82943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
8295fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (ctxt->xptr) {
82963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    name = xmlXPathParseNCName(ctxt);
82973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
8298fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard                op2 = ctxt->comp->last;
82993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
83003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
83013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != '(') {
83023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
83033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
83043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
83053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
83063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8307afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompileExpr(ctxt);
8308fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		/* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
83093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		CHECK_ERROR;
83103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
83123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != ')') {
83133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
83143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
83153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
8316fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		rangeto = 1;
83173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		goto eval_predicates;
83183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
83193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
83203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
83212156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if (CUR == '*') {
83222156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    axis = AXIS_CHILD;
83232156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	} else {
83242156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name == NULL)
83252156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		name = xmlXPathParseNCName(ctxt);
83262156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name != NULL) {
83272156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = xmlXPathIsAxisName(name);
83282156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		if (axis != 0) {
83292156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    SKIP_BLANKS;
83302156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    if ((CUR == ':') && (NXT(1) == ':')) {
83312156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			SKIP(2);
83322156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			xmlFree(name);
83332156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			name = NULL;
83342156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    } else {
83352156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			/* an element name can conflict with an axis one :-\ */
83362156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			axis = AXIS_CHILD;
83372156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    }
83383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
83393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    axis = AXIS_CHILD;
83403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
83412156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    } else if (CUR == '@') {
83422156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		NEXT;
83432156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_ATTRIBUTE;
83443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
83452156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_CHILD;
83463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
83473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
83483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
83503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8351afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
83523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (test == 0)
83533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
83543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
83563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
83573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Basis : computing new set\n");
83583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
83599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
83613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Basis : ");
8362fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (ctxt->value == NULL)
8363fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "no value\n");
8364fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else if (ctxt->value->nodesetval == NULL)
8365fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
8366fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else
8367fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
83683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
83693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83703473f88a7abdf4e585e267288fb77e898c580d2bOwen Tayloreval_predicates:
8371d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	op1 = ctxt->comp->last;
8372d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	ctxt->comp->last = -1;
8373d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
83743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '[') {
8376d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    xmlXPathCompPredicate(ctxt, 0);
83773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8378d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8379fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8380fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (rangeto) {
8381fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
8382fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	} else
8383fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8384fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
8385fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard			   test, type, (void *)prefix, (void *)name);
8386d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
83873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
83893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "Step : ");
8390fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    if (ctxt->value == NULL)
8391fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "no value\n");
8392fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else if (ctxt->value->nodesetval == NULL)
8393fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "Empty\n");
8394fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else
8395fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
8396fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		ctxt->value->nodesetval);
83973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
83983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8401afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelativeLocationPath:
84023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
84033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [3]   RelativeLocationPath ::=   Step
84053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | RelativeLocationPath '/' Step
84063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedRelativeLocationPath
84073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [11]  AbbreviatedRelativeLocationPath ::=   RelativeLocationPath '//' Step
84083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8409afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a relative location path.
84103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8411afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
84123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef VMS
8413afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelLocationPath
84143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
8415afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelativeLocationPath
84163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
84173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor(xmlXPathParserContextPtr ctxt) {
84183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '/') && (NXT(1) == '/')) {
84203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
84213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
84239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		         NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
84243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
84253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
84263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8428afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompStep(ctxt);
84293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '/') {
84313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
84323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
84333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
84349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
84353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
8436afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
84373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
84383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
84393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
8440afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
84413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8447afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLocationPath:
84483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
84493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [1]   LocationPath ::=   RelativeLocationPath
84513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbsoluteLocationPath
84523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [2]   AbsoluteLocationPath ::=   '/' RelativeLocationPath?
84533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedAbsoluteLocationPath
84543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [10]   AbbreviatedAbsoluteLocationPath ::=
84553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                           '//' RelativeLocationPath
84563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8457afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a location path
8458afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
84593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * // is short for /descendant-or-self::node()/. For example,
84603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * //para is short for /descendant-or-self::node()/child::para and
84613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * so will select any para element in the document (even a para element
84623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * that is a document element will be selected by //para since the
84633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document element node is a child of the root node); div//para is
84643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * short for div/descendant-or-self::node()/child::para and so will
84653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * select all para descendants of div children.
84663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8467afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8468afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
84693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '/') {
8471afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelativeLocationPath(ctxt);
84723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
84733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '/') {
84743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((CUR == '/') && (NXT(1) == '/')) {
84753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP(2);
84763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
84779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
84789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
8479afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompRelativeLocationPath(ctxt);
84803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else if (CUR == '/') {
84813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
8482608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		SKIP_BLANKS;
8483608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		if ((CUR != 0 ) &&
8484608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		    ((IS_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
8485608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		     (CUR == '@') || (CUR == '*')))
8486afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		    xmlXPathCompRelativeLocationPath(ctxt);
84873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
84883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
84939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
84949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 		XPath precompiled expression evaluation			*
84959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
84969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
84979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
8499d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
8500d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
85019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8502d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathNodeCollectAndTest:
8503d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
8504d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  the XPath precompiled step operation
8505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
8506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
85079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
8508d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * This is the function implementing a step: based on the current list
8509d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
8510d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * axis and selecting them it also do the predicate filtering
8511d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
8512d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Pushes the new NodeSet resulting from the search.
8513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
8514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
85159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
8517d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
8518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                           xmlXPathStepOpPtr op,
8519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard			   xmlNodePtr * first, xmlNodePtr * last)
8520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
8521d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathAxisVal axis = op->value;
8522d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTestVal test = op->value2;
8523d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTypeVal type = op->value3;
8524d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *prefix = op->value4;
8525d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *name = op->value5;
8526e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    const xmlChar *URI = NULL;
85279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8528d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0;
8530d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i, t = 0;
8532d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr ret, list;
8533d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTraversalFunction next = NULL;
8534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
853575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    xmlNodeSetPtr (*mergeNodeSet) (xmlNodeSetPtr, xmlNodeSetPtr);
8536d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr cur = NULL;
8537d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr obj;
8538d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr nodelist;
8539d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr tmp;
8540d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
8542d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    obj = valuePop(ctxt);
8543d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAdd;
854475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    mergeNodeSet = xmlXPathNodeSetMerge;
8545e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (prefix != NULL) {
8546f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
8547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (URI == NULL)
8548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
8549e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    }
8550d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
8552d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8553d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (axis) {
8554d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR:
8555d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
8557d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
8560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8561d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
8562d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
8565d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
8568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8569d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ATTRIBUTE:
8570d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
8572d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
857675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8578d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_CHILD:
8579d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
8581d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
858475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8586d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT:
8587d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
8589d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8591f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
8592f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8593d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
8594d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8595f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8596f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
8597d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
8600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8601d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING:
8602d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8603f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
8604d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8605f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
8607f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8608d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
8609d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
8612d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8614f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
8615f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8616d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_NAMESPACE:
8617d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8618f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
8619d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
862375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8625d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PARENT:
8626d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8627f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
8628d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8629f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8630f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
8631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8632d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING:
8633d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8634f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
8635d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8636f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
8638f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8639d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING_SIBLING:
8640d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8641f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8642f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
8643d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
8646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8647d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_SELF:
8648d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
8650d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8652f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
865475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8656d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8657d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (next == NULL)
8658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
8659d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8660d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    nodelist = obj->nodesetval;
8661d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (nodelist == NULL) {
8662f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
8663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
8664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
8665d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8666d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
8667d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ret = NULL;
8668d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8669d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
8670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
8671d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (test) {
8672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
8673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
8675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
8677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
8679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8680f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
8681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
8683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
8685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
8687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
8689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
8691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
8692f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
8694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
8696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
8697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
8698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
8699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8700d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8701d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
8702d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8703d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    /*
8704d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * 2.3 Node Tests
8705d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
8706d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
8707d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For other axes, the principal node type is element.
8708d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *
8709d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * A node test * is true for any node of the
8710cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
8711d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * select all element children of the context node
8712d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     */
8713d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    tmp = ctxt->context->node;
8714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
8715d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
8716d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
8718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        list = xmlXPathNodeSetCreate(NULL);
8719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
8720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
8721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
8722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
8723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((first != NULL) && (*first == cur))
8724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
8725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
8726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
8727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
8728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
8729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
8730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
8731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
8732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(last != NULL) && (*last != NULL) &&
8733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
8734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
8735d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            t++;
8736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP
8737d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
8738d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
8740d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NONE:
8741f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
8742f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(t);
8743d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_TYPE:
8744f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
8745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
8746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
8747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
8748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
8749f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_NAMESPACE_DECL) ||
8750f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_ATTRIBUTE_NODE) ||
8751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
8752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
8753f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
87547583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
87557583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			((type == NODE_TYPE_TEXT) &&
87567583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
8757d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8758d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                        n++;
8759d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8760f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
8761f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
8762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
8763d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_PI:
8764f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
8765f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
8766f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
8767f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
8768d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8769f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
8770d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
8772f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
8773f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
8774d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_ALL:
8775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
8776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
8777d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
8779d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
8781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
8782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
8783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
8784d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
8786d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8787044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard                            xmlXPathNodeSetAddNs(list, ctxt->context->node,
8788044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				                 (xmlNsPtr) cur);
8789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
8790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
8791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
8792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
8793d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
8795d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
8797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
8798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
8799d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
8801d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
8803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
8804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
8805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
8806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
8807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
8808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
8809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
8810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
8811d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NAME:
8812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
8813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
8814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
8815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
8816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
8817d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
8819d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
8821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
8822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
8823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
8824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
8825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
8826d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
8828d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
8830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
8831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
8832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
8833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
8834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
8835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
8836f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
8838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
8839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
8840f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
8841d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8842f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
8843d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
8845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
8846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
8847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
8848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
8849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
8850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
8851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
8852d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
8854d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
8856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
8857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
8858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
8859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
8860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
8861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
8862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
8863f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
8864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
8865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
8867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
88688b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#ifdef DEBUG_STEP
8869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
88708b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#endif
8871044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				    xmlXPathNodeSetAddNs(list,
8872044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					ctxt->context->node, (xmlNsPtr) cur);
8873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
8874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
8875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
8876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
8877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
8878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
8879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
8880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
8881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
8882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (cur != NULL);
8883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        /*
8885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         * If there is some predicate filtering do it now
8886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         */
88876fbcf42aa301dca50737c65fb738752328ca3a4cDaniel Veillard        if ((op->ch2 != -1) && (list != NULL) && (list->nodeNr > 0)) {
8888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathObjectPtr obj2;
8889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathWrapNodeSet(list));
8891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch2]);
8892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
8893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2 = valuePop(ctxt);
8894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            list = obj2->nodesetval;
8895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2->nodesetval = NULL;
8896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(obj2);
8897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
8898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (ret == NULL) {
8899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = list;
8900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } else {
890175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard            ret = mergeNodeSet(ret, list);
8902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeNodeSet(list);
8903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
8904d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8905d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = tmp;
8906d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8907d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
8908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
8909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, n);
8910d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8911d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
89120ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
89130ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
89140ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
89150ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
89160ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
89170ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
89180ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
8919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
8920d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
8921d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8922d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
8923f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNodeCollectAndTestNth:
8924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
8925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  the XPath precompiled step operation
8926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @indx:  the index to collect
8927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
8928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
8929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
8930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is the function implementing a step: based on the current list
8931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
8932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * axis and selecting them it also do the predicate filtering
8933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
8934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Pushes the new NodeSet resulting from the search.
8935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
8936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
8937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
8938f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeCollectAndTestNth(xmlXPathParserContextPtr ctxt,
8939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlXPathStepOpPtr op, int indx,
8940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr * first, xmlNodePtr * last)
8941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
8942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathAxisVal axis = op->value;
8943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTestVal test = op->value2;
8944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTypeVal type = op->value3;
8945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *prefix = op->value4;
8946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *name = op->value5;
8947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *URI = NULL;
8948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0, t = 0;
8949f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i;
8951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr list;
8952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTraversalFunction next = NULL;
8953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
8954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr cur = NULL;
8955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr obj;
8956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr nodelist;
8957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp;
8958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
8959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
8960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    obj = valuePop(ctxt);
8961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAdd;
8962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (prefix != NULL) {
8963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
8964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (URI == NULL)
8965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
8966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
8967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
8968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
8969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (first != NULL) {
8970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*first != NULL)
8971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = %s ",
8972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*first)->name);
8973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
8974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = NULL ");
8975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
8976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (last != NULL) {
8977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*last != NULL)
8978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = %s ",
8979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*last)->name);
8980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
8981f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = NULL ");
8982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
8983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
8984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (axis) {
8985f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR:
8986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
8987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
8988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
8989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
8991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
8993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
8994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
8996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
8997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
8999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ATTRIBUTE:
9001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
9007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_CHILD:
9009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
9014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9015f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT:
9016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING:
9031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9038f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9039f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9042f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9045f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_NAMESPACE:
9046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9051f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
9052f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9053f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PARENT:
9054f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9057f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9058f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING:
9061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9062f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9072f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9073f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_SELF:
9076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9078f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
9082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (next == NULL)
9085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    nodelist = obj->nodesetval;
9088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (nodelist == NULL) {
9089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (test) {
9098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
9099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
9101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9102f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
9103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
9105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
9107f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
9109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
9111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    /*
9130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * 2.3 Node Tests
9131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For other axes, the principal node type is element.
9134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *
9135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * A node test * is true for any node of the
9136cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * select all element children of the context node
9138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     */
9139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = ctxt->context->node;
9140f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    list = xmlXPathNodeSetCreate(NULL);
9141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        n = 0;
9146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((first != NULL) && (*first == cur))
9151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9157f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (last != NULL) && (*last != NULL) &&
9160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            t++;
9163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NONE:
9165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
9166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(0);
9167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_TYPE:
9168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
9176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_TEXT_NODE)))) {
9177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9182f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_PI:
9183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_ALL:
9193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9203044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				xmlXPathNodeSetAddNs(list, ctxt->context->node,
9204044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard						     (xmlNsPtr) cur);
9205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NAME:
9226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9227f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9228f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9229f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9230f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9231f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9232f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9233f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9235f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9236f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9238f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9240f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9265f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9270f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9271f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9272f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9273f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9275f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
9276f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
9277f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (n == indx)
9278044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					xmlXPathNodeSetAddNs(list,
9279044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					   ctxt->context->node, (xmlNsPtr) cur);
9280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9281f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9284f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9286f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9287f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9289f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (n < indx);
9290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    ctxt->context->node = tmp;
9292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, list->nodeNr);
9296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(list));
92980ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
92990ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
93000ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
93010ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
93020ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
93030ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
93040ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
9307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalFirst:
9310d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9311d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  an XPath compiled operation
9312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  the first elem found so far
9313d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
9314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the first
9315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
9316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of examined objects.
9318d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
9319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9320f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
9321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathStepOpPtr op, xmlNodePtr * first)
9322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
9324d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprPtr comp;
9325d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
9326d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9327556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9328d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    comp = ctxt->comp;
9329d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (op->op) {
9330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9331f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
9333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
9334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
9335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9336556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9337f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9338f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9339f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9341f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9342f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
9343f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9344f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *first = ctxt->value->nodesetval->nodeTab[0];
9346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
9348f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
9349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9350556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9351f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9353f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9354f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9358f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9360f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9361f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
9362f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
9363f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
9364f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
9365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9371556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9372f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9373f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9374556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9377f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9380556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9383556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
9389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9391556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeCollectAndTestNth(ctxt, op, indx,
9410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                          first, NULL);
9411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL);
9416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
9419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
9420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
9421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
9423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
9425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
9426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            first);
9427556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
9431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
9434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
9435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
943742596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard
9438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9439f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalLast:
9440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
9442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  the last elem found so far
9443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the last
9445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
9446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9450f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
9451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                       xmlNodePtr * last)
9452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
9454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
9455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
94569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9457556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
9459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
9460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
9463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
9464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
9465556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
9472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *last =
9475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->value->nodesetval->nodeTab[ctxt->value->
9476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     nodesetval->nodeNr -
9477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     1];
9478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
9480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
9481556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9490f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9491f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9492f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9494f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
9498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
9499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
9500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
9501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9507556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9510556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9516556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9519556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9521f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9522f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9523f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (0);
9525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9527556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9544f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
9546f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
9547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
9548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              last);
9549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9552f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last);
9554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
9557f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
9558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
9559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
9561f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
9563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
9564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                           last);
9565556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
9569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
9572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
9573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
95759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEval:
9578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
9580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation
9582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9585f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
9586f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0;
9588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int equal, ret;
9589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
9590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
95917089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlNodePtr bak;
95927089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlDocPtr bakd;
95936000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack    int pp;
9594692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack    int cs;
95959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9596556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9597f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
9598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
9599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_AND:
96027089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
96037089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
96046000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9605692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9607556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9608f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
9610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
96127089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
96137089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
96146000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9615692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9617556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
9618556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
9619556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
9620556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
9621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval &= arg2->boolval;
9624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9626f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9627f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_OR:
96287089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
96297089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
96306000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9631692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9632f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9633556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9634f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
9636f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
96387089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
96397089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
96406000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9641692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9642f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9643556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
9644556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
9645556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
9646556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
9647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval |= arg2->boolval;
9650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9652f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_EQUAL:
96547089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
96557089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
96566000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9657692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9659556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
96607089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
96617089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
96626000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9663692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9665556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            equal = xmlXPathEqualValues(ctxt);
9667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value)
9668f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                valuePush(ctxt, xmlXPathNewBoolean(equal));
9669f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else
9670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                valuePush(ctxt, xmlXPathNewBoolean(!equal));
9671f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_CMP:
96737089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
96747089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
96756000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9676692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9678556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
96797089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
96807089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
96816000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9682692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9684556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
9686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewBoolean(ret));
9687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PLUS:
96897089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
96907089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
96916000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9692692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9694556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
96957089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard            if (op->ch2 != -1) {
96967089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->doc = bakd;
96977089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->node = bak;
96986000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack		ctxt->context->proximityPosition = pp;
9699692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack		ctxt->context->contextSize = cs;
9700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
97017089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    }
9702556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
9704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathSubValues(ctxt);
9705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
9706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathAddValues(ctxt);
9707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
9708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathValueFlipSign(ctxt);
9709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 3) {
9710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CAST_TO_NUMBER;
9711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NUMBER);
9712f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_MULT:
97157089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
97167089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
97176000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9718692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9720556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
97217089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
97227089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
97236000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9724692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9726556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
9728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathMultValues(ctxt);
9729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
9730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathDivValues(ctxt);
9731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
9732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathModValues(ctxt);
9733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
97357089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
97367089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
97376000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9738692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9740556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
97417089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
97427089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
97436000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9744692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9746556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9753f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9754f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9755f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9756f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9757f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9758f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9759f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9760f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9761f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9763f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9764556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9765f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9766f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9767556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9768f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9769f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9772f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9773556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9774f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9776556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9777f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
9782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9784556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
9803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
9804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
9805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              NULL);
9806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL);
9811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
9814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
9815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
9816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VARIABLE:{
9818556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathObjectPtr val;
9819556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard
9820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
9821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
9822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9823556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                if (op->value5 == NULL) {
9824556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookup(ctxt->context, op->value4);
9825556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
9826556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
9827556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
9828556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
9829556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
9830556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		} else {
9831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI;
9832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    URI = xmlXPathNsLookup(ctxt->context, op->value5);
9834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (URI == NULL) {
9835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
9836cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
9837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4, op->value5);
9838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
9839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9840556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookupNS(ctxt->context,
9841556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                                                       op->value4, URI);
9842556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
9843556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
9844556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
9845556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
9846556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
9847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FUNCTION:{
9851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFunction func;
9852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                const xmlChar *oldFunc, *oldFuncURI;
9853556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		int i;
9854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
9856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
9857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9858556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		if (ctxt->valueNr < op->value) {
9859556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    xmlGenericError(xmlGenericErrorContext,
9860cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard			    "xmlXPathCompOpEval: parameter error\n");
9861556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    ctxt->error = XPATH_INVALID_OPERAND;
9862556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    return (total);
9863556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		}
9864556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		for (i = 0; i < op->value; i++)
9865556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
9866556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			xmlGenericError(xmlGenericErrorContext,
9867cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard				"xmlXPathCompOpEval: parameter error\n");
9868556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_INVALID_OPERAND;
9869556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return (total);
9870556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
9871f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->cache != NULL)
9872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    func = (xmlXPathFunction) op->cache;
9873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                else {
9874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI = NULL;
9875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->value5 == NULL)
9877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func =
9878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFunctionLookup(ctxt->context,
9879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   op->value4);
9880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    else {
9881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        URI = xmlXPathNsLookup(ctxt->context, op->value5);
9882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (URI == NULL) {
9883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlGenericError(xmlGenericErrorContext,
9884cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                            "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
9885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            op->value4, op->value5);
9886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func = xmlXPathFunctionLookupNS(ctxt->context,
9889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                        op->value4, URI);
9890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (func == NULL) {
9892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
9893cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: function %s not found\n",
9894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4);
9895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
9896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cache = (void *) func;
9898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cacheURI = (void *) URI;
9899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFunc = ctxt->context->function;
9901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFuncURI = ctxt->context->functionURI;
9902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = op->value4;
9903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = op->cacheURI;
9904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                func(ctxt, op->value);
9905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = oldFunc;
9906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = oldFuncURI;
9907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ARG:
9910088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bakd = ctxt->context->doc;
9911088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bak = ctxt->context->node;
9912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9914088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->doc = bakd;
9915088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
9916556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9918f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9919088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->doc = bakd;
9920088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
9921556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9923f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PREDICATE:
9924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FILTER:{
9925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res;
9926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr obj, tmp;
9927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr newset = NULL;
9928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
9929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodePtr oldnode;
9930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
9931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[1] selection i.e. the first elem
9934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
9936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
9937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_VALUE)) {
9938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[op->ch2].value4;
9941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER) &&
9942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (val->floatval == 1.0)) {
9943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr first = NULL;
9944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
9946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalFirst(ctxt,
9947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &comp->steps[op->ch1],
9948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &first);
9949556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
9950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
9951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
9952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the first value
9953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
9954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
9955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
9956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
9957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1))
9958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
9959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
9960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[last()] selection i.e. the last elem
9964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
9966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
9967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
9968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    int f = comp->steps[op->ch2].ch1;
9969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((f != -1) &&
9971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].op == XPATH_OP_FUNCTION) &&
9972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value5 == NULL) &&
9973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value == 0) &&
9974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value4 != NULL) &&
9975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (xmlStrEqual
9976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         (comp->steps[f].value4, BAD_CAST "last"))) {
9977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr last = NULL;
9978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
9980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalLast(ctxt,
9981f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch1],
9982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &last);
9983556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
9984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
9985f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
9986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the last value
9987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
9988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
9989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
9990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
9991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeTab != NULL) &&
9992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1)) {
9993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeTab[0] =
9994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                ctxt->value->nodesetval->nodeTab[ctxt->
9995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 value->
9996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodesetval->
9997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodeNr -
9998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 1];
9999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10008556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value == NULL)
10012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
100159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
10017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Hum are we filtering the result of an XPointer expression
10019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value->type == XPATH_LOCATIONSET) {
10021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr newlocset = NULL;
10022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr oldlocset;
10023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Extract the old locset, and then evaluate the result of the
10026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * expression for all the element in the locset. use it to grow
10027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * up a new locset.
10028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_TYPE0(XPATH_LOCATIONSET);
10030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    obj = valuePop(ctxt);
10031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    oldlocset = obj->user;
10032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
10035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = 0;
10036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = 0;
10037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10038f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10039f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10042f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, obj);
10045f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newlocset = xmlXPtrLocationSetCreate(NULL);
10049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldlocset->locNr; i++) {
10051f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10052f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a
10053f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * single item in the nodelocset.
10054f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldlocset->locTab[i]->user;
10056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10057f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10058f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldlocset->locNr;
10059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10062f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10072f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10073f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newlocset,
10074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  xmlXPathObjectCopy
10075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  (oldlocset->locTab[i]));
10076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10078f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation locset.
10093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
10098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
10099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
101029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
101039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Extract the old set, and then evaluate the result of the
10106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * expression for all the element in the set. use it to grow
10107f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * up a new set.
10108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
10110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
10111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
10112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
10114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((oldset == NULL) || (oldset->nodeNr == 0)) {
10117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = 0;
10118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = 0;
10119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->ch2 != -1)
10120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEval(ctxt,
10122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                               &comp->steps[op->ch2]);
10123556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    CHECK_ERROR0;
10124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    res = valuePop(ctxt);
10125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (res != NULL)
10126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathFreeObject(res);
10127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, obj);
10128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_ERROR0;
10130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                } else {
10131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Initialize the new set.
10133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newset = xmlXPathNodeSetCreate(NULL);
10135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
10137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of
10139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * a single item in the nodeset.
10140f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
10142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldset->nodeNr;
10145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10157f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
10160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation set.
10177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
10182f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPathWrapNodeSet(newset));
10183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = oldnode;
10185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10190556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL) &&
10192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->type == XPATH_NODESET) &&
10193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->nodesetval != NULL))
10194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
101969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
10197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RANGETO:{
10198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr range;
10199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res, obj;
10200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr tmp;
10201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlLocationSetPtr newset = NULL;
10202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
10203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
10204f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
10212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
10213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
10214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                newset = xmlXPtrLocationSetCreate(NULL);
10217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (oldset != NULL) {
10219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
10220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a single item
10222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * in the nodeset.
10223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
10225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10227f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10228f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10229f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10230f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10231f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10232f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10233f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10235f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10236f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10238f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        range =
10240f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
10241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                      res);
10242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (range != NULL) {
10243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newset, range);
10244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * The result is used as the new evaluation set.
10262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(obj);
10264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10265f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->contextSize = -1;
10266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->proximityPosition = -1;
10267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
10268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
102709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
102719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
102729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlGenericError(xmlGenericErrorContext,
10273f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "XPath: unknown precompiled operation %d\n", op->op);
10274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (total);
102759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
102769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
102779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
102789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathRunEval:
102799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
102809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
102819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
102829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
10283fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic void
102849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
102859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr comp;
102869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
102879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((ctxt == NULL) || (ctxt->comp == NULL))
102889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
102899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
102909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->valueTab == NULL) {
102919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* Allocate the value stack */
102929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueTab = (xmlXPathObjectPtr *)
102939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
102949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (ctxt->valueTab == NULL) {
102959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlFree(ctxt);
102969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
102979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueNr = 0;
102989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueMax = 10;
102999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->value = NULL;
103009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
103019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp = ctxt->comp;
1030229b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    if(comp->last < 0) {
1030329b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	xmlGenericError(xmlGenericErrorContext,
1030429b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	    "xmlXPathRunEval: last is less than zero\n");
1030529b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	return;
1030629b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    }
103079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
103089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
103099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10310afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/************************************************************************
10311afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
10312afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * 			Public interfaces				*
10313afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
10314afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard ************************************************************************/
10315afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10316afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10317fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathEvalPredicate:
10318fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath context
10319fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @res:  the Predicate Expression evaluation result
10320fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
10321fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Evaluate a predicate result for the current node.
10322fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
10323fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * the result to a boolean. If the result is a number, the result will
10324fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * be converted to true if the number is equal to the position of the
10325fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * context node in the context node list (as returned by the position
10326fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * function) and will be converted to false otherwise; if the result
10327fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * is not a number, then the result will be converted as if by a call
10328fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * to the boolean function.
10329fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
10330cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
10331fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
10332fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardint
10333fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
10334fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (res == NULL) return(0);
10335fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    switch (res->type) {
10336fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_BOOLEAN:
10337fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->boolval);
10338fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NUMBER:
10339fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->floatval == ctxt->proximityPosition);
10340fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NODESET:
10341fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_XSLT_TREE:
10342d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (res->nodesetval == NULL)
10343d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		return(0);
10344fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
10345fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_STRING:
10346fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return((res->stringval != NULL) &&
10347fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
10348fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        default:
10349fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    STRANGE
10350fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
10351fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(0);
10352fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
10353fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
10354fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
10355afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvaluatePredicateResult:
10356afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
10357afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @res:  the Predicate Expression evaluation result
10358afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10359afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Evaluate a predicate result for the current node.
10360afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
10361afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * the result to a boolean. If the result is a number, the result will
10362afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * be converted to true if the number is equal to the position of the
10363afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * context node in the context node list (as returned by the position
10364afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * function) and will be converted to false otherwise; if the result
10365afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * is not a number, then the result will be converted as if by a call
10366afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * to the boolean function.
10367afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10368cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
10369afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10370afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardint
10371afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
10372afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard                                xmlXPathObjectPtr res) {
10373afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (res == NULL) return(0);
10374afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    switch (res->type) {
10375afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_BOOLEAN:
10376afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->boolval);
10377afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NUMBER:
10378afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->floatval == ctxt->context->proximityPosition);
10379afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NODESET:
10380afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_XSLT_TREE:
1038173639a73c5a51c3739595f54c338bb531c1319c2Daniel Veillard	    if (res->nodesetval == NULL)
10382911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		return(0);
10383afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
10384afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_STRING:
10385afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return((res->stringval != NULL) &&
10386afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
10387afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        default:
10388afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    STRANGE
10389afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    }
10390afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(0);
10391afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
10392afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10393afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10394afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompile:
10395afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @str:  the XPath expression
10396afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10397afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an XPath expression
10398afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10399cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
10400afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *         the caller has to free the object.
10401afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10402afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompExprPtr
10403afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompile(const xmlChar *str) {
10404afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathParserContextPtr ctxt;
10405afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompExprPtr comp;
10406afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10407afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathInit();
10408afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10409afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt = xmlXPathNewParserContext(str, NULL);
10410afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
1041150fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin
1041240af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    if (*ctxt->cur != 0) {
1041350fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	/*
1041450fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * aleksey: in some cases this line prints *second* error message
1041550fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * (see bug #78858) and probably this should be fixed.
1041650fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * However, we are not sure that all error messages are printed
1041750fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * out in other places. It's not critical so we leave it as-is for now
1041850fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 */
1041940af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
1042040af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = NULL;
1042140af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    } else {
1042240af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = ctxt->comp;
1042340af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	ctxt->comp = NULL;
1042440af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    }
10425afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathFreeParserContext(ctxt);
10426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
10427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp != NULL) {
10428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->string = xmlStrdup(str);
10429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
10430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
10432afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(comp);
10433afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
10434afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
104359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
104369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompiledEval:
104379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled XPath expression
104389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctx:  the XPath context
104399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
104409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
104419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
10442cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
104439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *         the caller has to free the object.
104449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
104459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathObjectPtr
104469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
104479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ctxt;
104489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathObjectPtr res, tmp, init = NULL;
104499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int stack = 0;
104508146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
104518146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    static int reentance = 0;
104528146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
104539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
104549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((comp == NULL) || (ctx == NULL))
104559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
104569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathInit();
104579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
104589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_CONTEXT(ctx)
104599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
104608146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
104618146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance++;
104628146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (reentance > 1)
104638146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	xmlXPathDisableOptimizer = 1;
104648146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
104658146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
10466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
10467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp->nb++;
10468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((comp->string != NULL) && (comp->nb > 100)) {
10469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	fprintf(stderr, "100 x %s\n", comp->string);
10470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
10471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
104739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt = xmlXPathCompParserContext(comp, ctx);
104749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathRunEval(ctxt);
104759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
104769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->value == NULL) {
104779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
10478cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: evaluation failed\n");
104799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
104809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } else {
104819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = valuePop(ctxt);
104829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
104839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
104859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    do {
104869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        tmp = valuePop(ctxt);
104879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (tmp != NULL) {
104889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (tmp != init)
104899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		stack++;
104909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathFreeObject(tmp);
104919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
104929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } while (tmp != NULL);
104939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((stack != 0) && (res != NULL)) {
104949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
10495cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: %d object left on the stack\n",
104969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	        stack);
104979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
104989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->error != XPATH_EXPRESSION_OK) {
104999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeObject(res);
105009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
105019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
105029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
105039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10504afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt->comp = NULL;
105059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathFreeParserContext(ctxt);
105068146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
105078146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance--;
105088146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
105099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(res);
105109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
105119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10512afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10513afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvalExpr:
10514afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
10515afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10516afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and evaluate an XPath expression in the given context,
10517afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * then push the result on the context stack
10518afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10519afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
10520afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
10521afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
1052250fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin    CHECK_ERROR;
10523afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathRunEval(ctxt);
10524afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
105259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
105263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
105273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEval:
105283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
105293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the XPath context
105303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
105313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath Location Path in the given context.
105323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10533cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
105343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
105353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
105363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
105373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
105383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ctxt;
105393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp, init = NULL;
105403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
105413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathInit();
105433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_CONTEXT(ctx)
105453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt = xmlXPathNewParserContext(str, ctx);
105473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(ctxt);
105483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->value == NULL) {
105503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
105513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: evaluation failed\n");
105523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
105533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (*ctxt->cur != 0) {
105543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
105553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
105563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
105573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(ctxt);
105583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
105593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
105613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(ctxt);
105623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
105633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (tmp != init)
105643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		stack++;
105653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
105663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
105673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
105683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
105693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
105703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: %d object left on the stack\n",
105713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
105723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
105733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->error != XPATH_EXPRESSION_OK) {
105743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(res);
105753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
105763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
105779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
105783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(ctxt);
105793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
105803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
105813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
105833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEvalExpression:
105843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
105853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
105863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
105873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath expression in the given context.
105883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
105893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
105903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
105913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
105923473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
105933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
105943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr pctxt;
105953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp;
105963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
105973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
105983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathInit();
105993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
106003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_CONTEXT(ctxt)
106013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
106023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    pctxt = xmlXPathNewParserContext(str, ctxt);
106033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(pctxt);
106043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
106053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*pctxt->cur != 0) {
106063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
106073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
106083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
106093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(pctxt);
106103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
106113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
106123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(pctxt);
106133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
106143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
106153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    stack++;
106163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
106173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
106183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
106193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
106203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEvalExpression: %d object left on the stack\n",
106213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
106223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
106233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(pctxt);
106243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
106253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
106263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
106273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
106283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterAllFunctions:
106293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
106303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
106313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Registers all default XPath functions in this context
106323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
106333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
106343473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
106353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
106363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
106373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathBooleanFunction);
106383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
106393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCeilingFunction);
106403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
106413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCountFunction);
106423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
106433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathConcatFunction);
106443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
106453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathContainsFunction);
106463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
106473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathIdFunction);
106483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
106493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFalseFunction);
106503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
106513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFloorFunction);
106523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
106533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLastFunction);
106543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
106553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLangFunction);
106563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
106573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLocalNameFunction);
106583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
106593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNotFunction);
106603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
106613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNameFunction);
106623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
106633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNamespaceURIFunction);
106643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
106653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNormalizeFunction);
106663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
106673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNumberFunction);
106683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
106693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathPositionFunction);
106703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
106713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathRoundFunction);
106723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
106733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringFunction);
106743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
106753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringLengthFunction);
106763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
106773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStartsWithFunction);
106783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
106793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringFunction);
106803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
106813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringBeforeFunction);
106823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
106833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringAfterFunction);
106843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
106853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSumFunction);
106863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
106873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTrueFunction);
106883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
106893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTranslateFunction);
106903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
106913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
106923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* LIBXML_XPATH_ENABLED */
10693