Put local variables footer in all c, h files.
[idzebra-moved-to-github.git] / index / zrpn.c
index 87190e1..2a25753 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zrpn.c,v 1.182 2005-04-29 10:54:45 adam Exp $
+/* $Id: zrpn.c,v 1.212 2006-05-10 08:13:23 adam Exp $
    Copyright (C) 1995-2005
    Index Data ApS
 
@@ -24,7 +24,8 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <assert.h>
 #ifdef WIN32
 #include <io.h>
-#else
+#endif
+#if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include <ctype.h>
@@ -36,18 +37,6 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <charmap.h>
 #include <rset.h>
 
-static const struct key_control it_ctrl =
-{ 
-    sizeof(struct it_key),
-    2, /* we have sysnos and seqnos in this key, nothing more */
-    key_compare_it, 
-    key_logdump_txt,   /* FIXME  - clean up these functions */
-    key_get_seq,
-};
-
-
-const struct key_control *key_it_ctrl = &it_ctrl;
-
 struct rpn_char_map_info
 {
     ZebraMaps zm;
@@ -62,7 +51,6 @@ typedef struct
     Z_AttributesPlusTerm *zapt;
 } AttrType;
 
-
 static int log_level_set = 0;
 static int log_level_rpn = 0;
 
@@ -94,7 +82,7 @@ static void rpn_char_map_prepare(struct zebra_register *reg, int reg_type,
 }
 
 static int attr_find_ex(AttrType *src, oid_value *attributeSetP,
-                         const char **string_value)
+                       const char **string_value)
 {
     int num_attributes;
 
@@ -185,16 +173,20 @@ struct grep_info {
     ZebraSet termset;
 };        
 
-static void term_untrans(ZebraHandle zh, int reg_type,
-                           char *dst, const char *src)
+void zebra_term_untrans(ZebraHandle zh, int reg_type,
+                       char *dst, const char *src)
 {
     int len = 0;
     while (*src)
     {
         const char *cp = zebra_maps_output(zh->reg->zebra_maps,
                                           reg_type, &src);
-        if (!cp && len < IT_MAX_WORD-1)
-            dst[len++] = *src++;
+       if (!cp)
+       {
+           if (len < IT_MAX_WORD-1)
+               dst[len++] = *src;
+           src++;
+       }
         else
             while (*cp && len < IT_MAX_WORD-1)
                 dst[len++] = *cp++;
@@ -247,13 +239,13 @@ static void add_isam_p(const char *name, const char *info,
         const char *db;
         int set, use;
         char term_tmp[IT_MAX_WORD];
-        int su_code = 0;
-        int len = key_SU_decode (&su_code, name);
+        int ord = 0;
+        int len = key_SU_decode (&ord, (const unsigned char *) name);
         
-        term_untrans  (p->zh, p->reg_type, term_tmp, name+len+1);
-        yaz_log(log_level_rpn, "grep: %d %c %s", su_code, name[len], term_tmp);
+        zebra_term_untrans  (p->zh, p->reg_type, term_tmp, name+len+1);
+        yaz_log(log_level_rpn, "grep: %d %c %s", ord, name[len], term_tmp);
         zebraExplain_lookup_ord (p->zh->reg->zei,
-                                 su_code, &db, &set, &use);
+                                 ord, 0 /* index_type */, &db, &set, &use, 0);
         yaz_log(log_level_rpn, "grep:  set=%d use=%d db=%s", set, use, db);
         
         resultSetAddTerm(p->zh, p->termset, name[len], db,
@@ -534,7 +526,7 @@ static int term_104(ZebraMaps zebra_maps, int reg_type,
                    const char **src, char *dst, int space_split,
                    char *dst_term)
 {
-    const char *s0, *s1;
+    const char *s0;
     const char **map;
     int i = 0;
     int j = 0;
@@ -582,17 +574,33 @@ static int term_104(ZebraMaps zebra_maps, int reg_type,
         }
        else
         {
-            s1 = s0;
-            map = zebra_maps_input(zebra_maps, reg_type, &s0, strlen(s0), 0);
+           const char *s1 = s0;
+           int q_map_match = 0;
+           map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0), 
+                                   &q_map_match);
             if (space_split && **map == *CHR_SPACE)
                 break;
-            while (s1 < s0)
-            {
-                if (strchr(REGEX_CHARS, *s1))
-                    dst[i++] = '\\';
-                dst_term[j++] = *s1;
-                dst[i++] = *s1++;
-            }
+
+           /* add non-space char */
+           memcpy(dst_term+j, s1, s0 - s1);
+           j += (s0 - s1);
+           if (!q_map_match)
+           {
+               while (s1 < s0)
+               {
+                   if (strchr(REGEX_CHARS, *s1))
+                       dst[i++] = '\\';
+                   dst[i++] = *s1++;
+               }
+           }
+           else
+           {
+               char tmpbuf[80];
+               esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
+               
+               strcpy(dst + i, map[0]);
+               i += strlen(map[0]);
+           }
         }
     }
     dst[i] = '\0';
@@ -606,7 +614,7 @@ static int term_105(ZebraMaps zebra_maps, int reg_type,
                    const char **src, char *dst, int space_split,
                    char *dst_term, int right_truncate)
 {
-    const char *s0, *s1;
+    const char *s0;
     const char **map;
     int i = 0;
     int j = 0;
@@ -629,17 +637,33 @@ static int term_105(ZebraMaps zebra_maps, int reg_type,
         }
        else
         {
-            s1 = s0;
-            map = zebra_maps_input(zebra_maps, reg_type, &s0, strlen(s0), 0);
+           const char *s1 = s0;
+           int q_map_match = 0;
+           map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0), 
+                                   &q_map_match);
             if (space_split && **map == *CHR_SPACE)
                 break;
-            while (s1 < s0)
-            {
-                if (strchr(REGEX_CHARS, *s1))
-                    dst[i++] = '\\';
-                dst_term[j++] = *s1;
-                dst[i++] = *s1++;
-            }
+
+           /* add non-space char */
+           memcpy(dst_term+j, s1, s0 - s1);
+           j += (s0 - s1);
+           if (!q_map_match)
+           {
+               while (s1 < s0)
+               {
+                   if (strchr(REGEX_CHARS, *s1))
+                       dst[i++] = '\\';
+                   dst[i++] = *s1++;
+               }
+           }
+           else
+           {
+               char tmpbuf[80];
+               esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
+               
+               strcpy(dst + i, map[0]);
+               i += strlen(map[0]);
+           }
         }
     }
     if (right_truncate)
@@ -955,7 +979,7 @@ static int string_relation(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         strcat(term_tmp, ")");
        break;
     default:
-       *error_code = 117;
+       *error_code = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE;
        return 0;
     }
     return 1;
@@ -967,9 +991,58 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                             struct grep_info *grep_info,
                             int reg_type, int complete_flag,
                             int num_bases, char **basenames,
-                            char *term_dst, int xpath_use);
+                            char *term_dst, int xpath_use,
+                            struct ord_list **ol);
+
+static ZEBRA_RES term_limits_APT(ZebraHandle zh,
+                                Z_AttributesPlusTerm *zapt,
+                                zint *hits_limit_value,
+                                const char **term_ref_id_str,
+                                NMEM nmem)
+{
+    AttrType term_ref_id_attr;
+    AttrType hits_limit_attr;
+    int term_ref_id_int;
+    attr_init(&hits_limit_attr, zapt, 9);
+    *hits_limit_value  = attr_find(&hits_limit_attr, NULL);
+
+    attr_init(&term_ref_id_attr, zapt, 10);
+    term_ref_id_int = attr_find_ex(&term_ref_id_attr, NULL, term_ref_id_str);
+    if (term_ref_id_int >= 0)
+    {
+       char *res = nmem_malloc(nmem, 20);
+       sprintf(res, "%d", term_ref_id_int);
+       *term_ref_id_str = res;
+    }
+
+    /* no limit given ? */
+    if (*hits_limit_value == -1)
+    {
+       if (*term_ref_id_str)
+       {
+           /* use global if term_ref is present */
+           *hits_limit_value = zh->approx_limit;
+       }
+       else
+       {
+           /* no counting if term_ref is not present */
+           *hits_limit_value = 0;
+       }
+    }
+    else if (*hits_limit_value == 0)
+    {
+       /* 0 is the same as global limit */
+       *hits_limit_value = zh->approx_limit;
+    }
+    yaz_log(YLOG_DEBUG, "term_limits_APT ref_id=%s limit=" ZINT_FORMAT,
+           *term_ref_id_str ? *term_ref_id_str : "none",
+           *hits_limit_value);
+    return ZEBRA_OK;
+}
 
-static ZEBRA_RES term_trunc(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
+static ZEBRA_RES term_trunc(ZebraHandle zh,
+                           Z_AttributesPlusTerm *zapt,
                            const char **term_sub, 
                            oid_value attributeSet, NMEM stream,
                            struct grep_info *grep_info,
@@ -978,14 +1051,21 @@ static ZEBRA_RES term_trunc(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                            char *term_dst,
                            const char *rank_type, int xpath_use,
                            NMEM rset_nmem,
-                           RSET *rset)
+                           RSET *rset,
+                           struct rset_key_control *kc)
 {
     ZEBRA_RES res;
+    struct ord_list *ol;
+    zint hits_limit_value;
+    const char *term_ref_id_str = 0;
     *rset = 0;
+
+    term_limits_APT(zh, zapt, &hits_limit_value, &term_ref_id_str,
+                   stream);
     grep_info->isam_p_indx = 0;
     res = string_term(zh, zapt, term_sub, attributeSet, stream, grep_info,
                      reg_type, complete_flag, num_bases, basenames,
-                     term_dst, xpath_use);
+                     term_dst, xpath_use, &ol);
     if (res != ZEBRA_OK)
         return res;
     if (!*term_sub)  /* no more terms ? */
@@ -995,26 +1075,21 @@ static ZEBRA_RES term_trunc(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                       grep_info->isam_p_indx, term_dst,
                       strlen(term_dst), rank_type, 1 /* preserve pos */,
                       zapt->term->which, rset_nmem,
-                      key_it_ctrl, key_it_ctrl->scope);
+                      kc, kc->scope, ol, reg_type, hits_limit_value,
+                      term_ref_id_str);
     if (!*rset)
        return ZEBRA_FAIL;
     return ZEBRA_OK;
 }
 
-static char *nmem_strdup_i(NMEM nmem, int v)
-{
-    char val_str[64];
-    sprintf(val_str, "%d", v);
-    return nmem_strdup(nmem, val_str);
-}
-
 static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                             const char **term_sub, 
                             oid_value attributeSet, NMEM stream,
                             struct grep_info *grep_info,
                             int reg_type, int complete_flag,
                             int num_bases, char **basenames,
-                            char *term_dst, int xpath_use)
+                            char *term_dst, int xpath_use,
+                            struct ord_list **ol)
 {
     char term_dict[2*IT_MAX_WORD+4000];
     int j, r, base_no;
@@ -1029,8 +1104,8 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     int space_split = complete_flag ? 0 : 1;
 
     int bases_ok = 0;     /* no of databases with OK attribute */
-    int errCode = 0;      /* err code (if any is not OK) */
-    char *errString = 0;  /* addinfo */
+
+    *ol = ord_list_create(stream);
 
     rpn_char_map_prepare (zh->reg, reg_type, &rcmi);
     attr_init(&use, zapt, 1);
@@ -1058,8 +1133,8 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
 
         if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
         {
-            zh->errCode = YAZ_BIB1_DATABASE_UNAVAILABLE;
-            zh->errString = basenames[base_no];
+           zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
+                          basenames[base_no]);
             return ZEBRA_FAIL;
         }
         if (xpath_use > 0 && use_value == -2) 
@@ -1082,6 +1157,7 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         }
        else if (use_string &&
                 (ord = zebraExplain_lookup_attr_str(zh->reg->zei,
+                                                    reg_type,
                                                     use_string)) >= 0)
        {
            /* we have a match for a raw string attribute */
@@ -1100,6 +1176,7 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                 term_dict[prefix_len++] = ord_buf[i];
             }
             attp.local_attributes = 0;  /* no more attributes */
+           *ol = ord_list_append(stream, *ol, ord);
        }
         else 
         {
@@ -1112,11 +1189,13 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                 if (r == -1)
                 {
                     /* set was found, but value wasn't defined */
-                    errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
                     if (use_string)
-                        errString = nmem_strdup(stream, use_string);
+                       zebra_setError(zh, 
+                                      YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
+                                      use_string);
                     else
-                        errString = nmem_strdup_i (stream, use_value);
+                       zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, 
+                                           use_value);
                 }
                 else
                 {
@@ -1128,8 +1207,10 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                     oident.value = curAttributeSet;
                     oid_ent_to_oid (&oident, oid);
                     
-                    errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
-                    errString = nmem_strdup(stream, oident.desc);
+                   zebra_setError(zh, 
+                                  YAZ_BIB1_UNSUPP_ATTRIBUTE_SET,
+                                  oident.desc);
+                   
                 }
                 continue;
             }
@@ -1141,10 +1222,12 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
            int i, ord_len;
            
            ord = zebraExplain_lookup_attr_su(zh->reg->zei,
+                                             reg_type,
                                              attp.attset_ordinal,
                                              local_attr->local);
            if (ord < 0)
                continue;
+           *ol = ord_list_append(stream, *ol, ord);
            if (prefix_len)
                term_dict[prefix_len++] = '|';
            else
@@ -1156,15 +1239,14 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                term_dict[prefix_len++] = 1;
                term_dict[prefix_len++] = ord_buf[i];
            }
+           if (ord_len > init_pos)
+               init_pos = ord_len;
        }
        bases_ok++;
         if (prefix_len)
            attr_ok = 1;
 
         term_dict[prefix_len++] = ')';
-        term_dict[prefix_len++] = 1;
-        term_dict[prefix_len++] = reg_type;
-        yaz_log(log_level_rpn, "reg_type = %d", term_dict[prefix_len-1]);
         term_dict[prefix_len] = '\0';
         j = prefix_len;
         switch (truncation_value)
@@ -1178,7 +1260,7 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
            {
                if (relation_error)
                {
-                   zh->errCode = relation_error;
+                   zebra_setError(zh, relation_error, 0);
                    return ZEBRA_FAIL;
                }
                *term_sub = 0;
@@ -1236,9 +1318,8 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
             strcat(term_dict, ")");
             break;
         case 103:       /* Regexp-2 */
-            r = 1;
+            regex_range = 1;
             term_dict[j++] = '(';
-           init_pos = 2;
             if (!term_103(zh->reg->zebra_maps, reg_type,
                           &termp, term_dict + j, &regex_range,
                          space_split, term_dst))
@@ -1247,6 +1328,7 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                 return ZEBRA_OK;
            }
             strcat(term_dict, ")");
+           break;
         case 104:        /* process # and ! in term */
             term_dict[j++] = '(';
             if (!term_104(zh->reg->zebra_maps, reg_type,
@@ -1278,8 +1360,9 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
             strcat(term_dict, ")");
             break;
        default:
-           zh->errCode = YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE;
-           zh->errString = nmem_strdup_i(stream, truncation_value);
+           zebra_setError_zint(zh,
+                               YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE,
+                               truncation_value);
            return ZEBRA_FAIL;
         }
        if (attr_ok)
@@ -1299,11 +1382,7 @@ static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
        }
     }
     if (!bases_ok)
-    {
-        zh->errCode = errCode;
-        zh->errString = errString;
         return ZEBRA_FAIL;
-    }
     *term_sub = termp;
     yaz_log(YLOG_DEBUG, "%d positions", grep_info->isam_p_indx);
     return ZEBRA_OK;
@@ -1322,7 +1401,7 @@ static ZEBRA_RES zapt_term_to_utf8(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     case Z_Term_general:
         if (zh->iconv_to_utf8 != 0)
         {
-            char *inbuf = term->u.general->buf;
+            char *inbuf = (char *) term->u.general->buf;
             size_t inleft = term->u.general->len;
             char *outbuf = termz;
             size_t outleft = IT_MAX_WORD-1;
@@ -1333,9 +1412,11 @@ static ZEBRA_RES zapt_term_to_utf8(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
             if (ret == (size_t)(-1))
             {
                 ret = yaz_iconv(zh->iconv_to_utf8, 0, 0, 0, 0);
-                zh->errCode =
-                   YAZ_BIB1_QUERY_TERM_INCLUDES_CHARS_THAT_DO_NOT_TRANSLATE_INTO_;
-                return -1;
+               zebra_setError(
+                   zh, 
+                   YAZ_BIB1_QUERY_TERM_INCLUDES_CHARS_THAT_DO_NOT_TRANSLATE_INTO_,
+                   0);
+                return ZEBRA_FAIL;
             }
             *outbuf = 0;
         }
@@ -1356,7 +1437,7 @@ static ZEBRA_RES zapt_term_to_utf8(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         termz[sizez] = '\0';
         break;
     default:
-        zh->errCode = YAZ_BIB1_UNSUPP_CODED_VALUE_FOR_TERM;
+       zebra_setError(zh, YAZ_BIB1_UNSUPP_CODED_VALUE_FOR_TERM, 0);
        return ZEBRA_FAIL;
     }
     return ZEBRA_OK;
@@ -1400,50 +1481,6 @@ static ZEBRA_RES trans_scan_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     return ZEBRA_OK;
 }
 
-char *normalize_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
-                     const char *termz, NMEM stream, unsigned reg_id)
-{
-    WRBUF wrbuf = 0;
-    AttrType truncation;
-    int truncation_value;
-    char *ex_list = 0;
-
-    attr_init(&truncation, zapt, 5);
-    truncation_value = attr_find(&truncation, NULL);
-
-    switch (truncation_value)
-    {
-    default:
-        ex_list = "";
-        break;
-    case 101:
-        ex_list = "#";
-        break;
-    case 102:
-    case 103:
-        ex_list = 0;
-        break;
-    case 104:
-        ex_list = "!#";
-        break;
-    case 105:
-        ex_list = "!*";
-        break;
-    }
-    if (ex_list)
-        wrbuf = zebra_replace(zh->reg->zebra_maps, reg_id, ex_list,
-                              termz, strlen(termz));
-    if (!wrbuf)
-        return nmem_strdup(stream, termz);
-    else
-    {
-        char *buf = (char*) nmem_malloc(stream, wrbuf_len(wrbuf)+1);
-        memcpy (buf, wrbuf_buf(wrbuf), wrbuf_len(wrbuf));
-        buf[wrbuf_len(wrbuf)] = '\0';
-        return buf;
-    }
-}
-
 static void grep_info_delete(struct grep_info *grep_info)
 {
 #ifdef TERM_COUNT
@@ -1452,11 +1489,10 @@ static void grep_info_delete(struct grep_info *grep_info)
     xfree(grep_info->isam_p_buf);
 }
 
-static int grep_info_prepare(ZebraHandle zh,
-                            Z_AttributesPlusTerm *zapt,
-                            struct grep_info *grep_info,
-                            int reg_type,
-                            NMEM stream)
+static ZEBRA_RES grep_info_prepare(ZebraHandle zh,
+                                  Z_AttributesPlusTerm *zapt,
+                                  struct grep_info *grep_info,
+                                  int reg_type)
 {
     AttrType termset;
     int termset_value_numeric;
@@ -1472,7 +1508,7 @@ static int grep_info_prepare(ZebraHandle zh,
     grep_info->termset = 0;
 
     if (!zapt)
-        return 0;
+        return ZEBRA_OK;
     attr_init(&termset, zapt, 8);
     termset_value_numeric =
         attr_find_ex(&termset, NULL, &termset_value_string);
@@ -1492,35 +1528,50 @@ static int grep_info_prepare(ZebraHandle zh,
         grep_info->termset = resultSetAdd(zh, termset_name, 1);
         if (!grep_info->termset)
         {
-            zh->errCode = YAZ_BIB1_ILLEGAL_RESULT_SET_NAME;
-            zh->errString = nmem_strdup(stream, termset_name);
-            return -1;
+           zebra_setError(zh, YAZ_BIB1_ILLEGAL_RESULT_SET_NAME, termset_name);
+            return ZEBRA_FAIL;
         }
     }
-    return 0;
+    return ZEBRA_OK;
 }
                                
-
+/**
+  \brief Create result set(s) for list of terms
+  \param zh Zebra Handle
+  \param termz term as used in query but converted to UTF-8
+  \param attributeSet default attribute set
+  \param stream memory for result
+  \param reg_type register type ('w', 'p',..)
+  \param complete_flag whether it's phrases or not
+  \param rank_type term flags for ranking
+  \param xpath_use use attribute for X-Path (-1 for no X-path)
+  \param num_bases number of databases
+  \param basenames array of databases
+  \param rset_mem memory for result sets
+  \param result_sets output result set for each term in list (output)
+  \param number number of output result sets
+  \param kc rset key control to be used for created result sets
+*/
 static ZEBRA_RES term_list_trunc(ZebraHandle zh,
                                 Z_AttributesPlusTerm *zapt,
-                                const char *termz_org,
+                                const char *termz,
                                 oid_value attributeSet,
                                 NMEM stream,
                                 int reg_type, int complete_flag,
                                 const char *rank_type, int xpath_use,
                                 int num_bases, char **basenames, 
                                 NMEM rset_nmem,
-                                RSET **result_sets, int *num_result_sets)
+                                RSET **result_sets, int *num_result_sets,
+                                struct rset_key_control *kc)
 {
     char term_dst[IT_MAX_WORD+1];
     struct grep_info grep_info;
-    char *termz = normalize_term(zh, zapt, termz_org, stream, reg_type);
     const char *termp = termz;
     int alloc_sets = 0;
 
     *num_result_sets = 0;
     *term_dst = 0;
-    if (grep_info_prepare(zh, zapt, &grep_info, reg_type, stream))
+    if (grep_info_prepare(zh, zapt, &grep_info, reg_type) == ZEBRA_FAIL)
         return ZEBRA_FAIL;
     while(1)
     { 
@@ -1542,7 +1593,8 @@ static ZEBRA_RES term_list_trunc(ZebraHandle zh,
                         num_bases, basenames,
                         term_dst, rank_type,
                         xpath_use, rset_nmem,
-                        &(*result_sets)[*num_result_sets]);
+                        &(*result_sets)[*num_result_sets],
+                        kc);
        if (res != ZEBRA_OK)
        {
            int i;
@@ -1568,7 +1620,8 @@ static ZEBRA_RES rpn_search_APT_phrase(ZebraHandle zh,
                                       const char *rank_type, int xpath_use,
                                       int num_bases, char **basenames, 
                                       NMEM rset_nmem,
-                                      RSET *rset)
+                                      RSET *rset,
+                                      struct rset_key_control *kc)
 {
     RSET *result_sets = 0;
     int num_result_sets = 0;
@@ -1578,15 +1631,15 @@ static ZEBRA_RES rpn_search_APT_phrase(ZebraHandle zh,
                        rank_type, xpath_use,
                        num_bases, basenames,
                        rset_nmem,
-                       &result_sets, &num_result_sets);
+                       &result_sets, &num_result_sets, kc);
     if (res != ZEBRA_OK)
        return res;
     if (num_result_sets == 0)
-       *rset = rsnull_create (rset_nmem, key_it_ctrl); 
+       *rset = rsnull_create (rset_nmem, kc, 0); 
     else if (num_result_sets == 1)
        *rset = result_sets[0];
     else
-       *rset = rsprox_create(rset_nmem, key_it_ctrl, key_it_ctrl->scope,
+       *rset = rsprox_create(rset_nmem, kc, kc->scope,
                              num_result_sets, result_sets,
                              1 /* ordered */, 0 /* exclusion */,
                              3 /* relation */, 1 /* distance */);
@@ -1605,7 +1658,8 @@ static ZEBRA_RES rpn_search_APT_or_list(ZebraHandle zh,
                                        int xpath_use,
                                        int num_bases, char **basenames,
                                        NMEM rset_nmem,
-                                       RSET *rset)
+                                       RSET *rset,
+                                       struct rset_key_control *kc)
 {
     RSET *result_sets = 0;
     int num_result_sets = 0;
@@ -1615,15 +1669,15 @@ static ZEBRA_RES rpn_search_APT_or_list(ZebraHandle zh,
                        rank_type, xpath_use,
                        num_bases, basenames,
                        rset_nmem,
-                       &result_sets, &num_result_sets);
+                       &result_sets, &num_result_sets, kc);
     if (res != ZEBRA_OK)
        return res;
     if (num_result_sets == 0)
-       *rset = rsnull_create (rset_nmem, key_it_ctrl); 
+       *rset = rsnull_create (rset_nmem, kc, 0); 
     else if (num_result_sets == 1)
        *rset = result_sets[0];
     else
-       *rset = rsmulti_or_create(rset_nmem, key_it_ctrl, key_it_ctrl->scope,
+       *rset = rsmulti_or_create(rset_nmem, kc, kc->scope, 0 /* termid */,
                                  num_result_sets, result_sets);
     if (!*rset)
        return ZEBRA_FAIL;
@@ -1640,7 +1694,8 @@ static ZEBRA_RES rpn_search_APT_and_list(ZebraHandle zh,
                                         int xpath_use,
                                         int num_bases, char **basenames,
                                         NMEM rset_nmem,
-                                        RSET *rset)
+                                        RSET *rset,
+                                        struct rset_key_control *kc)
 {
     RSET *result_sets = 0;
     int num_result_sets = 0;
@@ -1650,15 +1705,16 @@ static ZEBRA_RES rpn_search_APT_and_list(ZebraHandle zh,
                        rank_type, xpath_use,
                        num_bases, basenames,
                        rset_nmem,
-                       &result_sets, &num_result_sets);
+                       &result_sets, &num_result_sets,
+                       kc);
     if (res != ZEBRA_OK)
        return res;
     if (num_result_sets == 0)
-       *rset = rsnull_create (rset_nmem, key_it_ctrl); 
+       *rset = rsnull_create (rset_nmem, kc, 0); 
     else if (num_result_sets == 1)
        *rset = result_sets[0];
     else
-       *rset = rsmulti_and_create(rset_nmem, key_it_ctrl, key_it_ctrl->scope,
+       *rset = rsmulti_and_create(rset_nmem, kc, kc->scope,
                                   num_result_sets, result_sets);
     if (!*rset)
        return ZEBRA_FAIL;
@@ -1715,7 +1771,7 @@ static int numeric_relation(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         sprintf(term_tmp, "(0*%d)", term_value);
        break;
     default:
-       *error_code = 117;
+       *error_code = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE;
        return 0;
     }
     yaz_log(log_level_rpn, "dict_lookup_grep: %s", term_tmp);
@@ -1745,8 +1801,6 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     struct rpn_char_map_info rcmi;
 
     int bases_ok = 0;     /* no of databases with OK attribute */
-    int errCode = 0;      /* err code (if any is not OK) */
-    char *errString = 0;  /* addinfo */
 
     rpn_char_map_prepare (zh->reg, reg_type, &rcmi);
     attr_init(&use, zapt, 1);
@@ -1782,28 +1836,30 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         else
         {
             if ((r = att_getentbyatt (zh, &attp, curAttributeSet, use_value,
-                                            use_string)))
+                                     use_string)))
             {
                 yaz_log(YLOG_DEBUG, "att_getentbyatt fail. set=%d use=%d r=%d",
                       curAttributeSet, use_value, r);
                 if (r == -1)
                 {
-                    errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
                     if (use_string)
-                        errString = nmem_strdup(stream, use_string);
+                       zebra_setError(zh, 
+                                      YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
+                                      use_string);
                     else
-                        errString = nmem_strdup_i (stream, use_value);
+                       zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, 
+                                           use_value);
                 }
                 else
-                    errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
+                   zebra_setError(zh, YAZ_BIB1_UNSUPP_ATTRIBUTE_SET, 0);
                 continue;
             }
         }
         if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
         {
-            zh->errCode = YAZ_BIB1_DATABASE_UNAVAILABLE;
-            zh->errString = basenames[base_no];
-            return -1;
+           zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
+                          basenames[base_no]);
+            return ZEBRA_FAIL;
         }
         for (local_attr = attp.local_attributes; local_attr;
              local_attr = local_attr->next)
@@ -1813,6 +1869,7 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
             int i, ord_len;
 
             ord = zebraExplain_lookup_attr_su(zh->reg->zei,
+                                             reg_type,
                                              attp.attset_ordinal,
                                              local_attr->local);
             if (ord < 0)
@@ -1831,15 +1888,11 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         }
         if (!prefix_len)
         {
-            errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
-            errString = nmem_strdup_i(stream, use_value);
+           zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, use_value);
             continue;
         }
         bases_ok++;
-        term_dict[prefix_len++] = ')';        
-        term_dict[prefix_len++] = 1;
-        term_dict[prefix_len++] = reg_type;
-        yaz_log(YLOG_DEBUG, "reg_type = %d", term_dict[prefix_len-1]);
+        term_dict[prefix_len++] = ')';
         term_dict[prefix_len] = '\0';
         if (!numeric_relation(zh, zapt, &termp, term_dict,
                              attributeSet, grep_info, &max_pos, reg_type,
@@ -1847,8 +1900,7 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
        {
            if (relation_error)
            {
-               zh->errCode = relation_error;
-               zh->errString = 0;
+               zebra_setError(zh, relation_error, 0);
                return ZEBRA_FAIL;
            }
            *term_sub = 0;
@@ -1856,16 +1908,13 @@ static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
        }
     }
     if (!bases_ok)
-    {
-        zh->errCode = errCode;
-        zh->errString = errString;
         return ZEBRA_FAIL;
-    }
     *term_sub = termp;
     yaz_log(YLOG_DEBUG, "%d positions", grep_info->isam_p_indx);
     return ZEBRA_OK;
 }
 
+                                
 static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
                                        Z_AttributesPlusTerm *zapt,
                                        const char *termz,
@@ -1875,7 +1924,8 @@ static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
                                        const char *rank_type, int xpath_use,
                                        int num_bases, char **basenames,
                                        NMEM rset_nmem,
-                                       RSET *rset)
+                                       RSET *rset,
+                                       struct rset_key_control *kc)
 {
     char term_dst[IT_MAX_WORD+1];
     const char *termp = termz;
@@ -1884,9 +1934,13 @@ static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
     ZEBRA_RES res;
     struct grep_info grep_info;
     int alloc_sets = 0;
+    zint hits_limit_value;
+    const char *term_ref_id_str = 0;
+
+    term_limits_APT(zh, zapt, &hits_limit_value, &term_ref_id_str, stream);
 
     yaz_log(log_level_rpn, "APT_numeric t='%s'", termz);
-    if (grep_info_prepare(zh, zapt, &grep_info, reg_type, stream))
+    if (grep_info_prepare(zh, zapt, &grep_info, reg_type) == ZEBRA_FAIL)
         return ZEBRA_FAIL;
     while (1)
     { 
@@ -1915,7 +1969,9 @@ static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
                       strlen(term_dst), rank_type,
                       0 /* preserve position */,
                       zapt->term->which, rset_nmem, 
-                      key_it_ctrl,key_it_ctrl->scope);
+                      kc, kc->scope, 0, reg_type,
+                      hits_limit_value,
+                      term_ref_id_str);
        if (!result_sets[num_result_sets])
            break;
        num_result_sets++;
@@ -1929,11 +1985,11 @@ static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
        return ZEBRA_FAIL;
     }
     if (num_result_sets == 0)
-        *rset = rsnull_create(rset_nmem, key_it_ctrl);
+        *rset = rsnull_create(rset_nmem, kc, 0);
     if (num_result_sets == 1)
         *rset = result_sets[0];
     else
-       *rset = rsmulti_and_create(rset_nmem, key_it_ctrl, key_it_ctrl->scope,
+       *rset = rsmulti_and_create(rset_nmem, kc, kc->scope,
                                   num_result_sets, result_sets);
     if (!*rset)
        return ZEBRA_FAIL;
@@ -1946,12 +2002,13 @@ static ZEBRA_RES rpn_search_APT_local(ZebraHandle zh,
                                      oid_value attributeSet,
                                      NMEM stream,
                                      const char *rank_type, NMEM rset_nmem,
-                                     RSET *rset)
+                                     RSET *rset,
+                                     struct rset_key_control *kc)
 {
     RSFD rsfd;
     struct it_key key;
     int sys;
-    *rset = rstemp_create(rset_nmem,key_it_ctrl,key_it_ctrl->scope,
+    *rset = rstemp_create(rset_nmem, kc, kc->scope,
                          res_get (zh->res, "setTmpDir"),0 );
     rsfd = rset_open(*rset, RSETF_WRITE);
     
@@ -1970,16 +2027,15 @@ static ZEBRA_RES rpn_sort_spec(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                               oid_value attributeSet, NMEM stream,
                               Z_SortKeySpecList *sort_sequence,
                               const char *rank_type,
-                              RSET *rset)
+                              NMEM rset_nmem,
+                              RSET *rset,
+                              struct rset_key_control *kc)
 {
     int i;
     int sort_relation_value;
     AttrType sort_relation_type;
-    int use_value;
-    AttrType use_type;
     Z_SortKeySpec *sks;
     Z_SortKey *sk;
-    Z_AttributeElement *ae;
     int oid[OID_SIZE];
     oident oe;
     char termz[20];
@@ -1987,9 +2043,6 @@ static ZEBRA_RES rpn_sort_spec(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     attr_init(&sort_relation_type, zapt, 7);
     sort_relation_value = attr_find(&sort_relation_type, &attributeSet);
 
-    attr_init(&use_type, zapt, 1);
-    use_value = attr_find(&use_type, &attributeSet);
-
     if (!sort_sequence->specs)
     {
         sort_sequence->num_specs = 10;
@@ -2025,21 +2078,7 @@ static ZEBRA_RES rpn_sort_spec(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
         nmem_malloc(stream, sizeof(*sk->u.sortAttributes));
 
     sk->u.sortAttributes->id = oid;
-    sk->u.sortAttributes->list = (Z_AttributeList *)
-        nmem_malloc(stream, sizeof(*sk->u.sortAttributes->list));
-    sk->u.sortAttributes->list->num_attributes = 1;
-    sk->u.sortAttributes->list->attributes = (Z_AttributeElement **)
-        nmem_malloc(stream, sizeof(*sk->u.sortAttributes->list->attributes));
-    ae = *sk->u.sortAttributes->list->attributes = (Z_AttributeElement *)
-        nmem_malloc(stream, sizeof(**sk->u.sortAttributes->list->attributes));
-    ae->attributeSet = 0;
-    ae->attributeType = (int *)
-        nmem_malloc(stream, sizeof(*ae->attributeType));
-    *ae->attributeType = 1;
-    ae->which = Z_AttributeValue_numeric;
-    ae->value.numeric = (int *)
-        nmem_malloc(stream, sizeof(*ae->value.numeric));
-    *ae->value.numeric = use_value;
+    sk->u.sortAttributes->list = zapt->attributes;
 
     sks->sortRelation = (int *)
         nmem_malloc(stream, sizeof(*sks->sortRelation));
@@ -2057,7 +2096,7 @@ static ZEBRA_RES rpn_sort_spec(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
     sks->which = Z_SortKeySpec_null;
     sks->u.null = odr_nullval ();
     sort_sequence->specs[i] = sks;
-    *rset = rsnull_create (NULL, key_it_ctrl);
+    *rset = rsnull_create (rset_nmem, kc, 0);
     return ZEBRA_OK;
 }
 
@@ -2083,23 +2122,25 @@ static int parse_xpath(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
 
 static RSET xpath_trunc(ZebraHandle zh, NMEM stream,
                         int reg_type, const char *term, int use,
-                        oid_value curAttributeSet, NMEM rset_nmem)
+                        oid_value curAttributeSet, NMEM rset_nmem,
+                       struct rset_key_control *kc)
 {
     RSET rset;
     struct grep_info grep_info;
     char term_dict[2048];
     char ord_buf[32];
     int prefix_len = 0;
-    int ord = zebraExplain_lookup_attr_su(zh->reg->zei, curAttributeSet, use);
+    int ord = zebraExplain_lookup_attr_su(zh->reg->zei, reg_type,
+                                         curAttributeSet, use);
     int ord_len, i, r, max_pos;
     int term_type = Z_Term_characterString;
     const char *flags = "void";
 
-    if (grep_info_prepare(zh, 0 /* zapt */, &grep_info, '0', stream))
-        return rsnull_create (rset_nmem,key_it_ctrl);
+    if (grep_info_prepare(zh, 0 /* zapt */, &grep_info, '0') == ZEBRA_FAIL)
+        return rsnull_create(rset_nmem, kc, 0);
     
     if (ord < 0)
-        return rsnull_create (rset_nmem,key_it_ctrl);
+        return rsnull_create(rset_nmem, kc, 0);
     if (prefix_len)
         term_dict[prefix_len++] = '|';
     else
@@ -2112,9 +2153,6 @@ static RSET xpath_trunc(ZebraHandle zh, NMEM stream,
         term_dict[prefix_len++] = ord_buf[i];
     }
     term_dict[prefix_len++] = ')';
-    term_dict[prefix_len++] = 1;
-    term_dict[prefix_len++] = reg_type;
-    
     strcpy(term_dict+prefix_len, term);
     
     grep_info.isam_p_indx = 0;
@@ -2125,24 +2163,31 @@ static RSET xpath_trunc(ZebraHandle zh, NMEM stream,
     rset = rset_trunc(zh, grep_info.isam_p_buf,
                      grep_info.isam_p_indx, term, strlen(term),
                      flags, 1, term_type,rset_nmem,
-                     key_it_ctrl, key_it_ctrl->scope);
+                     kc, kc->scope, 0, reg_type, 0 /* hits_limit */,
+                     0 /* term_ref_id_str */);
     grep_info_delete(&grep_info);
     return rset;
 }
 
-static RSET rpn_search_xpath(ZebraHandle zh,
-                            oid_value attributeSet,
-                            int num_bases, char **basenames,
-                            NMEM stream, const char *rank_type, RSET rset,
-                            int xpath_len, struct xpath_location_step *xpath,
-                             NMEM rset_nmem)
+static
+ZEBRA_RES rpn_search_xpath(ZebraHandle zh,
+                          oid_value attributeSet,
+                          int num_bases, char **basenames,
+                          NMEM stream, const char *rank_type, RSET rset,
+                          int xpath_len, struct xpath_location_step *xpath,
+                          NMEM rset_nmem,
+                          RSET *rset_out,
+                          struct rset_key_control *kc)
 {
     oid_value curAttributeSet = attributeSet;
     int base_no;
     int i;
 
     if (xpath_len < 0)
-        return rset;
+    {
+       *rset_out = rset;
+       return ZEBRA_OK;
+    }
 
     yaz_log(YLOG_DEBUG, "xpath len=%d", xpath_len);
     for (i = 0; i<xpath_len; i++)
@@ -2181,9 +2226,10 @@ static RSET rpn_search_xpath(ZebraHandle zh,
         
         if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
         {
-            zh->errCode = YAZ_BIB1_DATABASE_UNAVAILABLE;
-            zh->errString = basenames[base_no];
-            return rset;
+           zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
+                          basenames[base_no]);
+           *rset_out = rset;
+           return ZEBRA_FAIL;
         }
         while (--level >= 0)
         {
@@ -2245,7 +2291,7 @@ static RSET rpn_search_xpath(ZebraHandle zh,
                 wrbuf_puts(wbuf, "");
                 rset_attr = xpath_trunc(
                     zh, stream, '0', wrbuf_buf(wbuf), 3, 
-                    curAttributeSet,rset_nmem);
+                    curAttributeSet, rset_nmem, kc);
                 wrbuf_free(wbuf, 1);
             } 
             else 
@@ -2257,31 +2303,29 @@ static RSET rpn_search_xpath(ZebraHandle zh,
             if (strlen(xpath_rev))
             {
                 rset_start_tag = xpath_trunc(zh, stream, '0', 
-                        xpath_rev, 1, curAttributeSet, rset_nmem);
+                        xpath_rev, 1, curAttributeSet, rset_nmem, kc);
             
                 rset_end_tag = xpath_trunc(zh, stream, '0', 
-                        xpath_rev, 2, curAttributeSet, rset_nmem);
+                        xpath_rev, 2, curAttributeSet, rset_nmem, kc);
 
-                rset = rsbetween_create(rset_nmem, key_it_ctrl,
-                                       key_it_ctrl->scope,
+                rset = rsbetween_create(rset_nmem, kc, kc->scope,
                                        rset_start_tag, rset,
                                        rset_end_tag, rset_attr);
             }
             first_path = 0;
         }
     }
-
-    return rset;
+    *rset_out = rset;
+    return ZEBRA_OK;
 }
 
-
-
 static ZEBRA_RES rpn_search_APT(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                                oid_value attributeSet, NMEM stream,
                                Z_SortKeySpecList *sort_sequence,
                                int num_bases, char **basenames, 
                                NMEM rset_nmem,
-                               RSET *rset)
+                               RSET *rset,
+                               struct rset_key_control *kc)
 {
     ZEBRA_RES res = ZEBRA_OK;
     unsigned reg_id;
@@ -2312,22 +2356,31 @@ static ZEBRA_RES rpn_search_APT(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
 
     if (sort_flag)
         return rpn_sort_spec(zh, zapt, attributeSet, stream, sort_sequence,
-                            rank_type, rset);
+                            rank_type, rset_nmem, rset, kc);
+    /* consider if an X-Path query is used */
     xpath_len = parse_xpath(zh, zapt, attributeSet, xpath, 10, stream);
     if (xpath_len >= 0)
     {
-        xpath_use = 1016;
-        if (xpath[xpath_len-1].part[0] == '@')
-            xpath_use = 1015;
+        xpath_use = 1016;  /* searching for element by default */
+        if (xpath[xpath_len-1].part[0] == '@') 
+            xpath_use = 1015;  /* last step an attribute .. */
     }
 
+    /* search using one of the various search type strategies
+       termz is our UTF-8 search term
+       attributeSet is top-level default attribute set 
+       stream is ODR for search
+       reg_id is the register type
+       complete_flag is 1 for complete subfield, 0 for incomplete
+       xpath_use is use-attribute to be used for X-Path search, 0 for none
+    */
     if (!strcmp(search_type, "phrase"))
     {
         res = rpn_search_APT_phrase(zh, zapt, termz, attributeSet, stream,
                                    reg_id, complete_flag, rank_type,
                                    xpath_use,
                                    num_bases, basenames, rset_nmem,
-                                   rset);
+                                   rset, kc);
     }
     else if (!strcmp(search_type, "and-list"))
     {
@@ -2335,7 +2388,7 @@ static ZEBRA_RES rpn_search_APT(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                                      reg_id, complete_flag, rank_type,
                                      xpath_use,
                                      num_bases, basenames, rset_nmem,
-                                     rset);
+                                     rset, kc);
     }
     else if (!strcmp(search_type, "or-list"))
     {
@@ -2343,35 +2396,33 @@ static ZEBRA_RES rpn_search_APT(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
                                     reg_id, complete_flag, rank_type,
                                     xpath_use,
                                     num_bases, basenames, rset_nmem,
-                                    rset);
+                                    rset, kc);
     }
     else if (!strcmp(search_type, "local"))
     {
         res = rpn_search_APT_local(zh, zapt, termz, attributeSet, stream,
-                                  rank_type, rset_nmem, rset);
+                                  rank_type, rset_nmem, rset, kc);
     }
     else if (!strcmp(search_type, "numeric"))
     {
         res = rpn_search_APT_numeric(zh, zapt, termz, attributeSet, stream,
                                     reg_id, complete_flag, rank_type,
                                     xpath_use,
-                                    num_bases, basenames, rset_nmem, rset);
+                                    num_bases, basenames, rset_nmem,
+                                    rset, kc);
     }
     else
     {
-        zh->errCode = YAZ_BIB1_UNSUPP_STRUCTURE_ATTRIBUTE;
-       return ZEBRA_FAIL;
+       zebra_setError(zh, YAZ_BIB1_UNSUPP_STRUCTURE_ATTRIBUTE, 0);
+       res = ZEBRA_FAIL;
     }
     if (res != ZEBRA_OK)
        return res;
     if (!*rset)
        return ZEBRA_FAIL;
-    *rset = rpn_search_xpath(zh, attributeSet, num_bases, basenames,
-                            stream, rank_type, *rset, 
-                            xpath_len, xpath, rset_nmem);
-    if (!*rset)
-       return ZEBRA_FAIL;
-    return ZEBRA_OK;
+    return rpn_search_xpath(zh, attributeSet, num_bases, basenames,
+                           stream, rank_type, *rset, 
+                           xpath_len, xpath, rset_nmem, rset, kc);
 }
 
 static ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
@@ -2380,7 +2431,8 @@ static ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
                                      Z_SortKeySpecList *sort_sequence,
                                      int num_bases, char **basenames,
                                      RSET **result_sets, int *num_result_sets,
-                                     Z_Operator *parent_op);
+                                     Z_Operator *parent_op,
+                                     struct rset_key_control *kc);
 
 ZEBRA_RES rpn_search_top(ZebraHandle zh, Z_RPNStructure *zs,
                         oid_value attributeSet, 
@@ -2391,25 +2443,32 @@ ZEBRA_RES rpn_search_top(ZebraHandle zh, Z_RPNStructure *zs,
 {
     RSET *result_sets = 0;
     int num_result_sets = 0;
-    ZEBRA_RES res = rpn_search_structure(zh, zs, attributeSet,
-                                        stream, rset_nmem,
-                                        sort_sequence, 
-                                        num_bases, basenames,
-                                        &result_sets, &num_result_sets,
-                                        0 /* no op */);
+    ZEBRA_RES res;
+    struct rset_key_control *kc = zebra_key_control_create(zh);
+
+    res = rpn_search_structure(zh, zs, attributeSet,
+                              stream, rset_nmem,
+                              sort_sequence, 
+                              num_bases, basenames,
+                              &result_sets, &num_result_sets,
+                              0 /* no parent op */,
+                              kc);
     if (res != ZEBRA_OK)
     {
        int i;
        for (i = 0; i<num_result_sets; i++)
            rset_delete(result_sets[i]);
        *result_set = 0;
-       return res;
     }
-    assert(num_result_sets == 1);
-    assert(result_sets);
-    assert(*result_sets);
-    *result_set = *result_sets;
-    return ZEBRA_OK;
+    else
+    {
+       assert(num_result_sets == 1);
+       assert(result_sets);
+       assert(*result_sets);
+       *result_set = *result_sets;
+    }
+    (*kc->dec)(kc);
+    return res;
 }
 
 ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
@@ -2418,7 +2477,8 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
                               Z_SortKeySpecList *sort_sequence,
                               int num_bases, char **basenames,
                               RSET **result_sets, int *num_result_sets,
-                              Z_Operator *parent_op)
+                              Z_Operator *parent_op,
+                              struct rset_key_control *kc)
 {
     *num_result_sets = 0;
     if (zs->which == Z_RPNStructure_complex)
@@ -2435,7 +2495,7 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
                                   sort_sequence,
                                   num_bases, basenames,
                                   &result_sets_l, &num_result_sets_l,
-                                  zop);
+                                  zop, kc);
        if (res != ZEBRA_OK)
        {
            int i;
@@ -2448,7 +2508,7 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
                                   sort_sequence,
                                   num_bases, basenames,
                                   &result_sets_r, &num_result_sets_r,
-                                  zop);
+                                  zop, kc);
        if (res != ZEBRA_OK)
        {
            int i;
@@ -2478,39 +2538,40 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
            switch (zop->which)
            {
            case Z_Operator_and:
-               rset = rsmulti_and_create(rset_nmem, key_it_ctrl,
-                                         key_it_ctrl->scope,
+               rset = rsmulti_and_create(rset_nmem, kc,
+                                         kc->scope,
                                          *num_result_sets, *result_sets);
                break;
            case Z_Operator_or:
-               rset = rsmulti_or_create(rset_nmem, key_it_ctrl,
-                                        key_it_ctrl->scope,
+               rset = rsmulti_or_create(rset_nmem, kc,
+                                        kc->scope, 0, /* termid */
                                         *num_result_sets, *result_sets);
                break;
            case Z_Operator_and_not:
-               rset = rsbool_create_not(rset_nmem, key_it_ctrl,
-                                        key_it_ctrl->scope,
+               rset = rsbool_create_not(rset_nmem, kc,
+                                        kc->scope,
                                         (*result_sets)[0],
                                         (*result_sets)[1]);
                break;
            case Z_Operator_prox:
                if (zop->u.prox->which != Z_ProximityOperator_known)
                {
-                   zh->errCode = YAZ_BIB1_UNSUPP_PROX_UNIT_CODE;
+                   zebra_setError(zh, 
+                                  YAZ_BIB1_UNSUPP_PROX_UNIT_CODE,
+                                  0);
                    return ZEBRA_FAIL;
                }
                if (*zop->u.prox->u.known != Z_ProxUnit_word)
                {
-                   char *val = (char *) nmem_malloc(stream, 16);
-                   zh->errCode = YAZ_BIB1_UNSUPP_PROX_UNIT_CODE;
-                   zh->errString = val;
-                   sprintf(val, "%d", *zop->u.prox->u.known);
+                   zebra_setError_zint(zh,
+                                       YAZ_BIB1_UNSUPP_PROX_UNIT_CODE,
+                                       *zop->u.prox->u.known);
                    return ZEBRA_FAIL;
                }
                else
                {
-                   rset = rsprox_create(rset_nmem, key_it_ctrl,
-                                        key_it_ctrl->scope,
+                   rset = rsprox_create(rset_nmem, kc,
+                                        kc->scope,
                                         *num_result_sets, *result_sets, 
                                         *zop->u.prox->ordered,
                                         (!zop->u.prox->exclusion ? 
@@ -2520,7 +2581,7 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
                }
                break;
            default:
-               zh->errCode = YAZ_BIB1_OPERATOR_UNSUPP;
+               zebra_setError(zh, YAZ_BIB1_OPERATOR_UNSUPP, 0);
                return ZEBRA_FAIL;
            }
            *num_result_sets = 1;
@@ -2539,7 +2600,8 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
             yaz_log(YLOG_DEBUG, "rpn_search_APT");
             res = rpn_search_APT(zh, zs->u.simple->u.attributesPlusTerm,
                                 attributeSet, stream, sort_sequence,
-                                num_bases, basenames, rset_nmem, &rset);
+                                num_bases, basenames, rset_nmem, &rset,
+                                kc);
            if (res != ZEBRA_OK)
                return res;
         }
@@ -2549,16 +2611,16 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
             rset = resultSetRef(zh, zs->u.simple->u.resultSetId);
             if (!rset)
             {
-                zh->errCode = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
-                zh->errString =
-                    nmem_strdup(stream, zs->u.simple->u.resultSetId);
+               zebra_setError(zh, 
+                              YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
+                              zs->u.simple->u.resultSetId);
                return ZEBRA_FAIL;
             }
            rset_dup(rset);
         }
         else
         {
-            zh->errCode = YAZ_BIB1_UNSUPP_SEARCH;
+           zebra_setError(zh, YAZ_BIB1_UNSUPP_SEARCH, 0);
             return ZEBRA_FAIL;
         }
        *num_result_sets = 1;
@@ -2568,7 +2630,7 @@ ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
     }
     else
     {
-        zh->errCode = YAZ_BIB1_UNSUPP_SEARCH;
+       zebra_setError(zh, YAZ_BIB1_UNSUPP_SEARCH, 0);
         return ZEBRA_FAIL;
     }
     return ZEBRA_OK;
@@ -2598,6 +2660,7 @@ static int scan_handle (char *name, const char *info, int pos, void *client)
        idx = scan_info->after - pos + scan_info->before;
     else
         idx = - pos - 1;
+
     if (idx < 0)
        return 0;
     scan_info->list[idx].term = (char *)
@@ -2608,13 +2671,13 @@ static int scan_handle (char *name, const char *info, int pos, void *client)
     return 0;
 }
 
-static void scan_term_untrans (ZebraHandle zh, NMEM stream, int reg_type,
-                               char **dst, const char *src)
+void zebra_term_untrans_iconv(ZebraHandle zh, NMEM stream, int reg_type,
+                             char **dst, const char *src)
 {
     char term_src[IT_MAX_WORD];
     char term_dst[IT_MAX_WORD];
     
-    term_untrans (zh, reg_type, term_src, src);
+    zebra_term_untrans (zh, reg_type, term_src, src);
 
     if (zh->iconv_from_utf8 != 0)
     {
@@ -2640,28 +2703,29 @@ static void scan_term_untrans (ZebraHandle zh, NMEM stream, int reg_type,
         *dst = nmem_strdup(stream, term_src);
 }
 
-static void count_set (RSET r, int *count)
+static void count_set(ZebraHandle zh, RSET rset, zint *count)
 {
     zint psysno = 0;
-    int kno = 0;
     struct it_key key;
     RSFD rfd;
 
     yaz_log(YLOG_DEBUG, "count_set");
 
+    rset->hits_limit = zh->approx_limit;
+
     *count = 0;
-    rfd = rset_open (r, RSETF_READ);
-    while (rset_read (rfd, &key,0 /* never mind terms */))
+    rfd = rset_open(rset, RSETF_READ);
+    while (rset_read(rfd, &key,0 /* never mind terms */))
     {
         if (key.mem[0] != psysno)
         {
             psysno = key.mem[0];
-            (*count)++;
+           if (rfd->counted_items >= rset->hits_limit)
+               break;
         }
-        kno++;
     }
     rset_close (rfd);
-    yaz_log(YLOG_DEBUG, "%d keys, %d records", kno, *count);
+    *count = rset->hits_count;
 }
 
 ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
@@ -2695,6 +2759,7 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
     int complete_flag;
     int sort_flag;
     NMEM rset_nmem = NULL; 
+    struct rset_key_control *kc = 0;
 
     *list = 0;
     *is_partial = 0;
@@ -2738,7 +2803,7 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
                        rank_type, &complete_flag, &sort_flag))
     {
         *num_entries = 0;
-        zh->errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_TYPE;
+       zebra_setError(zh, YAZ_BIB1_UNSUPP_ATTRIBUTE_TYPE, 0);
         return ZEBRA_FAIL;
     }
     yaz_log(YLOG_DEBUG, "use_value = %d", use_value);
@@ -2753,14 +2818,14 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
 
        if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
        {
-           zh->errString = basenames[base_no];
-           zh->errCode = YAZ_BIB1_DATABASE_UNAVAILABLE;
+           zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
+                          basenames[base_no]);
            *num_entries = 0;
            return ZEBRA_FAIL;
        }
 
        if (use_string &&
-           (ord = zebraExplain_lookup_attr_str(zh->reg->zei,
+           (ord = zebraExplain_lookup_attr_str(zh->reg->zei, reg_id,
                                                use_string)) >= 0)
        {
            /* we have a match for a raw string attribute */
@@ -2781,16 +2846,16 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
                {
                    errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
                     if (use_string)
-                        errString = odr_strdup(stream, use_string);
+                       zebra_setError(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
+                                      use_string);
                     else
-                   {
-                       char val_str[32];
-                       sprintf(val_str, "%d", use_value);
-                        errString = odr_strdup(stream, val_str);
-                   }
+                       zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
+                                           use_value);
                }   
                else
-                   errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
+               {
+                   zebra_setError(zh, YAZ_BIB1_UNSUPP_ATTRIBUTE_SET, 0);
+               }
                continue;
            }
        }
@@ -2798,7 +2863,7 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
        for (local_attr = attp.local_attributes; local_attr && ord_no < 32;
             local_attr = local_attr->next)
        {
-           ord = zebraExplain_lookup_attr_su(zh->reg->zei,
+           ord = zebraExplain_lookup_attr_su(zh->reg->zei, reg_id,
                                              attp.attset_ordinal,
                                              local_attr->local);
            if (ord > 0)
@@ -2807,8 +2872,7 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
     }
     if (!bases_ok && errCode)
     {
-        zh->errCode = errCode;
-        zh->errString = errString;
+       zebra_setError(zh, errCode, errString);
         *num_entries = 0;
        return ZEBRA_FAIL;
     }
@@ -2818,19 +2882,17 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
         return ZEBRA_OK;
     }
     /* prepare dictionary scanning */
-    if (pos < 1 || pos > num)
-    {
-       zh->errCode = YAZ_BIB1_SCAN_UNSUPP_VALUE_OF_POSITION_IN_RESPONSE;
-       *num_entries = 0;
-       return ZEBRA_FAIL;
-    }
     if (num < 1)
     {
        *num_entries = 0;
        return ZEBRA_OK;
     }
     before = pos-1;
+    if (before < 0)
+       before = 0;
     after = 1+num-pos;
+    if (after < 0)
+       after = 0;
     yaz_log(YLOG_DEBUG, "rpn_scan pos=%d num=%d before=%d "
            "after=%d before+after=%d",
            pos, num, before, after, before+after);
@@ -2855,7 +2917,6 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
             scan_info->list[j].term = NULL;
 
         prefix_len += key_SU_encode (ords[i], termz + prefix_len);
-        termz[prefix_len++] = reg_id;
         termz[prefix_len] = 0;
         strcpy(scan_info->prefix, termz);
 
@@ -2869,6 +2930,7 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
         odr_malloc(stream, (before+after)*sizeof(*glist));
 
     rset_nmem = nmem_create();
+    kc = zebra_key_control_create(zh);
 
     /* consider terms after main term */
     for (i = 0; i < ord_no; i++)
@@ -2880,8 +2942,10 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
         int j, j0 = -1;
         const char *mterm = NULL;
         const char *tst;
-        RSET rset;
-        
+        RSET rset = 0;
+       int lo = i + pos-1; /* offset in result list */
+
+       /* find: j0 is the first of the minimal values */
         for (j = 0; j < ord_no; j++)
         {
             if (ptr[j] < before+after && ptr[j] >= 0 &&
@@ -2893,50 +2957,79 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
             }
         }
         if (j0 == -1)
-            break;
-        scan_term_untrans(zh, stream->mem, reg_id,
-                         &glist[i+before].term, mterm);
-        rset = rset_trunc(zh, &scan_info_array[j0].list[ptr[j0]].isam_p, 1,
-                         glist[i+before].term, strlen(glist[i+before].term),
-                         NULL, 0, zapt->term->which, rset_nmem, 
-                         key_it_ctrl,key_it_ctrl->scope);
-        ptr[j0]++;
+            break;  /* no value found, stop */
+
+       /* get result set for first one , but only if it's within bounds */
+       if (lo >= 0)
+       {
+           /* get result set for first term */
+           zebra_term_untrans_iconv(zh, stream->mem, reg_id,
+                                    &glist[lo].term, mterm);
+           rset = rset_trunc(zh, &scan_info_array[j0].list[ptr[j0]].isam_p, 1,
+                             glist[lo].term, strlen(glist[lo].term),
+                             NULL, 0, zapt->term->which, rset_nmem, 
+                             kc, kc->scope, 0, reg_id, 0 /* hits_limit */,
+                             0 /* term_ref_id_str */);
+       }
+       ptr[j0]++; /* move index for this set .. */
+       /* get result set for remaining scan terms */
         for (j = j0+1; j<ord_no; j++)
         {
             if (ptr[j] < before+after && ptr[j] >= 0 &&
                 (tst = scan_info_array[j].list[ptr[j]].term) &&
                 !strcmp (tst, mterm))
             {
-                RSET rsets[2];
-               
-               rsets[0] = rset;
-                rsets[1] =
-                   rset_trunc(zh, &scan_info_array[j].list[ptr[j]].isam_p, 1,
-                              glist[i+before].term,
-                              strlen(glist[i+before].term), NULL, 0,
-                              zapt->term->which,rset_nmem,
-                              key_it_ctrl, key_it_ctrl->scope);
-                rset = rsmulti_or_create(rset_nmem, key_it_ctrl,
-                                        2, key_it_ctrl->scope, rsets);
+               if (lo >= 0)
+               {
+                   RSET rsets[2];
+                   
+                   rsets[0] = rset;
+                   rsets[1] =
+                       rset_trunc(
+                           zh, &scan_info_array[j].list[ptr[j]].isam_p, 1,
+                           glist[lo].term,
+                           strlen(glist[lo].term), NULL, 0,
+                           zapt->term->which,rset_nmem,
+                           kc, kc->scope, 0, reg_id, 0 /* hits_limit */,
+                           0 /* term_ref_id_str */ );
+                   rset = rsmulti_or_create(rset_nmem, kc,
+                                            kc->scope, 0 /* termid */,
+                                            2, rsets);
+               }
                 ptr[j]++;
             }
         }
-        if (limit_set)
+       if (lo >= 0)
        {
-           RSET rsets[2];
-           rsets[0] = rset;
-           rsets[1] = rset_dup(limit_set);
-           
-           rset = rsmulti_and_create(rset_nmem, key_it_ctrl,
-                                     key_it_ctrl->scope, 2, rsets);
+           zint count;
+           /* merge with limit_set if given */
+           if (limit_set)
+           {
+               RSET rsets[2];
+               rsets[0] = rset;
+               rsets[1] = rset_dup(limit_set);
+               
+               rset = rsmulti_and_create(rset_nmem, kc,
+                                         kc->scope,
+                                         2, rsets);
+           }
+           /* count it */
+           count_set(zh, rset, &count);
+           glist[lo].occurrences = count;
+           rset_delete(rset);
        }
-       count_set(rset, &glist[i+before].occurrences);
-       rset_delete(rset);
     }
     if (i < after)
     {
        *num_entries -= (after-i);
        *is_partial = 1;
+       if (*num_entries < 0)
+       {
+           (*kc->dec)(kc);
+           nmem_destroy(rset_nmem);
+           *num_entries = 0;
+           return ZEBRA_OK;
+       }
     }
     /* consider terms before main term */
     for (i = 0; i<ord_no; i++)
@@ -2948,6 +3041,8 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
        const char *mterm = NULL;
        const char *tst;
        RSET rset;
+       int lo = before-1-i; /* offset in result list */
+       zint count;
        
        for (j = 0; j <ord_no; j++)
        {
@@ -2962,14 +3057,15 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
        if (j0 == -1)
            break;
        
-       scan_term_untrans (zh, stream->mem, reg_id,
-                          &glist[before-1-i].term, mterm);
+       zebra_term_untrans_iconv(zh, stream->mem, reg_id,
+                                &glist[lo].term, mterm);
        
        rset = rset_trunc
            (zh, &scan_info_array[j0].list[before-1-ptr[j0]].isam_p, 1,
-            glist[before-1-i].term, strlen(glist[before-1-i].term),
-            NULL, 0, zapt->term->which,rset_nmem,
-            key_it_ctrl,key_it_ctrl->scope);
+            glist[lo].term, strlen(glist[lo].term),
+            NULL, 0, zapt->term->which, rset_nmem,
+            kc, kc->scope, 0, reg_id, 0 /* hits_limit */,
+            0 /* term_ref_id_str */);
        
        ptr[j0]++;
        
@@ -2985,12 +3081,13 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
                rsets[1] = rset_trunc(
                    zh,
                    &scan_info_array[j].list[before-1-ptr[j]].isam_p, 1,
-                   glist[before-1-i].term,
-                   strlen(glist[before-1-i].term), NULL, 0,
+                   glist[lo].term,
+                   strlen(glist[lo].term), NULL, 0,
                    zapt->term->which, rset_nmem,
-                   key_it_ctrl, key_it_ctrl->scope);
-               rset = rsmulti_or_create(rset_nmem, key_it_ctrl,
-                                        2, key_it_ctrl->scope, rsets);
+                   kc, kc->scope, 0, reg_id, 0 /* hits_limit */,
+                   0 /* term_ref_id_str */);
+               rset = rsmulti_or_create(rset_nmem, kc,
+                                        kc->scope, 0 /* termid */, 2, rsets);
                
                ptr[j]++;
            }
@@ -3001,21 +3098,28 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
            rsets[0] = rset;
            rsets[1] = rset_dup(limit_set);
            
-           rset = rsmulti_and_create(rset_nmem, key_it_ctrl,
-                                     key_it_ctrl->scope, 2, rsets);
+           rset = rsmulti_and_create(rset_nmem, kc,
+                                     kc->scope, 2, rsets);
        }
-       count_set (rset, &glist[before-1-i].occurrences);
+       count_set(zh, rset, &count);
+       glist[lo].occurrences = count;
        rset_delete (rset);
     }
+    (*kc->dec)(kc);
+    nmem_destroy(rset_nmem);
     i = before-i;
     if (i)
     {
         *is_partial = 1;
         *position -= i;
         *num_entries -= i;
+       if (*num_entries <= 0)
+       {
+           *num_entries = 0;
+           return ZEBRA_OK;
+       }
     }
     
-    nmem_destroy(rset_nmem);
     *list = glist + i;               /* list is set to first 'real' entry */
     
     yaz_log(YLOG_DEBUG, "position = %d, num_entries = %d",
@@ -3023,3 +3127,11 @@ ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
     return ZEBRA_OK;
 }
 
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+