ReactOS 0.4.16-dev-2232-gc2aaa52
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
42#ifdef LIBXML_XPTR_ENABLED
43
44/* Add support of the xmlns() xpointer scheme to initialize the namespaces */
45#define XPTR_XMLNS_SCHEME
46
47#include "private/error.h"
48
49#define TODO \
50 xmlGenericError(xmlGenericErrorContext, \
51 "Unimplemented block at %s:%d\n", \
52 __FILE__, __LINE__);
53
54#define STRANGE \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Internal error at %s:%d\n", \
57 __FILE__, __LINE__);
58
59/************************************************************************
60 * *
61 * Some factorized error routines *
62 * *
63 ************************************************************************/
64
71static void
72xmlXPtrErrMemory(const char *extra)
73{
76 NULL, NULL, 0, 0,
77 "Memory allocation failed : %s\n", extra);
78}
79
87static void LIBXML_ATTR_FORMAT(3,0)
88xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
89 const char * msg, const xmlChar *extra)
90{
91 if (ctxt != NULL)
92 ctxt->error = error;
93 if ((ctxt == NULL) || (ctxt->context == NULL)) {
97 (const char *) extra, NULL, NULL, 0, 0,
98 msg, extra);
99 return;
100 }
101
102 /* cleanup current last error */
103 xmlResetError(&ctxt->context->lastError);
104
105 ctxt->context->lastError.domain = XML_FROM_XPOINTER;
106 ctxt->context->lastError.code = error;
107 ctxt->context->lastError.level = XML_ERR_ERROR;
108 ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
109 ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
110 ctxt->context->lastError.node = ctxt->context->debugNode;
111 if (ctxt->context->error != NULL) {
112 ctxt->context->error(ctxt->context->userData,
113 &ctxt->context->lastError);
114 } else {
116 NULL, ctxt->context->debugNode, XML_FROM_XPOINTER,
118 (const char *) extra, (const char *) ctxt->base, NULL,
119 ctxt->cur - ctxt->base, 0,
120 msg, extra);
121 }
122}
123
124/************************************************************************
125 * *
126 * A few helper functions for child sequences *
127 * *
128 ************************************************************************/
129#ifdef LIBXML_XPTR_LOCS_ENABLED
130/* xmlXPtrAdvanceNode is a private function, but used by xinclude.c */
131xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level);
138static int
139xmlXPtrGetArity(xmlNodePtr cur) {
140 int i;
141 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
142 return(-1);
143 cur = cur->children;
144 for (i = 0;cur != NULL;cur = cur->next) {
145 if ((cur->type == XML_ELEMENT_NODE) ||
146 (cur->type == XML_DOCUMENT_NODE) ||
147 (cur->type == XML_HTML_DOCUMENT_NODE)) {
148 i++;
149 }
150 }
151 return(i);
152}
153
161static int
162xmlXPtrGetIndex(xmlNodePtr cur) {
163 int i;
164 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
165 return(-1);
166 for (i = 1;cur != NULL;cur = cur->prev) {
167 if ((cur->type == XML_ELEMENT_NODE) ||
168 (cur->type == XML_DOCUMENT_NODE) ||
169 (cur->type == XML_HTML_DOCUMENT_NODE)) {
170 i++;
171 }
172 }
173 return(i);
174}
175#endif /* LIBXML_XPTR_LOCS_ENABLED */
176
184static xmlNodePtr
185xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
186 int i;
187 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
188 return(cur);
189 cur = cur->children;
190 for (i = 0;i <= no;cur = cur->next) {
191 if (cur == NULL)
192 return(cur);
193 if ((cur->type == XML_ELEMENT_NODE) ||
194 (cur->type == XML_DOCUMENT_NODE) ||
195 (cur->type == XML_HTML_DOCUMENT_NODE)) {
196 i++;
197 if (i == no)
198 break;
199 }
200 }
201 return(cur);
202}
203
204#ifdef LIBXML_XPTR_LOCS_ENABLED
205/************************************************************************
206 * *
207 * Handling of XPointer specific types *
208 * *
209 ************************************************************************/
210
223static int
224xmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) {
225 if ((node1 == NULL) || (node2 == NULL))
226 return(-2);
227 /*
228 * a couple of optimizations which will avoid computations in most cases
229 */
230 if (node1 == node2) {
231 if (index1 < index2)
232 return(1);
233 if (index1 > index2)
234 return(-1);
235 return(0);
236 }
237 return(xmlXPathCmpNodes(node1, node2));
238}
239
249static xmlXPathObjectPtr
250xmlXPtrNewPoint(xmlNodePtr node, int indx) {
251 xmlXPathObjectPtr ret;
252
253 if (node == NULL)
254 return(NULL);
255 if (indx < 0)
256 return(NULL);
257
258 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
259 if (ret == NULL) {
260 xmlXPtrErrMemory("allocating point");
261 return(NULL);
262 }
263 memset(ret, 0 , sizeof(xmlXPathObject));
264 ret->type = XPATH_POINT;
265 ret->user = (void *) node;
266 ret->index = indx;
267 return(ret);
268}
269
276static void
277xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) {
278 int tmp;
279 xmlNodePtr tmp2;
280 if (range == NULL)
281 return;
282 if (range->type != XPATH_RANGE)
283 return;
284 if (range->user2 == NULL)
285 return;
286 tmp = xmlXPtrCmpPoints(range->user, range->index,
287 range->user2, range->index2);
288 if (tmp == -1) {
289 tmp2 = range->user;
290 range->user = range->user2;
291 range->user2 = tmp2;
292 tmp = range->index;
293 range->index = range->index2;
294 range->index2 = tmp;
295 }
296}
297
307static int
308xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
309 if (range1 == range2)
310 return(1);
311 if ((range1 == NULL) || (range2 == NULL))
312 return(0);
313 if (range1->type != range2->type)
314 return(0);
315 if (range1->type != XPATH_RANGE)
316 return(0);
317 if (range1->user != range2->user)
318 return(0);
319 if (range1->index != range2->index)
320 return(0);
321 if (range1->user2 != range2->user2)
322 return(0);
323 if (range1->index2 != range2->index2)
324 return(0);
325 return(1);
326}
327
339static xmlXPathObjectPtr
340xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
341 xmlNodePtr end, int endindex) {
342 xmlXPathObjectPtr ret;
343
344 /*
345 * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
346 * Disallow them for now.
347 */
348 if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
349 return(NULL);
350 if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
351 return(NULL);
352
353 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
354 if (ret == NULL) {
355 xmlXPtrErrMemory("allocating range");
356 return(NULL);
357 }
358 memset(ret, 0, sizeof(xmlXPathObject));
359 ret->type = XPATH_RANGE;
360 ret->user = start;
361 ret->index = startindex;
362 ret->user2 = end;
363 ret->index2 = endindex;
364 return(ret);
365}
366
378xmlXPathObjectPtr
379xmlXPtrNewRange(xmlNodePtr start, int startindex,
380 xmlNodePtr end, int endindex) {
381 xmlXPathObjectPtr ret;
382
383 if (start == NULL)
384 return(NULL);
385 if (end == NULL)
386 return(NULL);
387 if (startindex < 0)
388 return(NULL);
389 if (endindex < 0)
390 return(NULL);
391
392 ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
393 xmlXPtrRangeCheckOrder(ret);
394 return(ret);
395}
396
406xmlXPathObjectPtr
407xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
408 xmlXPathObjectPtr ret;
409
410 if (start == NULL)
411 return(NULL);
412 if (end == NULL)
413 return(NULL);
414 if (start->type != XPATH_POINT)
415 return(NULL);
416 if (end->type != XPATH_POINT)
417 return(NULL);
418
419 ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
420 end->index);
421 xmlXPtrRangeCheckOrder(ret);
422 return(ret);
423}
424
434xmlXPathObjectPtr
435xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
436 xmlXPathObjectPtr ret;
437
438 if (start == NULL)
439 return(NULL);
440 if (end == NULL)
441 return(NULL);
442 if (start->type != XPATH_POINT)
443 return(NULL);
444
445 ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
446 xmlXPtrRangeCheckOrder(ret);
447 return(ret);
448}
449
459xmlXPathObjectPtr
460xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
461 xmlXPathObjectPtr ret;
462
463 if (start == NULL)
464 return(NULL);
465 if (end == NULL)
466 return(NULL);
467 if (end->type != XPATH_POINT)
468 return(NULL);
469
470 ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
471 xmlXPtrRangeCheckOrder(ret);
472 return(ret);
473}
474
484xmlXPathObjectPtr
485xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
486 xmlXPathObjectPtr ret;
487
488 if (start == NULL)
489 return(NULL);
490 if (end == NULL)
491 return(NULL);
492
493 ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
494 xmlXPtrRangeCheckOrder(ret);
495 return(ret);
496}
497
506xmlXPathObjectPtr
507xmlXPtrNewCollapsedRange(xmlNodePtr start) {
508 xmlXPathObjectPtr ret;
509
510 if (start == NULL)
511 return(NULL);
512
513 ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
514 return(ret);
515}
516
526xmlXPathObjectPtr
527xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
528 xmlNodePtr endNode;
529 int endIndex;
530 xmlXPathObjectPtr ret;
531
532 if (start == NULL)
533 return(NULL);
534 if (end == NULL)
535 return(NULL);
536 switch (end->type) {
537 case XPATH_POINT:
538 endNode = end->user;
539 endIndex = end->index;
540 break;
541 case XPATH_RANGE:
542 endNode = end->user2;
543 endIndex = end->index2;
544 break;
545 case XPATH_NODESET:
546 /*
547 * Empty set ...
548 */
549 if ((end->nodesetval == NULL) || (end->nodesetval->nodeNr <= 0))
550 return(NULL);
551 endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
552 endIndex = -1;
553 break;
554 default:
555 /* TODO */
556 return(NULL);
557 }
558
559 ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
560 xmlXPtrRangeCheckOrder(ret);
561 return(ret);
562}
563
564#define XML_RANGESET_DEFAULT 10
565
574xmlLocationSetPtr
575xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
576 xmlLocationSetPtr ret;
577
578 ret = (xmlLocationSetPtr) xmlMalloc(sizeof(xmlLocationSet));
579 if (ret == NULL) {
580 xmlXPtrErrMemory("allocating locationset");
581 return(NULL);
582 }
583 memset(ret, 0 , sizeof(xmlLocationSet));
584 if (val != NULL) {
585 ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
586 sizeof(xmlXPathObjectPtr));
587 if (ret->locTab == NULL) {
588 xmlXPtrErrMemory("allocating locationset");
589 xmlFree(ret);
590 return(NULL);
591 }
592 memset(ret->locTab, 0 ,
593 XML_RANGESET_DEFAULT * sizeof(xmlXPathObjectPtr));
594 ret->locMax = XML_RANGESET_DEFAULT;
595 ret->locTab[ret->locNr++] = val;
596 }
597 return(ret);
598}
599
608void
609xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
610 int i;
611
612 if ((cur == NULL) || (val == NULL)) return;
613
614 /*
615 * check against doublons
616 */
617 for (i = 0;i < cur->locNr;i++) {
618 if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
619 xmlXPathFreeObject(val);
620 return;
621 }
622 }
623
624 /*
625 * grow the locTab if needed
626 */
627 if (cur->locMax == 0) {
628 cur->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
629 sizeof(xmlXPathObjectPtr));
630 if (cur->locTab == NULL) {
631 xmlXPtrErrMemory("adding location to set");
632 return;
633 }
634 memset(cur->locTab, 0 ,
635 XML_RANGESET_DEFAULT * sizeof(xmlXPathObjectPtr));
636 cur->locMax = XML_RANGESET_DEFAULT;
637 } else if (cur->locNr == cur->locMax) {
638 xmlXPathObjectPtr *temp;
639
640 cur->locMax *= 2;
641 temp = (xmlXPathObjectPtr *) xmlRealloc(cur->locTab, cur->locMax *
642 sizeof(xmlXPathObjectPtr));
643 if (temp == NULL) {
644 xmlXPtrErrMemory("adding location to set");
645 return;
646 }
647 cur->locTab = temp;
648 }
649 cur->locTab[cur->locNr++] = val;
650}
651
661xmlLocationSetPtr
662xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) {
663 int i;
664
665 if (val1 == NULL) return(NULL);
666 if (val2 == NULL) return(val1);
667
668 /*
669 * !!!!! this can be optimized a lot, knowing that both
670 * val1 and val2 already have unicity of their values.
671 */
672
673 for (i = 0;i < val2->locNr;i++)
674 xmlXPtrLocationSetAdd(val1, val2->locTab[i]);
675
676 return(val1);
677}
678
686void
687xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
688 int i;
689
690 if (cur == NULL) return;
691 if (val == NULL) return;
692
693 /*
694 * check against doublons
695 */
696 for (i = 0;i < cur->locNr;i++)
697 if (cur->locTab[i] == val) break;
698
699 if (i >= cur->locNr) {
700 return;
701 }
702 cur->locNr--;
703 for (;i < cur->locNr;i++)
704 cur->locTab[i] = cur->locTab[i + 1];
705 cur->locTab[cur->locNr] = NULL;
706}
707
715void
716xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val) {
717 if (cur == NULL) return;
718 if (val >= cur->locNr) return;
719 cur->locNr--;
720 for (;val < cur->locNr;val++)
721 cur->locTab[val] = cur->locTab[val + 1];
722 cur->locTab[cur->locNr] = NULL;
723}
724
731void
732xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
733 int i;
734
735 if (obj == NULL) return;
736 if (obj->locTab != NULL) {
737 for (i = 0;i < obj->locNr; i++) {
738 xmlXPathFreeObject(obj->locTab[i]);
739 }
740 xmlFree(obj->locTab);
741 }
742 xmlFree(obj);
743}
744
755xmlXPathObjectPtr
756xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) {
757 xmlXPathObjectPtr ret;
758
759 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
760 if (ret == NULL) {
761 xmlXPtrErrMemory("allocating locationset");
762 return(NULL);
763 }
764 memset(ret, 0 , sizeof(xmlXPathObject));
765 ret->type = XPATH_LOCATIONSET;
766 if (end == NULL)
767 ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start));
768 else
769 ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewRangeNodes(start,end));
770 return(ret);
771}
772
782xmlXPathObjectPtr
783xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) {
784 xmlXPathObjectPtr ret;
785
786 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
787 if (ret == NULL) {
788 xmlXPtrErrMemory("allocating locationset");
789 return(NULL);
790 }
791 memset(ret, 0, sizeof(xmlXPathObject));
792 ret->type = XPATH_LOCATIONSET;
793 if (set != NULL) {
794 int i;
795 xmlLocationSetPtr newset;
796
797 newset = xmlXPtrLocationSetCreate(NULL);
798 if (newset == NULL)
799 return(ret);
800
801 for (i = 0;i < set->nodeNr;i++)
802 xmlXPtrLocationSetAdd(newset,
803 xmlXPtrNewCollapsedRange(set->nodeTab[i]));
804
805 ret->user = (void *) newset;
806 }
807 return(ret);
808}
809
818xmlXPathObjectPtr
819xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
820 xmlXPathObjectPtr ret;
821
822 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
823 if (ret == NULL) {
824 xmlXPtrErrMemory("allocating locationset");
825 return(NULL);
826 }
827 memset(ret, 0, sizeof(xmlXPathObject));
828 ret->type = XPATH_LOCATIONSET;
829 ret->user = (void *) val;
830 return(ret);
831}
832#endif /* LIBXML_XPTR_LOCS_ENABLED */
833
834/************************************************************************
835 * *
836 * The parser *
837 * *
838 ************************************************************************/
839
840static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
841
842/*
843 * Macros for accessing the content. Those should be used only by the parser,
844 * and not exported.
845 *
846 * Dirty macros, i.e. one need to make assumption on the context to use them
847 *
848 * CUR returns the current xmlChar value, i.e. a 8 bit value
849 * in ISO-Latin or UTF-8.
850 * This should be used internally by the parser
851 * only to compare to ASCII values otherwise it would break when
852 * running with UTF-8 encoding.
853 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
854 * to compare on ASCII based substring.
855 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
856 * strings within the parser.
857 * CURRENT Returns the current char value, with the full decoding of
858 * UTF-8 if we are using this mode. It returns an int.
859 * NEXT Skip to the next character, this does the proper decoding
860 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
861 * It returns the pointer to the current xmlChar.
862 */
863
864#define CUR (*ctxt->cur)
865#define SKIP(val) ctxt->cur += (val)
866#define NXT(val) ctxt->cur[(val)]
867
868#define SKIP_BLANKS \
869 while (IS_BLANK_CH(*(ctxt->cur))) NEXT
870
871#define CURRENT (*ctxt->cur)
872#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
873
874/*
875 * xmlXPtrGetChildNo:
876 * @ctxt: the XPointer Parser context
877 * @index: the child number
878 *
879 * Move the current node of the nodeset on the stack to the
880 * given child if found
881 */
882static void
883xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) {
884 xmlNodePtr cur = NULL;
885 xmlXPathObjectPtr obj;
886 xmlNodeSetPtr oldset;
887
888 CHECK_TYPE(XPATH_NODESET);
889 obj = valuePop(ctxt);
890 oldset = obj->nodesetval;
891 if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) {
892 xmlXPathFreeObject(obj);
893 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
894 return;
895 }
896 cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx);
897 if (cur == NULL) {
898 xmlXPathFreeObject(obj);
899 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
900 return;
901 }
902 oldset->nodeTab[0] = cur;
903 valuePush(ctxt, obj);
904}
905
940static void
941xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
942 xmlChar *buffer, *cur;
943 int len;
944 int level;
945
946 if (name == NULL)
947 name = xmlXPathParseName(ctxt);
948 if (name == NULL)
949 XP_ERROR(XPATH_EXPR_ERROR);
950
951 if (CUR != '(') {
952 xmlFree(name);
953 XP_ERROR(XPATH_EXPR_ERROR);
954 }
955 NEXT;
956 level = 1;
957
958 len = xmlStrlen(ctxt->cur);
959 len++;
961 if (buffer == NULL) {
962 xmlXPtrErrMemory("allocating buffer");
963 xmlFree(name);
964 return;
965 }
966
967 cur = buffer;
968 while (CUR != 0) {
969 if (CUR == ')') {
970 level--;
971 if (level == 0) {
972 NEXT;
973 break;
974 }
975 } else if (CUR == '(') {
976 level++;
977 } else if (CUR == '^') {
978 if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
979 NEXT;
980 }
981 }
982 *cur++ = CUR;
983 NEXT;
984 }
985 *cur = 0;
986
987 if ((level != 0) && (CUR == 0)) {
988 xmlFree(name);
990 XP_ERROR(XPTR_SYNTAX_ERROR);
991 }
992
993 if (xmlStrEqual(name, (xmlChar *) "xpointer") ||
994 xmlStrEqual(name, (xmlChar *) "xpath1")) {
995 const xmlChar *oldBase = ctxt->base;
996 const xmlChar *oldCur = ctxt->cur;
997
998 ctxt->cur = ctxt->base = buffer;
999 /*
1000 * To evaluate an xpointer scheme element (4.3) we need:
1001 * context initialized to the root
1002 * context position initialized to 1
1003 * context size initialized to 1
1004 */
1005 ctxt->context->node = (xmlNodePtr)ctxt->context->doc;
1006 ctxt->context->proximityPosition = 1;
1007 ctxt->context->contextSize = 1;
1008#ifdef LIBXML_XPTR_LOCS_ENABLED
1009 ctxt->xptr = xmlStrEqual(name, (xmlChar *) "xpointer");
1010#endif
1011 xmlXPathEvalExpr(ctxt);
1012 ctxt->base = oldBase;
1013 ctxt->cur = oldCur;
1014 } else if (xmlStrEqual(name, (xmlChar *) "element")) {
1015 const xmlChar *oldBase = ctxt->base;
1016 const xmlChar *oldCur = ctxt->cur;
1017 xmlChar *name2;
1018
1019 ctxt->cur = ctxt->base = buffer;
1020 if (buffer[0] == '/') {
1021 xmlXPathRoot(ctxt);
1022 xmlXPtrEvalChildSeq(ctxt, NULL);
1023 } else {
1024 name2 = xmlXPathParseName(ctxt);
1025 if (name2 == NULL) {
1026 ctxt->base = oldBase;
1027 ctxt->cur = oldCur;
1028 xmlFree(buffer);
1029 xmlFree(name);
1030 XP_ERROR(XPATH_EXPR_ERROR);
1031 }
1032 xmlXPtrEvalChildSeq(ctxt, name2);
1033 }
1034 ctxt->base = oldBase;
1035 ctxt->cur = oldCur;
1036#ifdef XPTR_XMLNS_SCHEME
1037 } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
1038 const xmlChar *oldBase = ctxt->base;
1039 const xmlChar *oldCur = ctxt->cur;
1040 xmlChar *prefix;
1041
1042 ctxt->cur = ctxt->base = buffer;
1043 prefix = xmlXPathParseNCName(ctxt);
1044 if (prefix == NULL) {
1045 ctxt->base = oldBase;
1046 ctxt->cur = oldCur;
1047 xmlFree(buffer);
1048 xmlFree(name);
1049 XP_ERROR(XPTR_SYNTAX_ERROR);
1050 }
1052 if (CUR != '=') {
1053 ctxt->base = oldBase;
1054 ctxt->cur = oldCur;
1055 xmlFree(prefix);
1056 xmlFree(buffer);
1057 xmlFree(name);
1058 XP_ERROR(XPTR_SYNTAX_ERROR);
1059 }
1060 NEXT;
1062
1063 xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur);
1064 ctxt->base = oldBase;
1065 ctxt->cur = oldCur;
1066 xmlFree(prefix);
1067#endif /* XPTR_XMLNS_SCHEME */
1068 } else {
1069 xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME,
1070 "unsupported scheme '%s'\n", name);
1071 }
1072 xmlFree(buffer);
1073 xmlFree(name);
1074}
1075
1103static void
1104xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1105 if (name == NULL)
1106 name = xmlXPathParseName(ctxt);
1107 if (name == NULL)
1108 XP_ERROR(XPATH_EXPR_ERROR);
1109 while (name != NULL) {
1110 ctxt->error = XPATH_EXPRESSION_OK;
1111 xmlXPtrEvalXPtrPart(ctxt, name);
1112
1113 /* in case of syntax error, break here */
1114 if ((ctxt->error != XPATH_EXPRESSION_OK) &&
1115 (ctxt->error != XML_XPTR_UNKNOWN_SCHEME))
1116 return;
1117
1118 /*
1119 * If the returned value is a non-empty nodeset
1120 * or location set, return here.
1121 */
1122 if (ctxt->value != NULL) {
1123 xmlXPathObjectPtr obj = ctxt->value;
1124
1125 switch (obj->type) {
1126#ifdef LIBXML_XPTR_LOCS_ENABLED
1127 case XPATH_LOCATIONSET: {
1128 xmlLocationSetPtr loc = ctxt->value->user;
1129 if ((loc != NULL) && (loc->locNr > 0))
1130 return;
1131 break;
1132 }
1133#endif
1134 case XPATH_NODESET: {
1135 xmlNodeSetPtr loc = ctxt->value->nodesetval;
1136 if ((loc != NULL) && (loc->nodeNr > 0))
1137 return;
1138 break;
1139 }
1140 default:
1141 break;
1142 }
1143
1144 /*
1145 * Evaluating to improper values is equivalent to
1146 * a sub-resource error, clean-up the stack
1147 */
1148 do {
1149 obj = valuePop(ctxt);
1150 if (obj != NULL) {
1151 xmlXPathFreeObject(obj);
1152 }
1153 } while (obj != NULL);
1154 }
1155
1156 /*
1157 * Is there another XPointer part.
1158 */
1160 name = xmlXPathParseName(ctxt);
1161 }
1162}
1163
1175static void
1176xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1177 /*
1178 * XPointer don't allow by syntax to address in multirooted trees
1179 * this might prove useful in some cases, warn about it.
1180 */
1181 if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) {
1182 xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START,
1183 "warning: ChildSeq not starting by /1\n", NULL);
1184 }
1185
1186 if (name != NULL) {
1187 valuePush(ctxt, xmlXPathNewString(name));
1188 xmlFree(name);
1189 xmlXPathIdFunction(ctxt, 1);
1190 CHECK_ERROR;
1191 }
1192
1193 while (CUR == '/') {
1194 int child = 0, overflow = 0;
1195 NEXT;
1196
1197 while ((CUR >= '0') && (CUR <= '9')) {
1198 int d = CUR - '0';
1199 if (child > INT_MAX / 10)
1200 overflow = 1;
1201 else
1202 child *= 10;
1203 if (child > INT_MAX - d)
1204 overflow = 1;
1205 else
1206 child += d;
1207 NEXT;
1208 }
1209 if (overflow)
1210 child = 0;
1211 xmlXPtrGetChildNo(ctxt, child);
1212 }
1213}
1214
1215
1226static void
1227xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
1228 if (ctxt->valueTab == NULL) {
1229 /* Allocate the value stack */
1230 ctxt->valueTab = (xmlXPathObjectPtr *)
1231 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
1232 if (ctxt->valueTab == NULL) {
1233 xmlXPtrErrMemory("allocating evaluation context");
1234 return;
1235 }
1236 ctxt->valueNr = 0;
1237 ctxt->valueMax = 10;
1238 ctxt->value = NULL;
1239 }
1241 if (CUR == '/') {
1242 xmlXPathRoot(ctxt);
1243 xmlXPtrEvalChildSeq(ctxt, NULL);
1244 } else {
1245 xmlChar *name;
1246
1247 name = xmlXPathParseName(ctxt);
1248 if (name == NULL)
1249 XP_ERROR(XPATH_EXPR_ERROR);
1250 if (CUR == '(') {
1251 xmlXPtrEvalFullXPtr(ctxt, name);
1252 /* Short evaluation */
1253 return;
1254 } else {
1255 /* this handle both Bare Names and Child Sequences */
1256 xmlXPtrEvalChildSeq(ctxt, name);
1257 }
1258 }
1260 if (CUR != 0)
1261 XP_ERROR(XPATH_EXPR_ERROR);
1262}
1263
1264
1265/************************************************************************
1266 * *
1267 * General routines *
1268 * *
1269 ************************************************************************/
1270
1271#ifdef LIBXML_XPTR_LOCS_ENABLED
1272static
1273void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1274static
1275void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1276static
1277void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1278static
1279void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs);
1280static
1281void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs);
1282static
1283void xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs);
1284static
1285void xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1286#endif /* LIBXML_XPTR_LOCS_ENABLED */
1287
1299xmlXPathContextPtr
1300xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
1301 xmlXPathContextPtr ret;
1302 (void) here;
1303 (void) origin;
1304
1305 ret = xmlXPathNewContext(doc);
1306 if (ret == NULL)
1307 return(ret);
1308#ifdef LIBXML_XPTR_LOCS_ENABLED
1309 ret->xptr = 1;
1310 ret->here = here;
1311 ret->origin = origin;
1312
1313 xmlXPathRegisterFunc(ret, (xmlChar *)"range",
1314 xmlXPtrRangeFunction);
1315 xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
1316 xmlXPtrRangeInsideFunction);
1317 xmlXPathRegisterFunc(ret, (xmlChar *)"string-range",
1318 xmlXPtrStringRangeFunction);
1319 xmlXPathRegisterFunc(ret, (xmlChar *)"start-point",
1320 xmlXPtrStartPointFunction);
1321 xmlXPathRegisterFunc(ret, (xmlChar *)"end-point",
1322 xmlXPtrEndPointFunction);
1323 xmlXPathRegisterFunc(ret, (xmlChar *)"here",
1324 xmlXPtrHereFunction);
1325 xmlXPathRegisterFunc(ret, (xmlChar *)" origin",
1326 xmlXPtrOriginFunction);
1327#endif /* LIBXML_XPTR_LOCS_ENABLED */
1328
1329 return(ret);
1330}
1331
1342xmlXPathObjectPtr
1343xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
1344 xmlXPathParserContextPtr ctxt;
1345 xmlXPathObjectPtr res = NULL, tmp;
1346 xmlXPathObjectPtr init = NULL;
1347 int stack = 0;
1348
1349 xmlInitParser();
1350
1351 if ((ctx == NULL) || (str == NULL))
1352 return(NULL);
1353
1354 ctxt = xmlXPathNewParserContext(str, ctx);
1355 if (ctxt == NULL)
1356 return(NULL);
1357 xmlXPtrEvalXPointer(ctxt);
1358
1359 if ((ctxt->value != NULL) &&
1360#ifdef LIBXML_XPTR_LOCS_ENABLED
1361 (ctxt->value->type != XPATH_LOCATIONSET) &&
1362#endif
1363 (ctxt->value->type != XPATH_NODESET)) {
1364 xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED,
1365 "xmlXPtrEval: evaluation failed to return a node set\n",
1366 NULL);
1367 } else {
1368 res = valuePop(ctxt);
1369 }
1370
1371 do {
1372 tmp = valuePop(ctxt);
1373 if (tmp != NULL) {
1374 if (tmp != init) {
1375 if (tmp->type == XPATH_NODESET) {
1376 /*
1377 * Evaluation may push a root nodeset which is unused
1378 */
1379 xmlNodeSetPtr set;
1380 set = tmp->nodesetval;
1381 if ((set == NULL) || (set->nodeNr != 1) ||
1382 (set->nodeTab[0] != (xmlNodePtr) ctx->doc))
1383 stack++;
1384 } else
1385 stack++;
1386 }
1387 xmlXPathFreeObject(tmp);
1388 }
1389 } while (tmp != NULL);
1390 if (stack != 0) {
1391 xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS,
1392 "xmlXPtrEval: object(s) left on the eval stack\n",
1393 NULL);
1394 }
1395 if (ctxt->error != XPATH_EXPRESSION_OK) {
1396 xmlXPathFreeObject(res);
1397 res = NULL;
1398 }
1399
1400 xmlXPathFreeParserContext(ctxt);
1401 return(res);
1402}
1403
1404#ifdef LIBXML_XPTR_LOCS_ENABLED
1414static xmlNodePtr
1415xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
1416 /* pointers to generated nodes */
1417 xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp;
1418 /* pointers to traversal nodes */
1419 xmlNodePtr start, cur, end;
1420 int index1, index2;
1421
1422 if (range == NULL)
1423 return(NULL);
1424 if (range->type != XPATH_RANGE)
1425 return(NULL);
1426 start = (xmlNodePtr) range->user;
1427
1428 if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
1429 return(NULL);
1430 end = range->user2;
1431 if (end == NULL)
1432 return(xmlCopyNode(start, 1));
1433 if (end->type == XML_NAMESPACE_DECL)
1434 return(NULL);
1435
1436 cur = start;
1437 index1 = range->index;
1438 index2 = range->index2;
1439 while (cur != NULL) {
1440 if (cur == end) {
1441 if (cur->type == XML_TEXT_NODE) {
1442 const xmlChar *content = cur->content;
1443 int len;
1444
1445 if (content == NULL) {
1446 tmp = xmlNewTextLen(NULL, 0);
1447 } else {
1448 len = index2;
1449 if ((cur == start) && (index1 > 1)) {
1450 content += (index1 - 1);
1451 len -= (index1 - 1);
1452 index1 = 0;
1453 } else {
1454 len = index2;
1455 }
1456 tmp = xmlNewTextLen(content, len);
1457 }
1458 /* single sub text node selection */
1459 if (list == NULL)
1460 return(tmp);
1461 /* prune and return full set */
1462 if (last != NULL)
1463 xmlAddNextSibling(last, tmp);
1464 else
1465 xmlAddChild(parent, tmp);
1466 return(list);
1467 } else {
1468 tmp = xmlCopyNode(cur, 0);
1469 if (list == NULL) {
1470 list = tmp;
1471 parent = tmp;
1472 } else {
1473 if (last != NULL)
1474 parent = xmlAddNextSibling(last, tmp);
1475 else
1476 parent = xmlAddChild(parent, tmp);
1477 }
1478 last = NULL;
1479
1480 if (index2 > 1) {
1481 end = xmlXPtrGetNthChild(cur, index2 - 1);
1482 index2 = 0;
1483 }
1484 if ((cur == start) && (index1 > 1)) {
1485 cur = xmlXPtrGetNthChild(cur, index1 - 1);
1486 index1 = 0;
1487 } else {
1488 cur = cur->children;
1489 }
1490 /*
1491 * Now gather the remaining nodes from cur to end
1492 */
1493 continue; /* while */
1494 }
1495 } else if ((cur == start) &&
1496 (list == NULL) /* looks superfluous but ... */ ) {
1497 if ((cur->type == XML_TEXT_NODE) ||
1498 (cur->type == XML_CDATA_SECTION_NODE)) {
1499 const xmlChar *content = cur->content;
1500
1501 if (content == NULL) {
1502 tmp = xmlNewTextLen(NULL, 0);
1503 } else {
1504 if (index1 > 1) {
1505 content += (index1 - 1);
1506 }
1507 tmp = xmlNewText(content);
1508 }
1509 last = list = tmp;
1510 } else {
1511 if ((cur == start) && (index1 > 1)) {
1512 tmp = xmlCopyNode(cur, 0);
1513 list = tmp;
1514 parent = tmp;
1515 last = NULL;
1516 cur = xmlXPtrGetNthChild(cur, index1 - 1);
1517 index1 = 0;
1518 /*
1519 * Now gather the remaining nodes from cur to end
1520 */
1521 continue; /* while */
1522 }
1523 tmp = xmlCopyNode(cur, 1);
1524 list = tmp;
1525 parent = NULL;
1526 last = tmp;
1527 }
1528 } else {
1529 tmp = NULL;
1530 switch (cur->type) {
1531 case XML_DTD_NODE:
1532 case XML_ELEMENT_DECL:
1533 case XML_ATTRIBUTE_DECL:
1534 case XML_ENTITY_NODE:
1535 /* Do not copy DTD information */
1536 break;
1537 case XML_ENTITY_DECL:
1538 TODO /* handle crossing entities -> stack needed */
1539 break;
1540 case XML_XINCLUDE_START:
1541 case XML_XINCLUDE_END:
1542 /* don't consider it part of the tree content */
1543 break;
1544 case XML_ATTRIBUTE_NODE:
1545 /* Humm, should not happen ! */
1546 STRANGE
1547 break;
1548 default:
1549 tmp = xmlCopyNode(cur, 1);
1550 break;
1551 }
1552 if (tmp != NULL) {
1553 if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1554 STRANGE
1555 return(NULL);
1556 }
1557 if (last != NULL)
1558 xmlAddNextSibling(last, tmp);
1559 else {
1560 last = xmlAddChild(parent, tmp);
1561 }
1562 }
1563 }
1564 /*
1565 * Skip to next node in document order
1566 */
1567 if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1568 STRANGE
1569 return(NULL);
1570 }
1571 cur = xmlXPtrAdvanceNode(cur, NULL);
1572 }
1573 return(list);
1574}
1575
1586xmlNodePtr
1587xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) {
1588 xmlNodePtr list = NULL, last = NULL;
1589 int i;
1590
1591 if (obj == NULL)
1592 return(NULL);
1593 switch (obj->type) {
1594 case XPATH_NODESET: {
1595 xmlNodeSetPtr set = obj->nodesetval;
1596 if (set == NULL)
1597 return(NULL);
1598 for (i = 0;i < set->nodeNr;i++) {
1599 if (set->nodeTab[i] == NULL)
1600 continue;
1601 switch (set->nodeTab[i]->type) {
1602 case XML_TEXT_NODE:
1603 case XML_CDATA_SECTION_NODE:
1604 case XML_ELEMENT_NODE:
1605 case XML_ENTITY_REF_NODE:
1606 case XML_ENTITY_NODE:
1607 case XML_PI_NODE:
1608 case XML_COMMENT_NODE:
1609 case XML_DOCUMENT_NODE:
1610 case XML_HTML_DOCUMENT_NODE:
1611 case XML_XINCLUDE_START:
1612 case XML_XINCLUDE_END:
1613 break;
1614 case XML_ATTRIBUTE_NODE:
1615 case XML_NAMESPACE_DECL:
1616 case XML_DOCUMENT_TYPE_NODE:
1617 case XML_DOCUMENT_FRAG_NODE:
1618 case XML_NOTATION_NODE:
1619 case XML_DTD_NODE:
1620 case XML_ELEMENT_DECL:
1621 case XML_ATTRIBUTE_DECL:
1622 case XML_ENTITY_DECL:
1623 continue; /* for */
1624 }
1625 if (last == NULL)
1626 list = last = xmlCopyNode(set->nodeTab[i], 1);
1627 else {
1628 xmlAddNextSibling(last, xmlCopyNode(set->nodeTab[i], 1));
1629 if (last->next != NULL)
1630 last = last->next;
1631 }
1632 }
1633 break;
1634 }
1635 case XPATH_LOCATIONSET: {
1636 xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1637 if (set == NULL)
1638 return(NULL);
1639 for (i = 0;i < set->locNr;i++) {
1640 if (last == NULL)
1641 list = last = xmlXPtrBuildNodeList(set->locTab[i]);
1642 else
1643 xmlAddNextSibling(last,
1644 xmlXPtrBuildNodeList(set->locTab[i]));
1645 if (last != NULL) {
1646 while (last->next != NULL)
1647 last = last->next;
1648 }
1649 }
1650 break;
1651 }
1652 case XPATH_RANGE:
1653 return(xmlXPtrBuildRangeNodeList(obj));
1654 case XPATH_POINT:
1655 return(xmlCopyNode(obj->user, 0));
1656 default:
1657 break;
1658 }
1659 return(list);
1660}
1661
1662/************************************************************************
1663 * *
1664 * XPointer functions *
1665 * *
1666 ************************************************************************/
1667
1677static int
1678xmlXPtrNbLocChildren(xmlNodePtr node) {
1679 int ret = 0;
1680 if (node == NULL)
1681 return(-1);
1682 switch (node->type) {
1683 case XML_HTML_DOCUMENT_NODE:
1684 case XML_DOCUMENT_NODE:
1685 case XML_ELEMENT_NODE:
1686 node = node->children;
1687 while (node != NULL) {
1688 if (node->type == XML_ELEMENT_NODE)
1689 ret++;
1690 node = node->next;
1691 }
1692 break;
1693 case XML_ATTRIBUTE_NODE:
1694 return(-1);
1695
1696 case XML_PI_NODE:
1697 case XML_COMMENT_NODE:
1698 case XML_TEXT_NODE:
1699 case XML_CDATA_SECTION_NODE:
1700 case XML_ENTITY_REF_NODE:
1701 ret = xmlStrlen(node->content);
1702 break;
1703 default:
1704 return(-1);
1705 }
1706 return(ret);
1707}
1708
1717static void
1718xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1719 CHECK_ARITY(0);
1720
1721 if (ctxt->context->here == NULL)
1722 XP_ERROR(XPTR_SYNTAX_ERROR);
1723
1724 valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->here, NULL));
1725}
1726
1735static void
1736xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1737 CHECK_ARITY(0);
1738
1739 if (ctxt->context->origin == NULL)
1740 XP_ERROR(XPTR_SYNTAX_ERROR);
1741
1742 valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->origin, NULL));
1743}
1744
1768static void
1769xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1770 xmlXPathObjectPtr tmp, obj, point;
1771 xmlLocationSetPtr newset = NULL;
1772 xmlLocationSetPtr oldset = NULL;
1773
1774 CHECK_ARITY(1);
1775 if ((ctxt->value == NULL) ||
1776 ((ctxt->value->type != XPATH_LOCATIONSET) &&
1777 (ctxt->value->type != XPATH_NODESET)))
1778 XP_ERROR(XPATH_INVALID_TYPE)
1779
1780 obj = valuePop(ctxt);
1781 if (obj->type == XPATH_NODESET) {
1782 /*
1783 * First convert to a location set
1784 */
1785 tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1786 xmlXPathFreeObject(obj);
1787 if (tmp == NULL)
1788 XP_ERROR(XPATH_MEMORY_ERROR)
1789 obj = tmp;
1790 }
1791
1792 newset = xmlXPtrLocationSetCreate(NULL);
1793 if (newset == NULL) {
1794 xmlXPathFreeObject(obj);
1795 XP_ERROR(XPATH_MEMORY_ERROR);
1796 }
1797 oldset = (xmlLocationSetPtr) obj->user;
1798 if (oldset != NULL) {
1799 int i;
1800
1801 for (i = 0; i < oldset->locNr; i++) {
1802 tmp = oldset->locTab[i];
1803 if (tmp == NULL)
1804 continue;
1805 point = NULL;
1806 switch (tmp->type) {
1807 case XPATH_POINT:
1808 point = xmlXPtrNewPoint(tmp->user, tmp->index);
1809 break;
1810 case XPATH_RANGE: {
1811 xmlNodePtr node = tmp->user;
1812 if (node != NULL) {
1813 if ((node->type == XML_ATTRIBUTE_NODE) ||
1814 (node->type == XML_NAMESPACE_DECL)) {
1815 xmlXPathFreeObject(obj);
1816 xmlXPtrFreeLocationSet(newset);
1817 XP_ERROR(XPTR_SYNTAX_ERROR);
1818 }
1819 point = xmlXPtrNewPoint(node, tmp->index);
1820 }
1821 break;
1822 }
1823 default:
1824 /*** Should we raise an error ?
1825 xmlXPathFreeObject(obj);
1826 xmlXPathFreeObject(newset);
1827 XP_ERROR(XPATH_INVALID_TYPE)
1828 ***/
1829 break;
1830 }
1831 if (point != NULL)
1832 xmlXPtrLocationSetAdd(newset, point);
1833 }
1834 }
1835 xmlXPathFreeObject(obj);
1836 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1837}
1838
1864static void
1865xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1866 xmlXPathObjectPtr tmp, obj, point;
1867 xmlLocationSetPtr newset = NULL;
1868 xmlLocationSetPtr oldset = NULL;
1869
1870 CHECK_ARITY(1);
1871 if ((ctxt->value == NULL) ||
1872 ((ctxt->value->type != XPATH_LOCATIONSET) &&
1873 (ctxt->value->type != XPATH_NODESET)))
1874 XP_ERROR(XPATH_INVALID_TYPE)
1875
1876 obj = valuePop(ctxt);
1877 if (obj->type == XPATH_NODESET) {
1878 /*
1879 * First convert to a location set
1880 */
1881 tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1882 xmlXPathFreeObject(obj);
1883 if (tmp == NULL)
1884 XP_ERROR(XPATH_MEMORY_ERROR)
1885 obj = tmp;
1886 }
1887
1888 newset = xmlXPtrLocationSetCreate(NULL);
1889 if (newset == NULL) {
1890 xmlXPathFreeObject(obj);
1891 XP_ERROR(XPATH_MEMORY_ERROR);
1892 }
1893 oldset = (xmlLocationSetPtr) obj->user;
1894 if (oldset != NULL) {
1895 int i;
1896
1897 for (i = 0; i < oldset->locNr; i++) {
1898 tmp = oldset->locTab[i];
1899 if (tmp == NULL)
1900 continue;
1901 point = NULL;
1902 switch (tmp->type) {
1903 case XPATH_POINT:
1904 point = xmlXPtrNewPoint(tmp->user, tmp->index);
1905 break;
1906 case XPATH_RANGE: {
1907 xmlNodePtr node = tmp->user2;
1908 if (node != NULL) {
1909 if ((node->type == XML_ATTRIBUTE_NODE) ||
1910 (node->type == XML_NAMESPACE_DECL)) {
1911 xmlXPathFreeObject(obj);
1912 xmlXPtrFreeLocationSet(newset);
1913 XP_ERROR(XPTR_SYNTAX_ERROR);
1914 }
1915 point = xmlXPtrNewPoint(node, tmp->index2);
1916 } else if (tmp->user == NULL) {
1917 point = xmlXPtrNewPoint(node,
1918 xmlXPtrNbLocChildren(node));
1919 }
1920 break;
1921 }
1922 default:
1923 /*** Should we raise an error ?
1924 xmlXPathFreeObject(obj);
1925 xmlXPathFreeObject(newset);
1926 XP_ERROR(XPATH_INVALID_TYPE)
1927 ***/
1928 break;
1929 }
1930 if (point != NULL)
1931 xmlXPtrLocationSetAdd(newset, point);
1932 }
1933 }
1934 xmlXPathFreeObject(obj);
1935 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1936}
1937
1938
1950static xmlXPathObjectPtr
1951xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
1952 if (loc == NULL)
1953 return(NULL);
1954 if ((ctxt == NULL) || (ctxt->context == NULL) ||
1955 (ctxt->context->doc == NULL))
1956 return(NULL);
1957 switch (loc->type) {
1958 case XPATH_POINT:
1959 return(xmlXPtrNewRange(loc->user, loc->index,
1960 loc->user, loc->index));
1961 case XPATH_RANGE:
1962 if (loc->user2 != NULL) {
1963 return(xmlXPtrNewRange(loc->user, loc->index,
1964 loc->user2, loc->index2));
1965 } else {
1966 xmlNodePtr node = (xmlNodePtr) loc->user;
1967 if (node == (xmlNodePtr) ctxt->context->doc) {
1968 return(xmlXPtrNewRange(node, 0, node,
1969 xmlXPtrGetArity(node)));
1970 } else {
1971 switch (node->type) {
1972 case XML_ATTRIBUTE_NODE:
1973 /* !!! our model is slightly different than XPath */
1974 return(xmlXPtrNewRange(node, 0, node,
1975 xmlXPtrGetArity(node)));
1976 case XML_ELEMENT_NODE:
1977 case XML_TEXT_NODE:
1978 case XML_CDATA_SECTION_NODE:
1979 case XML_ENTITY_REF_NODE:
1980 case XML_PI_NODE:
1981 case XML_COMMENT_NODE:
1982 case XML_DOCUMENT_NODE:
1983 case XML_NOTATION_NODE:
1984 case XML_HTML_DOCUMENT_NODE: {
1985 int indx = xmlXPtrGetIndex(node);
1986
1987 node = node->parent;
1988 return(xmlXPtrNewRange(node, indx - 1,
1989 node, indx + 1));
1990 }
1991 default:
1992 return(NULL);
1993 }
1994 }
1995 }
1996 default:
1997 TODO /* missed one case ??? */
1998 }
1999 return(NULL);
2000}
2001
2015static void
2016xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2017 int i;
2018 xmlXPathObjectPtr set;
2019 xmlLocationSetPtr oldset;
2020 xmlLocationSetPtr newset;
2021
2022 CHECK_ARITY(1);
2023 if ((ctxt->value == NULL) ||
2024 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2025 (ctxt->value->type != XPATH_NODESET)))
2026 XP_ERROR(XPATH_INVALID_TYPE)
2027
2028 set = valuePop(ctxt);
2029 if (set->type == XPATH_NODESET) {
2030 xmlXPathObjectPtr tmp;
2031
2032 /*
2033 * First convert to a location set
2034 */
2035 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2036 xmlXPathFreeObject(set);
2037 if (tmp == NULL)
2038 XP_ERROR(XPATH_MEMORY_ERROR)
2039 set = tmp;
2040 }
2041 oldset = (xmlLocationSetPtr) set->user;
2042
2043 /*
2044 * The loop is to compute the covering range for each item and add it
2045 */
2046 newset = xmlXPtrLocationSetCreate(NULL);
2047 if (newset == NULL) {
2048 xmlXPathFreeObject(set);
2049 XP_ERROR(XPATH_MEMORY_ERROR);
2050 }
2051 if (oldset != NULL) {
2052 for (i = 0;i < oldset->locNr;i++) {
2053 xmlXPtrLocationSetAdd(newset,
2054 xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
2055 }
2056 }
2057
2058 /*
2059 * Save the new value and cleanup
2060 */
2061 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2062 xmlXPathFreeObject(set);
2063}
2064
2074static xmlXPathObjectPtr
2075xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
2076 if (loc == NULL)
2077 return(NULL);
2078 if ((ctxt == NULL) || (ctxt->context == NULL) ||
2079 (ctxt->context->doc == NULL))
2080 return(NULL);
2081 switch (loc->type) {
2082 case XPATH_POINT: {
2083 xmlNodePtr node = (xmlNodePtr) loc->user;
2084 switch (node->type) {
2085 case XML_PI_NODE:
2086 case XML_COMMENT_NODE:
2087 case XML_TEXT_NODE:
2088 case XML_CDATA_SECTION_NODE: {
2089 if (node->content == NULL) {
2090 return(xmlXPtrNewRange(node, 0, node, 0));
2091 } else {
2092 return(xmlXPtrNewRange(node, 0, node,
2093 xmlStrlen(node->content)));
2094 }
2095 }
2096 case XML_ATTRIBUTE_NODE:
2097 case XML_ELEMENT_NODE:
2098 case XML_ENTITY_REF_NODE:
2099 case XML_DOCUMENT_NODE:
2100 case XML_NOTATION_NODE:
2101 case XML_HTML_DOCUMENT_NODE: {
2102 return(xmlXPtrNewRange(node, 0, node,
2103 xmlXPtrGetArity(node)));
2104 }
2105 default:
2106 break;
2107 }
2108 return(NULL);
2109 }
2110 case XPATH_RANGE: {
2111 xmlNodePtr node = (xmlNodePtr) loc->user;
2112 if (loc->user2 != NULL) {
2113 return(xmlXPtrNewRange(node, loc->index,
2114 loc->user2, loc->index2));
2115 } else {
2116 switch (node->type) {
2117 case XML_PI_NODE:
2118 case XML_COMMENT_NODE:
2119 case XML_TEXT_NODE:
2120 case XML_CDATA_SECTION_NODE: {
2121 if (node->content == NULL) {
2122 return(xmlXPtrNewRange(node, 0, node, 0));
2123 } else {
2124 return(xmlXPtrNewRange(node, 0, node,
2125 xmlStrlen(node->content)));
2126 }
2127 }
2128 case XML_ATTRIBUTE_NODE:
2129 case XML_ELEMENT_NODE:
2130 case XML_ENTITY_REF_NODE:
2131 case XML_DOCUMENT_NODE:
2132 case XML_NOTATION_NODE:
2133 case XML_HTML_DOCUMENT_NODE: {
2134 return(xmlXPtrNewRange(node, 0, node,
2135 xmlXPtrGetArity(node)));
2136 }
2137 default:
2138 break;
2139 }
2140 return(NULL);
2141 }
2142 }
2143 default:
2144 TODO /* missed one case ??? */
2145 }
2146 return(NULL);
2147}
2148
2169static void
2170xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2171 int i;
2172 xmlXPathObjectPtr set;
2173 xmlLocationSetPtr oldset;
2174 xmlLocationSetPtr newset;
2175
2176 CHECK_ARITY(1);
2177 if ((ctxt->value == NULL) ||
2178 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2179 (ctxt->value->type != XPATH_NODESET)))
2180 XP_ERROR(XPATH_INVALID_TYPE)
2181
2182 set = valuePop(ctxt);
2183 if (set->type == XPATH_NODESET) {
2184 xmlXPathObjectPtr tmp;
2185
2186 /*
2187 * First convert to a location set
2188 */
2189 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2190 xmlXPathFreeObject(set);
2191 if (tmp == NULL)
2192 XP_ERROR(XPATH_MEMORY_ERROR)
2193 set = tmp;
2194 }
2195
2196 /*
2197 * The loop is to compute the covering range for each item and add it
2198 */
2199 newset = xmlXPtrLocationSetCreate(NULL);
2200 if (newset == NULL) {
2201 xmlXPathFreeObject(set);
2202 XP_ERROR(XPATH_MEMORY_ERROR);
2203 }
2204 oldset = (xmlLocationSetPtr) set->user;
2205 if (oldset != NULL) {
2206 for (i = 0;i < oldset->locNr;i++) {
2207 xmlXPtrLocationSetAdd(newset,
2208 xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
2209 }
2210 }
2211
2212 /*
2213 * Save the new value and cleanup
2214 */
2215 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2216 xmlXPathFreeObject(set);
2217}
2218
2229void
2230xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
2231 int nargs ATTRIBUTE_UNUSED) {
2232 XP_ERROR(XPATH_EXPR_ERROR);
2233}
2234
2245xmlNodePtr
2246xmlXPtrAdvanceNode(xmlNodePtr cur, int *level) {
2247next:
2248 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2249 return(NULL);
2250 if (cur->children != NULL) {
2251 cur = cur->children ;
2252 if (level != NULL)
2253 (*level)++;
2254 goto found;
2255 }
2256skip: /* This label should only be needed if something is wrong! */
2257 if (cur->next != NULL) {
2258 cur = cur->next;
2259 goto found;
2260 }
2261 do {
2262 cur = cur->parent;
2263 if (level != NULL)
2264 (*level)--;
2265 if (cur == NULL) return(NULL);
2266 if (cur->next != NULL) {
2267 cur = cur->next;
2268 goto found;
2269 }
2270 } while (cur != NULL);
2271
2272found:
2273 if ((cur->type != XML_ELEMENT_NODE) &&
2274 (cur->type != XML_TEXT_NODE) &&
2275 (cur->type != XML_DOCUMENT_NODE) &&
2276 (cur->type != XML_HTML_DOCUMENT_NODE) &&
2277 (cur->type != XML_CDATA_SECTION_NODE)) {
2278 if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */
2279 TODO
2280 goto skip;
2281 }
2282 goto next;
2283 }
2284 return(cur);
2285}
2286
2297static int
2298xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) {
2299 xmlNodePtr cur;
2300 int pos;
2301 int len;
2302
2303 if ((node == NULL) || (indx == NULL))
2304 return(-1);
2305 cur = *node;
2306 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2307 return(-1);
2308 pos = *indx;
2309
2310 while (bytes >= 0) {
2311 /*
2312 * First position to the beginning of the first text node
2313 * corresponding to this point
2314 */
2315 while ((cur != NULL) &&
2316 ((cur->type == XML_ELEMENT_NODE) ||
2317 (cur->type == XML_DOCUMENT_NODE) ||
2318 (cur->type == XML_HTML_DOCUMENT_NODE))) {
2319 if (pos > 0) {
2320 cur = xmlXPtrGetNthChild(cur, pos);
2321 pos = 0;
2322 } else {
2323 cur = xmlXPtrAdvanceNode(cur, NULL);
2324 pos = 0;
2325 }
2326 }
2327
2328 if (cur == NULL) {
2329 *node = NULL;
2330 *indx = 0;
2331 return(-1);
2332 }
2333
2334 /*
2335 * if there is no move needed return the current value.
2336 */
2337 if (pos == 0) pos = 1;
2338 if (bytes == 0) {
2339 *node = cur;
2340 *indx = pos;
2341 return(0);
2342 }
2343 /*
2344 * We should have a text (or cdata) node ...
2345 */
2346 len = 0;
2347 if ((cur->type != XML_ELEMENT_NODE) &&
2348 (cur->content != NULL)) {
2349 len = xmlStrlen(cur->content);
2350 }
2351 if (pos > len) {
2352 /* Strange, the indx in the text node is greater than it's len */
2353 STRANGE
2354 pos = len;
2355 }
2356 if (pos + bytes >= len) {
2357 bytes -= (len - pos);
2358 cur = xmlXPtrAdvanceNode(cur, NULL);
2359 pos = 0;
2360 } else if (pos + bytes < len) {
2361 pos += bytes;
2362 *node = cur;
2363 *indx = pos;
2364 return(0);
2365 }
2366 }
2367 return(-1);
2368}
2369
2386static int
2387xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
2388 xmlNodePtr *end, int *endindex) {
2389 xmlNodePtr cur;
2390 int pos; /* 0 based */
2391 int len; /* in bytes */
2392 int stringlen; /* in bytes */
2393 int match;
2394
2395 if (string == NULL)
2396 return(-1);
2397 if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
2398 return(-1);
2399 if ((end == NULL) || (*end == NULL) ||
2400 ((*end)->type == XML_NAMESPACE_DECL) || (endindex == NULL))
2401 return(-1);
2402 cur = start;
2403 pos = startindex - 1;
2404 stringlen = xmlStrlen(string);
2405
2406 while (stringlen > 0) {
2407 if ((cur == *end) && (pos + stringlen > *endindex))
2408 return(0);
2409
2410 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2411 len = xmlStrlen(cur->content);
2412 if (len >= pos + stringlen) {
2413 match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
2414 if (match) {
2415 *end = cur;
2416 *endindex = pos + stringlen;
2417 return(1);
2418 } else {
2419 return(0);
2420 }
2421 } else {
2422 int sub = len - pos;
2423 match = (!xmlStrncmp(&cur->content[pos], string, sub));
2424 if (match) {
2425 string = &string[sub];
2426 stringlen -= sub;
2427 } else {
2428 return(0);
2429 }
2430 }
2431 }
2432 cur = xmlXPtrAdvanceNode(cur, NULL);
2433 if (cur == NULL)
2434 return(0);
2435 pos = 0;
2436 }
2437 return(1);
2438}
2439
2456static int
2457xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
2458 xmlNodePtr *end, int *endindex) {
2459 xmlNodePtr cur;
2460 const xmlChar *str;
2461 int pos; /* 0 based */
2462 int len; /* in bytes */
2463 xmlChar first;
2464
2465 if (string == NULL)
2466 return(-1);
2467 if ((start == NULL) || (*start == NULL) ||
2468 ((*start)->type == XML_NAMESPACE_DECL) || (startindex == NULL))
2469 return(-1);
2470 if ((end == NULL) || (endindex == NULL))
2471 return(-1);
2472 cur = *start;
2473 pos = *startindex - 1;
2474 first = string[0];
2475
2476 while (cur != NULL) {
2477 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2478 len = xmlStrlen(cur->content);
2479 while (pos <= len) {
2480 if (first != 0) {
2481 str = xmlStrchr(&cur->content[pos], first);
2482 if (str != NULL) {
2483 pos = (str - (xmlChar *)(cur->content));
2484 if (xmlXPtrMatchString(string, cur, pos + 1,
2485 end, endindex)) {
2486 *start = cur;
2487 *startindex = pos + 1;
2488 return(1);
2489 }
2490 pos++;
2491 } else {
2492 pos = len + 1;
2493 }
2494 } else {
2495 /*
2496 * An empty string is considered to match before each
2497 * character of the string-value and after the final
2498 * character.
2499 */
2500 *start = cur;
2501 *startindex = pos + 1;
2502 *end = cur;
2503 *endindex = pos + 1;
2504 return(1);
2505 }
2506 }
2507 }
2508 if ((cur == *end) && (pos >= *endindex))
2509 return(0);
2510 cur = xmlXPtrAdvanceNode(cur, NULL);
2511 if (cur == NULL)
2512 return(0);
2513 pos = 1;
2514 }
2515 return(0);
2516}
2517
2527static int
2528xmlXPtrGetLastChar(xmlNodePtr *node, int *indx) {
2529 xmlNodePtr cur;
2530 int pos, len = 0;
2531
2532 if ((node == NULL) || (*node == NULL) ||
2533 ((*node)->type == XML_NAMESPACE_DECL) || (indx == NULL))
2534 return(-1);
2535 cur = *node;
2536 pos = *indx;
2537
2538 if ((cur->type == XML_ELEMENT_NODE) ||
2539 (cur->type == XML_DOCUMENT_NODE) ||
2540 (cur->type == XML_HTML_DOCUMENT_NODE)) {
2541 if (pos > 0) {
2542 cur = xmlXPtrGetNthChild(cur, pos);
2543 }
2544 }
2545 while (cur != NULL) {
2546 if (cur->last != NULL)
2547 cur = cur->last;
2548 else if ((cur->type != XML_ELEMENT_NODE) &&
2549 (cur->content != NULL)) {
2550 len = xmlStrlen(cur->content);
2551 break;
2552 } else {
2553 return(-1);
2554 }
2555 }
2556 if (cur == NULL)
2557 return(-1);
2558 *node = cur;
2559 *indx = len;
2560 return(0);
2561}
2562
2573static int
2574xmlXPtrGetStartPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2575 if ((obj == NULL) || (node == NULL) || (indx == NULL))
2576 return(-1);
2577
2578 switch (obj->type) {
2579 case XPATH_POINT:
2580 *node = obj->user;
2581 if (obj->index <= 0)
2582 *indx = 0;
2583 else
2584 *indx = obj->index;
2585 return(0);
2586 case XPATH_RANGE:
2587 *node = obj->user;
2588 if (obj->index <= 0)
2589 *indx = 0;
2590 else
2591 *indx = obj->index;
2592 return(0);
2593 default:
2594 break;
2595 }
2596 return(-1);
2597}
2598
2609static int
2610xmlXPtrGetEndPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2611 if ((obj == NULL) || (node == NULL) || (indx == NULL))
2612 return(-1);
2613
2614 switch (obj->type) {
2615 case XPATH_POINT:
2616 *node = obj->user;
2617 if (obj->index <= 0)
2618 *indx = 0;
2619 else
2620 *indx = obj->index;
2621 return(0);
2622 case XPATH_RANGE:
2623 *node = obj->user;
2624 if (obj->index <= 0)
2625 *indx = 0;
2626 else
2627 *indx = obj->index;
2628 return(0);
2629 default:
2630 break;
2631 }
2632 return(-1);
2633}
2634
2671static void
2672xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2673 int i, startindex, endindex = 0, fendindex;
2674 xmlNodePtr start, end = 0, fend;
2675 xmlXPathObjectPtr set = NULL;
2676 xmlLocationSetPtr oldset;
2677 xmlLocationSetPtr newset = NULL;
2678 xmlXPathObjectPtr string = NULL;
2679 xmlXPathObjectPtr position = NULL;
2680 xmlXPathObjectPtr number = NULL;
2681 int found, pos = 0, num = 0;
2682
2683 /*
2684 * Grab the arguments
2685 */
2686 if ((nargs < 2) || (nargs > 4))
2687 XP_ERROR(XPATH_INVALID_ARITY);
2688
2689 if (nargs >= 4) {
2690 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2691 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2692 goto error;
2693 }
2694 number = valuePop(ctxt);
2695 if (number != NULL)
2696 num = (int) number->floatval;
2697 }
2698 if (nargs >= 3) {
2699 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2700 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2701 goto error;
2702 }
2703 position = valuePop(ctxt);
2704 if (position != NULL)
2705 pos = (int) position->floatval;
2706 }
2707 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
2708 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2709 goto error;
2710 }
2711 string = valuePop(ctxt);
2712 if ((ctxt->value == NULL) ||
2713 ((ctxt->value->type != XPATH_LOCATIONSET) &&
2714 (ctxt->value->type != XPATH_NODESET))) {
2715 xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2716 goto error;
2717 }
2718 set = valuePop(ctxt);
2719 newset = xmlXPtrLocationSetCreate(NULL);
2720 if (newset == NULL) {
2721 xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2722 goto error;
2723 }
2724 if (set->nodesetval == NULL) {
2725 goto error;
2726 }
2727 if (set->type == XPATH_NODESET) {
2728 xmlXPathObjectPtr tmp;
2729
2730 /*
2731 * First convert to a location set
2732 */
2733 tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2734 xmlXPathFreeObject(set);
2735 set = NULL;
2736 if (tmp == NULL) {
2737 xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2738 goto error;
2739 }
2740 set = tmp;
2741 }
2742 oldset = (xmlLocationSetPtr) set->user;
2743
2744 /*
2745 * The loop is to search for each element in the location set
2746 * the list of location set corresponding to that search
2747 */
2748 for (i = 0;i < oldset->locNr;i++) {
2749
2750 xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex);
2751 xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex);
2752 xmlXPtrAdvanceChar(&start, &startindex, 0);
2753 xmlXPtrGetLastChar(&end, &endindex);
2754
2755 do {
2756 fend = end;
2757 fendindex = endindex;
2758 found = xmlXPtrSearchString(string->stringval, &start, &startindex,
2759 &fend, &fendindex);
2760 if (found == 1) {
2761 if (position == NULL) {
2762 xmlXPtrLocationSetAdd(newset,
2763 xmlXPtrNewRange(start, startindex, fend, fendindex));
2764 } else if (xmlXPtrAdvanceChar(&start, &startindex,
2765 pos - 1) == 0) {
2766 if ((number != NULL) && (num > 0)) {
2767 int rindx;
2768 xmlNodePtr rend;
2769 rend = start;
2770 rindx = startindex - 1;
2771 if (xmlXPtrAdvanceChar(&rend, &rindx,
2772 num) == 0) {
2773 xmlXPtrLocationSetAdd(newset,
2774 xmlXPtrNewRange(start, startindex,
2775 rend, rindx));
2776 }
2777 } else if ((number != NULL) && (num <= 0)) {
2778 xmlXPtrLocationSetAdd(newset,
2779 xmlXPtrNewRange(start, startindex,
2780 start, startindex));
2781 } else {
2782 xmlXPtrLocationSetAdd(newset,
2783 xmlXPtrNewRange(start, startindex,
2784 fend, fendindex));
2785 }
2786 }
2787 start = fend;
2788 startindex = fendindex;
2789 if (string->stringval[0] == 0)
2790 startindex++;
2791 }
2792 } while (found == 1);
2793 }
2794
2795 /*
2796 * Save the new value and cleanup
2797 */
2798error:
2799 if (newset != NULL)
2800 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2801 xmlXPathFreeObject(set);
2802 xmlXPathFreeObject(string);
2803 if (position) xmlXPathFreeObject(position);
2804 if (number) xmlXPathFreeObject(number);
2805}
2806
2817void
2818xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) {
2819 const xmlChar *cur;
2820 xmlXPathObjectPtr res;
2821 xmlXPathObjectPtr obj, tmp;
2822 xmlLocationSetPtr newset = NULL;
2823 xmlLocationSetPtr oldset;
2824 int i;
2825
2826 if (ctxt == NULL) return;
2827
2829 if (CUR != '[') {
2830 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2831 }
2832 NEXT;
2834
2835 /*
2836 * Extract the old set, and then evaluate the result of the
2837 * expression for all the element in the set. use it to grow
2838 * up a new set.
2839 */
2840 CHECK_TYPE(XPATH_LOCATIONSET);
2841 obj = valuePop(ctxt);
2842 oldset = obj->user;
2843 ctxt->context->node = NULL;
2844
2845 if ((oldset == NULL) || (oldset->locNr == 0)) {
2846 ctxt->context->contextSize = 0;
2847 ctxt->context->proximityPosition = 0;
2848 xmlXPathEvalExpr(ctxt);
2849 res = valuePop(ctxt);
2850 if (res != NULL)
2851 xmlXPathFreeObject(res);
2852 valuePush(ctxt, obj);
2853 CHECK_ERROR;
2854 } else {
2855 /*
2856 * Save the expression pointer since we will have to evaluate
2857 * it multiple times. Initialize the new set.
2858 */
2859 cur = ctxt->cur;
2860 newset = xmlXPtrLocationSetCreate(NULL);
2861
2862 for (i = 0; i < oldset->locNr; i++) {
2863 ctxt->cur = cur;
2864
2865 /*
2866 * Run the evaluation with a node list made of a single item
2867 * in the nodeset.
2868 */
2869 ctxt->context->node = oldset->locTab[i]->user;
2870 tmp = xmlXPathNewNodeSet(ctxt->context->node);
2871 valuePush(ctxt, tmp);
2872 ctxt->context->contextSize = oldset->locNr;
2873 ctxt->context->proximityPosition = i + 1;
2874
2875 xmlXPathEvalExpr(ctxt);
2876 CHECK_ERROR;
2877
2878 /*
2879 * The result of the evaluation need to be tested to
2880 * decided whether the filter succeeded or not
2881 */
2882 res = valuePop(ctxt);
2883 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
2884 xmlXPtrLocationSetAdd(newset,
2885 xmlXPathObjectCopy(oldset->locTab[i]));
2886 }
2887
2888 /*
2889 * Cleanup
2890 */
2891 if (res != NULL)
2892 xmlXPathFreeObject(res);
2893 if (ctxt->value == tmp) {
2894 res = valuePop(ctxt);
2895 xmlXPathFreeObject(res);
2896 }
2897
2898 ctxt->context->node = NULL;
2899 }
2900
2901 /*
2902 * The result is used as the new evaluation set.
2903 */
2904 xmlXPathFreeObject(obj);
2905 ctxt->context->node = NULL;
2906 ctxt->context->contextSize = -1;
2907 ctxt->context->proximityPosition = -1;
2908 valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2909 }
2910 if (CUR != ']') {
2911 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2912 }
2913
2914 NEXT;
2916}
2917#endif /* LIBXML_XPTR_LOCS_ENABLED */
2918
2919#endif
#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
#define NULL
Definition: types.h:112
#define SKIP_BLANKS
Definition: pattern.c:1186
#define NXT(val)
Definition: pattern.c:1183
#define CUR
Definition: pattern.c:1181
content
Definition: atl_ax.c:994
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
#define INT_MAX
Definition: limits.h:26
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
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
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
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
xmlMallocFunc xmlMallocAtomic
Definition: globals.c:204
XML_GLOBALS_PARSER XMLPUBFUN void xmlInitParser(void)
Definition: threads.c:569
XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *nod, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg,...) LIBXML_ATTR_FORMAT(16
#define memset(x, y, z)
Definition: compat.h:39
Definition: match.c:28
Definition: name.c:39
Definition: format.c:80
Character const *const prefix
Definition: tempnam.cpp:195
Definition: dlist.c:348
void * next
Definition: dlist.c:360
static int init
Definition: wintirpc.c:33
XMLPUBFUN void xmlResetError(xmlErrorPtr err)
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_FROM_XPOINTER
Definition: xmlerror.h:50
@ XML_XPTR_EXTRA_OBJECTS
Definition: xmlerror.h:683
@ XML_XPTR_UNKNOWN_SCHEME
Definition: xmlerror.h:680
@ XML_XPTR_EVAL_FAILED
Definition: xmlerror.h:682
@ XML_XPTR_CHILDSEQ_START
Definition: xmlerror.h:681
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN int xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:215
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
XMLPUBFUN const xmlChar * xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:327
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:472
#define const
Definition: zconf.h:233