1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * xpointer.c : Code to handle XML Pointer
3*7c568831SAndroid Build Coastguard Worker *
4*7c568831SAndroid Build Coastguard Worker * Base implementation was made accordingly to
5*7c568831SAndroid Build Coastguard Worker * W3C Candidate Recommendation 7 June 2000
6*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/2000/CR-xptr-20000607
7*7c568831SAndroid Build Coastguard Worker *
8*7c568831SAndroid Build Coastguard Worker * Added support for the element() scheme described in:
9*7c568831SAndroid Build Coastguard Worker * W3C Proposed Recommendation 13 November 2002
10*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/2002/PR-xptr-element-20021113/
11*7c568831SAndroid Build Coastguard Worker *
12*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software.
13*7c568831SAndroid Build Coastguard Worker *
14*7c568831SAndroid Build Coastguard Worker * [email protected]
15*7c568831SAndroid Build Coastguard Worker */
16*7c568831SAndroid Build Coastguard Worker
17*7c568831SAndroid Build Coastguard Worker /* To avoid EBCDIC trouble when parsing on zOS */
18*7c568831SAndroid Build Coastguard Worker #if defined(__MVS__)
19*7c568831SAndroid Build Coastguard Worker #pragma convert("ISO8859-1")
20*7c568831SAndroid Build Coastguard Worker #endif
21*7c568831SAndroid Build Coastguard Worker
22*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
23*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
24*7c568831SAndroid Build Coastguard Worker
25*7c568831SAndroid Build Coastguard Worker /*
26*7c568831SAndroid Build Coastguard Worker * TODO: better handling of error cases, the full expression should
27*7c568831SAndroid Build Coastguard Worker * be parsed beforehand instead of a progressive evaluation
28*7c568831SAndroid Build Coastguard Worker * TODO: Access into entities references are not supported now ...
29*7c568831SAndroid Build Coastguard Worker * need a start to be able to pop out of entities refs since
30*7c568831SAndroid Build Coastguard Worker * parent is the entity declaration, not the ref.
31*7c568831SAndroid Build Coastguard Worker */
32*7c568831SAndroid Build Coastguard Worker
33*7c568831SAndroid Build Coastguard Worker #include <string.h>
34*7c568831SAndroid Build Coastguard Worker #include <libxml/xpointer.h>
35*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
36*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
37*7c568831SAndroid Build Coastguard Worker #include <libxml/uri.h>
38*7c568831SAndroid Build Coastguard Worker #include <libxml/xpath.h>
39*7c568831SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
40*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
41*7c568831SAndroid Build Coastguard Worker
42*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_ENABLED
43*7c568831SAndroid Build Coastguard Worker
44*7c568831SAndroid Build Coastguard Worker /* Add support of the xmlns() xpointer scheme to initialize the namespaces */
45*7c568831SAndroid Build Coastguard Worker #define XPTR_XMLNS_SCHEME
46*7c568831SAndroid Build Coastguard Worker
47*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
48*7c568831SAndroid Build Coastguard Worker #include "private/xpath.h"
49*7c568831SAndroid Build Coastguard Worker
50*7c568831SAndroid Build Coastguard Worker /************************************************************************
51*7c568831SAndroid Build Coastguard Worker * *
52*7c568831SAndroid Build Coastguard Worker * Some factorized error routines *
53*7c568831SAndroid Build Coastguard Worker * *
54*7c568831SAndroid Build Coastguard Worker ************************************************************************/
55*7c568831SAndroid Build Coastguard Worker
56*7c568831SAndroid Build Coastguard Worker /**
57*7c568831SAndroid Build Coastguard Worker * xmlXPtrErr:
58*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPTR evaluation context
59*7c568831SAndroid Build Coastguard Worker * @extra: extra information
60*7c568831SAndroid Build Coastguard Worker *
61*7c568831SAndroid Build Coastguard Worker * Handle an XPointer error
62*7c568831SAndroid Build Coastguard Worker */
63*7c568831SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(3,0)
xmlXPtrErr(xmlXPathParserContextPtr ctxt,int code,const char * msg,const xmlChar * extra)64*7c568831SAndroid Build Coastguard Worker xmlXPtrErr(xmlXPathParserContextPtr ctxt, int code,
65*7c568831SAndroid Build Coastguard Worker const char * msg, const xmlChar *extra)
66*7c568831SAndroid Build Coastguard Worker {
67*7c568831SAndroid Build Coastguard Worker xmlStructuredErrorFunc serror = NULL;
68*7c568831SAndroid Build Coastguard Worker void *data = NULL;
69*7c568831SAndroid Build Coastguard Worker xmlNodePtr node = NULL;
70*7c568831SAndroid Build Coastguard Worker int res;
71*7c568831SAndroid Build Coastguard Worker
72*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
73*7c568831SAndroid Build Coastguard Worker return;
74*7c568831SAndroid Build Coastguard Worker /* Only report the first error */
75*7c568831SAndroid Build Coastguard Worker if (ctxt->error != 0)
76*7c568831SAndroid Build Coastguard Worker return;
77*7c568831SAndroid Build Coastguard Worker
78*7c568831SAndroid Build Coastguard Worker ctxt->error = code;
79*7c568831SAndroid Build Coastguard Worker
80*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL) {
81*7c568831SAndroid Build Coastguard Worker xmlErrorPtr err = &ctxt->context->lastError;
82*7c568831SAndroid Build Coastguard Worker
83*7c568831SAndroid Build Coastguard Worker /* cleanup current last error */
84*7c568831SAndroid Build Coastguard Worker xmlResetError(err);
85*7c568831SAndroid Build Coastguard Worker
86*7c568831SAndroid Build Coastguard Worker err->domain = XML_FROM_XPOINTER;
87*7c568831SAndroid Build Coastguard Worker err->code = code;
88*7c568831SAndroid Build Coastguard Worker err->level = XML_ERR_ERROR;
89*7c568831SAndroid Build Coastguard Worker err->str1 = (char *) xmlStrdup(ctxt->base);
90*7c568831SAndroid Build Coastguard Worker if (err->str1 == NULL) {
91*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
92*7c568831SAndroid Build Coastguard Worker return;
93*7c568831SAndroid Build Coastguard Worker }
94*7c568831SAndroid Build Coastguard Worker err->int1 = ctxt->cur - ctxt->base;
95*7c568831SAndroid Build Coastguard Worker err->node = ctxt->context->debugNode;
96*7c568831SAndroid Build Coastguard Worker
97*7c568831SAndroid Build Coastguard Worker serror = ctxt->context->error;
98*7c568831SAndroid Build Coastguard Worker data = ctxt->context->userData;
99*7c568831SAndroid Build Coastguard Worker node = ctxt->context->debugNode;
100*7c568831SAndroid Build Coastguard Worker }
101*7c568831SAndroid Build Coastguard Worker
102*7c568831SAndroid Build Coastguard Worker res = xmlRaiseError(serror, NULL, data, NULL, node,
103*7c568831SAndroid Build Coastguard Worker XML_FROM_XPOINTER, code, XML_ERR_ERROR, NULL, 0,
104*7c568831SAndroid Build Coastguard Worker (const char *) extra, (const char *) ctxt->base,
105*7c568831SAndroid Build Coastguard Worker NULL, ctxt->cur - ctxt->base, 0,
106*7c568831SAndroid Build Coastguard Worker msg, extra);
107*7c568831SAndroid Build Coastguard Worker if (res < 0)
108*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
109*7c568831SAndroid Build Coastguard Worker }
110*7c568831SAndroid Build Coastguard Worker
111*7c568831SAndroid Build Coastguard Worker /************************************************************************
112*7c568831SAndroid Build Coastguard Worker * *
113*7c568831SAndroid Build Coastguard Worker * A few helper functions for child sequences *
114*7c568831SAndroid Build Coastguard Worker * *
115*7c568831SAndroid Build Coastguard Worker ************************************************************************/
116*7c568831SAndroid Build Coastguard Worker
117*7c568831SAndroid Build Coastguard Worker /**
118*7c568831SAndroid Build Coastguard Worker * xmlXPtrGetNthChild:
119*7c568831SAndroid Build Coastguard Worker * @cur: the node
120*7c568831SAndroid Build Coastguard Worker * @no: the child number
121*7c568831SAndroid Build Coastguard Worker *
122*7c568831SAndroid Build Coastguard Worker * Returns the @no'th element child of @cur or NULL
123*7c568831SAndroid Build Coastguard Worker */
124*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPtrGetNthChild(xmlNodePtr cur,int no)125*7c568831SAndroid Build Coastguard Worker xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
126*7c568831SAndroid Build Coastguard Worker int i;
127*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
128*7c568831SAndroid Build Coastguard Worker return(cur);
129*7c568831SAndroid Build Coastguard Worker cur = cur->children;
130*7c568831SAndroid Build Coastguard Worker for (i = 0;i <= no;cur = cur->next) {
131*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
132*7c568831SAndroid Build Coastguard Worker return(cur);
133*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_ELEMENT_NODE) ||
134*7c568831SAndroid Build Coastguard Worker (cur->type == XML_DOCUMENT_NODE) ||
135*7c568831SAndroid Build Coastguard Worker (cur->type == XML_HTML_DOCUMENT_NODE)) {
136*7c568831SAndroid Build Coastguard Worker i++;
137*7c568831SAndroid Build Coastguard Worker if (i == no)
138*7c568831SAndroid Build Coastguard Worker break;
139*7c568831SAndroid Build Coastguard Worker }
140*7c568831SAndroid Build Coastguard Worker }
141*7c568831SAndroid Build Coastguard Worker return(cur);
142*7c568831SAndroid Build Coastguard Worker }
143*7c568831SAndroid Build Coastguard Worker
144*7c568831SAndroid Build Coastguard Worker /************************************************************************
145*7c568831SAndroid Build Coastguard Worker * *
146*7c568831SAndroid Build Coastguard Worker * The parser *
147*7c568831SAndroid Build Coastguard Worker * *
148*7c568831SAndroid Build Coastguard Worker ************************************************************************/
149*7c568831SAndroid Build Coastguard Worker
150*7c568831SAndroid Build Coastguard Worker static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
151*7c568831SAndroid Build Coastguard Worker
152*7c568831SAndroid Build Coastguard Worker /*
153*7c568831SAndroid Build Coastguard Worker * Macros for accessing the content. Those should be used only by the parser,
154*7c568831SAndroid Build Coastguard Worker * and not exported.
155*7c568831SAndroid Build Coastguard Worker *
156*7c568831SAndroid Build Coastguard Worker * Dirty macros, i.e. one need to make assumption on the context to use them
157*7c568831SAndroid Build Coastguard Worker *
158*7c568831SAndroid Build Coastguard Worker * CUR returns the current xmlChar value, i.e. a 8 bit value
159*7c568831SAndroid Build Coastguard Worker * in ISO-Latin or UTF-8.
160*7c568831SAndroid Build Coastguard Worker * This should be used internally by the parser
161*7c568831SAndroid Build Coastguard Worker * only to compare to ASCII values otherwise it would break when
162*7c568831SAndroid Build Coastguard Worker * running with UTF-8 encoding.
163*7c568831SAndroid Build Coastguard Worker * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
164*7c568831SAndroid Build Coastguard Worker * to compare on ASCII based substring.
165*7c568831SAndroid Build Coastguard Worker * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
166*7c568831SAndroid Build Coastguard Worker * strings within the parser.
167*7c568831SAndroid Build Coastguard Worker * CURRENT Returns the current char value, with the full decoding of
168*7c568831SAndroid Build Coastguard Worker * UTF-8 if we are using this mode. It returns an int.
169*7c568831SAndroid Build Coastguard Worker * NEXT Skip to the next character, this does the proper decoding
170*7c568831SAndroid Build Coastguard Worker * in UTF-8 mode. It also pop-up unfinished entities on the fly.
171*7c568831SAndroid Build Coastguard Worker * It returns the pointer to the current xmlChar.
172*7c568831SAndroid Build Coastguard Worker */
173*7c568831SAndroid Build Coastguard Worker
174*7c568831SAndroid Build Coastguard Worker #define CUR (*ctxt->cur)
175*7c568831SAndroid Build Coastguard Worker #define SKIP(val) ctxt->cur += (val)
176*7c568831SAndroid Build Coastguard Worker #define NXT(val) ctxt->cur[(val)]
177*7c568831SAndroid Build Coastguard Worker
178*7c568831SAndroid Build Coastguard Worker #define SKIP_BLANKS \
179*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*(ctxt->cur))) NEXT
180*7c568831SAndroid Build Coastguard Worker
181*7c568831SAndroid Build Coastguard Worker #define CURRENT (*ctxt->cur)
182*7c568831SAndroid Build Coastguard Worker #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
183*7c568831SAndroid Build Coastguard Worker
184*7c568831SAndroid Build Coastguard Worker /*
185*7c568831SAndroid Build Coastguard Worker * xmlXPtrGetChildNo:
186*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPointer Parser context
187*7c568831SAndroid Build Coastguard Worker * @index: the child number
188*7c568831SAndroid Build Coastguard Worker *
189*7c568831SAndroid Build Coastguard Worker * Move the current node of the nodeset on the stack to the
190*7c568831SAndroid Build Coastguard Worker * given child if found
191*7c568831SAndroid Build Coastguard Worker */
192*7c568831SAndroid Build Coastguard Worker static void
xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt,int indx)193*7c568831SAndroid Build Coastguard Worker xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) {
194*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur = NULL;
195*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
196*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr oldset;
197*7c568831SAndroid Build Coastguard Worker
198*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NODESET);
199*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
200*7c568831SAndroid Build Coastguard Worker oldset = obj->nodesetval;
201*7c568831SAndroid Build Coastguard Worker if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) {
202*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(obj);
203*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathNewNodeSet(NULL));
204*7c568831SAndroid Build Coastguard Worker return;
205*7c568831SAndroid Build Coastguard Worker }
206*7c568831SAndroid Build Coastguard Worker cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx);
207*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
208*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(obj);
209*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathNewNodeSet(NULL));
210*7c568831SAndroid Build Coastguard Worker return;
211*7c568831SAndroid Build Coastguard Worker }
212*7c568831SAndroid Build Coastguard Worker oldset->nodeTab[0] = cur;
213*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, obj);
214*7c568831SAndroid Build Coastguard Worker }
215*7c568831SAndroid Build Coastguard Worker
216*7c568831SAndroid Build Coastguard Worker /**
217*7c568831SAndroid Build Coastguard Worker * xmlXPtrEvalXPtrPart:
218*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPointer Parser context
219*7c568831SAndroid Build Coastguard Worker * @name: the preparsed Scheme for the XPtrPart
220*7c568831SAndroid Build Coastguard Worker *
221*7c568831SAndroid Build Coastguard Worker * XPtrPart ::= 'xpointer' '(' XPtrExpr ')'
222*7c568831SAndroid Build Coastguard Worker * | Scheme '(' SchemeSpecificExpr ')'
223*7c568831SAndroid Build Coastguard Worker *
224*7c568831SAndroid Build Coastguard Worker * Scheme ::= NCName - 'xpointer' [VC: Non-XPointer schemes]
225*7c568831SAndroid Build Coastguard Worker *
226*7c568831SAndroid Build Coastguard Worker * SchemeSpecificExpr ::= StringWithBalancedParens
227*7c568831SAndroid Build Coastguard Worker *
228*7c568831SAndroid Build Coastguard Worker * StringWithBalancedParens ::=
229*7c568831SAndroid Build Coastguard Worker * [^()]* ('(' StringWithBalancedParens ')' [^()]*)*
230*7c568831SAndroid Build Coastguard Worker * [VC: Parenthesis escaping]
231*7c568831SAndroid Build Coastguard Worker *
232*7c568831SAndroid Build Coastguard Worker * XPtrExpr ::= Expr [VC: Parenthesis escaping]
233*7c568831SAndroid Build Coastguard Worker *
234*7c568831SAndroid Build Coastguard Worker * VC: Parenthesis escaping:
235*7c568831SAndroid Build Coastguard Worker * The end of an XPointer part is signaled by the right parenthesis ")"
236*7c568831SAndroid Build Coastguard Worker * character that is balanced with the left parenthesis "(" character
237*7c568831SAndroid Build Coastguard Worker * that began the part. Any unbalanced parenthesis character inside the
238*7c568831SAndroid Build Coastguard Worker * expression, even within literals, must be escaped with a circumflex (^)
239*7c568831SAndroid Build Coastguard Worker * character preceding it. If the expression contains any literal
240*7c568831SAndroid Build Coastguard Worker * occurrences of the circumflex, each must be escaped with an additional
241*7c568831SAndroid Build Coastguard Worker * circumflex (that is, ^^). If the unescaped parentheses in the expression
242*7c568831SAndroid Build Coastguard Worker * are not balanced, a syntax error results.
243*7c568831SAndroid Build Coastguard Worker *
244*7c568831SAndroid Build Coastguard Worker * Parse and evaluate an XPtrPart. Basically it generates the unescaped
245*7c568831SAndroid Build Coastguard Worker * string and if the scheme is 'xpointer' it will call the XPath interpreter.
246*7c568831SAndroid Build Coastguard Worker *
247*7c568831SAndroid Build Coastguard Worker * TODO: there is no new scheme registration mechanism
248*7c568831SAndroid Build Coastguard Worker */
249*7c568831SAndroid Build Coastguard Worker
250*7c568831SAndroid Build Coastguard Worker static void
xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt,xmlChar * name)251*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
252*7c568831SAndroid Build Coastguard Worker xmlChar *buffer, *cur;
253*7c568831SAndroid Build Coastguard Worker int len;
254*7c568831SAndroid Build Coastguard Worker int level;
255*7c568831SAndroid Build Coastguard Worker
256*7c568831SAndroid Build Coastguard Worker if (name == NULL)
257*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseName(ctxt);
258*7c568831SAndroid Build Coastguard Worker if (name == NULL)
259*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
260*7c568831SAndroid Build Coastguard Worker
261*7c568831SAndroid Build Coastguard Worker if (CUR != '(') {
262*7c568831SAndroid Build Coastguard Worker xmlFree(name);
263*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
264*7c568831SAndroid Build Coastguard Worker }
265*7c568831SAndroid Build Coastguard Worker NEXT;
266*7c568831SAndroid Build Coastguard Worker level = 1;
267*7c568831SAndroid Build Coastguard Worker
268*7c568831SAndroid Build Coastguard Worker len = xmlStrlen(ctxt->cur);
269*7c568831SAndroid Build Coastguard Worker len++;
270*7c568831SAndroid Build Coastguard Worker buffer = xmlMalloc(len);
271*7c568831SAndroid Build Coastguard Worker if (buffer == NULL) {
272*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
273*7c568831SAndroid Build Coastguard Worker xmlFree(name);
274*7c568831SAndroid Build Coastguard Worker return;
275*7c568831SAndroid Build Coastguard Worker }
276*7c568831SAndroid Build Coastguard Worker
277*7c568831SAndroid Build Coastguard Worker cur = buffer;
278*7c568831SAndroid Build Coastguard Worker while (CUR != 0) {
279*7c568831SAndroid Build Coastguard Worker if (CUR == ')') {
280*7c568831SAndroid Build Coastguard Worker level--;
281*7c568831SAndroid Build Coastguard Worker if (level == 0) {
282*7c568831SAndroid Build Coastguard Worker NEXT;
283*7c568831SAndroid Build Coastguard Worker break;
284*7c568831SAndroid Build Coastguard Worker }
285*7c568831SAndroid Build Coastguard Worker } else if (CUR == '(') {
286*7c568831SAndroid Build Coastguard Worker level++;
287*7c568831SAndroid Build Coastguard Worker } else if (CUR == '^') {
288*7c568831SAndroid Build Coastguard Worker if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
289*7c568831SAndroid Build Coastguard Worker NEXT;
290*7c568831SAndroid Build Coastguard Worker }
291*7c568831SAndroid Build Coastguard Worker }
292*7c568831SAndroid Build Coastguard Worker *cur++ = CUR;
293*7c568831SAndroid Build Coastguard Worker NEXT;
294*7c568831SAndroid Build Coastguard Worker }
295*7c568831SAndroid Build Coastguard Worker *cur = 0;
296*7c568831SAndroid Build Coastguard Worker
297*7c568831SAndroid Build Coastguard Worker if ((level != 0) && (CUR == 0)) {
298*7c568831SAndroid Build Coastguard Worker xmlFree(name);
299*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
300*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPTR_SYNTAX_ERROR);
301*7c568831SAndroid Build Coastguard Worker }
302*7c568831SAndroid Build Coastguard Worker
303*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, (xmlChar *) "xpointer") ||
304*7c568831SAndroid Build Coastguard Worker xmlStrEqual(name, (xmlChar *) "xpath1")) {
305*7c568831SAndroid Build Coastguard Worker const xmlChar *oldBase = ctxt->base;
306*7c568831SAndroid Build Coastguard Worker const xmlChar *oldCur = ctxt->cur;
307*7c568831SAndroid Build Coastguard Worker
308*7c568831SAndroid Build Coastguard Worker ctxt->cur = ctxt->base = buffer;
309*7c568831SAndroid Build Coastguard Worker /*
310*7c568831SAndroid Build Coastguard Worker * To evaluate an xpointer scheme element (4.3) we need:
311*7c568831SAndroid Build Coastguard Worker * context initialized to the root
312*7c568831SAndroid Build Coastguard Worker * context position initialized to 1
313*7c568831SAndroid Build Coastguard Worker * context size initialized to 1
314*7c568831SAndroid Build Coastguard Worker */
315*7c568831SAndroid Build Coastguard Worker ctxt->context->node = (xmlNodePtr)ctxt->context->doc;
316*7c568831SAndroid Build Coastguard Worker ctxt->context->proximityPosition = 1;
317*7c568831SAndroid Build Coastguard Worker ctxt->context->contextSize = 1;
318*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpr(ctxt);
319*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
320*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
321*7c568831SAndroid Build Coastguard Worker } else if (xmlStrEqual(name, (xmlChar *) "element")) {
322*7c568831SAndroid Build Coastguard Worker const xmlChar *oldBase = ctxt->base;
323*7c568831SAndroid Build Coastguard Worker const xmlChar *oldCur = ctxt->cur;
324*7c568831SAndroid Build Coastguard Worker xmlChar *name2;
325*7c568831SAndroid Build Coastguard Worker
326*7c568831SAndroid Build Coastguard Worker ctxt->cur = ctxt->base = buffer;
327*7c568831SAndroid Build Coastguard Worker if (buffer[0] == '/') {
328*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
329*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalChildSeq(ctxt, NULL);
330*7c568831SAndroid Build Coastguard Worker } else {
331*7c568831SAndroid Build Coastguard Worker name2 = xmlXPathParseName(ctxt);
332*7c568831SAndroid Build Coastguard Worker if (name2 == NULL) {
333*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
334*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
335*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
336*7c568831SAndroid Build Coastguard Worker xmlFree(name);
337*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
338*7c568831SAndroid Build Coastguard Worker }
339*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalChildSeq(ctxt, name2);
340*7c568831SAndroid Build Coastguard Worker }
341*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
342*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
343*7c568831SAndroid Build Coastguard Worker #ifdef XPTR_XMLNS_SCHEME
344*7c568831SAndroid Build Coastguard Worker } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
345*7c568831SAndroid Build Coastguard Worker const xmlChar *oldBase = ctxt->base;
346*7c568831SAndroid Build Coastguard Worker const xmlChar *oldCur = ctxt->cur;
347*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
348*7c568831SAndroid Build Coastguard Worker
349*7c568831SAndroid Build Coastguard Worker ctxt->cur = ctxt->base = buffer;
350*7c568831SAndroid Build Coastguard Worker prefix = xmlXPathParseNCName(ctxt);
351*7c568831SAndroid Build Coastguard Worker if (prefix == NULL) {
352*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
353*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
354*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
355*7c568831SAndroid Build Coastguard Worker xmlFree(name);
356*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPTR_SYNTAX_ERROR);
357*7c568831SAndroid Build Coastguard Worker }
358*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
359*7c568831SAndroid Build Coastguard Worker if (CUR != '=') {
360*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
361*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
362*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
363*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
364*7c568831SAndroid Build Coastguard Worker xmlFree(name);
365*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPTR_SYNTAX_ERROR);
366*7c568831SAndroid Build Coastguard Worker }
367*7c568831SAndroid Build Coastguard Worker NEXT;
368*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
369*7c568831SAndroid Build Coastguard Worker
370*7c568831SAndroid Build Coastguard Worker if (xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur) < 0)
371*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
372*7c568831SAndroid Build Coastguard Worker ctxt->base = oldBase;
373*7c568831SAndroid Build Coastguard Worker ctxt->cur = oldCur;
374*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
375*7c568831SAndroid Build Coastguard Worker #endif /* XPTR_XMLNS_SCHEME */
376*7c568831SAndroid Build Coastguard Worker } else {
377*7c568831SAndroid Build Coastguard Worker xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME,
378*7c568831SAndroid Build Coastguard Worker "unsupported scheme '%s'\n", name);
379*7c568831SAndroid Build Coastguard Worker }
380*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
381*7c568831SAndroid Build Coastguard Worker xmlFree(name);
382*7c568831SAndroid Build Coastguard Worker }
383*7c568831SAndroid Build Coastguard Worker
384*7c568831SAndroid Build Coastguard Worker /**
385*7c568831SAndroid Build Coastguard Worker * xmlXPtrEvalFullXPtr:
386*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPointer Parser context
387*7c568831SAndroid Build Coastguard Worker * @name: the preparsed Scheme for the first XPtrPart
388*7c568831SAndroid Build Coastguard Worker *
389*7c568831SAndroid Build Coastguard Worker * FullXPtr ::= XPtrPart (S? XPtrPart)*
390*7c568831SAndroid Build Coastguard Worker *
391*7c568831SAndroid Build Coastguard Worker * As the specs says:
392*7c568831SAndroid Build Coastguard Worker * -----------
393*7c568831SAndroid Build Coastguard Worker * When multiple XPtrParts are provided, they must be evaluated in
394*7c568831SAndroid Build Coastguard Worker * left-to-right order. If evaluation of one part fails, the nexti
395*7c568831SAndroid Build Coastguard Worker * is evaluated. The following conditions cause XPointer part failure:
396*7c568831SAndroid Build Coastguard Worker *
397*7c568831SAndroid Build Coastguard Worker * - An unknown scheme
398*7c568831SAndroid Build Coastguard Worker * - A scheme that does not locate any sub-resource present in the resource
399*7c568831SAndroid Build Coastguard Worker * - A scheme that is not applicable to the media type of the resource
400*7c568831SAndroid Build Coastguard Worker *
401*7c568831SAndroid Build Coastguard Worker * The XPointer application must consume a failed XPointer part and
402*7c568831SAndroid Build Coastguard Worker * attempt to evaluate the next one, if any. The result of the first
403*7c568831SAndroid Build Coastguard Worker * XPointer part whose evaluation succeeds is taken to be the fragment
404*7c568831SAndroid Build Coastguard Worker * located by the XPointer as a whole. If all the parts fail, the result
405*7c568831SAndroid Build Coastguard Worker * for the XPointer as a whole is a sub-resource error.
406*7c568831SAndroid Build Coastguard Worker * -----------
407*7c568831SAndroid Build Coastguard Worker *
408*7c568831SAndroid Build Coastguard Worker * Parse and evaluate a Full XPtr i.e. possibly a cascade of XPath based
409*7c568831SAndroid Build Coastguard Worker * expressions or other schemes.
410*7c568831SAndroid Build Coastguard Worker */
411*7c568831SAndroid Build Coastguard Worker static void
xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt,xmlChar * name)412*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
413*7c568831SAndroid Build Coastguard Worker if (name == NULL)
414*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseName(ctxt);
415*7c568831SAndroid Build Coastguard Worker if (name == NULL)
416*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
417*7c568831SAndroid Build Coastguard Worker while (name != NULL) {
418*7c568831SAndroid Build Coastguard Worker ctxt->error = XPATH_EXPRESSION_OK;
419*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalXPtrPart(ctxt, name);
420*7c568831SAndroid Build Coastguard Worker
421*7c568831SAndroid Build Coastguard Worker /* in case of syntax error, break here */
422*7c568831SAndroid Build Coastguard Worker if ((ctxt->error != XPATH_EXPRESSION_OK) &&
423*7c568831SAndroid Build Coastguard Worker (ctxt->error != XML_XPTR_UNKNOWN_SCHEME))
424*7c568831SAndroid Build Coastguard Worker return;
425*7c568831SAndroid Build Coastguard Worker
426*7c568831SAndroid Build Coastguard Worker /*
427*7c568831SAndroid Build Coastguard Worker * If the returned value is a non-empty nodeset
428*7c568831SAndroid Build Coastguard Worker * or location set, return here.
429*7c568831SAndroid Build Coastguard Worker */
430*7c568831SAndroid Build Coastguard Worker if (ctxt->value != NULL) {
431*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj = ctxt->value;
432*7c568831SAndroid Build Coastguard Worker
433*7c568831SAndroid Build Coastguard Worker switch (obj->type) {
434*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET: {
435*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr loc = ctxt->value->nodesetval;
436*7c568831SAndroid Build Coastguard Worker if ((loc != NULL) && (loc->nodeNr > 0))
437*7c568831SAndroid Build Coastguard Worker return;
438*7c568831SAndroid Build Coastguard Worker break;
439*7c568831SAndroid Build Coastguard Worker }
440*7c568831SAndroid Build Coastguard Worker default:
441*7c568831SAndroid Build Coastguard Worker break;
442*7c568831SAndroid Build Coastguard Worker }
443*7c568831SAndroid Build Coastguard Worker
444*7c568831SAndroid Build Coastguard Worker /*
445*7c568831SAndroid Build Coastguard Worker * Evaluating to improper values is equivalent to
446*7c568831SAndroid Build Coastguard Worker * a sub-resource error, clean-up the stack
447*7c568831SAndroid Build Coastguard Worker */
448*7c568831SAndroid Build Coastguard Worker do {
449*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
450*7c568831SAndroid Build Coastguard Worker if (obj != NULL) {
451*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(obj);
452*7c568831SAndroid Build Coastguard Worker }
453*7c568831SAndroid Build Coastguard Worker } while (obj != NULL);
454*7c568831SAndroid Build Coastguard Worker }
455*7c568831SAndroid Build Coastguard Worker
456*7c568831SAndroid Build Coastguard Worker /*
457*7c568831SAndroid Build Coastguard Worker * Is there another XPointer part.
458*7c568831SAndroid Build Coastguard Worker */
459*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
460*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseName(ctxt);
461*7c568831SAndroid Build Coastguard Worker }
462*7c568831SAndroid Build Coastguard Worker }
463*7c568831SAndroid Build Coastguard Worker
464*7c568831SAndroid Build Coastguard Worker /**
465*7c568831SAndroid Build Coastguard Worker * xmlXPtrEvalChildSeq:
466*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPointer Parser context
467*7c568831SAndroid Build Coastguard Worker * @name: a possible ID name of the child sequence
468*7c568831SAndroid Build Coastguard Worker *
469*7c568831SAndroid Build Coastguard Worker * ChildSeq ::= '/1' ('/' [0-9]*)*
470*7c568831SAndroid Build Coastguard Worker * | Name ('/' [0-9]*)+
471*7c568831SAndroid Build Coastguard Worker *
472*7c568831SAndroid Build Coastguard Worker * Parse and evaluate a Child Sequence. This routine also handle the
473*7c568831SAndroid Build Coastguard Worker * case of a Bare Name used to get a document ID.
474*7c568831SAndroid Build Coastguard Worker */
475*7c568831SAndroid Build Coastguard Worker static void
xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt,xmlChar * name)476*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) {
477*7c568831SAndroid Build Coastguard Worker /*
478*7c568831SAndroid Build Coastguard Worker * XPointer don't allow by syntax to address in multirooted trees
479*7c568831SAndroid Build Coastguard Worker * this might prove useful in some cases, warn about it.
480*7c568831SAndroid Build Coastguard Worker */
481*7c568831SAndroid Build Coastguard Worker if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) {
482*7c568831SAndroid Build Coastguard Worker xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START,
483*7c568831SAndroid Build Coastguard Worker "warning: ChildSeq not starting by /1\n", NULL);
484*7c568831SAndroid Build Coastguard Worker }
485*7c568831SAndroid Build Coastguard Worker
486*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
487*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathNewString(name));
488*7c568831SAndroid Build Coastguard Worker xmlFree(name);
489*7c568831SAndroid Build Coastguard Worker xmlXPathIdFunction(ctxt, 1);
490*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
491*7c568831SAndroid Build Coastguard Worker }
492*7c568831SAndroid Build Coastguard Worker
493*7c568831SAndroid Build Coastguard Worker while (CUR == '/') {
494*7c568831SAndroid Build Coastguard Worker int child = 0, overflow = 0;
495*7c568831SAndroid Build Coastguard Worker NEXT;
496*7c568831SAndroid Build Coastguard Worker
497*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
498*7c568831SAndroid Build Coastguard Worker int d = CUR - '0';
499*7c568831SAndroid Build Coastguard Worker if (child > INT_MAX / 10)
500*7c568831SAndroid Build Coastguard Worker overflow = 1;
501*7c568831SAndroid Build Coastguard Worker else
502*7c568831SAndroid Build Coastguard Worker child *= 10;
503*7c568831SAndroid Build Coastguard Worker if (child > INT_MAX - d)
504*7c568831SAndroid Build Coastguard Worker overflow = 1;
505*7c568831SAndroid Build Coastguard Worker else
506*7c568831SAndroid Build Coastguard Worker child += d;
507*7c568831SAndroid Build Coastguard Worker NEXT;
508*7c568831SAndroid Build Coastguard Worker }
509*7c568831SAndroid Build Coastguard Worker if (overflow)
510*7c568831SAndroid Build Coastguard Worker child = 0;
511*7c568831SAndroid Build Coastguard Worker xmlXPtrGetChildNo(ctxt, child);
512*7c568831SAndroid Build Coastguard Worker }
513*7c568831SAndroid Build Coastguard Worker }
514*7c568831SAndroid Build Coastguard Worker
515*7c568831SAndroid Build Coastguard Worker
516*7c568831SAndroid Build Coastguard Worker /**
517*7c568831SAndroid Build Coastguard Worker * xmlXPtrEvalXPointer:
518*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPointer Parser context
519*7c568831SAndroid Build Coastguard Worker *
520*7c568831SAndroid Build Coastguard Worker * XPointer ::= Name
521*7c568831SAndroid Build Coastguard Worker * | ChildSeq
522*7c568831SAndroid Build Coastguard Worker * | FullXPtr
523*7c568831SAndroid Build Coastguard Worker *
524*7c568831SAndroid Build Coastguard Worker * Parse and evaluate an XPointer
525*7c568831SAndroid Build Coastguard Worker */
526*7c568831SAndroid Build Coastguard Worker static void
xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt)527*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
528*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
529*7c568831SAndroid Build Coastguard Worker /* Allocate the value stack */
530*7c568831SAndroid Build Coastguard Worker ctxt->valueTab = (xmlXPathObjectPtr *)
531*7c568831SAndroid Build Coastguard Worker xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
532*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
533*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
534*7c568831SAndroid Build Coastguard Worker return;
535*7c568831SAndroid Build Coastguard Worker }
536*7c568831SAndroid Build Coastguard Worker ctxt->valueNr = 0;
537*7c568831SAndroid Build Coastguard Worker ctxt->valueMax = 10;
538*7c568831SAndroid Build Coastguard Worker ctxt->value = NULL;
539*7c568831SAndroid Build Coastguard Worker }
540*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
541*7c568831SAndroid Build Coastguard Worker if (CUR == '/') {
542*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
543*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalChildSeq(ctxt, NULL);
544*7c568831SAndroid Build Coastguard Worker } else {
545*7c568831SAndroid Build Coastguard Worker xmlChar *name;
546*7c568831SAndroid Build Coastguard Worker
547*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseName(ctxt);
548*7c568831SAndroid Build Coastguard Worker if (name == NULL)
549*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
550*7c568831SAndroid Build Coastguard Worker if (CUR == '(') {
551*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalFullXPtr(ctxt, name);
552*7c568831SAndroid Build Coastguard Worker /* Short evaluation */
553*7c568831SAndroid Build Coastguard Worker return;
554*7c568831SAndroid Build Coastguard Worker } else {
555*7c568831SAndroid Build Coastguard Worker /* this handle both Bare Names and Child Sequences */
556*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalChildSeq(ctxt, name);
557*7c568831SAndroid Build Coastguard Worker }
558*7c568831SAndroid Build Coastguard Worker }
559*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
560*7c568831SAndroid Build Coastguard Worker if (CUR != 0)
561*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
562*7c568831SAndroid Build Coastguard Worker }
563*7c568831SAndroid Build Coastguard Worker
564*7c568831SAndroid Build Coastguard Worker
565*7c568831SAndroid Build Coastguard Worker /************************************************************************
566*7c568831SAndroid Build Coastguard Worker * *
567*7c568831SAndroid Build Coastguard Worker * General routines *
568*7c568831SAndroid Build Coastguard Worker * *
569*7c568831SAndroid Build Coastguard Worker ************************************************************************/
570*7c568831SAndroid Build Coastguard Worker
571*7c568831SAndroid Build Coastguard Worker /**
572*7c568831SAndroid Build Coastguard Worker * xmlXPtrNewContext:
573*7c568831SAndroid Build Coastguard Worker * @doc: the XML document
574*7c568831SAndroid Build Coastguard Worker * @here: the node that directly contains the XPointer being evaluated or NULL
575*7c568831SAndroid Build Coastguard Worker * @origin: the element from which a user or program initiated traversal of
576*7c568831SAndroid Build Coastguard Worker * the link, or NULL.
577*7c568831SAndroid Build Coastguard Worker *
578*7c568831SAndroid Build Coastguard Worker * Create a new XPointer context
579*7c568831SAndroid Build Coastguard Worker *
580*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathContext just allocated.
581*7c568831SAndroid Build Coastguard Worker */
582*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr
xmlXPtrNewContext(xmlDocPtr doc,xmlNodePtr here,xmlNodePtr origin)583*7c568831SAndroid Build Coastguard Worker xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
584*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ret;
585*7c568831SAndroid Build Coastguard Worker (void) here;
586*7c568831SAndroid Build Coastguard Worker (void) origin;
587*7c568831SAndroid Build Coastguard Worker
588*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewContext(doc);
589*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
590*7c568831SAndroid Build Coastguard Worker return(ret);
591*7c568831SAndroid Build Coastguard Worker
592*7c568831SAndroid Build Coastguard Worker return(ret);
593*7c568831SAndroid Build Coastguard Worker }
594*7c568831SAndroid Build Coastguard Worker
595*7c568831SAndroid Build Coastguard Worker /**
596*7c568831SAndroid Build Coastguard Worker * xmlXPtrEval:
597*7c568831SAndroid Build Coastguard Worker * @str: the XPointer expression
598*7c568831SAndroid Build Coastguard Worker * @ctx: the XPointer context
599*7c568831SAndroid Build Coastguard Worker *
600*7c568831SAndroid Build Coastguard Worker * Evaluate the XPath Location Path in the given context.
601*7c568831SAndroid Build Coastguard Worker *
602*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
603*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
604*7c568831SAndroid Build Coastguard Worker */
605*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPtrEval(const xmlChar * str,xmlXPathContextPtr ctx)606*7c568831SAndroid Build Coastguard Worker xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
607*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr ctxt;
608*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr res = NULL, tmp;
609*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr init = NULL;
610*7c568831SAndroid Build Coastguard Worker int stack = 0;
611*7c568831SAndroid Build Coastguard Worker
612*7c568831SAndroid Build Coastguard Worker xmlInitParser();
613*7c568831SAndroid Build Coastguard Worker
614*7c568831SAndroid Build Coastguard Worker if ((ctx == NULL) || (str == NULL))
615*7c568831SAndroid Build Coastguard Worker return(NULL);
616*7c568831SAndroid Build Coastguard Worker
617*7c568831SAndroid Build Coastguard Worker xmlResetError(&ctx->lastError);
618*7c568831SAndroid Build Coastguard Worker
619*7c568831SAndroid Build Coastguard Worker ctxt = xmlXPathNewParserContext(str, ctx);
620*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) {
621*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctx);
622*7c568831SAndroid Build Coastguard Worker return(NULL);
623*7c568831SAndroid Build Coastguard Worker }
624*7c568831SAndroid Build Coastguard Worker xmlXPtrEvalXPointer(ctxt);
625*7c568831SAndroid Build Coastguard Worker if (ctx->lastError.code != XML_ERR_OK)
626*7c568831SAndroid Build Coastguard Worker goto error;
627*7c568831SAndroid Build Coastguard Worker
628*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
629*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_NODESET)) {
630*7c568831SAndroid Build Coastguard Worker xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED,
631*7c568831SAndroid Build Coastguard Worker "xmlXPtrEval: evaluation failed to return a node set\n",
632*7c568831SAndroid Build Coastguard Worker NULL);
633*7c568831SAndroid Build Coastguard Worker } else {
634*7c568831SAndroid Build Coastguard Worker res = valuePop(ctxt);
635*7c568831SAndroid Build Coastguard Worker }
636*7c568831SAndroid Build Coastguard Worker
637*7c568831SAndroid Build Coastguard Worker do {
638*7c568831SAndroid Build Coastguard Worker tmp = valuePop(ctxt);
639*7c568831SAndroid Build Coastguard Worker if (tmp != NULL) {
640*7c568831SAndroid Build Coastguard Worker if (tmp != init) {
641*7c568831SAndroid Build Coastguard Worker if (tmp->type == XPATH_NODESET) {
642*7c568831SAndroid Build Coastguard Worker /*
643*7c568831SAndroid Build Coastguard Worker * Evaluation may push a root nodeset which is unused
644*7c568831SAndroid Build Coastguard Worker */
645*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set;
646*7c568831SAndroid Build Coastguard Worker set = tmp->nodesetval;
647*7c568831SAndroid Build Coastguard Worker if ((set == NULL) || (set->nodeNr != 1) ||
648*7c568831SAndroid Build Coastguard Worker (set->nodeTab[0] != (xmlNodePtr) ctx->doc))
649*7c568831SAndroid Build Coastguard Worker stack++;
650*7c568831SAndroid Build Coastguard Worker } else
651*7c568831SAndroid Build Coastguard Worker stack++;
652*7c568831SAndroid Build Coastguard Worker }
653*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(tmp);
654*7c568831SAndroid Build Coastguard Worker }
655*7c568831SAndroid Build Coastguard Worker } while (tmp != NULL);
656*7c568831SAndroid Build Coastguard Worker if (stack != 0) {
657*7c568831SAndroid Build Coastguard Worker xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS,
658*7c568831SAndroid Build Coastguard Worker "xmlXPtrEval: object(s) left on the eval stack\n",
659*7c568831SAndroid Build Coastguard Worker NULL);
660*7c568831SAndroid Build Coastguard Worker }
661*7c568831SAndroid Build Coastguard Worker if (ctx->lastError.code != XML_ERR_OK) {
662*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(res);
663*7c568831SAndroid Build Coastguard Worker res = NULL;
664*7c568831SAndroid Build Coastguard Worker }
665*7c568831SAndroid Build Coastguard Worker
666*7c568831SAndroid Build Coastguard Worker error:
667*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(ctxt);
668*7c568831SAndroid Build Coastguard Worker return(res);
669*7c568831SAndroid Build Coastguard Worker }
670*7c568831SAndroid Build Coastguard Worker
671*7c568831SAndroid Build Coastguard Worker #endif
672*7c568831SAndroid Build Coastguard Worker
673