xref: /aosp_15_r20/external/libxml2/xpointer.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
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