Diff for /embedaddon/libxml2/xpath.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2012/02/21 23:37:58 version 1.1.1.3, 2014/06/15 19:53:29
Line 55 Line 55
 #include <libxml/pattern.h>  #include <libxml/pattern.h>
 #endif  #endif
   
   #include "buf.h"
   
 #ifdef LIBXML_PATTERN_ENABLED  #ifdef LIBXML_PATTERN_ENABLED
 #define XPATH_STREAMING  #define XPATH_STREAMING
 #endif  #endif
Line 64 Line 66
             "Unimplemented block at %s:%d\n",                           \              "Unimplemented block at %s:%d\n",                           \
             __FILE__, __LINE__);              __FILE__, __LINE__);
   
   /**
    * WITH_TIM_SORT:
    *
    * Use the Timsort algorithm provided in timsort.h to sort
    * nodeset as this is a great improvement over the old Shell sort
    * used in xmlXPathNodeSetSort()
    */
   #define WITH_TIM_SORT
   
 /*  /*
 * XP_OPTIMIZED_NON_ELEM_COMPARISON:  * XP_OPTIMIZED_NON_ELEM_COMPARISON:
 * If defined, this will use xmlXPathCmpNodesExt() instead of  * If defined, this will use xmlXPathCmpNodesExt() instead of
Line 90 Line 101
 /* #define XP_DEBUG_OBJ_USAGE */  /* #define XP_DEBUG_OBJ_USAGE */
   
 /*  /*
    * XPATH_MAX_STEPS:
    * when compiling an XPath expression we arbitrary limit the maximum
    * number of step operation in the compiled expression. 1000000 is
    * an insanely large value which should never be reached under normal
    * circumstances
    */
   #define XPATH_MAX_STEPS 1000000
   
   /*
    * XPATH_MAX_STACK_DEPTH:
    * when evaluating an XPath expression we arbitrary limit the maximum
    * number of object allowed to be pushed on the stack. 1000000 is
    * an insanely large value which should never be reached under normal
    * circumstances
    */
   #define XPATH_MAX_STACK_DEPTH 1000000
   
   /*
    * XPATH_MAX_NODESET_LENGTH:
    * when evaluating an XPath expression nodesets are created and we
    * arbitrary limit the maximum length of those node set. 10000000 is
    * an insanely large value which should never be reached under normal
    * circumstances, one would first need to construct an in memory tree
    * with more than 10 millions nodes.
    */
   #define XPATH_MAX_NODESET_LENGTH 10000000
   
   /*
  * TODO:   * TODO:
  * There are a few spots where some tests are done which depend upon ascii   * There are a few spots where some tests are done which depend upon ascii
  * data.  These should be enhanced for full UTF8 support (see particularly   * data.  These should be enhanced for full UTF8 support (see particularly
  * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)   * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
  */   */
   
   /*
    * Wrapper for the Timsort argorithm from timsort.h
    */
   #ifdef WITH_TIM_SORT
   #define SORT_NAME libxml_domnode
   #define SORT_TYPE xmlNodePtr
   /**
    * wrap_cmp:
    * @x: a node
    * @y: another node
    *
    * Comparison function for the Timsort implementation
    *
    * Returns -2 in case of error -1 if first point < second point, 0 if
    *         it's the same node, +1 otherwise
    */
   static
   int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
   #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
       static int xmlXPathCmpNodesExt(xmlNodePtr, xmlNodePtr);
       static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
       {
           int res = xmlXPathCmpNodesExt(x, y);
           return res == -2 ? res : -res;
       }
   #else
       static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
       {
           int res = xmlXPathCmpNodes(x, y);
           return res == -2 ? res : -res;
       }
   #endif
   #define SORT_CMP(x, y)  (wrap_cmp(x, y))
   #include "timsort.h"
   #endif /* WITH_TIM_SORT */
   
 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
   
 /************************************************************************  /************************************************************************
Line 252  static const char *xmlXPathErrorMessages[] = { Line 327  static const char *xmlXPathErrorMessages[] = {
     "Encoding error\n",      "Encoding error\n",
     "Char out of XML range\n",      "Char out of XML range\n",
     "Invalid or incomplete context\n",      "Invalid or incomplete context\n",
       "Stack usage errror\n",
       "Forbidden variable\n",
     "?? Unknown error ??\n"     /* Must be last in the list! */      "?? Unknown error ??\n"     /* Must be last in the list! */
 };  };
 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \  #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
Line 419  xmlPointerListAddSize(xmlPointerListPtr list, Line 496  xmlPointerListAddSize(xmlPointerListPtr list,
     if (list->items == NULL) {      if (list->items == NULL) {
         if (initialSize <= 0)          if (initialSize <= 0)
             initialSize = 1;              initialSize = 1;
        list->items = (void **) xmlMalloc(        list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
            initialSize * sizeof(void *)); 
         if (list->items == NULL) {          if (list->items == NULL) {
             xmlXPathErrMemory(NULL,              xmlXPathErrMemory(NULL,
                 "xmlPointerListCreate: allocating item\n");                  "xmlPointerListCreate: allocating item\n");
Line 429  xmlPointerListAddSize(xmlPointerListPtr list, Line 505  xmlPointerListAddSize(xmlPointerListPtr list,
         list->number = 0;          list->number = 0;
         list->size = initialSize;          list->size = initialSize;
     } else if (list->size <= list->number) {      } else if (list->size <= list->number) {
           if (list->size > 50000000) {
               xmlXPathErrMemory(NULL,
                   "xmlPointerListAddSize: re-allocating item\n");
               return(-1);
           }
         list->size *= 2;          list->size *= 2;
         list->items = (void **) xmlRealloc(list->items,          list->items = (void **) xmlRealloc(list->items,
             list->size * sizeof(void *));              list->size * sizeof(void *));
         if (list->items == NULL) {          if (list->items == NULL) {
             xmlXPathErrMemory(NULL,              xmlXPathErrMemory(NULL,
                "xmlPointerListCreate: re-allocating item\n");                "xmlPointerListAddSize: re-allocating item\n");
             list->size = 0;              list->size = 0;
             return(-1);              return(-1);
         }          }
Line 552  typedef enum { Line 633  typedef enum {
     NODE_TYPE_PI = XML_PI_NODE      NODE_TYPE_PI = XML_PI_NODE
 } xmlXPathTypeVal;  } xmlXPathTypeVal;
   
 #define XP_REWRITE_DOS_CHILD_ELEM 1  
   
 typedef struct _xmlXPathStepOp xmlXPathStepOp;  typedef struct _xmlXPathStepOp xmlXPathStepOp;
 typedef xmlXPathStepOp *xmlXPathStepOpPtr;  typedef xmlXPathStepOp *xmlXPathStepOpPtr;
 struct _xmlXPathStepOp {  struct _xmlXPathStepOp {
Line 567  struct _xmlXPathStepOp { Line 646  struct _xmlXPathStepOp {
     void *value5;      void *value5;
     void *cache;      void *cache;
     void *cacheURI;      void *cacheURI;
     int rewriteType;  
 };  };
   
 struct _xmlXPathCompExpr {  struct _xmlXPathCompExpr {
Line 722  xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, Line 800  xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1,
     if (comp->nbStep >= comp->maxStep) {      if (comp->nbStep >= comp->maxStep) {
         xmlXPathStepOp *real;          xmlXPathStepOp *real;
   
           if (comp->maxStep >= XPATH_MAX_STEPS) {
               xmlXPathErrMemory(NULL, "adding step\n");
               return(-1);
           }
         comp->maxStep *= 2;          comp->maxStep *= 2;
         real = (xmlXPathStepOp *) xmlRealloc(comp->steps,          real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
                                       comp->maxStep * sizeof(xmlXPathStepOp));                                        comp->maxStep * sizeof(xmlXPathStepOp));
Line 733  xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, Line 815  xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1,
         comp->steps = real;          comp->steps = real;
     }      }
     comp->last = comp->nbStep;      comp->last = comp->nbStep;
     comp->steps[comp->nbStep].rewriteType = 0;  
     comp->steps[comp->nbStep].ch1 = ch1;      comp->steps[comp->nbStep].ch1 = ch1;
     comp->steps[comp->nbStep].ch2 = ch2;      comp->steps[comp->nbStep].ch2 = ch2;
     comp->steps[comp->nbStep].op = op;      comp->steps[comp->nbStep].op = op;
Line 2051  xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNo Line 2132  xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNo
             ret->type = XPATH_NODESET;              ret->type = XPATH_NODESET;
             ret->boolval = 0;              ret->boolval = 0;
             ret->nodesetval = xmlXPathNodeSetCreate(val);              ret->nodesetval = xmlXPathNodeSetCreate(val);
               if (ret->nodesetval == NULL) {
                   ctxt->lastError.domain = XML_FROM_XPATH;
                   ctxt->lastError.code = XML_ERR_NO_MEMORY;
                   return(NULL);
               }
 #ifdef XP_DEBUG_OBJ_USAGE  #ifdef XP_DEBUG_OBJ_USAGE
             xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);              xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
 #endif  #endif
Line 2398  xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xm Line 2484  xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xm
  ************************************************************************/   ************************************************************************/
   
 /**  /**
    * xmlXPathSetFrame:
    * @ctxt: an XPath parser context
    *
    * Set the callee evaluation frame
    *
    * Returns the previous frame value to be restored once done
    */
   static int
   xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
       int ret;
   
       if (ctxt == NULL)
           return(0);
       ret = ctxt->valueFrame;
       ctxt->valueFrame = ctxt->valueNr;
       return(ret);
   }
   
   /**
    * xmlXPathPopFrame:
    * @ctxt: an XPath parser context
    * @frame: the previous frame value
    *
    * Remove the callee evaluation frame
    */
   static void
   xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
       if (ctxt == NULL)
           return;
       if (ctxt->valueNr < ctxt->valueFrame) {
           xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
       }
       ctxt->valueFrame = frame;
   }
   
   /**
  * valuePop:   * valuePop:
  * @ctxt: an XPath evaluation context   * @ctxt: an XPath evaluation context
  *   *
Line 2412  valuePop(xmlXPathParserContextPtr ctxt) Line 2534  valuePop(xmlXPathParserContextPtr ctxt)
   
     if ((ctxt == NULL) || (ctxt->valueNr <= 0))      if ((ctxt == NULL) || (ctxt->valueNr <= 0))
         return (NULL);          return (NULL);
   
       if (ctxt->valueNr <= ctxt->valueFrame) {
           xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
           return (NULL);
       }
   
     ctxt->valueNr--;      ctxt->valueNr--;
     if (ctxt->valueNr > 0)      if (ctxt->valueNr > 0)
         ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];          ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
Line 2437  valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjec Line 2565  valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjec
     if (ctxt->valueNr >= ctxt->valueMax) {      if (ctxt->valueNr >= ctxt->valueMax) {
         xmlXPathObjectPtr *tmp;          xmlXPathObjectPtr *tmp;
   
           if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
               xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
               ctxt->error = XPATH_MEMORY_ERROR;
               return (0);
           }
         tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,          tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
                                              2 * ctxt->valueMax *                                               2 * ctxt->valueMax *
                                              sizeof(ctxt->valueTab[0]));                                               sizeof(ctxt->valueTab[0]));
         if (tmp == NULL) {          if (tmp == NULL) {
            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");            xmlXPathErrMemory(NULL, "pushing value\n");
             ctxt->error = XPATH_MEMORY_ERROR;
             return (0);              return (0);
         }          }
         ctxt->valueMax *= 2;          ctxt->valueMax *= 2;
Line 3276  turtle_comparison: Line 3410  turtle_comparison:
  */   */
 void  void
 xmlXPathNodeSetSort(xmlNodeSetPtr set) {  xmlXPathNodeSetSort(xmlNodeSetPtr set) {
   #ifndef WITH_TIM_SORT
     int i, j, incr, len;      int i, j, incr, len;
     xmlNodePtr tmp;      xmlNodePtr tmp;
   #endif
   
     if (set == NULL)      if (set == NULL)
         return;          return;
   
    /* Use Shell's sort to sort the node-set */#ifndef WITH_TIM_SORT
     /*
      * Use the old Shell's sort implementation to sort the node-set
      * Timsort ought to be quite faster
      */
     len = set->nodeNr;      len = set->nodeNr;
     for (incr = len / 2; incr > 0; incr /= 2) {      for (incr = len / 2; incr > 0; incr /= 2) {
         for (i = incr; i < len; i++) {          for (i = incr; i < len; i++) {
Line 3305  xmlXPathNodeSetSort(xmlNodeSetPtr set) { Line 3445  xmlXPathNodeSetSort(xmlNodeSetPtr set) {
             }              }
         }          }
     }      }
   #else /* WITH_TIM_SORT */
       libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
   #endif /* WITH_TIM_SORT */
 }  }
   
 #define XML_NODESET_DEFAULT     10  #define XML_NODESET_DEFAULT     10
Line 3483  xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr Line 3626  xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr
  * @ns:  a the namespace node   * @ns:  a the namespace node
  *   *
  * add a new namespace node to an existing NodeSet   * add a new namespace node to an existing NodeSet
    *
    * Returns 0 in case of success and -1 in case of error
  */   */
voidint
 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
     int i;      int i;
   
Line 3492  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod Line 3637  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod
     if ((cur == NULL) || (ns == NULL) || (node == NULL) ||      if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
         (ns->type != XML_NAMESPACE_DECL) ||          (ns->type != XML_NAMESPACE_DECL) ||
         (node->type != XML_ELEMENT_NODE))          (node->type != XML_ELEMENT_NODE))
        return;        return(-1);
   
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */      /* @@ with_ns to check whether namespace nodes should be looked at @@ */
     /*      /*
Line 3503  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod Line 3648  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod
             (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&              (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
             (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&              (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
             (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))              (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
            return;            return(0);
     }      }
   
     /*      /*
Line 3514  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod Line 3659  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod
                                              sizeof(xmlNodePtr));                                               sizeof(xmlNodePtr));
         if (cur->nodeTab == NULL) {          if (cur->nodeTab == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
         memset(cur->nodeTab, 0 ,          memset(cur->nodeTab, 0 ,
                XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));                 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
Line 3522  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod Line 3667  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod
     } else if (cur->nodeNr == cur->nodeMax) {      } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;          xmlNodePtr *temp;
   
        cur->nodeMax *= 2;        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
        temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
             return(-1);
         }
         temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
                                       sizeof(xmlNodePtr));                                        sizeof(xmlNodePtr));
         if (temp == NULL) {          if (temp == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
           cur->nodeMax *= 2;
         cur->nodeTab = temp;          cur->nodeTab = temp;
     }      }
     cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);      cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
       return(0);
 }  }
   
 /**  /**
Line 3540  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod Line 3690  xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr nod
  * @val:  a new xmlNodePtr   * @val:  a new xmlNodePtr
  *   *
  * add a new xmlNodePtr to an existing NodeSet   * add a new xmlNodePtr to an existing NodeSet
    *
    * Returns 0 in case of success, and -1 in case of error
  */   */
voidint
 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
     int i;      int i;
   
    if ((cur == NULL) || (val == NULL)) return;    if ((cur == NULL) || (val == NULL)) return(-1);
   
 #if 0  
     if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))  
         return; /* an XSLT fake node */  
 #endif  
   
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */      /* @@ with_ns to check whether namespace nodes should be looked at @@ */
     /*      /*
      * prevent duplcates       * prevent duplcates
      */       */
     for (i = 0;i < cur->nodeNr;i++)      for (i = 0;i < cur->nodeNr;i++)
        if (cur->nodeTab[i] == val) return;        if (cur->nodeTab[i] == val) return(0);
   
     /*      /*
      * grow the nodeTab if needed       * grow the nodeTab if needed
Line 3567  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val)  Line 3714  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) 
                                              sizeof(xmlNodePtr));                                               sizeof(xmlNodePtr));
         if (cur->nodeTab == NULL) {          if (cur->nodeTab == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
         memset(cur->nodeTab, 0 ,          memset(cur->nodeTab, 0 ,
                XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));                 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
Line 3575  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val)  Line 3722  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) 
     } else if (cur->nodeNr == cur->nodeMax) {      } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;          xmlNodePtr *temp;
   
        cur->nodeMax *= 2;        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
        temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
             return(-1);
         }
         temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
                                       sizeof(xmlNodePtr));                                        sizeof(xmlNodePtr));
         if (temp == NULL) {          if (temp == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
           cur->nodeMax *= 2;
         cur->nodeTab = temp;          cur->nodeTab = temp;
     }      }
     if (val->type == XML_NAMESPACE_DECL) {      if (val->type == XML_NAMESPACE_DECL) {
Line 3591  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val)  Line 3742  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) 
             xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);              xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
     } else      } else
         cur->nodeTab[cur->nodeNr++] = val;          cur->nodeTab[cur->nodeNr++] = val;
       return(0);
 }  }
   
 /**  /**
Line 3600  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val)  Line 3752  xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) 
  *   *
  * add a new xmlNodePtr to an existing NodeSet, optimized version   * add a new xmlNodePtr to an existing NodeSet, optimized version
  * when we are sure the node is not already in the set.   * when we are sure the node is not already in the set.
    *
    * Returns 0 in case of success and -1 in case of failure
  */   */
voidint
 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
    if ((cur == NULL) || (val == NULL)) return;    if ((cur == NULL) || (val == NULL)) return(-1);
   
 #if 0  
     if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))  
         return; /* an XSLT fake node */  
 #endif  
   
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */      /* @@ with_ns to check whether namespace nodes should be looked at @@ */
     /*      /*
      * grow the nodeTab if needed       * grow the nodeTab if needed
Line 3619  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr Line 3768  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr
                                              sizeof(xmlNodePtr));                                               sizeof(xmlNodePtr));
         if (cur->nodeTab == NULL) {          if (cur->nodeTab == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
         memset(cur->nodeTab, 0 ,          memset(cur->nodeTab, 0 ,
                XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));                 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
Line 3627  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr Line 3776  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr
     } else if (cur->nodeNr == cur->nodeMax) {      } else if (cur->nodeNr == cur->nodeMax) {
         xmlNodePtr *temp;          xmlNodePtr *temp;
   
        cur->nodeMax *= 2;        if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
        temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *            xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
             return(-1);
         }
         temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
                                       sizeof(xmlNodePtr));                                        sizeof(xmlNodePtr));
         if (temp == NULL) {          if (temp == NULL) {
             xmlXPathErrMemory(NULL, "growing nodeset\n");              xmlXPathErrMemory(NULL, "growing nodeset\n");
            return;            return(-1);
         }          }
         cur->nodeTab = temp;          cur->nodeTab = temp;
           cur->nodeMax *= 2;
     }      }
     if (val->type == XML_NAMESPACE_DECL) {      if (val->type == XML_NAMESPACE_DECL) {
         xmlNsPtr ns = (xmlNsPtr) val;          xmlNsPtr ns = (xmlNsPtr) val;
Line 3643  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr Line 3796  xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr
             xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);              xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
     } else      } else
         cur->nodeTab[cur->nodeNr++] = val;          cur->nodeTab[cur->nodeNr++] = val;
       return(0);
 }  }
   
 /**  /**
Line 3738  xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr Line 3892  xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr
         } else if (val1->nodeNr == val1->nodeMax) {          } else if (val1->nodeNr == val1->nodeMax) {
             xmlNodePtr *temp;              xmlNodePtr *temp;
   
            val1->nodeMax *= 2;            if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
            temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *                xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
                 return(NULL);
             }
             temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
                                              sizeof(xmlNodePtr));                                               sizeof(xmlNodePtr));
             if (temp == NULL) {              if (temp == NULL) {
                 xmlXPathErrMemory(NULL, "merging nodeset\n");                  xmlXPathErrMemory(NULL, "merging nodeset\n");
                 return(NULL);                  return(NULL);
             }              }
             val1->nodeTab = temp;              val1->nodeTab = temp;
               val1->nodeMax *= 2;
         }          }
         if (n2->type == XML_NAMESPACE_DECL) {          if (n2->type == XML_NAMESPACE_DECL) {
             xmlNsPtr ns = (xmlNsPtr) n2;              xmlNsPtr ns = (xmlNsPtr) n2;
Line 3759  xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr Line 3917  xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr
     return(val1);      return(val1);
 }  }
   
 #if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */  
 /**  
  * xmlXPathNodeSetMergeUnique:  
  * @val1:  the first NodeSet or NULL  
  * @val2:  the second NodeSet  
  *  
  * Merges two nodesets, all nodes from @val2 are added to @val1  
  * if @val1 is NULL, a new set is created and copied from @val2  
  *  
  * Returns @val1 once extended or NULL in case of error.  
  */  
 static xmlNodeSetPtr  
 xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {  
     int i;  
   
     if (val2 == NULL) return(val1);  
     if (val1 == NULL) {  
         val1 = xmlXPathNodeSetCreate(NULL);  
     }  
     if (val1 == NULL)  
         return (NULL);  
   
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */  
   
     for (i = 0;i < val2->nodeNr;i++) {  
         /*  
          * grow the nodeTab if needed  
          */  
         if (val1->nodeMax == 0) {  
             val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *  
                                                     sizeof(xmlNodePtr));  
             if (val1->nodeTab == NULL) {  
                 xmlXPathErrMemory(NULL, "merging nodeset\n");  
                 return(NULL);  
             }  
             memset(val1->nodeTab, 0 ,  
                    XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));  
             val1->nodeMax = XML_NODESET_DEFAULT;  
         } else if (val1->nodeNr == val1->nodeMax) {  
             xmlNodePtr *temp;  
   
             val1->nodeMax *= 2;  
             temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *  
                                              sizeof(xmlNodePtr));  
             if (temp == NULL) {  
                 xmlXPathErrMemory(NULL, "merging nodeset\n");  
                 return(NULL);  
             }  
             val1->nodeTab = temp;  
         }  
         if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {  
             xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];  
   
             val1->nodeTab[val1->nodeNr++] =  
                 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);  
         } else  
             val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];  
     }  
   
     return(val1);  
 }  
 #endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */  
   
 /**  /**
  * xmlXPathNodeSetMergeAndClear:   * xmlXPathNodeSetMergeAndClear:
  * @set1:  the first NodeSet or NULL   * @set1:  the first NodeSet or NULL
Line 3907  xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNo Line 4003  xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNo
             } else if (set1->nodeNr >= set1->nodeMax) {              } else if (set1->nodeNr >= set1->nodeMax) {
                 xmlNodePtr *temp;                  xmlNodePtr *temp;
   
                set1->nodeMax *= 2;                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
                     xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
                     return(NULL);
                 }
                 temp = (xmlNodePtr *) xmlRealloc(                  temp = (xmlNodePtr *) xmlRealloc(
                    set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));                    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
                 if (temp == NULL) {                  if (temp == NULL) {
                     xmlXPathErrMemory(NULL, "merging nodeset\n");                      xmlXPathErrMemory(NULL, "merging nodeset\n");
                     return(NULL);                      return(NULL);
                 }                  }
                 set1->nodeTab = temp;                  set1->nodeTab = temp;
                   set1->nodeMax *= 2;
             }              }
             if (n2->type == XML_NAMESPACE_DECL) {              if (n2->type == XML_NAMESPACE_DECL) {
                 xmlNsPtr ns = (xmlNsPtr) n2;                  xmlNsPtr ns = (xmlNsPtr) n2;
Line 3991  xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1 Line 4091  xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1
             } else if (set1->nodeNr >= set1->nodeMax) {              } else if (set1->nodeNr >= set1->nodeMax) {
                 xmlNodePtr *temp;                  xmlNodePtr *temp;
   
                set1->nodeMax *= 2;                if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
                     xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
                     return(NULL);
                 }
                 temp = (xmlNodePtr *) xmlRealloc(                  temp = (xmlNodePtr *) xmlRealloc(
                    set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));                    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
                 if (temp == NULL) {                  if (temp == NULL) {
                     xmlXPathErrMemory(NULL, "merging nodeset\n");                      xmlXPathErrMemory(NULL, "merging nodeset\n");
                     return(NULL);                      return(NULL);
                 }                  }
                 set1->nodeTab = temp;                  set1->nodeTab = temp;
                   set1->nodeMax *= 2;
             }              }
             set1->nodeTab[set1->nodeNr++] = n2;              set1->nodeTab[set1->nodeNr++] = n2;
         }          }
Line 4289  xmlXPathNewNodeSetList(xmlNodeSetPtr val) Line 4393  xmlXPathNewNodeSetList(xmlNodeSetPtr val)
         ret = xmlXPathNewNodeSet(NULL);          ret = xmlXPathNewNodeSet(NULL);
     else {      else {
         ret = xmlXPathNewNodeSet(val->nodeTab[0]);          ret = xmlXPathNewNodeSet(val->nodeTab[0]);
        if (ret)        if (ret) {
            for (i = 1; i < val->nodeNr; ++i)            for (i = 1; i < val->nodeNr; ++i) {
                xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);                if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
                     < 0) break;
             }
         }
     }      }
   
     return (ret);      return (ret);
Line 4367  xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPt Line 4474  xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPt
   
     for (i = 0; i < l1; i++) {      for (i = 0; i < l1; i++) {
         cur = xmlXPathNodeSetItem(nodes1, i);          cur = xmlXPathNodeSetItem(nodes1, i);
        if (!xmlXPathNodeSetContains(nodes2, cur))        if (!xmlXPathNodeSetContains(nodes2, cur)) {
            xmlXPathNodeSetAddUnique(ret, cur);            if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
                 break;
         }
     }      }
     return(ret);      return(ret);
 }  }
Line 4401  xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSet Line 4510  xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSet
   
     for (i = 0; i < l1; i++) {      for (i = 0; i < l1; i++) {
         cur = xmlXPathNodeSetItem(nodes1, i);          cur = xmlXPathNodeSetItem(nodes1, i);
        if (xmlXPathNodeSetContains(nodes2, cur))        if (xmlXPathNodeSetContains(nodes2, cur)) {
            xmlXPathNodeSetAddUnique(ret, cur);            if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
                 break;
         }
     }      }
     return(ret);      return(ret);
 }  }
Line 4438  xmlXPathDistinctSorted (xmlNodeSetPtr nodes) { Line 4549  xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
         strval = xmlXPathCastNodeToString(cur);          strval = xmlXPathCastNodeToString(cur);
         if (xmlHashLookup(hash, strval) == NULL) {          if (xmlHashLookup(hash, strval) == NULL) {
             xmlHashAddEntry(hash, strval, strval);              xmlHashAddEntry(hash, strval, strval);
            xmlXPathNodeSetAddUnique(ret, cur);            if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
                 break;
         } else {          } else {
             xmlFree(strval);              xmlFree(strval);
         }          }
Line 4530  xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNod Line 4642  xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNod
         cur = xmlXPathNodeSetItem(nodes, i);          cur = xmlXPathNodeSetItem(nodes, i);
         if (cur == node)          if (cur == node)
             break;              break;
        xmlXPathNodeSetAddUnique(ret, cur);        if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
             break;
     }      }
     return(ret);      return(ret);
 }  }
Line 4634  xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNo Line 4747  xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNo
         cur = xmlXPathNodeSetItem(nodes, i);          cur = xmlXPathNodeSetItem(nodes, i);
         if (cur == node)          if (cur == node)
             break;              break;
        xmlXPathNodeSetAddUnique(ret, cur);        if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
             break;
     }      }
     xmlXPathNodeSetSort(ret);   /* bug 413451 */      xmlXPathNodeSetSort(ret);   /* bug 413451 */
     return(ret);      return(ret);
Line 6154  xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xm Line 6268  xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xm
     ret->valueNr = 0;      ret->valueNr = 0;
     ret->valueMax = 10;      ret->valueMax = 10;
     ret->value = NULL;      ret->value = NULL;
       ret->valueFrame = 0;
   
     ret->context = ctxt;      ret->context = ctxt;
     ret->comp = comp;      ret->comp = comp;
Line 7656  xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt Line 7771  xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt
     return(NULL);      return(NULL);
 }  }
   
   #if 0
 /**  /**
  * xmlXPathNextDescendantOrSelfElemParent:   * xmlXPathNextDescendantOrSelfElemParent:
  * @ctxt:  the XPath Parser context   * @ctxt:  the XPath Parser context
Line 7683  xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur, Line 7799  xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur,
 #ifdef LIBXML_DOCB_ENABLED  #ifdef LIBXML_DOCB_ENABLED
             case XML_DOCB_DOCUMENT_NODE:              case XML_DOCB_DOCUMENT_NODE:
 #endif  #endif
            case XML_HTML_DOCUMENT_NODE:                        case XML_HTML_DOCUMENT_NODE:
                 return(contextNode);                  return(contextNode);
             default:              default:
                 return(NULL);                  return(NULL);
Line 7731  next_sibling: Line 7847  next_sibling:
     }      }
     return(NULL);      return(NULL);
 }  }
   #endif
   
 /**  /**
  * xmlXPathNextDescendant:   * xmlXPathNextDescendant:
Line 7758  xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,  Line 7875  xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, 
         return(ctxt->context->node->children);          return(ctxt->context->node->children);
     }      }
   
       if (cur->type == XML_NAMESPACE_DECL)
           return(NULL);
     if (cur->children != NULL) {      if (cur->children != NULL) {
         /*          /*
          * Do not descend on entities declarations           * Do not descend on entities declarations
Line 8140  xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, x Line 8259  xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, x
 static int  static int
 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {  xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
     if ((ancestor == NULL) || (node == NULL)) return(0);      if ((ancestor == NULL) || (node == NULL)) return(0);
       if (node->type == XML_NAMESPACE_DECL)
           return(0);
       if (ancestor->type == XML_NAMESPACE_DECL)
           return(0);
     /* nodes need to be in the same document */      /* nodes need to be in the same document */
     if (ancestor->doc != node->doc) return(0);      if (ancestor->doc != node->doc) return(0);
     /* avoid searching if ancestor or node is the root node */      /* avoid searching if ancestor or node is the root node */
Line 8177  xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, x Line 8300  xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, x
         if (cur->type == XML_ATTRIBUTE_NODE)          if (cur->type == XML_ATTRIBUTE_NODE)
             return(cur->parent);              return(cur->parent);
     }      }
    if (cur == NULL)    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
         return (NULL);          return (NULL);
     if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))      if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
         cur = cur->prev;          cur = cur->prev;
Line 8224  xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr Line 8347  xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr
             return (NULL);              return (NULL);
         ctxt->ancestor = cur->parent;          ctxt->ancestor = cur->parent;
     }      }
       if (cur->type == XML_NAMESPACE_DECL)
           return(NULL);
     if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))      if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
         cur = cur->prev;          cur = cur->prev;
     while (cur->prev == NULL) {      while (cur->prev == NULL) {
Line 8431  xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, i Line 8556  xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, i
             int i = 0;              int i = 0;
   
             tmp = cur->nodesetval->nodeTab[0];              tmp = cur->nodesetval->nodeTab[0];
            if (tmp != NULL) {            if ((tmp != NULL) && (tmp->type != XML_NAMESPACE_DECL)) {
                 tmp = tmp->children;                  tmp = tmp->children;
                 while (tmp != NULL) {                  while (tmp != NULL) {
                     tmp = tmp->next;                      tmp = tmp->next;
Line 9101  void Line 9226  void
 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {  xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
   xmlXPathObjectPtr str;    xmlXPathObjectPtr str;
   xmlXPathObjectPtr find;    xmlXPathObjectPtr find;
  xmlBufferPtr target;  xmlBufPtr target;
   const xmlChar *point;    const xmlChar *point;
   int offset;    int offset;
   
Line 9111  xmlXPathSubstringBeforeFunction(xmlXPathParserContextP Line 9236  xmlXPathSubstringBeforeFunction(xmlXPathParserContextP
   CAST_TO_STRING;    CAST_TO_STRING;
   str = valuePop(ctxt);    str = valuePop(ctxt);
   
  target = xmlBufferCreate();  target = xmlBufCreate();
   if (target) {    if (target) {
     point = xmlStrstr(str->stringval, find->stringval);      point = xmlStrstr(str->stringval, find->stringval);
     if (point) {      if (point) {
       offset = (int)(point - str->stringval);        offset = (int)(point - str->stringval);
      xmlBufferAdd(target, str->stringval, offset);      xmlBufAdd(target, str->stringval, offset);
     }      }
     valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,      valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
        xmlBufferContent(target)));        xmlBufContent(target)));
    xmlBufferFree(target);    xmlBufFree(target);
   }    }
   xmlXPathReleaseObject(ctxt->context, str);    xmlXPathReleaseObject(ctxt->context, str);
   xmlXPathReleaseObject(ctxt->context, find);    xmlXPathReleaseObject(ctxt->context, find);
Line 9144  void Line 9269  void
 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {  xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
   xmlXPathObjectPtr str;    xmlXPathObjectPtr str;
   xmlXPathObjectPtr find;    xmlXPathObjectPtr find;
  xmlBufferPtr target;  xmlBufPtr target;
   const xmlChar *point;    const xmlChar *point;
   int offset;    int offset;
   
Line 9154  xmlXPathSubstringAfterFunction(xmlXPathParserContextPt Line 9279  xmlXPathSubstringAfterFunction(xmlXPathParserContextPt
   CAST_TO_STRING;    CAST_TO_STRING;
   str = valuePop(ctxt);    str = valuePop(ctxt);
   
  target = xmlBufferCreate();  target = xmlBufCreate();
   if (target) {    if (target) {
     point = xmlStrstr(str->stringval, find->stringval);      point = xmlStrstr(str->stringval, find->stringval);
     if (point) {      if (point) {
       offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);        offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
      xmlBufferAdd(target, &str->stringval[offset],      xmlBufAdd(target, &str->stringval[offset],
                    xmlStrlen(str->stringval) - offset);                     xmlStrlen(str->stringval) - offset);
     }      }
     valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,      valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
        xmlBufferContent(target)));        xmlBufContent(target)));
    xmlBufferFree(target);    xmlBufFree(target);
   }    }
   xmlXPathReleaseObject(ctxt->context, str);    xmlXPathReleaseObject(ctxt->context, str);
   xmlXPathReleaseObject(ctxt->context, find);    xmlXPathReleaseObject(ctxt->context, find);
Line 9188  void Line 9313  void
 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {  xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
   xmlXPathObjectPtr obj = NULL;    xmlXPathObjectPtr obj = NULL;
   xmlChar *source = NULL;    xmlChar *source = NULL;
  xmlBufferPtr target;  xmlBufPtr target;
   xmlChar blank;    xmlChar blank;
   
   if (ctxt == NULL) return;    if (ctxt == NULL) return;
Line 9206  xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctx Line 9331  xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctx
   obj = valuePop(ctxt);    obj = valuePop(ctxt);
   source = obj->stringval;    source = obj->stringval;
   
  target = xmlBufferCreate();  target = xmlBufCreate();
   if (target && source) {    if (target && source) {
   
     /* Skip leading whitespaces */      /* Skip leading whitespaces */
Line 9220  xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctx Line 9345  xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctx
         blank = 0x20;          blank = 0x20;
       } else {        } else {
         if (blank) {          if (blank) {
          xmlBufferAdd(target, &blank, 1);          xmlBufAdd(target, &blank, 1);
           blank = 0;            blank = 0;
         }          }
        xmlBufferAdd(target, source, 1);        xmlBufAdd(target, source, 1);
       }        }
       source++;        source++;
     }      }
     valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,      valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
        xmlBufferContent(target)));        xmlBufContent(target)));
    xmlBufferFree(target);    xmlBufFree(target);
   }    }
   xmlXPathReleaseObject(ctxt->context, obj);    xmlXPathReleaseObject(ctxt->context, obj);
 }  }
Line 9260  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9385  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
     xmlXPathObjectPtr str;      xmlXPathObjectPtr str;
     xmlXPathObjectPtr from;      xmlXPathObjectPtr from;
     xmlXPathObjectPtr to;      xmlXPathObjectPtr to;
    xmlBufferPtr target;    xmlBufPtr target;
     int offset, max;      int offset, max;
     xmlChar ch;      xmlChar ch;
     const xmlChar *point;      const xmlChar *point;
Line 9275  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9400  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
     CAST_TO_STRING;      CAST_TO_STRING;
     str = valuePop(ctxt);      str = valuePop(ctxt);
   
    target = xmlBufferCreate();    target = xmlBufCreate();
     if (target) {      if (target) {
         max = xmlUTF8Strlen(to->stringval);          max = xmlUTF8Strlen(to->stringval);
         for (cptr = str->stringval; (ch=*cptr); ) {          for (cptr = str->stringval; (ch=*cptr); ) {
Line 9284  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9409  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
                 if (offset < max) {                  if (offset < max) {
                     point = xmlUTF8Strpos(to->stringval, offset);                      point = xmlUTF8Strpos(to->stringval, offset);
                     if (point)                      if (point)
                        xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));                        xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
                 }                  }
             } else              } else
                xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));                xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
   
             /* Step to next character in input */              /* Step to next character in input */
             cptr++;              cptr++;
Line 9296  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9421  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
                 if ( (ch & 0xc0) != 0xc0 ) {                  if ( (ch & 0xc0) != 0xc0 ) {
                     xmlGenericError(xmlGenericErrorContext,                      xmlGenericError(xmlGenericErrorContext,
                         "xmlXPathTranslateFunction: Invalid UTF8 string\n");                          "xmlXPathTranslateFunction: Invalid UTF8 string\n");
                       /* not asserting an XPath error is probably better */
                     break;                      break;
                 }                  }
                 /* then skip over remaining bytes for this char */                  /* then skip over remaining bytes for this char */
Line 9303  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9429  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
                     if ( (*cptr++ & 0xc0) != 0x80 ) {                      if ( (*cptr++ & 0xc0) != 0x80 ) {
                         xmlGenericError(xmlGenericErrorContext,                          xmlGenericError(xmlGenericErrorContext,
                             "xmlXPathTranslateFunction: Invalid UTF8 string\n");                              "xmlXPathTranslateFunction: Invalid UTF8 string\n");
                           /* not asserting an XPath error is probably better */
                         break;                          break;
                     }                      }
                 if (ch & 0x80) /* must have had error encountered */                  if (ch & 0x80) /* must have had error encountered */
Line 9311  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx Line 9438  xmlXPathTranslateFunction(xmlXPathParserContextPtr ctx
         }          }
     }      }
     valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,      valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
        xmlBufferContent(target)));        xmlBufContent(target)));
    xmlBufferFree(target);    xmlBufFree(target);
     xmlXPathReleaseObject(ctxt->context, str);      xmlXPathReleaseObject(ctxt->context, str);
     xmlXPathReleaseObject(ctxt->context, from);      xmlXPathReleaseObject(ctxt->context, from);
     xmlXPathReleaseObject(ctxt->context, to);      xmlXPathReleaseObject(ctxt->context, to);
Line 9819  xmlChar * Line 9946  xmlChar *
 xmlXPathParseName(xmlXPathParserContextPtr ctxt) {  xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
     const xmlChar *in;      const xmlChar *in;
     xmlChar *ret;      xmlChar *ret;
    int count = 0;    size_t count = 0;
   
     if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);      if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
     /*      /*
Line 9838  xmlXPathParseName(xmlXPathParserContextPtr ctxt) { Line 9965  xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
             in++;              in++;
         if ((*in > 0) && (*in < 0x80)) {          if ((*in > 0) && (*in < 0x80)) {
             count = in - ctxt->cur;              count = in - ctxt->cur;
               if (count > XML_MAX_NAME_LENGTH) {
                   ctxt->cur = in;
                   XP_ERRORNULL(XPATH_EXPR_ERROR);
               }
             ret = xmlStrndup(ctxt->cur, count);              ret = xmlStrndup(ctxt->cur, count);
             ctxt->cur = in;              ctxt->cur = in;
             return(ret);              return(ret);
Line 9881  xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt Line 10012  xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt
             xmlChar *buffer;              xmlChar *buffer;
             int max = len * 2;              int max = len * 2;
   
               if (len > XML_MAX_NAME_LENGTH) {
                   XP_ERRORNULL(XPATH_EXPR_ERROR);
               }
             buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));              buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
             if (buffer == NULL) {              if (buffer == NULL) {
                 XP_ERRORNULL(XPATH_MEMORY_ERROR);                  XP_ERRORNULL(XPATH_MEMORY_ERROR);
Line 9892  xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt Line 10026  xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt
                    (IS_COMBINING(c)) ||                     (IS_COMBINING(c)) ||
                    (IS_EXTENDER(c))) {                     (IS_EXTENDER(c))) {
                 if (len + 10 > max) {                  if (len + 10 > max) {
                       if (max > XML_MAX_NAME_LENGTH) {
                           XP_ERRORNULL(XPATH_EXPR_ERROR);
                       }
                     max *= 2;                      max *= 2;
                     buffer = (xmlChar *) xmlRealloc(buffer,                      buffer = (xmlChar *) xmlRealloc(buffer,
                                                     max * sizeof(xmlChar));                                                      max * sizeof(xmlChar));
Line 10044  static void Line 10181  static void
 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)  xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
 {  {
     double ret = 0.0;      double ret = 0.0;
     double mult = 1;  
     int ok = 0;      int ok = 0;
     int exponent = 0;      int exponent = 0;
     int is_exponent_negative = 0;      int is_exponent_negative = 0;
Line 10245  xmlXPathCompVariableReference(xmlXPathParserContextPtr Line 10381  xmlXPathCompVariableReference(xmlXPathParserContextPtr
                    name, prefix);                     name, prefix);
     SKIP_BLANKS;      SKIP_BLANKS;
     if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {      if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
        XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR);        XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
     }      }
 }  }
   
Line 11609  xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr c Line 11745  xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr c
             */              */
             if (contextObj == NULL)              if (contextObj == NULL)
                 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);                  contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
            else            else {
                xmlXPathNodeSetAddUnique(contextObj->nodesetval,                if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
                    contextNode);                    contextNode) < 0) {
                     ctxt->error = XPATH_MEMORY_ERROR;
                     goto evaluation_exit;
                 }
             }
   
             valuePush(ctxt, contextObj);              valuePush(ctxt, contextObj);
   
Line 11712  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo Line 11852  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo
         xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;          xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
         xmlNodePtr oldContextNode, contextNode = NULL;          xmlNodePtr oldContextNode, contextNode = NULL;
         xmlXPathContextPtr xpctxt = ctxt->context;          xmlXPathContextPtr xpctxt = ctxt->context;
           int frame;
   
 #ifdef LIBXML_XPTR_ENABLED  #ifdef LIBXML_XPTR_ENABLED
             /*              /*
Line 11731  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo Line 11872  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo
         */          */
         exprOp = &ctxt->comp->steps[op->ch2];          exprOp = &ctxt->comp->steps[op->ch2];
         for (i = 0; i < set->nodeNr; i++) {          for (i = 0; i < set->nodeNr; i++) {
               xmlXPathObjectPtr tmp;
   
             if (set->nodeTab[i] == NULL)              if (set->nodeTab[i] == NULL)
                 continue;                  continue;
   
Line 11754  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo Line 11897  xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserCo
             */              */
             if (contextObj == NULL)              if (contextObj == NULL)
                 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);                  contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
            else            else {
                xmlXPathNodeSetAddUnique(contextObj->nodesetval,                if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
                    contextNode);                    contextNode) < 0) {
                     ctxt->error = XPATH_MEMORY_ERROR;
                     goto evaluation_exit;
                 }
             }
   
               frame = xmlXPathSetFrame(ctxt);
             valuePush(ctxt, contextObj);              valuePush(ctxt, contextObj);
             res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);              res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
               tmp = valuePop(ctxt);
               xmlXPathPopFrame(ctxt, frame);
   
             if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {              if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
                xmlXPathObjectPtr tmp;                while (tmp != contextObj) {
                /* pop the result */                    /*
                tmp = valuePop(ctxt);                     * Free up the result
                xmlXPathReleaseObject(xpctxt, tmp);                     * then pop off contextObj, which will be freed later
                /* then pop off contextObj, which will be freed later */                     */
                valuePop(ctxt);                    xmlXPathReleaseObject(xpctxt, tmp);
                     tmp = valuePop(ctxt);
                 }
                 goto evaluation_error;                  goto evaluation_error;
             }              }
               /* push the result back onto the stack */
               valuePush(ctxt, tmp);
   
             if (res)              if (res)
                 pos++;                  pos++;
Line 11921  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12075  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
 #define XP_TEST_HIT \  #define XP_TEST_HIT \
     if (hasAxisRange != 0) { \      if (hasAxisRange != 0) { \
         if (++pos == maxPos) { \          if (++pos == maxPos) { \
            addNode(seq, cur); \            if (addNode(seq, cur) < 0) \
        goto axis_range_end; } \                ctxt->error = XPATH_MEMORY_ERROR; \
             goto axis_range_end; } \
     } else { \      } else { \
        addNode(seq, cur); \        if (addNode(seq, cur) < 0) \
             ctxt->error = XPATH_MEMORY_ERROR; \
         if (breakOnFirstHit) goto first_hit; }          if (breakOnFirstHit) goto first_hit; }
   
 #define XP_TEST_HIT_NS \  #define XP_TEST_HIT_NS \
     if (hasAxisRange != 0) { \      if (hasAxisRange != 0) { \
         if (++pos == maxPos) { \          if (++pos == maxPos) { \
             hasNsNodes = 1; \              hasNsNodes = 1; \
            xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \            if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
                 ctxt->error = XPATH_MEMORY_ERROR; \
         goto axis_range_end; } \          goto axis_range_end; } \
     } else { \      } else { \
         hasNsNodes = 1; \          hasNsNodes = 1; \
        xmlXPathNodeSetAddNs(seq, \        if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
        xpctxt->node, (xmlNsPtr) cur); \            ctxt->error = XPATH_MEMORY_ERROR; \
         if (breakOnFirstHit) goto first_hit; }          if (breakOnFirstHit) goto first_hit; }
   
     xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;      xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
Line 11956  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12113  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
     xmlNodeSetPtr contextSeq;      xmlNodeSetPtr contextSeq;
     int contextIdx;      int contextIdx;
     xmlNodePtr contextNode;      xmlNodePtr contextNode;
     /* The context node for a compound traversal */  
     xmlNodePtr outerContextNode;  
     /* The final resulting node set wrt to all context nodes */      /* The final resulting node set wrt to all context nodes */
     xmlNodeSetPtr outSeq;      xmlNodeSetPtr outSeq;
     /*      /*
Line 11973  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12128  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
     int breakOnFirstHit;      int breakOnFirstHit;
   
     xmlXPathTraversalFunction next = NULL;      xmlXPathTraversalFunction next = NULL;
    /* compound axis traversal */    int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
    xmlXPathTraversalFunctionExt outerNext = NULL; 
    void (*addNode) (xmlNodeSetPtr, xmlNodePtr); 
     xmlXPathNodeSetMergeFunction mergeAndClear;      xmlXPathNodeSetMergeFunction mergeAndClear;
     xmlNodePtr oldContextNode;      xmlNodePtr oldContextNode;
     xmlXPathContextPtr xpctxt = ctxt->context;      xmlXPathContextPtr xpctxt = ctxt->context;
Line 12024  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12177  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
             break;              break;
         case AXIS_CHILD:          case AXIS_CHILD:
             last = NULL;              last = NULL;
             if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) {  
                 /*  
                 * This iterator will give us only nodes which can  
                 * hold element nodes.  
                 */  
                 outerNext = xmlXPathNextDescendantOrSelfElemParent;  
             }  
             if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&              if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
                 (type == NODE_TYPE_NODE))                  (type == NODE_TYPE_NODE))
             {              {
Line 12160  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12306  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
     addNode = xmlXPathNodeSetAddUnique;      addNode = xmlXPathNodeSetAddUnique;
     outSeq = NULL;      outSeq = NULL;
     seq = NULL;      seq = NULL;
     outerContextNode = NULL;  
     contextNode = NULL;      contextNode = NULL;
     contextIdx = 0;      contextIdx = 0;
   
   
    while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) {    while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
        if (outerNext != NULL) {           (ctxt->error == XPATH_EXPRESSION_OK)) {
            /*        xpctxt->node = contextSeq->nodeTab[contextIdx++];
            * This is a compound traversal. 
            */ 
            if (contextNode == NULL) { 
                /* 
                * Set the context for the outer traversal. 
                */ 
                outerContextNode = contextSeq->nodeTab[contextIdx++]; 
                contextNode = outerNext(NULL, outerContextNode); 
            } else 
                contextNode = outerNext(contextNode, outerContextNode); 
            if (contextNode == NULL) 
                continue; 
            /* 
            * Set the context for the main traversal. 
            */ 
            xpctxt->node = contextNode; 
        } else 
            xpctxt->node = contextSeq->nodeTab[contextIdx++]; 
   
         if (seq == NULL) {          if (seq == NULL) {
             seq = xmlXPathNodeSetCreate(NULL);              seq = xmlXPathNodeSetCreate(NULL);
Line 12272  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12399  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
                                 break;                                  break;
                         }                          }
                     } else if (cur->type == type) {                      } else if (cur->type == type) {
                        if (type == XML_NAMESPACE_DECL)                        if (cur->type == XML_NAMESPACE_DECL)
                             XP_TEST_HIT_NS                              XP_TEST_HIT_NS
                         else                          else
                             XP_TEST_HIT                              XP_TEST_HIT
Line 12383  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct Line 12510  xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ct
                     }                      }
                     break;                      break;
             } /* switch(test) */              } /* switch(test) */
        } while (cur != NULL);        } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
   
         goto apply_predicates;          goto apply_predicates;
   
Line 12424  first_hit: /* ---------------------------------------- Line 12551  first_hit: /* ----------------------------------------
 #endif  #endif
   
 apply_predicates: /* --------------------------------------------------- */  apply_predicates: /* --------------------------------------------------- */
           if (ctxt->error != XPATH_EXPRESSION_OK)
               goto error;
   
         /*          /*
         * Apply predicates.          * Apply predicates.
         */          */
         if ((predOp != NULL) && (seq->nodeNr > 0)) {          if ((predOp != NULL) && (seq->nodeNr > 0)) {
             /*              /*
             * E.g. when we have a "/foo[some expression][n]".              * E.g. when we have a "/foo[some expression][n]".
            */                  */
             /*              /*
             * QUESTION TODO: The old predicate evaluation took into              * QUESTION TODO: The old predicate evaluation took into
             *  account location-sets.              *  account location-sets.
Line 12439  apply_predicates: /* --------------------------------- Line 12569  apply_predicates: /* ---------------------------------
             *  All what I learned now from the evaluation semantics              *  All what I learned now from the evaluation semantics
             *  does not indicate that a location-set will be processed              *  does not indicate that a location-set will be processed
             *  here, so this looks OK.              *  here, so this looks OK.
            */                  */
             /*              /*
             * Iterate over all predicates, starting with the outermost              * Iterate over all predicates, starting with the outermost
             * predicate.              * predicate.
Line 12932  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr Line 13062  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr
                 tmp = xmlXPathCacheNewNodeSet(ctxt->context,                  tmp = xmlXPathCacheNewNodeSet(ctxt->context,
                     ctxt->context->node);                      ctxt->context->node);
             } else {              } else {
                xmlXPathNodeSetAddUnique(tmp->nodesetval,                if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
                    ctxt->context->node);                                             ctxt->context->node) < 0) {
                     ctxt->error = XPATH_MEMORY_ERROR;
                 }
             }              }
             valuePush(ctxt, tmp);              valuePush(ctxt, tmp);
             if (op->ch2 != -1)              if (op->ch2 != -1)
Line 13046  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr Line 13178  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr
                 tmp = xmlXPathCacheNewNodeSet(ctxt->context,                  tmp = xmlXPathCacheNewNodeSet(ctxt->context,
                     ctxt->context->node);                      ctxt->context->node);
             } else {              } else {
                xmlXPathNodeSetAddUnique(tmp->nodesetval,                if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
                    ctxt->context->node);                                             ctxt->context->node) < 0) {
                     ctxt->error = XPATH_MEMORY_ERROR;
                 }
             }              }
             valuePush(ctxt, tmp);              valuePush(ctxt, tmp);
             ctxt->context->contextSize = oldset->nodeNr;              ctxt->context->contextSize = oldset->nodeNr;
Line 13065  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr Line 13199  xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr
             */              */
             res = valuePop(ctxt);              res = valuePop(ctxt);
             if (xmlXPathEvaluatePredicateResult(ctxt, res)) {              if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
                xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);                if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0)
                     ctxt->error = XPATH_MEMORY_ERROR;
             }              }
             /*              /*
             * Cleanup              * Cleanup
Line 13357  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13492  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                         xmlGenericError(xmlGenericErrorContext,                          xmlGenericError(xmlGenericErrorContext,
             "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",              "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
                                     (char *) op->value4, (char *)op->value5);                                      (char *) op->value4, (char *)op->value5);
                           ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
                         return (total);                          return (total);
                     }                      }
                     val = xmlXPathVariableLookupNS(ctxt->context,                      val = xmlXPathVariableLookupNS(ctxt->context,
Line 13373  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13509  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                 xmlXPathFunction func;                  xmlXPathFunction func;
                 const xmlChar *oldFunc, *oldFuncURI;                  const xmlChar *oldFunc, *oldFuncURI;
                 int i;                  int i;
                   int frame;
   
                   frame = xmlXPathSetFrame(ctxt);
                 if (op->ch1 != -1)                  if (op->ch1 != -1)
                     total +=                      total +=
                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);                          xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
Line 13381  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13519  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                     xmlGenericError(xmlGenericErrorContext,                      xmlGenericError(xmlGenericErrorContext,
                             "xmlXPathCompOpEval: parameter error\n");                              "xmlXPathCompOpEval: parameter error\n");
                     ctxt->error = XPATH_INVALID_OPERAND;                      ctxt->error = XPATH_INVALID_OPERAND;
                       xmlXPathPopFrame(ctxt, frame);
                     return (total);                      return (total);
                 }                  }
                for (i = 0; i < op->value; i++)                for (i = 0; i < op->value; i++) {
                     if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {                      if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
                         xmlGenericError(xmlGenericErrorContext,                          xmlGenericError(xmlGenericErrorContext,
                                 "xmlXPathCompOpEval: parameter error\n");                                  "xmlXPathCompOpEval: parameter error\n");
                         ctxt->error = XPATH_INVALID_OPERAND;                          ctxt->error = XPATH_INVALID_OPERAND;
                           xmlXPathPopFrame(ctxt, frame);
                         return (total);                          return (total);
                     }                      }
                   }
                 if (op->cache != NULL)                  if (op->cache != NULL)
                     XML_CAST_FPTR(func) = op->cache;                      XML_CAST_FPTR(func) = op->cache;
                 else {                  else {
Line 13405  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13546  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                             xmlGenericError(xmlGenericErrorContext,                              xmlGenericError(xmlGenericErrorContext,
             "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",              "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
                                     (char *)op->value4, (char *)op->value5);                                      (char *)op->value4, (char *)op->value5);
                               xmlXPathPopFrame(ctxt, frame);
                               ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
                             return (total);                              return (total);
                         }                          }
                         func = xmlXPathFunctionLookupNS(ctxt->context,                          func = xmlXPathFunctionLookupNS(ctxt->context,
Line 13426  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13569  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                 func(ctxt, op->value);                  func(ctxt, op->value);
                 ctxt->context->function = oldFunc;                  ctxt->context->function = oldFunc;
                 ctxt->context->functionURI = oldFuncURI;                  ctxt->context->functionURI = oldFuncURI;
                   xmlXPathPopFrame(ctxt, frame);
                 return (total);                  return (total);
             }              }
         case XPATH_OP_ARG:          case XPATH_OP_ARG:
Line 13735  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13879  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                             tmp = xmlXPathCacheNewNodeSet(ctxt->context,                              tmp = xmlXPathCacheNewNodeSet(ctxt->context,
                                 ctxt->context->node);                                  ctxt->context->node);
                         } else {                          } else {
                            xmlXPathNodeSetAddUnique(tmp->nodesetval,                            if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
                                ctxt->context->node);                                               ctxt->context->node) < 0) {
                                 ctxt->error = XPATH_MEMORY_ERROR;
                             }
                         }                          }
                         valuePush(ctxt, tmp);                          valuePush(ctxt, tmp);
                         ctxt->context->contextSize = oldset->nodeNr;                          ctxt->context->contextSize = oldset->nodeNr;
Line 13766  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 13912  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
                         */                          */
                         res = valuePop(ctxt);                          res = valuePop(ctxt);
                         if (xmlXPathEvaluatePredicateResult(ctxt, res)) {                          if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
                            xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);                            if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i])
                                 < 0)
                                 ctxt->error = XPATH_MEMORY_ERROR;
                         }                          }
   
                         /*                          /*
Line 13982  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX Line 14130  xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlX
     }      }
     xmlGenericError(xmlGenericErrorContext,      xmlGenericError(xmlGenericErrorContext,
                     "XPath: unknown precompiled operation %d\n", op->op);                      "XPath: unknown precompiled operation %d\n", op->op);
       ctxt->error = XPATH_INVALID_OPERAND;
     return (total);      return (total);
 }  }
   
Line 14128  xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatt Line 14277  xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatt
             if (toBool)              if (toBool)
                 return(1);                  return(1);
             xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,              xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
                (xmlNodePtr) ctxt->doc);                                     (xmlNodePtr) ctxt->doc);
         } else {          } else {
             /* Select "self::node()" */              /* Select "self::node()" */
             if (toBool)              if (toBool)
Line 14221  next_node: Line 14370  next_node:
                 } else if (ret == 1) {                  } else if (ret == 1) {
                     if (toBool)                      if (toBool)
                         goto return_1;                          goto return_1;
                    xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);                    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
                         < 0) {
                         ctxt->lastError.domain = XML_FROM_XPATH;
                         ctxt->lastError.code = XML_ERR_NO_MEMORY;
                     }
                 }                  }
                 if ((cur->children == NULL) || (depth >= max_depth)) {                  if ((cur->children == NULL) || (depth >= max_depth)) {
                     ret = xmlStreamPop(patstream);                      ret = xmlStreamPop(patstream);
Line 14237  next_node: Line 14390  next_node:
         }          }
   
 scan_children:  scan_children:
           if (cur->type == XML_NAMESPACE_DECL) break;
         if ((cur->children != NULL) && (depth < max_depth)) {          if ((cur->children != NULL) && (depth < max_depth)) {
             /*              /*
              * Do not descend on entities declarations               * Do not descend on entities declarations
Line 14329  xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toB Line 14483  xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toB
         ctxt->valueNr = 0;          ctxt->valueNr = 0;
         ctxt->valueMax = 10;          ctxt->valueMax = 10;
         ctxt->value = NULL;          ctxt->value = NULL;
           ctxt->valueFrame = 0;
     }      }
 #ifdef XPATH_STREAMING  #ifdef XPATH_STREAMING
     if (ctxt->comp->stream) {      if (ctxt->comp->stream) {
Line 14556  xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, cons Line 14711  xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, cons
 }  }
 #endif /* XPATH_STREAMING */  #endif /* XPATH_STREAMING */
   
 static int  
 xmlXPathCanRewriteDosExpression(xmlChar *expr)  
 {  
     if (expr == NULL)  
         return(0);  
     do {  
         if ((*expr == '/') && (*(++expr) == '/'))  
             return(1);  
     } while (*expr++);  
     return(0);  
 }  
 static void  static void
xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
 {  {
     /*      /*
     * Try to rewrite "descendant-or-self::node()/foo" to an optimized      * Try to rewrite "descendant-or-self::node()/foo" to an optimized
     * internal representation.      * internal representation.
     */      */
     if (op->ch1 != -1) {  
         if ((op->op == XPATH_OP_COLLECT /* 11 */) &&  
             ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) &&  
             ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) &&  
             ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */))  
         {  
             /*  
             * This is a "child::foo"  
             */  
             xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];  
   
            if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&    if ((op->ch1 != -1) &&
                (prevop->ch1 != -1) &&        (op->op == XPATH_OP_COLLECT /* 11 */))
                ((xmlXPathAxisVal) prevop->value ==    {
                    AXIS_DESCENDANT_OR_SELF) &&        xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
                (prevop->ch2 == -1) &&
                ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&        if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
                ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) &&            ((xmlXPathAxisVal) prevop->value ==
                (comp->steps[prevop->ch1].op == XPATH_OP_ROOT))                AXIS_DESCENDANT_OR_SELF) &&
            {            (prevop->ch2 == -1) &&
                /*            ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
                * This is a "/descendant-or-self::node()" without predicates.            ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
                * Eliminate it.        {
                */            /*
                op->ch1 = prevop->ch1;            * This is a "descendant-or-self::node()" without predicates.
                op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM;            * Try to eliminate it.
            }            */
 
             switch ((xmlXPathAxisVal) op->value) {
                 case AXIS_CHILD:
                 case AXIS_DESCENDANT:
                     /*
                     * Convert "descendant-or-self::node()/child::" or
                     * "descendant-or-self::node()/descendant::" to
                     * "descendant::"
                     */
                     op->ch1   = prevop->ch1;
                     op->value = AXIS_DESCENDANT;
                     break;
                 case AXIS_SELF:
                 case AXIS_DESCENDANT_OR_SELF:
                     /*
                     * Convert "descendant-or-self::node()/self::" or
                     * "descendant-or-self::node()/descendant-or-self::" to
                     * to "descendant-or-self::"
                     */
                     op->ch1   = prevop->ch1;
                     op->value = AXIS_DESCENDANT_OR_SELF;
                     break;
                 default:
                     break;
             }
         }          }
         if (op->ch1 != -1)  
             xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]);  
     }      }
   
       /* Recurse */
       if (op->ch1 != -1)
           xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
     if (op->ch2 != -1)      if (op->ch2 != -1)
        xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]);        xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]);
 }  }
   
 /**  /**
Line 14664  xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xml Line 14825  xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xml
         comp->string = xmlStrdup(str);          comp->string = xmlStrdup(str);
         comp->nb = 0;          comp->nb = 0;
 #endif  #endif
        if ((comp->expr != NULL) &&        if ((comp->nbStep > 1) && (comp->last >= 0)) {
            (comp->nbStep > 2) &&            xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]);
            (comp->last >= 0) && 
            (xmlXPathCanRewriteDosExpression(comp->expr) == 1)) 
        { 
            xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]); 
         }          }
     }      }
     return(comp);      return(comp);
Line 14846  xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) { Line 15003  xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
 #endif  #endif
     {      {
         xmlXPathCompileExpr(ctxt, 1);          xmlXPathCompileExpr(ctxt, 1);
         /*  
         * In this scenario the expression string will sit in ctxt->base.  
         */  
         if ((ctxt->error == XPATH_EXPRESSION_OK) &&          if ((ctxt->error == XPATH_EXPRESSION_OK) &&
             (ctxt->comp != NULL) &&              (ctxt->comp != NULL) &&
            (ctxt->base != NULL) &&            (ctxt->comp->nbStep > 1) &&
            (ctxt->comp->nbStep > 2) &&            (ctxt->comp->last >= 0))
            (ctxt->comp->last >= 0) && 
            (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1)) 
         {          {
            xmlXPathRewriteDOSExpression(ctxt->comp,            xmlXPathOptimizeExpression(ctxt->comp,
                 &ctxt->comp->steps[ctxt->comp->last]);                  &ctxt->comp->steps[ctxt->comp->last]);
         }          }
     }      }
Line 14927  xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ct Line 15079  xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ct
 }  }
   
 /**  /**
    * xmlXPathSetContextNode:
    * @node: the node to to use as the context node
    * @ctx:  the XPath context
    *
    * Sets 'node' as the context node. The node must be in the same
    * document as that associated with the context.
    *
    * Returns -1 in case of error or 0 if successful
    */
   int
   xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
       if ((node == NULL) || (ctx == NULL))
           return(-1);
   
       if (node->doc == ctx->doc) {
           ctx->node = node;
           return(0);
       }
       return(-1);
   }
   
   /**
    * xmlXPathNodeEval:
    * @node: the node to to use as the context node
    * @str:  the XPath expression
    * @ctx:  the XPath context
    *
    * Evaluate the XPath Location Path in the given context. The node 'node'
    * is set as the context node. The context node is not restored.
    *
    * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
    *         the caller has to free the object.
    */
   xmlXPathObjectPtr
   xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
       if (str == NULL)
           return(NULL);
       if (xmlXPathSetContextNode(node, ctx) < 0)
           return(NULL);
       return(xmlXPathEval(str, ctx));
   }
   
   /**
  * xmlXPathEvalExpression:   * xmlXPathEvalExpression:
  * @str:  the XPath expression   * @str:  the XPath expression
  * @ctxt:  the XPath context   * @ctxt:  the XPath context
Line 15030  static void Line 15225  static void
 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     xmlXPathObjectPtr str;      xmlXPathObjectPtr str;
     int escape_reserved;      int escape_reserved;
    xmlBufferPtr target;    xmlBufPtr target;
     xmlChar *cptr;      xmlChar *cptr;
     xmlChar escape[4];      xmlChar escape[4];
   
Line 15041  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx Line 15236  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx
     CAST_TO_STRING;      CAST_TO_STRING;
     str = valuePop(ctxt);      str = valuePop(ctxt);
   
    target = xmlBufferCreate();    target = xmlBufCreate();
   
     escape[0] = '%';      escape[0] = '%';
     escape[3] = 0;      escape[3] = 0;
Line 15066  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx Line 15261  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx
                   *cptr == ':' || *cptr == '@' || *cptr == '&' ||                    *cptr == ':' || *cptr == '@' || *cptr == '&' ||
                   *cptr == '=' || *cptr == '+' || *cptr == '$' ||                    *cptr == '=' || *cptr == '+' || *cptr == '$' ||
                   *cptr == ','))) {                    *cptr == ','))) {
                xmlBufferAdd(target, cptr, 1);                xmlBufAdd(target, cptr, 1);
             } else {              } else {
                 if ((*cptr >> 4) < 10)                  if ((*cptr >> 4) < 10)
                     escape[1] = '0' + (*cptr >> 4);                      escape[1] = '0' + (*cptr >> 4);
Line 15077  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx Line 15272  xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctx
                 else                  else
                     escape[2] = 'A' - 10 + (*cptr & 0xF);                      escape[2] = 'A' - 10 + (*cptr & 0xF);
   
                xmlBufferAdd(target, &escape[0], 3);                xmlBufAdd(target, &escape[0], 3);
             }              }
         }          }
     }      }
     valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,      valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
        xmlBufferContent(target)));        xmlBufContent(target)));
    xmlBufferFree(target);    xmlBufFree(target);
     xmlXPathReleaseObject(ctxt->context, str);      xmlXPathReleaseObject(ctxt->context, str);
 }  }
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>