ReactOS 0.4.15-dev-7953-g1f49173
xpointer.c
Go to the documentation of this file.
1/*
2 * xpointer.c : Code to handle XML Pointer
3 *
4 * Base implementation was made accordingly to
5 * W3C Candidate Recommendation 7 June 2000
6 * http://www.w3.org/TR/2000/CR-xptr-20000607
7 *
8 * Added support for the element() scheme described in:
9 * W3C Proposed Recommendation 13 November 2002
10 * http://www.w3.org/TR/2002/PR-xptr-element-20021113/
11 *
12 * See Copyright for the status of this software.
13 *
14 * daniel@veillard.com
15 */
16
17/* To avoid EBCDIC trouble when parsing on zOS */
18#if defined(__MVS__)
19#pragma convert("ISO8859-1")
20#endif
21
22#define IN_LIBXML
23#include "libxml.h"
24
25/*
26 * TODO: better handling of error cases, the full expression should
27 * be parsed beforehand instead of a progressive evaluation
28 * TODO: Access into entities references are not supported now ...
29 * need a start to be able to pop out of entities refs since
30 * parent is the entity declaration, not the ref.
31 */
32
33#include <string.h>
34#include <libxml/xpointer.h>
35#include <libxml/xmlmemory.h>
37#include <libxml/uri.h>
38#include <libxml/xpath.h>
40#include <libxml/xmlerror.h>
41#include <libxml/globals.h>
42
43#ifdef LIBXML_XPTR_ENABLED
44
45/* Add support of the xmlns() xpointer scheme to initialize the namespaces */
46#define XPTR_XMLNS_SCHEME
47
48/* #define DEBUG_RANGES */
49#ifdef DEBUG_RANGES
50#ifdef LIBXML_DEBUG_ENABLED
51#include <libxml/debugXML.h>
52#endif
53#endif
54
55#define TODO \
56 xmlGenericError(xmlGenericErrorContext, \
57 "Unimplemented block at %s:%d\n", \
58 __FILE__, __LINE__);
59
60#define STRANGE \
61 xmlGenericError(xmlGenericErrorContext, \
62 "Internal error at %s:%d\n", \
63 __FILE__, __LINE__);
64
65/************************************************************************
66 * *
67 * Some factorized error routines *
68 * *
69 ************************************************************************/
70
77static void
78xmlXPtrErrMemory(const char *extra)
79{
80 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER,
82 NULL, NULL, 0, 0,
83 "Memory allocation failed : %s\n", extra);
84}
85
93static void LIBXML_ATTR_FORMAT(3,0)
94xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
95 const char * msg, const xmlChar *extra)
96{
97 if (ctxt != NULL)
98 ctxt->error = error;
99 if ((ctxt == NULL) || (ctxt->context == NULL)) {
100 __xmlRaiseError(NULL, NULL, NULL,
103 (const char *) extra, NULL, NULL, 0, 0,
104 msg, extra);
105 return;
106 }
107
108 /* cleanup current last error */
109 xmlResetError(&ctxt->context->lastError);
110
111 ctxt->context->lastError.domain = XML_FROM_XPOINTER;
112 ctxt->context->lastError.code = error;
113 ctxt->context->lastError.level = XML_ERR_ERROR;
114 ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
115 ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
116 ctxt->context->lastError.node = ctxt->context->debugNode;
117 if (ctxt->context->error != NULL) {
118 ctxt->context->error(ctxt->context->userData,
119 &ctxt->context->lastError);
120 } else {
121 __xmlRaiseError(NULL, NULL, NULL,
122 NULL, ctxt->context->debugNode, XML_FROM_XPOINTER,
124 (const char *) extra, (const char *) ctxt->base, NULL,
125 ctxt->cur - ctxt->base, 0,
126 msg, extra);
127 }
128}
129
130/************************************************************************
131 * *
132 * A few helper functions for child sequences *
133 * *
134 ************************************************************************/
135#ifdef LIBXML_XPTR_LOCS_ENABLED
136/* xmlXPtrAdvanceNode is a private function, but used by xinclude.c */
137xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level);
144static int
145xmlXPtrGetArity(xmlNodePtr cur) {
146 int i;
147 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
148 return(-1);
149 cur = cur->children;
150 for (i = 0;cur != NULL;cur = cur->next) {
151 if ((cur->type == XML_ELEMENT_NODE) ||
152 (cur->type == XML_DOCUMENT_NODE) ||
153 (cur->type == XML_HTML_DOCUMENT_NODE)) {
154 i++;
155 }
156 }
157 return(i);
158}
159
167static int
168xmlXPtrGetIndex(xmlNodePtr cur) {
169 int i;
170 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
171 return(-1);
172 for (i = 1;cur != NULL;cur = cur->prev) {
173 if ((cur->type == XML_ELEMENT_NODE) ||
174 (cur->type == XML_DOCUMENT_NODE) ||
175 (cur->type == XML_HTML_DOCUMENT_NODE)) {
176 i++;
177 }
178 }
179 return(i);
180}
181#endif /* LIBXML_XPTR_LOCS_ENABLED */
182
190static xmlNodePtr
191xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
192 int i;
193 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
194 return(cur);
195 cur = cur->children;
196 for (i = 0;i <= no;cur = cur->next) {
197 if (cur == NULL)
198 return(cur);
199 if ((cur->type == XML_ELEMENT_NODE) ||
200 (cur->type == XML_DOCUMENT_NODE) ||
201 (cur->type == XML_HTML_DOCUMENT_NODE)) {
202 i++;
203 if (i == no)
204 break;
205 }
206 }
207 return(cur);
208}
209
210#ifdef LIBXML_XPTR_LOCS_ENABLED
211/************************************************************************
212 * *
213 * Handling of XPointer specific types *
214 * *
215 ************************************************************************/
216
229static int
230xmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) {
231 if ((node1 == NULL) || (node2 == NULL))
232 return(-2);
233 /*
234 * a couple of optimizations which will avoid computations in most cases
235 */
236 if (node1 == node2) {
237 if (index1 < index2)
238 return(1);
239 if (index1 > index2)
240 return(-1);
241 return(0);
242 }
243 return(xmlXPathCmpNodes(node1, node2));
244}
245
255static xmlXPathObjectPtr
256xmlXPtrNewPoint(xmlNodePtr node, int indx) {
257 xmlXPathObjectPtr ret;
258
259 if (node == NULL)
260 return(NULL);
261 if (indx < 0)
262 return(NULL);
263
264 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
265 if (ret == NULL) {
266 xmlXPtrErrMemory("allocating point");
267 return(NULL);
268 }
269 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
270 ret->type = XPATH_POINT;
271 ret->user = (void *) node;
272 ret->index = indx;
273 return(ret);
274}
275
282static void
283xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) {
284 int tmp;
285 xmlNodePtr tmp2;
286 if (range == NULL)
287 return;
288 if (range->type != XPATH_RANGE)
289 return;
290 if (range->user2 == NULL)
291 return;
292 tmp = xmlXPtrCmpPoints(range->user, range->index,
293 range->user2, range->index2);
294 if (tmp == -1) {
295 tmp2 = range->user;
296 range->user = range->user2;
297 range->user2 = tmp2;
298 tmp = range->index;
299 range->index = range->index2;
300 range->index2 = tmp;
301 }
302}
303
313static int
314xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
315 if (range1 == range2)
316 return(1);
317 if ((range1 == NULL) || (range2 == NULL))
318 return(0);
319 if (range1->type != range2->type)
320 return(0);
321 if (range1->type != XPATH_RANGE)
322 return(0);
323 if (range1->user != range2->user)
324 return(0);
325 if (range1->index != range2->index)
326 return(0);
327 if (range1->user2 != range2->user2)
328 return(0);
329 if (range1->index2 != range2->index2)
330 return(0);
331 return(1);
332}
333
345static xmlXPathObjectPtr
346xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
347 xmlNodePtr end, int endindex) {
348 xmlXPathObjectPtr ret;
349
350 /*
351 * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
352 * Disallow them for now.
353 */
354 if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
355 return(NULL);
356 if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
357 return(NULL);
358
359 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
360 if (ret == NULL) {
361 xmlXPtrErrMemory("allocating range");
362 return(NULL);
363 }
364 memset(ret, 0, sizeof(xmlXPathObject));
365 ret->type = XPATH_RANGE;
366 ret->user = start;
367 ret->index = startindex;
368 ret->user2 = end;
369 ret->index2 = endindex;
370 return(ret);
371}
372
384xmlXPathObjectPtr
385xmlXPtrNewRange(xmlNodePtr start, int startindex,
386 xmlNodePtr end, int endindex) {
387 xmlXPathObjectPtr ret;
388
389 if (start == NULL)
390 return(NULL);
391 if (end == NULL)
392 return(NULL);
393 if (startindex < 0)
394 return(NULL);
395 if (endindex < 0)
396 return(NULL);
397
398 ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
399 xmlXPtrRangeCheckOrder(ret);
400 return(ret);
401}
402
412xmlXPathObjectPtr
413xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
414 xmlXPathObjectPtr ret;
415
416 if (start == NULL)
417 return(NULL);
418 if (end == NULL)
419 return(NULL);
420 if (start->type != XPATH_POINT)
421 return(NULL);
422 if (end->type != XPATH_POINT)
423 return(NULL);
424
425 ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
426 end->index);
427 xmlXPtrRangeCheckOrder(ret);
428 return(ret);
429}
430
440xmlXPathObjectPtr
441xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
442 xmlXPathObjectPtr ret;
443
444 if (start == NULL)
445 return(NULL);
446 if (end == NULL)
447 return(NULL);
448 if (start->type != XPATH_POINT)
449 return(NULL);
450
451 ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
452 xmlXPtrRangeCheckOrder(ret);
453 return(ret);
454}
455
465xmlXPathObjectPtr
466xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
467 xmlXPathObjectPtr ret;
468
469 if (start == NULL)
470 return(NULL);
471 if (end == NULL)
472 return(NULL);
473 if (end->type != XPATH_POINT)
474 return(NULL);
475
476 ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
477 xmlXPtrRangeCheckOrder(ret);
478 return(ret);
479}
480
490xmlXPathObjectPtr
491xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
492 xmlXPathObjectPtr ret;
493
494 if (start == NULL)
495 return(NULL);
496 if (end == NULL)
497 return(NULL);
498
499 ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
500 xmlXPtrRangeCheckOrder(ret);
501 return(ret);
502}
503
512xmlXPathObjectPtr
513xmlXPtrNewCollapsedRange(xmlNodePtr start) {
514 xmlXPathObjectPtr ret;
515
516 if (start == NULL)
517 return(NULL);
518
519 ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
520 return(ret);
521}
522
532xmlXPathObjectPtr
533xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
534 xmlNodePtr endNode;
535 int endIndex;
536 xmlXPathObjectPtr ret;
537
538 if (start == NULL)
539 return(NULL);
540 if (end == NULL)
541 return(NULL);
542 switch (end->type) {
543 case XPATH_POINT:
544 endNode = end->user;
545 endIndex = end->index;
546 break;
547 case XPATH_RANGE:
548 endNode = end->user2;
549 endIndex = end->index2;
550 break;
551 case XPATH_NODESET:
552 /*
553 * Empty set ...
554 */
555 if ((end->nodesetval == NULL) || (end->nodesetval->nodeNr <= 0))
556 return(NULL);
557 endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
558 endIndex = -1;
559 break;
560 default:
561 /* TODO */
562 return(NULL);
563 }
564
565 ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
566 xmlXPtrRangeCheckOrder(ret);
567 return(ret);
568}
569
570#define XML_RANGESET_DEFAULT 10
571
580xmlLocationSetPtr
581xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
582 xmlLocationSetPtr ret;
583
584 ret = (xmlLocationSetPtr) xmlMalloc(sizeof(xmlLocationSet));
585 if (ret == NULL) {
586 xmlXPtrErrMemory("allocating locationset");
587 return(NULL);
588 }
589 memset(ret, 0 , (size_t) sizeof(xmlLocationSet));
590 if (val != NULL) {
591 ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
592 sizeof(xmlXPathObjectPtr));
593 if (ret->locTab == NULL) {
594 xmlXPtrErrMemory("allocating locationset");
595 xmlFree(ret);
596 return(NULL);
597 }
598 memset(ret->locTab, 0 ,
599 XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
600 ret->locMax = XML_RANGESET_DEFAULT;
601 ret->locTab[ret->locNr++] = val;
602 }
603 return(ret);
604}
605
614void
615xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
616 int i;
617
618 if ((cur == NULL) || (val == NULL)) return;
619
620 /*
621 * check against doublons
622 */
623 for (i = 0;i < cur->locNr;i++) {
624 if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
625 xmlXPathFreeObject(val);
626 return;
627 }
628 }
629
630 /*
631 * grow the locTab if needed
632 */
633 if (cur->locMax == 0) {
634 cur->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
635 sizeof(xmlXPathObjectPtr));
636 if (cur->locTab == NULL) {
637 xmlXPtrErrMemory("adding location to set");
638 return;
639 }
640 memset(cur->locTab, 0 ,
641 XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
642 cur->locMax = XML_RANGESET_DEFAULT;
643 } else if (cur->locNr == cur->locMax) {
644 xmlXPathObjectPtr *temp;
645
646 cur->locMax *= 2;
647 temp = (xmlXPathObjectPtr *) xmlRealloc(cur->locTab, cur->locMax *
648 sizeof(xmlXPathObjectPtr));
649 if (temp == NULL) {
650 xmlXPtrErrMemory("adding location to set");
651 return;
652 }
653 cur->locTab = temp;
654 }
655 cur->locTab[cur->locNr++] = val;
656}
657
667xmlLocationSetPtr
668xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) {
669 int i;
670
671 if (val1 == NULL) return(NULL);
672 if (val2 == NULL) return(val1);
673
674 /*
675 * !!!!! this can be optimized a lot, knowing that both
676 * val1 and val2 already have unicity of their values.
677 */
678
679 for (i = 0;i < val2->locNr;i++)
680 xmlXPtrLocationSetAdd(val1, val2->locTab[i]);
681
682 return(val1);
683}
684
692void
693xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
694 int i;
695
696 if (cur == NULL) return;
697 if (val == NULL) return;
698
699 /*
700 * check against doublons
701 */
702 for (i = 0;i < cur->locNr;i++)
703 if (cur->locTab[i] == val) break;
704
705 if (i >= cur->locNr) {
706#ifdef DEBUG
708 "xmlXPtrLocationSetDel: Range wasn't found in RangeList\n");
709#endif
710 return;
711 }
712 cur->locNr--;
713 for (;i < cur->locNr;i++)
714 cur->locTab[i] = cur->locTab[i + 1];
715 cur->locTab[cur->locNr] = NULL;
716}
717
725void
726xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val) {
727 if (cur == NULL) return;
728 if (val >= cur->locNr) return;
729 cur->locNr--;
730 for (;val < cur->locNr;val++)
731 cur->locTab[val] = cur->locTab[val + 1];
732 cur->locTab[cur->locNr] = NULL;
733}
734
741void
742xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
743 int i;
744
745 if (obj == NULL) return;
746 if (obj->locTab != NULL) {
747 for (i = 0;i < obj->locNr; i++) {
748 xmlXPathFreeObject(obj->locTab[i]);
749 }
750 xmlFree(obj->locTab);
751 }
752 xmlFree(obj);
753}
754
765xmlXPathObjectPtr
766xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) {
767 xmlXPathObjectPtr ret;
768
769 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
770 if (ret == NULL) {
771 xmlXPtrErrMemory("allocating locationset");
772 return(NULL);
773 }
774 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
775 ret->type = XPATH_LOCATIONSET;
776 if (end == NULL)
777 ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start));
778 else
779 ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewRangeNodes(start,end));
780 return(ret);
781}
782
792xmlXPathObjectPtr
793xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) {
794 xmlXPathObjectPtr ret;
795
796 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
797 if (ret == NULL) {
798 xmlXPtrErrMemory("allocating locationset");
799 return(NULL);
800 }
801 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
802 ret->type = XPATH_LOCATIONSET;
803 if (set != NULL) {
804 int i;
805 xmlLocationSetPtr newset;
806
807 newset = xmlXPtrLocationSetCreate(NULL);
808 if (newset == NULL)
809 return(ret);
810
811 for (i = 0;i < set->nodeNr;i++)
812 xmlXPtrLocationSetAdd(newset,
813 xmlXPtrNewCollapsedRange(set->nodeTab[i]));
814
815 ret->user = (void *) newset;
816 }
817 return(ret);
818}
819
828xmlXPathObjectPtr
829xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
830 xmlXPathObjectPtr ret;
831
832 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
833 if (ret == NULL) {
834 xmlXPtrErrMemory("allocating locationset");
835 return(NULL);
836 }
837 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
838 ret->type = XPATH_LOCATIONSET;
839 ret->user = (void *) val;
840 return(ret);
841}
842#endif /* LIBXML_XPTR_LOCS_ENABLED */
843
844/************************************************************************
845 * *
846 * The parser *
847 * *
848 ************************************************************************/
849
850static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
851
852/*
853 * Macros for accessing the content. Those should be used only by the parser,
854 * and not exported.
855 *
856 * Dirty macros, i.e. one need to make assumption on the context to use them
857 *
858 * CUR returns the current xmlChar value, i.e. a 8 bit value
859 * in ISO-Latin or UTF-8.
860 * This should be used internally by the parser
861 * only to compare to ASCII values otherwise it would break when
862 * running with UTF-8 encoding.
863 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
864 * to compare on ASCII based substring.
865 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
866 * strings within the parser.
867 * CURRENT Returns the current char value, with the full decoding of
868 * UTF-8 if we are using this mode. It returns an int.
869 * NEXT Skip to the next character, this does the proper decoding
870 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
871 * It returns the pointer to the current xmlChar.
872 */
873
874#define CUR (*ctxt->cur)
875#define SKIP(val) ctxt->cur += (val)
876#define NXT(val) ctxt->cur[(val)]
877
878#define SKIP_BLANKS \
879 while (IS_BLANK_CH(*(ctxt->cur))) NEXT
880
881#define CURRENT (*ctxt->cur)
882#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
883
884/*
885 * xmlXPtrGetChildNo:
886 * @ctxt: the XPointer Parser context
887 * @index: the child number
888 *
889 * Move the current node of the nodeset on the stack to the
890 * given child if found
891 */
892static void
893xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) {
895 xmlXPathObjectPtr obj;
896 xmlNodeSetPtr oldset;
897
898 CHECK_TYPE(XPATH_NODESET);
899 obj = valuePop(ctxt);
900 oldset = obj->nodesetval;
901 if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) {
902 xmlXPathFreeObject(obj);
903 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
904 return;
905 }
906 cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx);
907 if (cur == NULL) {
908 xmlXPathFreeObject(obj);
909 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
910 return;
911 }
912 oldset->nodeTab[0] = cur;
913 valuePush(ctxt, obj);
914}
915
950static void
951xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
952 xmlChar *buffer, *cur;
953 int len;
954 int level;
955
956 if (name == NULL)
957 name = xmlXPathParseName(ctxt);
958 if (name == NULL)
959 XP_ERROR(XPATH_EXPR_ERROR);
960
961 if (CUR != '(') {
962 xmlFree(name);
963 XP_ERROR(XPATH_EXPR_ERROR);
964 }
965 NEXT;
966 level = 1;
967
968 len = xmlStrlen(ctxt->cur);
969 len++;
970 buffer = (xmlChar *) xmlMallocAtomic(len * sizeof (xmlChar));
971 if (buffer == NULL) {
972 xmlXPtrErrMemory("allocating buffer");
973 xmlFree(name);
974 return;
975 }
976
977 cur = buffer;
978 while (CUR != 0) {
979 if (CUR == ')') {
980 level--;
981 if (level == 0) {
982 NEXT;
983 break;
984 }
985 } else if (CUR == '(') {
986 level++;
987 } else if (CUR == '^') {
988 if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
989 NEXT;
990 }
991 }
992 *cur++ = CUR;
993 NEXT;
994 }
995 *cur = 0;
996
997 if ((level != 0) && (CUR == 0)) {
998 xmlFree(name);
1000 XP_ERROR(XPTR_SYNTAX_ERROR);
1001 }
1002
1003 if (xmlStrEqual(name, (xmlChar *) "xpointer") ||
1004 xmlStrEqual(name, (xmlChar *) "xpath1")) {
1005 const xmlChar *oldBase = ctxt->base;
1006 const xmlChar *oldCur = ctxt->cur;
1007
1008 ctxt->cur = ctxt->base = buffer;
1009 /*
1010 * To evaluate an xpointer scheme element (4.3) we need:
1011 * context initialized to the root
1012 * context position initialized to 1
1013 * context size initialized to 1
1014 */
1015 ctxt->context->node = (xmlNodePtr)ctxt->context->doc;
1016 ctxt->context->proximityPosition = 1;
1017 ctxt->context->contextSize = 1;
1018#ifdef LIBXML_XPTR_LOCS_ENABLED
1019 ctxt->xptr = xmlStrEqual(name, (xmlChar *) "xpointer");
1020#endif
1021 xmlXPathEvalExpr(ctxt);
1022 ctxt->base = oldBase;
1023 ctxt->cur = oldCur;
1024 } else if (xmlStrEqual(name, (xmlChar *) "element")) {
1025 const xmlChar *oldBase = ctxt->base;
1026 const xmlChar *oldCur = ctxt->cur;
1027 xmlChar *name2;
1028
1029 ctxt->cur = ctxt->base = buffer;
1030 if (buffer[0] == '/') {
1031 xmlXPathRoot(ctxt);
1032 xmlXPtrEvalChildSeq(ctxt, NULL);
1033 } else {
1034 name2 = xmlXPathParseName(ctxt);
1035 if (name2 == NULL) {
1036 ctxt->base = oldBase;
1037 ctxt->cur = oldCur;
1038 xmlFree(buffer);
1039 xmlFree(name);
1040 XP_ERROR(XPATH_EXPR_ERROR);
1041 }
1042 xmlXPtrEvalChildSeq(ctxt, name2);
1043 }
1044 ctxt->base = oldBase;
1045 ctxt->cur = oldCur;
1046#ifdef XPTR_XMLNS_SCHEME
1047 } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
1048 const xmlChar *oldBase = ctxt->base;
1049 const xmlChar *oldCur = ctxt->cur;
1050 xmlChar *prefix;
1051
1052 ctxt->cur = ctxt->base = buffer;
1053 prefix = xmlXPathParseNCName(ctxt);
1054 if (prefix == NULL) {
1055 ctxt->base = oldBase;
1056 ctxt->cur = oldCur;
1057 xmlFree(buffer);
1058 xmlFree(name);
1059 XP_ERROR(XPTR_SYNTAX_ERROR);
1060 }
1062 if (CUR != '=') {
1063 ctxt->base = oldBase;
1064 ctxt->cur = oldCur;
1065 xmlFree(prefix);
1066 xmlFree(buffer);
1067 xmlFree(name);
1068 XP_ERROR(XPTR_SYNTAX_ERROR);
1069 }
1070 NEXT;
1072
1073 xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur);
1074 ctxt->base = oldBase;
1075 ctxt->cur = oldCur;
1076 xmlFree(prefix);
1077#endif /* XPTR_XMLNS_SCHEME */
1078 } else {
1079 xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME,
1080 "unsupported scheme '%s'\n", name);
1081 }
1082 xmlFree(buffer);
1083 xmlFree(name);
1084}
1085
1113static void
1114xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1115 if (name == NULL)
1116 name = xmlXPathParseName(ctxt);
1117 if (name == NULL)
1118 XP_ERROR(XPATH_EXPR_ERROR);
1119 while (name != NULL) {
1120 ctxt->error = XPATH_EXPRESSION_OK;
1121 xmlXPtrEvalXPtrPart(ctxt, name);
1122
1123 /* in case of syntax error, break here */
1124 if ((ctxt->error != XPATH_EXPRESSION_OK) &&
1125 (ctxt->error != XML_XPTR_UNKNOWN_SCHEME))
1126 return;
1127
1128 /*
1129 * If the returned value is a non-empty nodeset
1130 * or location set, return here.
1131 */
1132 if (ctxt->value != NULL) {
1133 xmlXPathObjectPtr obj = ctxt->value;
1134
1135 switch (obj->type) {
1136#ifdef LIBXML_XPTR_LOCS_ENABLED
1137 case XPATH_LOCATIONSET: {
1138 xmlLocationSetPtr loc = ctxt->value->user;
1139 if ((loc != NULL) && (loc->locNr > 0))
1140 return;
1141 break;
1142 }
1143#endif
1144 case XPATH_NODESET: {
1145 xmlNodeSetPtr loc = ctxt->value->nodesetval;
1146 if ((loc != NULL) && (loc->nodeNr > 0))
1147 return;
1148 break;
1149 }
1150 default:
1151 break;
1152 }
1153
1154 /*
1155 * Evaluating to improper values is equivalent to
1156 * a sub-resource error, clean-up the stack
1157 */
1158 do {
1159 obj = valuePop(ctxt);
1160 if (obj != NULL) {
1161 xmlXPathFreeObject(obj);
1162 }
1163 } while (obj != NULL);
1164 }
1165
1166 /*
1167 * Is there another XPointer part.
1168 */
1170 name = xmlXPathParseName(ctxt);
1171 }
1172}
1173
1185static void
1186xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1187 /*
1188 * XPointer don't allow by syntax to address in multirooted trees
1189 * this might prove useful in some cases, warn about it.
1190 */
1191 if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) {
1192 xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START,
1193 "warning: ChildSeq not starting by /1\n", NULL);
1194 }
1195
1196 if (name != NULL) {
1197 valuePush(ctxt, xmlXPathNewString(name));
1198 xmlFree(name);
1199 xmlXPathIdFunction(ctxt, 1);
1200 CHECK_ERROR;
1201 }
1202
1203 while (CUR == '/') {
1204 int child = 0, overflow = 0;
1205 NEXT;
1206
1207 while ((CUR >= '0') && (CUR <= '9')) {
1208 int d = CUR - '0';
1209 if (child > INT_MAX / 10)
1210 overflow = 1;
1211 else
1212 child *= 10;
1213 if (child > INT_MAX - d)
1214 overflow = 1;
1215 else
1216 child += d;
1217 NEXT;
1218 }
1219 if (overflow)
1220 child = 0;
1221 xmlXPtrGetChildNo(ctxt, child);
1222 }
1223}
1224
1225
1236static void
1237xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
1238 if (ctxt->valueTab == NULL) {
1239 /* Allocate the value stack */
1240 ctxt->valueTab = (xmlXPathObjectPtr *)
1241 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
1242 if (ctxt->valueTab == NULL) {
1243 xmlXPtrErrMemory("allocating evaluation context");
1244 return;
1245 }
1246 ctxt->valueNr = 0;
1247 ctxt->valueMax = 10;
1248 ctxt->value = NULL;
1249 ctxt->valueFrame = 0;
1250 }
1252 if (CUR == '/') {
1253 xmlXPathRoot(ctxt);
1254 xmlXPtrEvalChildSeq(ctxt, NULL);
1255 } else {
1256 xmlChar *name;
1257
1258 name = xmlXPathParseName(ctxt);
1259 if (name == NULL)
1260 XP_ERROR(XPATH_EXPR_ERROR);
1261 if (CUR == '(') {
1262 xmlXPtrEvalFullXPtr(ctxt, name);
1263 /* Short evaluation */
1264 return;
1265 } else {
1266 /* this handle both Bare Names and Child Sequences */
1267 xmlXPtrEvalChildSeq(ctxt, name);
1268 }
1269 }
1271 if (CUR != 0)
1272 XP_ERROR(XPATH_EXPR_ERROR);
1273}
1274
1275
1276/************************************************************************
1277 * *
1278 * General routines *
1279 * *
1280 ************************************************************************/
1281
1282#ifdef LIBXML_XPTR_LOCS_ENABLED
1283static
1284void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1285static
1286void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1287static
1288void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1289static
1290void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs);
1291static
1292void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs);
1293static
1294void xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs);
1295static
1296void xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1297#endif /* LIBXML_XPTR_LOCS_ENABLED */
1298
1310xmlXPathContextPtr
1311xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
1312 xmlXPathContextPtr ret;
1313 (void) here;
1314 (void) origin;
1315
1316 ret = xmlXPathNewContext(doc);
1317 if (ret == NULL)
1318 return(ret);
1319#ifdef LIBXML_XPTR_LOCS_ENABLED
1320 ret->xptr = 1;
1321 ret->here = here;
1322 ret->origin = origin;
1323
1324 xmlXPathRegisterFunc(ret, (xmlChar *)"range",
1325 xmlXPtrRangeFunction);
1326 xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
1327 xmlXPtrRangeInsideFunction);
1328 xmlXPathRegisterFunc(ret, (xmlChar *)"string-range",
1329 xmlXPtrStringRangeFunction);
1330 xmlXPathRegisterFunc(ret, (xmlChar *)"start-point",
1331 xmlXPtrStartPointFunction);
1332 xmlXPathRegisterFunc(ret, (xmlChar *)"end-point",
1333 xmlXPtrEndPointFunction);
1334 xmlXPathRegisterFunc(ret, (xmlChar *)"here",
1335 xmlXPtrHereFunction);
1336 xmlXPathRegisterFunc(ret, (xmlChar *)" origin",
1337 xmlXPtrOriginFunction);
1338#endif /* LIBXML_XPTR_LOCS_ENABLED */
1339
1340 return(ret);
1341}
1342
1353xmlXPathObjectPtr
1354xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
1355 xmlXPathParserContextPtr ctxt;
1356 xmlXPathObjectPtr res = NULL, tmp;
1357 xmlXPathObjectPtr init = NULL;
1358 int stack = 0;
1359
1360 xmlInitParser();
1361
1362 if ((ctx == NULL) || (str == NULL))
1363 return(NULL);
1364
1365 ctxt = xmlXPathNewParserContext(str, ctx);
1366 if (ctxt == NULL)
1367 return(NULL);
1368 xmlXPtrEvalXPointer(ctxt);
1369
1370 if ((ctxt->value != NULL) &&
1371#ifdef LIBXML_XPTR_LOCS_ENABLED
1372 (ctxt->value->type != XPATH_LOCATIONSET) &&
1373#endif
1374 (ctxt->value->type != XPATH_NODESET)) {
1375 xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED,
1376 "xmlXPtrEval: evaluation failed to return a node set\n",
1377 NULL);
1378 } else {
1379 res = valuePop(ctxt);
1380 }
1381
1382 do {
1383 tmp = valuePop(ctxt);
1384 if (tmp != NULL) {
1385 if (tmp != init) {
1386 if (tmp->type == XPATH_NODESET) {
1387 /*
1388 * Evaluation may push a root nodeset which is unused
1389 */
1390 xmlNodeSetPtr set;
1391 set = tmp->nodesetval;
1392 if ((set == NULL) || (set->nodeNr != 1) ||
1393 (set->nodeTab[0] != (xmlNodePtr) ctx->doc))
1394 stack++;
1395 } else
1396 stack++;
1397 }
1398 xmlXPathFreeObject(tmp);
1399 }
1400 } while (tmp != NULL);
1401 if (stack != 0) {
1402 xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS,
1403 "xmlXPtrEval: object(s) left on the eval stack\n",
1404 NULL);
1405 }
1406 if (ctxt->error != XPATH_EXPRESSION_OK) {
1407 xmlXPathFreeObject(res);
1408 res = NULL;
1409 }
1410
1411 xmlXPathFreeParserContext(ctxt);
1412 return(res);
1413}
1414
1415#ifdef LIBXML_XPTR_LOCS_ENABLED
1425static xmlNodePtr
1426xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
1427 /* pointers to generated nodes */
1428 xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp;
1429 /* pointers to traversal nodes */
1431 int index1, index2;
1432
1433 if (range == NULL)
1434 return(NULL);
1435 if (range->type != XPATH_RANGE)
1436 return(NULL);
1437 start = (xmlNodePtr) range->user;
1438
1439 if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
1440 return(NULL);
1441 end = range->user2;
1442 if (end == NULL)
1443 return(xmlCopyNode(start, 1));
1444 if (end->type == XML_NAMESPACE_DECL)
1445 return(NULL);
1446
1447 cur = start;
1448 index1 = range->index;
1449 index2 = range->index2;
1450 while (cur != NULL) {
1451 if (cur == end) {
1452 if (cur->type == XML_TEXT_NODE) {
1453 const xmlChar *content = cur->content;
1454 int len;
1455
1456 if (content == NULL) {
1457 tmp = xmlNewTextLen(NULL, 0);
1458 } else {
1459 len = index2;
1460 if ((cur == start) && (index1 > 1)) {
1461 content += (index1 - 1);
1462 len -= (index1 - 1);
1463 index1 = 0;
1464 } else {
1465 len = index2;
1466 }
1467 tmp = xmlNewTextLen(content, len);
1468 }
1469 /* single sub text node selection */
1470 if (list == NULL)
1471 return(tmp);
1472 /* prune and return full set */
1473 if (last != NULL)
1474 xmlAddNextSibling(last, tmp);
1475 else
1476 xmlAddChild(parent, tmp);
1477 return(list);
1478 } else {
1479 tmp = xmlCopyNode(cur, 0);
1480 if (list == NULL) {
1481 list = tmp;
1482 parent = tmp;
1483 } else {
1484 if (last != NULL)
1486 else
1487 parent = xmlAddChild(parent, tmp);
1488 }
1489 last = NULL;
1490
1491 if (index2 > 1) {
1492 end = xmlXPtrGetNthChild(cur, index2 - 1);
1493 index2 = 0;
1494 }
1495 if ((cur == start) && (index1 > 1)) {
1496 cur = xmlXPtrGetNthChild(cur, index1 - 1);
1497 index1 = 0;
1498 } else {
1499 cur = cur->children;
1500 }
1501 /*
1502 * Now gather the remaining nodes from cur to end
1503 */
1504 continue; /* while */
1505 }
1506 } else if ((cur == start) &&
1507 (list == NULL) /* looks superfluous but ... */ ) {
1508 if ((cur->type == XML_TEXT_NODE) ||
1509 (cur->type == XML_CDATA_SECTION_NODE)) {
1510 const xmlChar *content = cur->content;
1511
1512 if (content == NULL) {
1513 tmp = xmlNewTextLen(NULL, 0);
1514 } else {
1515 if (index1 > 1) {
1516 content += (index1 - 1);
1517 }
1518 tmp = xmlNewText(content);
1519 }
1520 last = list = tmp;
1521 } else {
1522 if ((cur == start) && (index1 > 1)) {
1523 tmp = xmlCopyNode(cur, 0);
1524 list = tmp;
1525 parent = tmp;
1526 last = NULL;
1527 cur = xmlXPtrGetNthChild(cur, index1 - 1);
1528 index1 = 0;
1529 /*
1530 * Now gather the remaining nodes from cur to end
1531 */
1532 continue; /* while */
1533 }
1534 tmp = xmlCopyNode(cur, 1);
1535 list = tmp;
1536 parent = NULL;
1537 last = tmp;
1538 }
1539 } else {
1540 tmp = NULL;
1541 switch (cur->type) {
1542 case XML_DTD_NODE:
1543 case XML_ELEMENT_DECL:
1544 case XML_ATTRIBUTE_DECL:
1545 case XML_ENTITY_NODE:
1546 /* Do not copy DTD information */
1547 break;
1548 case XML_ENTITY_DECL:
1549 TODO /* handle crossing entities -> stack needed */
1550 break;
1551 case XML_XINCLUDE_START:
1552 case XML_XINCLUDE_END:
1553 /* don't consider it part of the tree content */
1554 break;
1555 case XML_ATTRIBUTE_NODE:
1556 /* Humm, should not happen ! */
1557 STRANGE
1558 break;
1559 default:
1560 tmp = xmlCopyNode(cur, 1);
1561 break;
1562 }
1563 if (tmp != NULL) {
1564 if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1565 STRANGE
1566 return(NULL);
1567 }
1568 if (last != NULL)
1569 xmlAddNextSibling(last, tmp);
1570 else {
1571 last = xmlAddChild(parent, tmp);
1572 }
1573 }
1574 }
1575 /*
1576 * Skip to next node in document order
1577 */
1578 if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1579 STRANGE
1580 return(NULL);
1581 }
1582 cur = xmlXPtrAdvanceNode(cur, NULL);
1583 }
1584 return(list);
1585}
1586
1598xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) {
1600 int i;
1601
1602 if (obj == NULL)
1603 return(NULL);
1604 switch (obj->type) {
1605 case XPATH_NODESET: {
1606 xmlNodeSetPtr set = obj->nodesetval;
1607 if (set == NULL)
1608 return(NULL);
1609 for (i = 0;i < set->nodeNr;i++) {
1610 if (set->nodeTab[i] == NULL)
1611 continue;
1612 switch (set->nodeTab[i]->type) {
1613 case XML_TEXT_NODE:
1615 case XML_ELEMENT_NODE:
1617 case XML_ENTITY_NODE:
1618 case XML_PI_NODE:
1619 case XML_COMMENT_NODE:
1620 case XML_DOCUMENT_NODE:
1622 case XML_XINCLUDE_START:
1623 case XML_XINCLUDE_END:
1624 break;
1625 case XML_ATTRIBUTE_NODE:
1626 case XML_NAMESPACE_DECL:
1629 case XML_NOTATION_NODE:
1630 case XML_DTD_NODE:
1631 case XML_ELEMENT_DECL:
1632 case XML_ATTRIBUTE_DECL:
1633 case XML_ENTITY_DECL:
1634 continue; /* for */
1635 }
1636 if (last == NULL)
1637 list = last = xmlCopyNode(set->nodeTab[i], 1);
1638 else {
1639 xmlAddNextSibling(last, xmlCopyNode(set->nodeTab[i], 1));
1640 if (last->next != NULL)
1641 last = last->next;
1642 }
1643 }
1644 break;
1645 }
1646 case XPATH_LOCATIONSET: {
1647 xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1648 if (set == NULL)
1649 return(NULL);
1650 for (i = 0;i < set->locNr;i++) {
1651 if (last == NULL)
1652 list = last = xmlXPtrBuildNodeList(set->locTab[i]);
1653 else
1655 xmlXPtrBuildNodeList(set->locTab[i]));
1656 if (last != NULL) {
1657 while (last->next != NULL)
1658 last = last->next;
1659 }
1660 }
1661 break;
1662 }
1663 case XPATH_RANGE:
1664 return(xmlXPtrBuildRangeNodeList(obj));
1665 case XPATH_POINT:
1666 return(xmlCopyNode(obj->user, 0));
1667 default:
1668 break;
1669 }
1670 return(list);
1671}
1672
1673/************************************************************************
1674 * *
1675 * XPointer functions *
1676 * *
1677 ************************************************************************/
1678
1688static int
1689xmlXPtrNbLocChildren(xmlNodePtr node) {
1690 int ret = 0;
1691 if (node == NULL)
1692 return(-1);
1693 switch (node->type) {
1695 case XML_DOCUMENT_NODE:
1696 case XML_ELEMENT_NODE:
1697 node = node->children;
1698 while (node != NULL) {
1699 if (node->type == XML_ELEMENT_NODE)
1700 ret++;
1701 node = node->next;
1702 }
1703 break;
1704 case XML_ATTRIBUTE_NODE:
1705 return(-1);
1706
1707 case XML_PI_NODE:
1708 case XML_COMMENT_NODE:
1709 case XML_TEXT_NODE:
1712 ret = xmlStrlen(node->content);
1713 break;
1714 default:
1715 return(-1);
1716 }
1717 return(ret);
1718}
1719
1728static void
1729xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1730 CHECK_ARITY(0);
1731
1732 if (ctxt->context->here == NULL)
1733 XP_ERROR(XPTR_SYNTAX_ERROR);
1734
1735 valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->here, NULL));
1736}
1737
1746static void
1747xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1748 CHECK_ARITY(0);
1749
1750 if (ctxt->context->origin == NULL)
1751 XP_ERROR(XPTR_SYNTAX_ERROR);
1752
1753 valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->origin, NULL));
1754}
1755
1779static void
1780xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1781 xmlXPathObjectPtr tmp, obj, point;
1782 xmlLocationSetPtr newset = NULL;
1783 xmlLocationSetPtr oldset = NULL;
1784
1785 CHECK_ARITY(1);
1786 if ((ctxt->value == NULL) ||
1787 ((ctxt->value->type != XPATH_LOCATIONSET) &&
1788 (ctxt->value->type != XPATH_NODESET)))
1789 XP_ERROR(XPATH_INVALID_TYPE)
1790
1791 obj = valuePop(ctxt);
1792 if (obj->type == XPATH_NODESET) {
1793 /*
1794 * First convert to a location set
1795 */
1796 tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1797 xmlXPathFreeObject(obj);
1798 if (tmp == NULL)
1799 XP_ERROR(XPATH_MEMORY_ERROR)
1800 obj = tmp;
1801 }
1802
1803 newset = xmlXPtrLocationSetCreate(NULL);
1804 if (newset == NULL) {
1805 xmlXPathFreeObject(obj);
1806 XP_ERROR(XPATH_MEMORY_ERROR);
1807 }
1808 oldset = (xmlLocationSetPtr) obj->user;
1809 if (oldset != NULL) {
1810 int i;
1811
1812 for (i = 0; i < oldset->locNr; i++) {
1813 tmp = oldset->locTab[i];
1814 if (tmp == NULL)
1815 continue;
1816 point = NULL;
1817 switch (tmp->type) {
1818 case XPATH_POINT:
1819 point = xmlXPtrNewPoint(tmp->user, tmp->index);
1820 break;
1821 case XPATH_RANGE: {
1822 xmlNodePtr node = tmp->user;
1823 if (node != NULL) {
1824 if ((node->type == XML_ATTRIBUTE_NODE) ||
1825 (node->type == XML_NAMESPACE_DECL)) {
1826 xmlXPathFreeObject(obj);
1827 xmlXPtrFreeLocationSet(newset);
1828 XP_ERROR(XPTR_SYNTAX_ERROR);
1829 }
1830 point = xmlXPtrNewPoint(node, tmp->index);
1831 }
1832 break;
1833 }
1834 default:
1835 /*** Should we raise an error ?
1836 xmlXPathFreeObject(obj);
1837 xmlXPathFreeObject(newset);
1838 XP_ERROR(XPATH_INVALID_TYPE)
1839 ***/
1840 break;
1841 }
1842 if (point != NULL)
1843 xmlXPtrLocationSetAdd(newset, point);
1844 }
1845 }
1846 xmlXPathFreeObject(obj);
1847 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1848}
1849
1875static void
1876xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1877 xmlXPathObjectPtr tmp, obj, point;
1878 xmlLocationSetPtr newset = NULL;
1879 xmlLocationSetPtr oldset = NULL;
1880
1881 CHECK_ARITY(1);
1882 if ((ctxt->value == NULL) ||
1883 ((ctxt->value->type != XPATH_LOCATIONSET) &&
1884 (ctxt->value->type != XPATH_NODESET)))
1885 XP_ERROR(XPATH_INVALID_TYPE)
1886
1887 obj = valuePop(ctxt);
1888 if (obj->type == XPATH_NODESET) {
1889 /*
1890 * First convert to a location set
1891 */
1892 tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1893 xmlXPathFreeObject(obj);
1894 if (tmp == NULL)
1895 XP_ERROR(XPATH_MEMORY_ERROR)
1896 obj = tmp;
1897 }
1898
1899 newset = xmlXPtrLocationSetCreate(NULL);
1900 if (newset == NULL) {
1901 xmlXPathFreeObject(obj);
1902 XP_ERROR(XPATH_MEMORY_ERROR);
1903 }
1904 oldset = (xmlLocationSetPtr) obj->user;
1905 if (oldset != NULL) {
1906 int i;
1907
1908 for (i = 0; i < oldset->locNr; i++) {
1909 tmp = oldset->locTab[i];
1910 if (tmp == NULL)
1911 continue;
1912 point = NULL;
1913 switch (tmp->type) {
1914 case XPATH_POINT:
1915 point = xmlXPtrNewPoint(tmp->user, tmp->index);
1916 break;
1917 case XPATH_RANGE: {
1918 xmlNodePtr node = tmp->user2;
1919 if (node != NULL) {
1920 if ((node->type == XML_ATTRIBUTE_NODE) ||
1921 (node->type == XML_NAMESPACE_DECL)) {
1922 xmlXPathFreeObject(obj);
1923 xmlXPtrFreeLocationSet(newset);
1924 XP_ERROR(XPTR_SYNTAX_ERROR);
1925 }
1926 point = xmlXPtrNewPoint(node, tmp->index2);
1927 } else if (tmp->user == NULL) {
1928 point = xmlXPtrNewPoint(node,
1929 xmlXPtrNbLocChildren(node));
1930 }
1931 break;
1932 }
1933 default:
1934 /*** Should we raise an error ?
1935 xmlXPathFreeObject(obj);
1936 xmlXPathFreeObject(newset);
1937 XP_ERROR(XPATH_INVALID_TYPE)
1938 ***/
1939 break;
1940 }
1941 if (point != NULL)
1942 xmlXPtrLocationSetAdd(newset, point);
1943 }
1944 }
1945 xmlXPathFreeObject(obj);
1946 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1947}
1948
1949
1961static xmlXPathObjectPtr
1962xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
1963 if (loc == NULL)
1964 return(NULL);
1965 if ((ctxt == NULL) || (ctxt->context == NULL) ||
1966 (ctxt->context->doc == NULL))
1967 return(NULL);
1968 switch (loc->type) {
1969 case XPATH_POINT:
1970 return(xmlXPtrNewRange(loc->user, loc->index,
1971 loc->user, loc->index));
1972 case XPATH_RANGE:
1973 if (loc->user2 != NULL) {
1974 return(xmlXPtrNewRange(loc->user, loc->index,
1975 loc->user2, loc->index2));
1976 } else {
1977 xmlNodePtr node = (xmlNodePtr) loc->user;
1978 if (node == (xmlNodePtr) ctxt->context->doc) {
1979 return(xmlXPtrNewRange(node, 0, node,
1980 xmlXPtrGetArity(node)));
1981 } else {
1982 switch (node->type) {
1983 case XML_ATTRIBUTE_NODE:
1984 /* !!! our model is slightly different than XPath */
1985 return(xmlXPtrNewRange(node, 0, node,
1986 xmlXPtrGetArity(node)));
1987 case XML_ELEMENT_NODE:
1988 case XML_TEXT_NODE:
1991 case XML_PI_NODE:
1992 case XML_COMMENT_NODE:
1993 case XML_DOCUMENT_NODE:
1994 case XML_NOTATION_NODE:
1996 int indx = xmlXPtrGetIndex(node);
1997
1998 node = node->parent;
1999 return(xmlXPtrNewRange(node, indx - 1,
2000 node, indx + 1));
2001 }
2002 default:
2003 return(NULL);
2004 }
2005 }
2006 }
2007 default:
2008 TODO /* missed one case ??? */
2009 }
2010 return(NULL);
2011}
2012
2026static void
2027xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2028 int i;
2029 xmlXPathObjectPtr set;
2030 xmlLocationSetPtr oldset;
2031 xmlLocationSetPtr newset;
2032
2033 CHECK_ARITY(1);
2034 if ((ctxt->value == NULL) ||
2035 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2036 (ctxt->value->type != XPATH_NODESET)))
2037 XP_ERROR(XPATH_INVALID_TYPE)
2038
2039 set = valuePop(ctxt);
2040 if (set->type == XPATH_NODESET) {
2041 xmlXPathObjectPtr tmp;
2042
2043 /*
2044 * First convert to a location set
2045 */
2046 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2047 xmlXPathFreeObject(set);
2048 if (tmp == NULL)
2049 XP_ERROR(XPATH_MEMORY_ERROR)
2050 set = tmp;
2051 }
2052 oldset = (xmlLocationSetPtr) set->user;
2053
2054 /*
2055 * The loop is to compute the covering range for each item and add it
2056 */
2057 newset = xmlXPtrLocationSetCreate(NULL);
2058 if (newset == NULL) {
2059 xmlXPathFreeObject(set);
2060 XP_ERROR(XPATH_MEMORY_ERROR);
2061 }
2062 if (oldset != NULL) {
2063 for (i = 0;i < oldset->locNr;i++) {
2064 xmlXPtrLocationSetAdd(newset,
2065 xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
2066 }
2067 }
2068
2069 /*
2070 * Save the new value and cleanup
2071 */
2072 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2073 xmlXPathFreeObject(set);
2074}
2075
2085static xmlXPathObjectPtr
2086xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
2087 if (loc == NULL)
2088 return(NULL);
2089 if ((ctxt == NULL) || (ctxt->context == NULL) ||
2090 (ctxt->context->doc == NULL))
2091 return(NULL);
2092 switch (loc->type) {
2093 case XPATH_POINT: {
2094 xmlNodePtr node = (xmlNodePtr) loc->user;
2095 switch (node->type) {
2096 case XML_PI_NODE:
2097 case XML_COMMENT_NODE:
2098 case XML_TEXT_NODE:
2100 if (node->content == NULL) {
2101 return(xmlXPtrNewRange(node, 0, node, 0));
2102 } else {
2103 return(xmlXPtrNewRange(node, 0, node,
2104 xmlStrlen(node->content)));
2105 }
2106 }
2107 case XML_ATTRIBUTE_NODE:
2108 case XML_ELEMENT_NODE:
2110 case XML_DOCUMENT_NODE:
2111 case XML_NOTATION_NODE:
2113 return(xmlXPtrNewRange(node, 0, node,
2114 xmlXPtrGetArity(node)));
2115 }
2116 default:
2117 break;
2118 }
2119 return(NULL);
2120 }
2121 case XPATH_RANGE: {
2122 xmlNodePtr node = (xmlNodePtr) loc->user;
2123 if (loc->user2 != NULL) {
2124 return(xmlXPtrNewRange(node, loc->index,
2125 loc->user2, loc->index2));
2126 } else {
2127 switch (node->type) {
2128 case XML_PI_NODE:
2129 case XML_COMMENT_NODE:
2130 case XML_TEXT_NODE:
2132 if (node->content == NULL) {
2133 return(xmlXPtrNewRange(node, 0, node, 0));
2134 } else {
2135 return(xmlXPtrNewRange(node, 0, node,
2136 xmlStrlen(node->content)));
2137 }
2138 }
2139 case XML_ATTRIBUTE_NODE:
2140 case XML_ELEMENT_NODE:
2142 case XML_DOCUMENT_NODE:
2143 case XML_NOTATION_NODE:
2145 return(xmlXPtrNewRange(node, 0, node,
2146 xmlXPtrGetArity(node)));
2147 }
2148 default:
2149 break;
2150 }
2151 return(NULL);
2152 }
2153 }
2154 default:
2155 TODO /* missed one case ??? */
2156 }
2157 return(NULL);
2158}
2159
2180static void
2181xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2182 int i;
2183 xmlXPathObjectPtr set;
2184 xmlLocationSetPtr oldset;
2185 xmlLocationSetPtr newset;
2186
2187 CHECK_ARITY(1);
2188 if ((ctxt->value == NULL) ||
2189 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2190 (ctxt->value->type != XPATH_NODESET)))
2191 XP_ERROR(XPATH_INVALID_TYPE)
2192
2193 set = valuePop(ctxt);
2194 if (set->type == XPATH_NODESET) {
2195 xmlXPathObjectPtr tmp;
2196
2197 /*
2198 * First convert to a location set
2199 */
2200 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2201 xmlXPathFreeObject(set);
2202 if (tmp == NULL)
2203 XP_ERROR(XPATH_MEMORY_ERROR)
2204 set = tmp;
2205 }
2206
2207 /*
2208 * The loop is to compute the covering range for each item and add it
2209 */
2210 newset = xmlXPtrLocationSetCreate(NULL);
2211 if (newset == NULL) {
2212 xmlXPathFreeObject(set);
2213 XP_ERROR(XPATH_MEMORY_ERROR);
2214 }
2215 oldset = (xmlLocationSetPtr) set->user;
2216 if (oldset != NULL) {
2217 for (i = 0;i < oldset->locNr;i++) {
2218 xmlXPtrLocationSetAdd(newset,
2219 xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
2220 }
2221 }
2222
2223 /*
2224 * Save the new value and cleanup
2225 */
2226 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2227 xmlXPathFreeObject(set);
2228}
2229
2240void
2241xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
2242 int nargs ATTRIBUTE_UNUSED) {
2243 XP_ERROR(XPATH_EXPR_ERROR);
2244}
2245
2257xmlXPtrAdvanceNode(xmlNodePtr cur, int *level) {
2258next:
2259 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2260 return(NULL);
2261 if (cur->children != NULL) {
2262 cur = cur->children ;
2263 if (level != NULL)
2264 (*level)++;
2265 goto found;
2266 }
2267skip: /* This label should only be needed if something is wrong! */
2268 if (cur->next != NULL) {
2269 cur = cur->next;
2270 goto found;
2271 }
2272 do {
2273 cur = cur->parent;
2274 if (level != NULL)
2275 (*level)--;
2276 if (cur == NULL) return(NULL);
2277 if (cur->next != NULL) {
2278 cur = cur->next;
2279 goto found;
2280 }
2281 } while (cur != NULL);
2282
2283found:
2284 if ((cur->type != XML_ELEMENT_NODE) &&
2285 (cur->type != XML_TEXT_NODE) &&
2286 (cur->type != XML_DOCUMENT_NODE) &&
2287 (cur->type != XML_HTML_DOCUMENT_NODE) &&
2288 (cur->type != XML_CDATA_SECTION_NODE)) {
2289 if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */
2290 TODO
2291 goto skip;
2292 }
2293 goto next;
2294 }
2295 return(cur);
2296}
2297
2308static int
2309xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) {
2311 int pos;
2312 int len;
2313
2314 if ((node == NULL) || (indx == NULL))
2315 return(-1);
2316 cur = *node;
2317 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2318 return(-1);
2319 pos = *indx;
2320
2321 while (bytes >= 0) {
2322 /*
2323 * First position to the beginning of the first text node
2324 * corresponding to this point
2325 */
2326 while ((cur != NULL) &&
2327 ((cur->type == XML_ELEMENT_NODE) ||
2328 (cur->type == XML_DOCUMENT_NODE) ||
2329 (cur->type == XML_HTML_DOCUMENT_NODE))) {
2330 if (pos > 0) {
2331 cur = xmlXPtrGetNthChild(cur, pos);
2332 pos = 0;
2333 } else {
2334 cur = xmlXPtrAdvanceNode(cur, NULL);
2335 pos = 0;
2336 }
2337 }
2338
2339 if (cur == NULL) {
2340 *node = NULL;
2341 *indx = 0;
2342 return(-1);
2343 }
2344
2345 /*
2346 * if there is no move needed return the current value.
2347 */
2348 if (pos == 0) pos = 1;
2349 if (bytes == 0) {
2350 *node = cur;
2351 *indx = pos;
2352 return(0);
2353 }
2354 /*
2355 * We should have a text (or cdata) node ...
2356 */
2357 len = 0;
2358 if ((cur->type != XML_ELEMENT_NODE) &&
2359 (cur->content != NULL)) {
2360 len = xmlStrlen(cur->content);
2361 }
2362 if (pos > len) {
2363 /* Strange, the indx in the text node is greater than it's len */
2364 STRANGE
2365 pos = len;
2366 }
2367 if (pos + bytes >= len) {
2368 bytes -= (len - pos);
2369 cur = xmlXPtrAdvanceNode(cur, NULL);
2370 pos = 0;
2371 } else if (pos + bytes < len) {
2372 pos += bytes;
2373 *node = cur;
2374 *indx = pos;
2375 return(0);
2376 }
2377 }
2378 return(-1);
2379}
2380
2397static int
2398xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
2399 xmlNodePtr *end, int *endindex) {
2401 int pos; /* 0 based */
2402 int len; /* in bytes */
2403 int stringlen; /* in bytes */
2404 int match;
2405
2406 if (string == NULL)
2407 return(-1);
2408 if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
2409 return(-1);
2410 if ((end == NULL) || (*end == NULL) ||
2411 ((*end)->type == XML_NAMESPACE_DECL) || (endindex == NULL))
2412 return(-1);
2413 cur = start;
2414 pos = startindex - 1;
2415 stringlen = xmlStrlen(string);
2416
2417 while (stringlen > 0) {
2418 if ((cur == *end) && (pos + stringlen > *endindex))
2419 return(0);
2420
2421 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2422 len = xmlStrlen(cur->content);
2423 if (len >= pos + stringlen) {
2424 match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
2425 if (match) {
2426#ifdef DEBUG_RANGES
2428 "found range %d bytes at index %d of ->",
2429 stringlen, pos + 1);
2430 xmlDebugDumpString(stdout, cur->content);
2432#endif
2433 *end = cur;
2434 *endindex = pos + stringlen;
2435 return(1);
2436 } else {
2437 return(0);
2438 }
2439 } else {
2440 int sub = len - pos;
2441 match = (!xmlStrncmp(&cur->content[pos], string, sub));
2442 if (match) {
2443#ifdef DEBUG_RANGES
2445 "found subrange %d bytes at index %d of ->",
2446 sub, pos + 1);
2447 xmlDebugDumpString(stdout, cur->content);
2449#endif
2450 string = &string[sub];
2451 stringlen -= sub;
2452 } else {
2453 return(0);
2454 }
2455 }
2456 }
2457 cur = xmlXPtrAdvanceNode(cur, NULL);
2458 if (cur == NULL)
2459 return(0);
2460 pos = 0;
2461 }
2462 return(1);
2463}
2464
2481static int
2482xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
2483 xmlNodePtr *end, int *endindex) {
2485 const xmlChar *str;
2486 int pos; /* 0 based */
2487 int len; /* in bytes */
2488 xmlChar first;
2489
2490 if (string == NULL)
2491 return(-1);
2492 if ((start == NULL) || (*start == NULL) ||
2493 ((*start)->type == XML_NAMESPACE_DECL) || (startindex == NULL))
2494 return(-1);
2495 if ((end == NULL) || (endindex == NULL))
2496 return(-1);
2497 cur = *start;
2498 pos = *startindex - 1;
2499 first = string[0];
2500
2501 while (cur != NULL) {
2502 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2503 len = xmlStrlen(cur->content);
2504 while (pos <= len) {
2505 if (first != 0) {
2506 str = xmlStrchr(&cur->content[pos], first);
2507 if (str != NULL) {
2508 pos = (str - (xmlChar *)(cur->content));
2509#ifdef DEBUG_RANGES
2511 "found '%c' at index %d of ->",
2512 first, pos + 1);
2513 xmlDebugDumpString(stdout, cur->content);
2515#endif
2516 if (xmlXPtrMatchString(string, cur, pos + 1,
2517 end, endindex)) {
2518 *start = cur;
2519 *startindex = pos + 1;
2520 return(1);
2521 }
2522 pos++;
2523 } else {
2524 pos = len + 1;
2525 }
2526 } else {
2527 /*
2528 * An empty string is considered to match before each
2529 * character of the string-value and after the final
2530 * character.
2531 */
2532#ifdef DEBUG_RANGES
2534 "found '' at index %d of ->",
2535 pos + 1);
2536 xmlDebugDumpString(stdout, cur->content);
2538#endif
2539 *start = cur;
2540 *startindex = pos + 1;
2541 *end = cur;
2542 *endindex = pos + 1;
2543 return(1);
2544 }
2545 }
2546 }
2547 if ((cur == *end) && (pos >= *endindex))
2548 return(0);
2549 cur = xmlXPtrAdvanceNode(cur, NULL);
2550 if (cur == NULL)
2551 return(0);
2552 pos = 1;
2553 }
2554 return(0);
2555}
2556
2566static int
2567xmlXPtrGetLastChar(xmlNodePtr *node, int *indx) {
2569 int pos, len = 0;
2570
2571 if ((node == NULL) || (*node == NULL) ||
2572 ((*node)->type == XML_NAMESPACE_DECL) || (indx == NULL))
2573 return(-1);
2574 cur = *node;
2575 pos = *indx;
2576
2577 if ((cur->type == XML_ELEMENT_NODE) ||
2578 (cur->type == XML_DOCUMENT_NODE) ||
2579 (cur->type == XML_HTML_DOCUMENT_NODE)) {
2580 if (pos > 0) {
2581 cur = xmlXPtrGetNthChild(cur, pos);
2582 }
2583 }
2584 while (cur != NULL) {
2585 if (cur->last != NULL)
2586 cur = cur->last;
2587 else if ((cur->type != XML_ELEMENT_NODE) &&
2588 (cur->content != NULL)) {
2589 len = xmlStrlen(cur->content);
2590 break;
2591 } else {
2592 return(-1);
2593 }
2594 }
2595 if (cur == NULL)
2596 return(-1);
2597 *node = cur;
2598 *indx = len;
2599 return(0);
2600}
2601
2612static int
2613xmlXPtrGetStartPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2614 if ((obj == NULL) || (node == NULL) || (indx == NULL))
2615 return(-1);
2616
2617 switch (obj->type) {
2618 case XPATH_POINT:
2619 *node = obj->user;
2620 if (obj->index <= 0)
2621 *indx = 0;
2622 else
2623 *indx = obj->index;
2624 return(0);
2625 case XPATH_RANGE:
2626 *node = obj->user;
2627 if (obj->index <= 0)
2628 *indx = 0;
2629 else
2630 *indx = obj->index;
2631 return(0);
2632 default:
2633 break;
2634 }
2635 return(-1);
2636}
2637
2648static int
2649xmlXPtrGetEndPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2650 if ((obj == NULL) || (node == NULL) || (indx == NULL))
2651 return(-1);
2652
2653 switch (obj->type) {
2654 case XPATH_POINT:
2655 *node = obj->user;
2656 if (obj->index <= 0)
2657 *indx = 0;
2658 else
2659 *indx = obj->index;
2660 return(0);
2661 case XPATH_RANGE:
2662 *node = obj->user;
2663 if (obj->index <= 0)
2664 *indx = 0;
2665 else
2666 *indx = obj->index;
2667 return(0);
2668 default:
2669 break;
2670 }
2671 return(-1);
2672}
2673
2710static void
2711xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2712 int i, startindex, endindex = 0, fendindex;
2713 xmlNodePtr start, end = 0, fend;
2714 xmlXPathObjectPtr set = NULL;
2715 xmlLocationSetPtr oldset;
2716 xmlLocationSetPtr newset = NULL;
2717 xmlXPathObjectPtr string = NULL;
2718 xmlXPathObjectPtr position = NULL;
2719 xmlXPathObjectPtr number = NULL;
2720 int found, pos = 0, num = 0;
2721
2722 /*
2723 * Grab the arguments
2724 */
2725 if ((nargs < 2) || (nargs > 4))
2726 XP_ERROR(XPATH_INVALID_ARITY);
2727
2728 if (nargs >= 4) {
2729 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2730 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2731 goto error;
2732 }
2733 number = valuePop(ctxt);
2734 if (number != NULL)
2735 num = (int) number->floatval;
2736 }
2737 if (nargs >= 3) {
2738 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2739 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2740 goto error;
2741 }
2742 position = valuePop(ctxt);
2743 if (position != NULL)
2744 pos = (int) position->floatval;
2745 }
2746 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
2747 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2748 goto error;
2749 }
2750 string = valuePop(ctxt);
2751 if ((ctxt->value == NULL) ||
2752 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2753 (ctxt->value->type != XPATH_NODESET))) {
2754 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2755 goto error;
2756 }
2757 set = valuePop(ctxt);
2758 newset = xmlXPtrLocationSetCreate(NULL);
2759 if (newset == NULL) {
2760 xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2761 goto error;
2762 }
2763 if (set->nodesetval == NULL) {
2764 goto error;
2765 }
2766 if (set->type == XPATH_NODESET) {
2767 xmlXPathObjectPtr tmp;
2768
2769 /*
2770 * First convert to a location set
2771 */
2772 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2773 xmlXPathFreeObject(set);
2774 set = NULL;
2775 if (tmp == NULL) {
2776 xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2777 goto error;
2778 }
2779 set = tmp;
2780 }
2781 oldset = (xmlLocationSetPtr) set->user;
2782
2783 /*
2784 * The loop is to search for each element in the location set
2785 * the list of location set corresponding to that search
2786 */
2787 for (i = 0;i < oldset->locNr;i++) {
2788#ifdef DEBUG_RANGES
2789 xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
2790#endif
2791
2792 xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex);
2793 xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex);
2794 xmlXPtrAdvanceChar(&start, &startindex, 0);
2795 xmlXPtrGetLastChar(&end, &endindex);
2796
2797#ifdef DEBUG_RANGES
2799 "from index %d of ->", startindex);
2800 xmlDebugDumpString(stdout, start->content);
2803 "to index %d of ->", endindex);
2804 xmlDebugDumpString(stdout, end->content);
2806#endif
2807 do {
2808 fend = end;
2809 fendindex = endindex;
2810 found = xmlXPtrSearchString(string->stringval, &start, &startindex,
2811 &fend, &fendindex);
2812 if (found == 1) {
2813 if (position == NULL) {
2814 xmlXPtrLocationSetAdd(newset,
2815 xmlXPtrNewRange(start, startindex, fend, fendindex));
2816 } else if (xmlXPtrAdvanceChar(&start, &startindex,
2817 pos - 1) == 0) {
2818 if ((number != NULL) && (num > 0)) {
2819 int rindx;
2820 xmlNodePtr rend;
2821 rend = start;
2822 rindx = startindex - 1;
2823 if (xmlXPtrAdvanceChar(&rend, &rindx,
2824 num) == 0) {
2825 xmlXPtrLocationSetAdd(newset,
2826 xmlXPtrNewRange(start, startindex,
2827 rend, rindx));
2828 }
2829 } else if ((number != NULL) && (num <= 0)) {
2830 xmlXPtrLocationSetAdd(newset,
2831 xmlXPtrNewRange(start, startindex,
2832 start, startindex));
2833 } else {
2834 xmlXPtrLocationSetAdd(newset,
2835 xmlXPtrNewRange(start, startindex,
2836 fend, fendindex));
2837 }
2838 }
2839 start = fend;
2840 startindex = fendindex;
2841 if (string->stringval[0] == 0)
2842 startindex++;
2843 }
2844 } while (found == 1);
2845 }
2846
2847 /*
2848 * Save the new value and cleanup
2849 */
2850error:
2851 if (newset != NULL)
2852 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2853 xmlXPathFreeObject(set);
2854 xmlXPathFreeObject(string);
2855 if (position) xmlXPathFreeObject(position);
2856 if (number) xmlXPathFreeObject(number);
2857}
2858
2869void
2870xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) {
2871 const xmlChar *cur;
2872 xmlXPathObjectPtr res;
2873 xmlXPathObjectPtr obj, tmp;
2874 xmlLocationSetPtr newset = NULL;
2875 xmlLocationSetPtr oldset;
2876 int i;
2877
2878 if (ctxt == NULL) return;
2879
2881 if (CUR != '[') {
2882 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2883 }
2884 NEXT;
2886
2887 /*
2888 * Extract the old set, and then evaluate the result of the
2889 * expression for all the element in the set. use it to grow
2890 * up a new set.
2891 */
2892 CHECK_TYPE(XPATH_LOCATIONSET);
2893 obj = valuePop(ctxt);
2894 oldset = obj->user;
2895 ctxt->context->node = NULL;
2896
2897 if ((oldset == NULL) || (oldset->locNr == 0)) {
2898 ctxt->context->contextSize = 0;
2899 ctxt->context->proximityPosition = 0;
2900 xmlXPathEvalExpr(ctxt);
2901 res = valuePop(ctxt);
2902 if (res != NULL)
2903 xmlXPathFreeObject(res);
2904 valuePush(ctxt, obj);
2905 CHECK_ERROR;
2906 } else {
2907 /*
2908 * Save the expression pointer since we will have to evaluate
2909 * it multiple times. Initialize the new set.
2910 */
2911 cur = ctxt->cur;
2912 newset = xmlXPtrLocationSetCreate(NULL);
2913
2914 for (i = 0; i < oldset->locNr; i++) {
2915 ctxt->cur = cur;
2916
2917 /*
2918 * Run the evaluation with a node list made of a single item
2919 * in the nodeset.
2920 */
2921 ctxt->context->node = oldset->locTab[i]->user;
2922 tmp = xmlXPathNewNodeSet(ctxt->context->node);
2923 valuePush(ctxt, tmp);
2924 ctxt->context->contextSize = oldset->locNr;
2925 ctxt->context->proximityPosition = i + 1;
2926
2927 xmlXPathEvalExpr(ctxt);
2928 CHECK_ERROR;
2929
2930 /*
2931 * The result of the evaluation need to be tested to
2932 * decided whether the filter succeeded or not
2933 */
2934 res = valuePop(ctxt);
2935 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
2936 xmlXPtrLocationSetAdd(newset,
2937 xmlXPathObjectCopy(oldset->locTab[i]));
2938 }
2939
2940 /*
2941 * Cleanup
2942 */
2943 if (res != NULL)
2944 xmlXPathFreeObject(res);
2945 if (ctxt->value == tmp) {
2946 res = valuePop(ctxt);
2947 xmlXPathFreeObject(res);
2948 }
2949
2950 ctxt->context->node = NULL;
2951 }
2952
2953 /*
2954 * The result is used as the new evaluation set.
2955 */
2956 xmlXPathFreeObject(obj);
2957 ctxt->context->node = NULL;
2958 ctxt->context->contextSize = -1;
2959 ctxt->context->proximityPosition = -1;
2960 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2961 }
2962 if (CUR != ']') {
2963 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2964 }
2965
2966 NEXT;
2968}
2969#endif /* LIBXML_XPTR_LOCS_ENABLED */
2970
2971#endif
2972
#define TODO
Definition: SAX2.c:44
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
Definition: list.h:37
Definition: _set.h:50
Definition: _stack.h:55
#define NULL
Definition: types.h:112
#define SKIP_BLANKS
Definition: pattern.c:1175
#define NXT(val)
Definition: pattern.c:1172
#define CUR
Definition: pattern.c:1170
content
Definition: atl_ax.c:994
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
r parent
Definition: btrfs.c:3010
switch(r->id)
Definition: btrfs.c:3046
POINTL point
Definition: edittest.c:50
#define NEXT(n, i)
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLuint GLuint end
Definition: gl.h:1545
GLint const GLchar GLint stringlen
Definition: glext.h:7232
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLenum GLint * range
Definition: glext.h:7539
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
#define INT_MAX
Definition: limits.h:40
#define stdout
Definition: stdio.h:99
voidpf uLong int origin
Definition: ioapi.h:144
#define d
Definition: ke_i.h:81
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define for
Definition: utility.h:88
static WCHAR name2[]
Definition: record.c:35
static unsigned int number
Definition: dsound.c:1479
static UINT UINT last
Definition: font.c:45
static HWND child
Definition: cursoricon.c:298
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
static calc_node_t temp
Definition: rpn_ieee.c:38
XMLPUBVAR xmlMallocFunc xmlMallocAtomic
Definition: globals.h:249
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN void XMLCALL xmlInitParser(void)
Definition: parser.c:14676
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode(xmlNodePtr node, int recursive)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewTextLen(const xmlChar *content, int len)
xmlNode * xmlNodePtr
Definition: tree.h:488
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
XMLPUBFUN xmlNodePtr XMLCALL xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem)
@ XML_DOCUMENT_TYPE_NODE
Definition: tree.h:169
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ELEMENT_DECL
Definition: tree.h:174
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_NOTATION_NODE
Definition: tree.h:171
@ XML_ATTRIBUTE_DECL
Definition: tree.h:175
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:551
Definition: tree.h:489
Definition: match.c:28
Definition: name.c:39
Definition: dlist.c:348
void * next
Definition: dlist.c:360
int ret
static int init
Definition: wintirpc.c:33
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_FROM_XPOINTER
Definition: xmlerror.h:50
XMLPUBFUN void XMLCALL xmlResetError(xmlErrorPtr err)
@ XML_XPTR_EXTRA_OBJECTS
Definition: xmlerror.h:682
@ XML_XPTR_UNKNOWN_SCHEME
Definition: xmlerror.h:679
@ XML_XPTR_EVAL_FAILED
Definition: xmlerror.h:681
@ XML_XPTR_CHILDSEQ_START
Definition: xmlerror.h:680
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:325
XMLPUBFUN int XMLCALL xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:213
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:486
#define const
Definition: zconf.h:233