1 /* $Id: zrpn.c,v 1.195 2005-06-06 21:31:08 adam Exp $
2 Copyright (C) 1995-2005
5 This file is part of the Zebra server.
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
32 #include <yaz/diagbib1.h>
34 #include <zebra_xpath.h>
39 struct rpn_char_map_info
50 Z_AttributesPlusTerm *zapt;
53 static struct ord_list *ord_list_create(NMEM nmem)
58 static struct ord_list *ord_list_append(NMEM nmem, struct ord_list *list,
61 struct ord_list *n = nmem_malloc(nmem, sizeof(*n));
67 static int log_level_set = 0;
68 static int log_level_rpn = 0;
70 static const char **rpn_char_map_handler(void *vp, const char **from, int len)
72 struct rpn_char_map_info *p = (struct rpn_char_map_info *) vp;
73 const char **out = zebra_maps_input(p->zm, p->reg_type, from, len, 0);
77 const char *outp = *out;
78 yaz_log(YLOG_LOG, "---");
81 yaz_log(YLOG_LOG, "%02X", *outp);
89 static void rpn_char_map_prepare(struct zebra_register *reg, int reg_type,
90 struct rpn_char_map_info *map_info)
92 map_info->zm = reg->zebra_maps;
93 map_info->reg_type = reg_type;
94 dict_grep_cmap(reg->dict, map_info, rpn_char_map_handler);
97 static int attr_find_ex(AttrType *src, oid_value *attributeSetP,
98 const char **string_value)
102 num_attributes = src->zapt->attributes->num_attributes;
103 while (src->major < num_attributes)
105 Z_AttributeElement *element;
107 element = src->zapt->attributes->attributes[src->major];
108 if (src->type == *element->attributeType)
110 switch (element->which)
112 case Z_AttributeValue_numeric:
114 if (element->attributeSet && attributeSetP)
118 attrset = oid_getentbyoid(element->attributeSet);
119 *attributeSetP = attrset->value;
121 return *element->value.numeric;
123 case Z_AttributeValue_complex:
124 if (src->minor >= element->value.complex->num_list)
126 if (element->attributeSet && attributeSetP)
130 attrset = oid_getentbyoid(element->attributeSet);
131 *attributeSetP = attrset->value;
133 if (element->value.complex->list[src->minor]->which ==
134 Z_StringOrNumeric_numeric)
138 *element->value.complex->list[src->minor-1]->u.numeric;
140 else if (element->value.complex->list[src->minor]->which ==
141 Z_StringOrNumeric_string)
147 element->value.complex->list[src->minor-1]->u.string;
161 static int attr_find(AttrType *src, oid_value *attributeSetP)
163 return attr_find_ex(src, attributeSetP, 0);
166 static void attr_init(AttrType *src, Z_AttributesPlusTerm *zapt,
189 void zebra_term_untrans(ZebraHandle zh, int reg_type,
190 char *dst, const char *src)
195 const char *cp = zebra_maps_output(zh->reg->zebra_maps,
197 if (!cp && len < IT_MAX_WORD-1)
200 while (*cp && len < IT_MAX_WORD-1)
206 static void add_isam_p(const char *name, const char *info,
211 log_level_rpn = yaz_log_module_level("rpn");
214 if (p->isam_p_indx == p->isam_p_size)
216 ISAM_P *new_isam_p_buf;
220 p->isam_p_size = 2*p->isam_p_size + 100;
221 new_isam_p_buf = (ISAM_P *) xmalloc(sizeof(*new_isam_p_buf) *
225 memcpy(new_isam_p_buf, p->isam_p_buf,
226 p->isam_p_indx * sizeof(*p->isam_p_buf));
227 xfree(p->isam_p_buf);
229 p->isam_p_buf = new_isam_p_buf;
232 new_term_no = (int *) xmalloc(sizeof(*new_term_no) * p->isam_p_size);
235 memcpy(new_term_no, p->isam_p_buf,
236 p->isam_p_indx * sizeof(*p->term_no));
239 p->term_no = new_term_no;
242 assert(*info == sizeof(*p->isam_p_buf));
243 memcpy(p->isam_p_buf + p->isam_p_indx, info+1, sizeof(*p->isam_p_buf));
250 char term_tmp[IT_MAX_WORD];
252 int len = key_SU_decode (&su_code, name);
254 zebra_term_untrans (p->zh, p->reg_type, term_tmp, name+len+1);
255 yaz_log(log_level_rpn, "grep: %d %c %s", su_code, name[len], term_tmp);
256 zebraExplain_lookup_ord (p->zh->reg->zei,
257 su_code, &db, &set, &use);
258 yaz_log(log_level_rpn, "grep: set=%d use=%d db=%s", set, use, db);
260 resultSetAddTerm(p->zh, p->termset, name[len], db,
267 static int grep_handle(char *name, const char *info, void *p)
269 add_isam_p(name, info, (struct grep_info *) p);
273 static int term_pre(ZebraMaps zebra_maps, int reg_type, const char **src,
274 const char *ct1, const char *ct2, int first)
276 const char *s1, *s0 = *src;
279 /* skip white space */
282 if (ct1 && strchr(ct1, *s0))
284 if (ct2 && strchr(ct2, *s0))
287 map = zebra_maps_input(zebra_maps, reg_type, &s1, strlen(s1), first);
288 if (**map != *CHR_SPACE)
297 static void esc_str(char *out_buf, int out_size,
298 const char *in_buf, int in_size)
304 assert(out_size > 20);
306 for (k = 0; k<in_size; k++)
308 int c = in_buf[k] & 0xff;
310 if (c < 32 || c > 126)
314 sprintf(out_buf +strlen(out_buf), "%02X:%c ", c, pc);
315 if (strlen(out_buf) > out_size-20)
317 strcat(out_buf, "..");
323 #define REGEX_CHARS " []()|.*+?!"
325 /* term_100: handle term, where trunc = none(no operators at all) */
326 static int term_100(ZebraMaps zebra_maps, int reg_type,
327 const char **src, char *dst, int space_split,
335 const char *space_start = 0;
336 const char *space_end = 0;
338 if (!term_pre(zebra_maps, reg_type, src, NULL, NULL, !space_split))
345 map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0),
349 if (**map == *CHR_SPACE)
352 else /* complete subfield only. */
354 if (**map == *CHR_SPACE)
355 { /* save space mapping for later .. */
360 else if (space_start)
361 { /* reload last space */
362 while (space_start < space_end)
364 if (strchr(REGEX_CHARS, *space_start))
366 dst_term[j++] = *space_start;
367 dst[i++] = *space_start++;
370 space_start = space_end = 0;
373 /* add non-space char */
374 memcpy(dst_term+j, s1, s0 - s1);
380 if (strchr(REGEX_CHARS, *s1))
388 esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
390 strcpy(dst + i, map[0]);
400 /* term_101: handle term, where trunc = Process # */
401 static int term_101(ZebraMaps zebra_maps, int reg_type,
402 const char **src, char *dst, int space_split,
410 if (!term_pre(zebra_maps, reg_type, src, "#", "#", !space_split))
419 dst_term[j++] = *s0++;
425 map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0),
427 if (space_split && **map == *CHR_SPACE)
430 /* add non-space char */
431 memcpy(dst_term+j, s1, s0 - s1);
437 if (strchr(REGEX_CHARS, *s1))
445 esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
447 strcpy(dst + i, map[0]);
453 dst_term[j++] = '\0';
458 /* term_103: handle term, where trunc = re-2 (regular expressions) */
459 static int term_103(ZebraMaps zebra_maps, int reg_type, const char **src,
460 char *dst, int *errors, int space_split,
468 if (!term_pre(zebra_maps, reg_type, src, "^\\()[].*+?|", "(", !space_split))
471 if (errors && *s0 == '+' && s0[1] && s0[2] == '+' && s0[3] &&
472 isdigit(((const unsigned char *)s0)[1]))
474 *errors = s0[1] - '0';
481 if (strchr("^\\()[].*+?|-", *s0))
490 map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0),
492 if (space_split && **map == *CHR_SPACE)
495 /* add non-space char */
496 memcpy(dst_term+j, s1, s0 - s1);
502 if (strchr(REGEX_CHARS, *s1))
510 esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
512 strcpy(dst + i, map[0]);
524 /* term_103: handle term, where trunc = re-1 (regular expressions) */
525 static int term_102(ZebraMaps zebra_maps, int reg_type, const char **src,
526 char *dst, int space_split, char *dst_term)
528 return term_103(zebra_maps, reg_type, src, dst, NULL, space_split,
533 /* term_104: handle term, where trunc = Process # and ! */
534 static int term_104(ZebraMaps zebra_maps, int reg_type,
535 const char **src, char *dst, int space_split,
543 if (!term_pre(zebra_maps, reg_type, src, "?*#", "?*#", !space_split))
550 dst_term[j++] = *s0++;
551 if (*s0 >= '0' && *s0 <= '9')
554 while (*s0 >= '0' && *s0 <= '9')
556 limit = limit * 10 + (*s0 - '0');
557 dst_term[j++] = *s0++;
577 dst_term[j++] = *s0++;
582 dst_term[j++] = *s0++;
588 map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0),
590 if (space_split && **map == *CHR_SPACE)
593 /* add non-space char */
594 memcpy(dst_term+j, s1, s0 - s1);
600 if (strchr(REGEX_CHARS, *s1))
608 esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
610 strcpy(dst + i, map[0]);
616 dst_term[j++] = '\0';
621 /* term_105/106: handle term, where trunc = Process * and ! and right trunc */
622 static int term_105(ZebraMaps zebra_maps, int reg_type,
623 const char **src, char *dst, int space_split,
624 char *dst_term, int right_truncate)
631 if (!term_pre(zebra_maps, reg_type, src, "*!", "*!", !space_split))
640 dst_term[j++] = *s0++;
645 dst_term[j++] = *s0++;
651 map = zebra_maps_search(zebra_maps, reg_type, &s0, strlen(s0),
653 if (space_split && **map == *CHR_SPACE)
656 /* add non-space char */
657 memcpy(dst_term+j, s1, s0 - s1);
663 if (strchr(REGEX_CHARS, *s1))
671 esc_str(tmpbuf, sizeof(tmpbuf), map[0], strlen(map[0]));
673 strcpy(dst + i, map[0]);
685 dst_term[j++] = '\0';
691 /* gen_regular_rel - generate regular expression from relation
692 * val: border value (inclusive)
693 * islt: 1 if <=; 0 if >=.
695 static void gen_regular_rel(char *dst, int val, int islt)
702 yaz_log(YLOG_DEBUG, "gen_regular_rel. val=%d, islt=%d", val, islt);
706 strcpy(dst, "(-[0-9]+|(");
714 strcpy(dst, "([0-9]+|-(");
726 sprintf(numstr, "%d", val);
727 for (w = strlen(numstr); --w >= 0; pos++)
746 strcpy(dst + dst_p, numstr);
747 dst_p = strlen(dst) - pos - 1;
775 for (i = 0; i<pos; i++)
788 /* match everything less than 10^(pos-1) */
790 for (i = 1; i<pos; i++)
791 strcat(dst, "[0-9]?");
795 /* match everything greater than 10^pos */
796 for (i = 0; i <= pos; i++)
797 strcat(dst, "[0-9]");
798 strcat(dst, "[0-9]*");
803 void string_rel_add_char(char **term_p, const char *src, int *indx)
805 if (src[*indx] == '\\')
806 *(*term_p)++ = src[(*indx)++];
807 *(*term_p)++ = src[(*indx)++];
811 * > abc ([b-].*|a[c-].*|ab[d-].*|abc.+)
812 * ([^-a].*|a[^-b].*ab[^-c].*|abc.+)
813 * >= abc ([b-].*|a[c-].*|ab[c-].*)
814 * ([^-a].*|a[^-b].*|ab[c-].*)
815 * < abc ([-0].*|a[-a].*|ab[-b].*)
816 * ([^a-].*|a[^b-].*|ab[^c-].*)
817 * <= abc ([-0].*|a[-a].*|ab[-b].*|abc)
818 * ([^a-].*|a[^b-].*|ab[^c-].*|abc)
820 static int string_relation(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
821 const char **term_sub, char *term_dict,
822 oid_value attributeSet,
823 int reg_type, int space_split, char *term_dst,
829 char *term_tmp = term_dict + strlen(term_dict);
830 char term_component[2*IT_MAX_WORD+20];
832 attr_init(&relation, zapt, 2);
833 relation_value = attr_find(&relation, NULL);
836 yaz_log(YLOG_DEBUG, "string relation value=%d", relation_value);
837 switch (relation_value)
840 if (!term_100(zh->reg->zebra_maps, reg_type,
841 term_sub, term_component,
842 space_split, term_dst))
844 yaz_log(log_level_rpn, "Relation <");
847 for (i = 0; term_component[i]; )
854 string_rel_add_char(&term_tmp, term_component, &j);
859 string_rel_add_char(&term_tmp, term_component, &i);
866 if ((term_tmp - term_dict) > IT_MAX_WORD)
873 if (!term_100(zh->reg->zebra_maps, reg_type,
874 term_sub, term_component,
875 space_split, term_dst))
877 yaz_log(log_level_rpn, "Relation <=");
880 for (i = 0; term_component[i]; )
885 string_rel_add_char(&term_tmp, term_component, &j);
889 string_rel_add_char(&term_tmp, term_component, &i);
898 if ((term_tmp - term_dict) > IT_MAX_WORD)
901 for (i = 0; term_component[i]; )
902 string_rel_add_char(&term_tmp, term_component, &i);
907 if (!term_100 (zh->reg->zebra_maps, reg_type,
908 term_sub, term_component, space_split, term_dst))
910 yaz_log(log_level_rpn, "Relation >");
913 for (i = 0; term_component[i];)
918 string_rel_add_char(&term_tmp, term_component, &j);
923 string_rel_add_char(&term_tmp, term_component, &i);
931 if ((term_tmp - term_dict) > IT_MAX_WORD)
934 for (i = 0; term_component[i];)
935 string_rel_add_char(&term_tmp, term_component, &i);
942 if (!term_100(zh->reg->zebra_maps, reg_type, term_sub,
943 term_component, space_split, term_dst))
945 yaz_log(log_level_rpn, "Relation >=");
948 for (i = 0; term_component[i];)
955 string_rel_add_char(&term_tmp, term_component, &j);
958 if (term_component[i+1])
962 string_rel_add_char(&term_tmp, term_component, &i);
966 string_rel_add_char(&term_tmp, term_component, &i);
973 if ((term_tmp - term_dict) > IT_MAX_WORD)
982 yaz_log(log_level_rpn, "Relation =");
983 if (!term_100(zh->reg->zebra_maps, reg_type, term_sub,
984 term_component, space_split, term_dst))
986 strcat(term_tmp, "(");
987 strcat(term_tmp, term_component);
988 strcat(term_tmp, ")");
991 *error_code = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE;
997 static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
998 const char **term_sub,
999 oid_value attributeSet, NMEM stream,
1000 struct grep_info *grep_info,
1001 int reg_type, int complete_flag,
1002 int num_bases, char **basenames,
1003 char *term_dst, int xpath_use,
1004 struct ord_list **ol);
1006 static ZEBRA_RES term_trunc(ZebraHandle zh,
1007 Z_AttributesPlusTerm *zapt,
1008 const char **term_sub,
1009 oid_value attributeSet, NMEM stream,
1010 struct grep_info *grep_info,
1011 int reg_type, int complete_flag,
1012 int num_bases, char **basenames,
1014 const char *rank_type, int xpath_use,
1017 struct rset_key_control *kc)
1020 struct ord_list *ol;
1022 grep_info->isam_p_indx = 0;
1023 res = string_term(zh, zapt, term_sub, attributeSet, stream, grep_info,
1024 reg_type, complete_flag, num_bases, basenames,
1025 term_dst, xpath_use, &ol);
1026 if (res != ZEBRA_OK)
1028 if (!*term_sub) /* no more terms ? */
1030 yaz_log(log_level_rpn, "term: %s", term_dst);
1031 *rset = rset_trunc(zh, grep_info->isam_p_buf,
1032 grep_info->isam_p_indx, term_dst,
1033 strlen(term_dst), rank_type, 1 /* preserve pos */,
1034 zapt->term->which, rset_nmem,
1041 static char *nmem_strdup_i(NMEM nmem, int v)
1044 sprintf(val_str, "%d", v);
1045 return nmem_strdup(nmem, val_str);
1048 static ZEBRA_RES string_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1049 const char **term_sub,
1050 oid_value attributeSet, NMEM stream,
1051 struct grep_info *grep_info,
1052 int reg_type, int complete_flag,
1053 int num_bases, char **basenames,
1054 char *term_dst, int xpath_use,
1055 struct ord_list **ol)
1057 char term_dict[2*IT_MAX_WORD+4000];
1059 AttrType truncation;
1060 int truncation_value;
1063 const char *use_string = 0;
1064 oid_value curAttributeSet = attributeSet;
1066 struct rpn_char_map_info rcmi;
1067 int space_split = complete_flag ? 0 : 1;
1069 int bases_ok = 0; /* no of databases with OK attribute */
1070 int errCode = 0; /* err code (if any is not OK) */
1071 char *errString = 0; /* addinfo */
1074 *ol = ord_list_create(stream);
1076 rpn_char_map_prepare (zh->reg, reg_type, &rcmi);
1077 attr_init(&use, zapt, 1);
1078 use_value = attr_find_ex(&use, &curAttributeSet, &use_string);
1079 yaz_log(log_level_rpn, "string_term, use value %d", use_value);
1080 attr_init(&truncation, zapt, 5);
1081 truncation_value = attr_find(&truncation, NULL);
1082 yaz_log(log_level_rpn, "truncation value %d", truncation_value);
1084 if (use_value == -1) /* no attribute - assumy "any" */
1086 for (base_no = 0; base_no < num_bases; base_no++)
1090 int regex_range = 0;
1093 data1_local_attribute id_xpath_attr;
1094 data1_local_attribute *local_attr;
1095 int max_pos, prefix_len = 0;
1100 if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
1102 zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
1103 basenames[base_no]);
1106 if (xpath_use > 0 && use_value == -2)
1108 /* xpath mode and we have a string attribute */
1109 attp.local_attributes = &id_xpath_attr;
1110 attp.attset_ordinal = VAL_IDXPATH;
1111 id_xpath_attr.next = 0;
1113 use_value = xpath_use; /* xpath_use as use-attribute now */
1114 id_xpath_attr.local = use_value;
1116 else if (curAttributeSet == VAL_IDXPATH && use_value >= 0)
1118 /* X-Path attribute, use numeric value directly */
1119 attp.local_attributes = &id_xpath_attr;
1120 attp.attset_ordinal = VAL_IDXPATH;
1121 id_xpath_attr.next = 0;
1122 id_xpath_attr.local = use_value;
1124 else if (use_string &&
1125 (ord = zebraExplain_lookup_attr_str(zh->reg->zei,
1128 /* we have a match for a raw string attribute */
1133 term_dict[prefix_len++] = '|';
1135 term_dict[prefix_len++] = '(';
1137 ord_len = key_SU_encode (ord, ord_buf);
1138 for (i = 0; i<ord_len; i++)
1140 term_dict[prefix_len++] = 1;
1141 term_dict[prefix_len++] = ord_buf[i];
1143 attp.local_attributes = 0; /* no more attributes */
1144 *ol = ord_list_append(stream, *ol, ord);
1148 /* lookup in the .att files . Allow string as well */
1149 if ((r = att_getentbyatt (zh, &attp, curAttributeSet, use_value,
1152 yaz_log(YLOG_DEBUG, "att_getentbyatt fail. set=%d use=%d r=%d",
1153 curAttributeSet, use_value, r);
1156 /* set was found, but value wasn't defined */
1157 errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
1159 errString = nmem_strdup(stream, use_string);
1161 errString = nmem_strdup_i (stream, use_value);
1166 struct oident oident;
1168 oident.proto = PROTO_Z3950;
1169 oident.oclass = CLASS_ATTSET;
1170 oident.value = curAttributeSet;
1171 oid_ent_to_oid (&oident, oid);
1173 errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
1174 errString = nmem_strdup(stream, oident.desc);
1179 for (local_attr = attp.local_attributes; local_attr;
1180 local_attr = local_attr->next)
1185 ord = zebraExplain_lookup_attr_su(zh->reg->zei,
1186 attp.attset_ordinal,
1190 *ol = ord_list_append(stream, *ol, ord);
1192 term_dict[prefix_len++] = '|';
1194 term_dict[prefix_len++] = '(';
1196 ord_len = key_SU_encode (ord, ord_buf);
1197 for (i = 0; i<ord_len; i++)
1199 term_dict[prefix_len++] = 1;
1200 term_dict[prefix_len++] = ord_buf[i];
1207 term_dict[prefix_len++] = ')';
1208 term_dict[prefix_len++] = 1;
1209 term_dict[prefix_len++] = reg_type;
1210 yaz_log(log_level_rpn, "reg_type = %d", term_dict[prefix_len-1]);
1211 term_dict[prefix_len] = '\0';
1213 switch (truncation_value)
1215 case -1: /* not specified */
1216 case 100: /* do not truncate */
1217 if (!string_relation (zh, zapt, &termp, term_dict,
1219 reg_type, space_split, term_dst,
1224 zebra_setError(zh, relation_error, 0);
1231 case 1: /* right truncation */
1232 term_dict[j++] = '(';
1233 if (!term_100(zh->reg->zebra_maps, reg_type,
1234 &termp, term_dict + j, space_split, term_dst))
1239 strcat(term_dict, ".*)");
1241 case 2: /* keft truncation */
1242 term_dict[j++] = '('; term_dict[j++] = '.'; term_dict[j++] = '*';
1243 if (!term_100(zh->reg->zebra_maps, reg_type,
1244 &termp, term_dict + j, space_split, term_dst))
1249 strcat(term_dict, ")");
1251 case 3: /* left&right truncation */
1252 term_dict[j++] = '('; term_dict[j++] = '.'; term_dict[j++] = '*';
1253 if (!term_100(zh->reg->zebra_maps, reg_type,
1254 &termp, term_dict + j, space_split, term_dst))
1259 strcat(term_dict, ".*)");
1261 case 101: /* process # in term */
1262 term_dict[j++] = '(';
1263 if (!term_101(zh->reg->zebra_maps, reg_type,
1264 &termp, term_dict + j, space_split, term_dst))
1269 strcat(term_dict, ")");
1271 case 102: /* Regexp-1 */
1272 term_dict[j++] = '(';
1273 if (!term_102(zh->reg->zebra_maps, reg_type,
1274 &termp, term_dict + j, space_split, term_dst))
1279 strcat(term_dict, ")");
1281 case 103: /* Regexp-2 */
1283 term_dict[j++] = '(';
1285 if (!term_103(zh->reg->zebra_maps, reg_type,
1286 &termp, term_dict + j, ®ex_range,
1287 space_split, term_dst))
1292 strcat(term_dict, ")");
1294 case 104: /* process # and ! in term */
1295 term_dict[j++] = '(';
1296 if (!term_104(zh->reg->zebra_maps, reg_type,
1297 &termp, term_dict + j, space_split, term_dst))
1302 strcat(term_dict, ")");
1304 case 105: /* process * and ! in term */
1305 term_dict[j++] = '(';
1306 if (!term_105(zh->reg->zebra_maps, reg_type,
1307 &termp, term_dict + j, space_split, term_dst, 1))
1312 strcat(term_dict, ")");
1314 case 106: /* process * and ! in term */
1315 term_dict[j++] = '(';
1316 if (!term_105(zh->reg->zebra_maps, reg_type,
1317 &termp, term_dict + j, space_split, term_dst, 0))
1322 strcat(term_dict, ")");
1325 zebra_setError_zint(zh,
1326 YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE,
1333 const char *input = term_dict + prefix_len;
1334 esc_str(buf, sizeof(buf), input, strlen(input));
1338 yaz_log(log_level_rpn, "dict_lookup_grep: %s", term_dict+prefix_len);
1339 r = dict_lookup_grep(zh->reg->dict, term_dict, regex_range,
1340 grep_info, &max_pos, init_pos,
1343 yaz_log(YLOG_WARN, "dict_lookup_grep fail %d", r);
1348 zebra_setError(zh, errCode, errString);
1352 yaz_log(YLOG_DEBUG, "%d positions", grep_info->isam_p_indx);
1357 /* convert APT search term to UTF8 */
1358 static ZEBRA_RES zapt_term_to_utf8(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1362 Z_Term *term = zapt->term;
1364 switch (term->which)
1366 case Z_Term_general:
1367 if (zh->iconv_to_utf8 != 0)
1369 char *inbuf = term->u.general->buf;
1370 size_t inleft = term->u.general->len;
1371 char *outbuf = termz;
1372 size_t outleft = IT_MAX_WORD-1;
1375 ret = yaz_iconv(zh->iconv_to_utf8, &inbuf, &inleft,
1377 if (ret == (size_t)(-1))
1379 ret = yaz_iconv(zh->iconv_to_utf8, 0, 0, 0, 0);
1382 YAZ_BIB1_QUERY_TERM_INCLUDES_CHARS_THAT_DO_NOT_TRANSLATE_INTO_,
1390 sizez = term->u.general->len;
1391 if (sizez > IT_MAX_WORD-1)
1392 sizez = IT_MAX_WORD-1;
1393 memcpy (termz, term->u.general->buf, sizez);
1394 termz[sizez] = '\0';
1397 case Z_Term_characterString:
1398 sizez = strlen(term->u.characterString);
1399 if (sizez > IT_MAX_WORD-1)
1400 sizez = IT_MAX_WORD-1;
1401 memcpy (termz, term->u.characterString, sizez);
1402 termz[sizez] = '\0';
1405 zebra_setError(zh, YAZ_BIB1_UNSUPP_CODED_VALUE_FOR_TERM, 0);
1411 /* convert APT SCAN term to internal cmap */
1412 static ZEBRA_RES trans_scan_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1413 char *termz, int reg_type)
1415 char termz0[IT_MAX_WORD];
1417 if (zapt_term_to_utf8(zh, zapt, termz0) == ZEBRA_FAIL)
1418 return ZEBRA_FAIL; /* error */
1422 const char *cp = (const char *) termz0;
1423 const char *cp_end = cp + strlen(cp);
1426 const char *space_map = NULL;
1429 while ((len = (cp_end - cp)) > 0)
1431 map = zebra_maps_input(zh->reg->zebra_maps, reg_type, &cp, len, 0);
1432 if (**map == *CHR_SPACE)
1437 for (src = space_map; *src; src++)
1440 for (src = *map; *src; src++)
1449 char *normalize_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1450 const char *termz, NMEM stream, unsigned reg_id)
1453 AttrType truncation;
1454 int truncation_value;
1457 attr_init(&truncation, zapt, 5);
1458 truncation_value = attr_find(&truncation, NULL);
1460 switch (truncation_value)
1480 wrbuf = zebra_replace(zh->reg->zebra_maps, reg_id, ex_list,
1481 termz, strlen(termz));
1483 return nmem_strdup(stream, termz);
1486 char *buf = (char*) nmem_malloc(stream, wrbuf_len(wrbuf)+1);
1487 memcpy (buf, wrbuf_buf(wrbuf), wrbuf_len(wrbuf));
1488 buf[wrbuf_len(wrbuf)] = '\0';
1493 static void grep_info_delete(struct grep_info *grep_info)
1496 xfree(grep_info->term_no);
1498 xfree(grep_info->isam_p_buf);
1501 static ZEBRA_RES grep_info_prepare(ZebraHandle zh,
1502 Z_AttributesPlusTerm *zapt,
1503 struct grep_info *grep_info,
1507 int termset_value_numeric;
1508 const char *termset_value_string;
1511 grep_info->term_no = 0;
1513 grep_info->isam_p_size = 0;
1514 grep_info->isam_p_buf = NULL;
1516 grep_info->reg_type = reg_type;
1517 grep_info->termset = 0;
1521 attr_init(&termset, zapt, 8);
1522 termset_value_numeric =
1523 attr_find_ex(&termset, NULL, &termset_value_string);
1524 if (termset_value_numeric != -1)
1527 const char *termset_name = 0;
1528 if (termset_value_numeric != -2)
1531 sprintf(resname, "%d", termset_value_numeric);
1532 termset_name = resname;
1535 termset_name = termset_value_string;
1536 yaz_log(log_level_rpn, "creating termset set %s", termset_name);
1537 grep_info->termset = resultSetAdd(zh, termset_name, 1);
1538 if (!grep_info->termset)
1540 zebra_setError(zh, YAZ_BIB1_ILLEGAL_RESULT_SET_NAME, termset_name);
1548 \brief Create result set(s) for list of terms
1549 \param zh Zebra Handle
1550 \param termz_org term as used in query but converted to UTF-8
1551 \param attributeSet default attribute set
1552 \param stream memory for result
1553 \param reg_type register type ('w', 'p',..)
1554 \param complete_flag whether it's phrases or not
1555 \param rank_type term flags for ranking
1556 \param xpath_use use attribute for X-Path (-1 for no X-path)
1557 \param num_bases number of databases
1558 \param basenames array of databases
1559 \param rset_mem memory for result sets
1560 \param result_sets output result set for each term in list (output)
1561 \param number number of output result sets
1562 \param kc rset key control to be used for created result sets
1564 static ZEBRA_RES term_list_trunc(ZebraHandle zh,
1565 Z_AttributesPlusTerm *zapt,
1566 const char *termz_org,
1567 oid_value attributeSet,
1569 int reg_type, int complete_flag,
1570 const char *rank_type, int xpath_use,
1571 int num_bases, char **basenames,
1573 RSET **result_sets, int *num_result_sets,
1574 struct rset_key_control *kc)
1576 char term_dst[IT_MAX_WORD+1];
1577 struct grep_info grep_info;
1578 char *termz = normalize_term(zh, zapt, termz_org, stream, reg_type);
1579 const char *termp = termz;
1582 *num_result_sets = 0;
1584 if (grep_info_prepare(zh, zapt, &grep_info, reg_type) == ZEBRA_FAIL)
1590 if (alloc_sets == *num_result_sets)
1593 RSET *rnew = (RSET *) nmem_malloc(stream, (alloc_sets+add) *
1596 memcpy(rnew, *result_sets, alloc_sets * sizeof(*rnew));
1597 alloc_sets = alloc_sets + add;
1598 *result_sets = rnew;
1600 res = term_trunc(zh, zapt, &termp, attributeSet,
1602 reg_type, complete_flag,
1603 num_bases, basenames,
1604 term_dst, rank_type,
1605 xpath_use, rset_nmem,
1606 &(*result_sets)[*num_result_sets],
1608 if (res != ZEBRA_OK)
1611 for (i = 0; i < *num_result_sets; i++)
1612 rset_delete((*result_sets)[i]);
1613 grep_info_delete (&grep_info);
1616 if ((*result_sets)[*num_result_sets] == 0)
1618 (*num_result_sets)++;
1620 grep_info_delete(&grep_info);
1624 static ZEBRA_RES rpn_search_APT_phrase(ZebraHandle zh,
1625 Z_AttributesPlusTerm *zapt,
1626 const char *termz_org,
1627 oid_value attributeSet,
1629 int reg_type, int complete_flag,
1630 const char *rank_type, int xpath_use,
1631 int num_bases, char **basenames,
1634 struct rset_key_control *kc)
1636 RSET *result_sets = 0;
1637 int num_result_sets = 0;
1639 term_list_trunc(zh, zapt, termz_org, attributeSet,
1640 stream, reg_type, complete_flag,
1641 rank_type, xpath_use,
1642 num_bases, basenames,
1644 &result_sets, &num_result_sets, kc);
1645 if (res != ZEBRA_OK)
1647 if (num_result_sets == 0)
1648 *rset = rsnull_create (rset_nmem, kc, 0);
1649 else if (num_result_sets == 1)
1650 *rset = result_sets[0];
1652 *rset = rsprox_create(rset_nmem, kc, kc->scope,
1653 num_result_sets, result_sets,
1654 1 /* ordered */, 0 /* exclusion */,
1655 3 /* relation */, 1 /* distance */);
1661 static ZEBRA_RES rpn_search_APT_or_list(ZebraHandle zh,
1662 Z_AttributesPlusTerm *zapt,
1663 const char *termz_org,
1664 oid_value attributeSet,
1666 int reg_type, int complete_flag,
1667 const char *rank_type,
1669 int num_bases, char **basenames,
1672 struct rset_key_control *kc)
1674 RSET *result_sets = 0;
1675 int num_result_sets = 0;
1677 term_list_trunc(zh, zapt, termz_org, attributeSet,
1678 stream, reg_type, complete_flag,
1679 rank_type, xpath_use,
1680 num_bases, basenames,
1682 &result_sets, &num_result_sets, kc);
1683 if (res != ZEBRA_OK)
1685 if (num_result_sets == 0)
1686 *rset = rsnull_create (rset_nmem, kc, 0);
1687 else if (num_result_sets == 1)
1688 *rset = result_sets[0];
1690 *rset = rsmulti_or_create(rset_nmem, kc, kc->scope, 0 /* termid */,
1691 num_result_sets, result_sets);
1697 static ZEBRA_RES rpn_search_APT_and_list(ZebraHandle zh,
1698 Z_AttributesPlusTerm *zapt,
1699 const char *termz_org,
1700 oid_value attributeSet,
1702 int reg_type, int complete_flag,
1703 const char *rank_type,
1705 int num_bases, char **basenames,
1708 struct rset_key_control *kc)
1710 RSET *result_sets = 0;
1711 int num_result_sets = 0;
1713 term_list_trunc(zh, zapt, termz_org, attributeSet,
1714 stream, reg_type, complete_flag,
1715 rank_type, xpath_use,
1716 num_bases, basenames,
1718 &result_sets, &num_result_sets,
1720 if (res != ZEBRA_OK)
1722 if (num_result_sets == 0)
1723 *rset = rsnull_create (rset_nmem, kc, 0);
1724 else if (num_result_sets == 1)
1725 *rset = result_sets[0];
1727 *rset = rsmulti_and_create(rset_nmem, kc, kc->scope,
1728 num_result_sets, result_sets);
1734 static int numeric_relation(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1735 const char **term_sub,
1737 oid_value attributeSet,
1738 struct grep_info *grep_info,
1748 char *term_tmp = term_dict + strlen(term_dict);
1751 attr_init(&relation, zapt, 2);
1752 relation_value = attr_find(&relation, NULL);
1754 yaz_log(log_level_rpn, "numeric relation value=%d", relation_value);
1756 if (!term_100(zh->reg->zebra_maps, reg_type, term_sub, term_tmp, 1,
1759 term_value = atoi (term_tmp);
1760 switch (relation_value)
1763 yaz_log(log_level_rpn, "Relation <");
1764 gen_regular_rel(term_tmp, term_value-1, 1);
1767 yaz_log(log_level_rpn, "Relation <=");
1768 gen_regular_rel(term_tmp, term_value, 1);
1771 yaz_log(log_level_rpn, "Relation >=");
1772 gen_regular_rel(term_tmp, term_value, 0);
1775 yaz_log(log_level_rpn, "Relation >");
1776 gen_regular_rel(term_tmp, term_value+1, 0);
1780 yaz_log(log_level_rpn, "Relation =");
1781 sprintf(term_tmp, "(0*%d)", term_value);
1784 *error_code = YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE;
1787 yaz_log(log_level_rpn, "dict_lookup_grep: %s", term_tmp);
1788 r = dict_lookup_grep(zh->reg->dict, term_dict, 0, grep_info, max_pos,
1791 yaz_log(YLOG_WARN, "dict_lookup_grep fail, rel = gt: %d", r);
1792 yaz_log(log_level_rpn, "%d positions", grep_info->isam_p_indx);
1796 static ZEBRA_RES numeric_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
1797 const char **term_sub,
1798 oid_value attributeSet,
1799 struct grep_info *grep_info,
1800 int reg_type, int complete_flag,
1801 int num_bases, char **basenames,
1802 char *term_dst, int xpath_use, NMEM stream)
1804 char term_dict[2*IT_MAX_WORD+2];
1808 const char *use_string = 0;
1809 oid_value curAttributeSet = attributeSet;
1811 struct rpn_char_map_info rcmi;
1813 int bases_ok = 0; /* no of databases with OK attribute */
1814 int errCode = 0; /* err code (if any is not OK) */
1815 char *errString = 0; /* addinfo */
1817 rpn_char_map_prepare (zh->reg, reg_type, &rcmi);
1818 attr_init(&use, zapt, 1);
1819 use_value = attr_find_ex(&use, &curAttributeSet, &use_string);
1821 if (use_value == -1)
1824 for (base_no = 0; base_no < num_bases; base_no++)
1827 data1_local_attribute id_xpath_attr;
1828 data1_local_attribute *local_attr;
1829 int max_pos, prefix_len = 0;
1830 int relation_error = 0;
1833 if (use_value == -2) /* string attribute (assume IDXPATH/any) */
1835 use_value = xpath_use;
1836 attp.local_attributes = &id_xpath_attr;
1837 attp.attset_ordinal = VAL_IDXPATH;
1838 id_xpath_attr.next = 0;
1839 id_xpath_attr.local = use_value;
1841 else if (curAttributeSet == VAL_IDXPATH)
1843 attp.local_attributes = &id_xpath_attr;
1844 attp.attset_ordinal = VAL_IDXPATH;
1845 id_xpath_attr.next = 0;
1846 id_xpath_attr.local = use_value;
1850 if ((r = att_getentbyatt (zh, &attp, curAttributeSet, use_value,
1853 yaz_log(YLOG_DEBUG, "att_getentbyatt fail. set=%d use=%d r=%d",
1854 curAttributeSet, use_value, r);
1857 errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
1859 errString = nmem_strdup(stream, use_string);
1861 errString = nmem_strdup_i (stream, use_value);
1864 errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
1868 if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
1870 zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
1871 basenames[base_no]);
1874 for (local_attr = attp.local_attributes; local_attr;
1875 local_attr = local_attr->next)
1881 ord = zebraExplain_lookup_attr_su(zh->reg->zei,
1882 attp.attset_ordinal,
1887 term_dict[prefix_len++] = '|';
1889 term_dict[prefix_len++] = '(';
1891 ord_len = key_SU_encode (ord, ord_buf);
1892 for (i = 0; i<ord_len; i++)
1894 term_dict[prefix_len++] = 1;
1895 term_dict[prefix_len++] = ord_buf[i];
1900 zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, use_value);
1904 term_dict[prefix_len++] = ')';
1905 term_dict[prefix_len++] = 1;
1906 term_dict[prefix_len++] = reg_type;
1907 yaz_log(YLOG_DEBUG, "reg_type = %d", term_dict[prefix_len-1]);
1908 term_dict[prefix_len] = '\0';
1909 if (!numeric_relation(zh, zapt, &termp, term_dict,
1910 attributeSet, grep_info, &max_pos, reg_type,
1911 term_dst, &relation_error))
1915 zebra_setError(zh, relation_error, 0);
1924 zebra_setError(zh, errCode, errString);
1928 yaz_log(YLOG_DEBUG, "%d positions", grep_info->isam_p_indx);
1932 static ZEBRA_RES rpn_search_APT_numeric(ZebraHandle zh,
1933 Z_AttributesPlusTerm *zapt,
1935 oid_value attributeSet,
1937 int reg_type, int complete_flag,
1938 const char *rank_type, int xpath_use,
1939 int num_bases, char **basenames,
1942 struct rset_key_control *kc)
1944 char term_dst[IT_MAX_WORD+1];
1945 const char *termp = termz;
1946 RSET *result_sets = 0;
1947 int num_result_sets = 0;
1949 struct grep_info grep_info;
1952 yaz_log(log_level_rpn, "APT_numeric t='%s'", termz);
1953 if (grep_info_prepare(zh, zapt, &grep_info, reg_type) == ZEBRA_FAIL)
1957 if (alloc_sets == num_result_sets)
1960 RSET *rnew = (RSET *) nmem_malloc(stream, (alloc_sets+add) *
1963 memcpy(rnew, result_sets, alloc_sets * sizeof(*rnew));
1964 alloc_sets = alloc_sets + add;
1967 yaz_log(YLOG_DEBUG, "APT_numeric termp=%s", termp);
1968 grep_info.isam_p_indx = 0;
1969 res = numeric_term(zh, zapt, &termp, attributeSet, &grep_info,
1970 reg_type, complete_flag, num_bases, basenames,
1971 term_dst, xpath_use,
1973 if (res == ZEBRA_FAIL || termp == 0)
1975 yaz_log(YLOG_DEBUG, "term: %s", term_dst);
1976 result_sets[num_result_sets] =
1977 rset_trunc(zh, grep_info.isam_p_buf,
1978 grep_info.isam_p_indx, term_dst,
1979 strlen(term_dst), rank_type,
1980 0 /* preserve position */,
1981 zapt->term->which, rset_nmem,
1983 if (!result_sets[num_result_sets])
1987 grep_info_delete(&grep_info);
1991 for (i = 0; i<num_result_sets; i++)
1992 rset_delete(result_sets[i]);
1995 if (num_result_sets == 0)
1996 *rset = rsnull_create(rset_nmem, kc, 0);
1997 if (num_result_sets == 1)
1998 *rset = result_sets[0];
2000 *rset = rsmulti_and_create(rset_nmem, kc, kc->scope,
2001 num_result_sets, result_sets);
2007 static ZEBRA_RES rpn_search_APT_local(ZebraHandle zh,
2008 Z_AttributesPlusTerm *zapt,
2010 oid_value attributeSet,
2012 const char *rank_type, NMEM rset_nmem,
2014 struct rset_key_control *kc)
2019 *rset = rstemp_create(rset_nmem, kc, kc->scope,
2020 res_get (zh->res, "setTmpDir"),0 );
2021 rsfd = rset_open(*rset, RSETF_WRITE);
2029 rset_write (rsfd, &key);
2034 static ZEBRA_RES rpn_sort_spec(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
2035 oid_value attributeSet, NMEM stream,
2036 Z_SortKeySpecList *sort_sequence,
2037 const char *rank_type,
2040 struct rset_key_control *kc)
2043 int sort_relation_value;
2044 AttrType sort_relation_type;
2051 attr_init(&sort_relation_type, zapt, 7);
2052 sort_relation_value = attr_find(&sort_relation_type, &attributeSet);
2054 if (!sort_sequence->specs)
2056 sort_sequence->num_specs = 10;
2057 sort_sequence->specs = (Z_SortKeySpec **)
2058 nmem_malloc(stream, sort_sequence->num_specs *
2059 sizeof(*sort_sequence->specs));
2060 for (i = 0; i<sort_sequence->num_specs; i++)
2061 sort_sequence->specs[i] = 0;
2063 if (zapt->term->which != Z_Term_general)
2066 i = atoi_n ((char *) zapt->term->u.general->buf,
2067 zapt->term->u.general->len);
2068 if (i >= sort_sequence->num_specs)
2070 sprintf(termz, "%d", i);
2072 oe.proto = PROTO_Z3950;
2073 oe.oclass = CLASS_ATTSET;
2074 oe.value = attributeSet;
2075 if (!oid_ent_to_oid (&oe, oid))
2078 sks = (Z_SortKeySpec *) nmem_malloc(stream, sizeof(*sks));
2079 sks->sortElement = (Z_SortElement *)
2080 nmem_malloc(stream, sizeof(*sks->sortElement));
2081 sks->sortElement->which = Z_SortElement_generic;
2082 sk = sks->sortElement->u.generic = (Z_SortKey *)
2083 nmem_malloc(stream, sizeof(*sk));
2084 sk->which = Z_SortKey_sortAttributes;
2085 sk->u.sortAttributes = (Z_SortAttributes *)
2086 nmem_malloc(stream, sizeof(*sk->u.sortAttributes));
2088 sk->u.sortAttributes->id = oid;
2089 sk->u.sortAttributes->list = zapt->attributes;
2091 sks->sortRelation = (int *)
2092 nmem_malloc(stream, sizeof(*sks->sortRelation));
2093 if (sort_relation_value == 1)
2094 *sks->sortRelation = Z_SortKeySpec_ascending;
2095 else if (sort_relation_value == 2)
2096 *sks->sortRelation = Z_SortKeySpec_descending;
2098 *sks->sortRelation = Z_SortKeySpec_ascending;
2100 sks->caseSensitivity = (int *)
2101 nmem_malloc(stream, sizeof(*sks->caseSensitivity));
2102 *sks->caseSensitivity = 0;
2104 sks->which = Z_SortKeySpec_null;
2105 sks->u.null = odr_nullval ();
2106 sort_sequence->specs[i] = sks;
2107 *rset = rsnull_create (rset_nmem, kc, 0);
2112 static int parse_xpath(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
2113 oid_value attributeSet,
2114 struct xpath_location_step *xpath, int max, NMEM mem)
2116 oid_value curAttributeSet = attributeSet;
2118 const char *use_string = 0;
2120 attr_init(&use, zapt, 1);
2121 attr_find_ex(&use, &curAttributeSet, &use_string);
2123 if (!use_string || *use_string != '/')
2126 return zebra_parse_xpath_str(use_string, xpath, max, mem);
2131 static RSET xpath_trunc(ZebraHandle zh, NMEM stream,
2132 int reg_type, const char *term, int use,
2133 oid_value curAttributeSet, NMEM rset_nmem,
2134 struct rset_key_control *kc)
2137 struct grep_info grep_info;
2138 char term_dict[2048];
2141 int ord = zebraExplain_lookup_attr_su(zh->reg->zei, curAttributeSet, use);
2142 int ord_len, i, r, max_pos;
2143 int term_type = Z_Term_characterString;
2144 const char *flags = "void";
2146 if (grep_info_prepare(zh, 0 /* zapt */, &grep_info, '0') == ZEBRA_FAIL)
2147 return rsnull_create(rset_nmem, kc, 0);
2150 return rsnull_create(rset_nmem, kc, 0);
2152 term_dict[prefix_len++] = '|';
2154 term_dict[prefix_len++] = '(';
2156 ord_len = key_SU_encode (ord, ord_buf);
2157 for (i = 0; i<ord_len; i++)
2159 term_dict[prefix_len++] = 1;
2160 term_dict[prefix_len++] = ord_buf[i];
2162 term_dict[prefix_len++] = ')';
2163 term_dict[prefix_len++] = 1;
2164 term_dict[prefix_len++] = reg_type;
2166 strcpy(term_dict+prefix_len, term);
2168 grep_info.isam_p_indx = 0;
2169 r = dict_lookup_grep(zh->reg->dict, term_dict, 0,
2170 &grep_info, &max_pos, 0, grep_handle);
2171 yaz_log(YLOG_DEBUG, "%s %d positions", term,
2172 grep_info.isam_p_indx);
2173 rset = rset_trunc(zh, grep_info.isam_p_buf,
2174 grep_info.isam_p_indx, term, strlen(term),
2175 flags, 1, term_type,rset_nmem,
2177 grep_info_delete(&grep_info);
2182 ZEBRA_RES rpn_search_xpath(ZebraHandle zh,
2183 oid_value attributeSet,
2184 int num_bases, char **basenames,
2185 NMEM stream, const char *rank_type, RSET rset,
2186 int xpath_len, struct xpath_location_step *xpath,
2189 struct rset_key_control *kc)
2191 oid_value curAttributeSet = attributeSet;
2201 yaz_log(YLOG_DEBUG, "xpath len=%d", xpath_len);
2202 for (i = 0; i<xpath_len; i++)
2204 yaz_log(log_level_rpn, "XPATH %d %s", i, xpath[i].part);
2208 curAttributeSet = VAL_IDXPATH;
2218 a[@attr = value]/b[@other = othervalue]
2220 /e/@a val range(e/,range(@a,freetext(w,1015,val),@a),e/)
2221 /a/b val range(b/a/,freetext(w,1016,val),b/a/)
2222 /a/b/@c val range(b/a/,range(@c,freetext(w,1016,val),@c),b/a/)
2223 /a/b[@c = y] val range(b/a/,freetext(w,1016,val),b/a/,@c = y)
2224 /a[@c = y]/b val range(a/,range(b/a/,freetext(w,1016,val),b/a/),a/,@c = y)
2225 /a[@c = x]/b[@c = y] range(a/,range(b/a/,freetext(w,1016,val),b/a/,@c = y),a/,@c = x)
2229 dict_grep_cmap (zh->reg->dict, 0, 0);
2231 for (base_no = 0; base_no < num_bases; base_no++)
2233 int level = xpath_len;
2236 if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
2238 zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
2239 basenames[base_no]);
2243 while (--level >= 0)
2245 char xpath_rev[128];
2247 RSET rset_start_tag = 0, rset_end_tag = 0, rset_attr = 0;
2251 for (i = level; i >= 1; --i)
2253 const char *cp = xpath[i].part;
2259 memcpy (xpath_rev + len, "[^/]*", 5);
2262 else if (*cp == ' ')
2265 xpath_rev[len++] = 1;
2266 xpath_rev[len++] = ' ';
2270 xpath_rev[len++] = *cp;
2271 xpath_rev[len++] = '/';
2273 else if (i == 1) /* // case */
2275 xpath_rev[len++] = '.';
2276 xpath_rev[len++] = '*';
2281 if (xpath[level].predicate &&
2282 xpath[level].predicate->which == XPATH_PREDICATE_RELATION &&
2283 xpath[level].predicate->u.relation.name[0])
2285 WRBUF wbuf = wrbuf_alloc();
2286 wrbuf_puts(wbuf, xpath[level].predicate->u.relation.name+1);
2287 if (xpath[level].predicate->u.relation.value)
2289 const char *cp = xpath[level].predicate->u.relation.value;
2290 wrbuf_putc(wbuf, '=');
2294 if (strchr(REGEX_CHARS, *cp))
2295 wrbuf_putc(wbuf, '\\');
2296 wrbuf_putc(wbuf, *cp);
2300 wrbuf_puts(wbuf, "");
2301 rset_attr = xpath_trunc(
2302 zh, stream, '0', wrbuf_buf(wbuf), 3,
2303 curAttributeSet, rset_nmem, kc);
2304 wrbuf_free(wbuf, 1);
2311 yaz_log(log_level_rpn, "xpath_rev (%d) = %s", level, xpath_rev);
2312 if (strlen(xpath_rev))
2314 rset_start_tag = xpath_trunc(zh, stream, '0',
2315 xpath_rev, 1, curAttributeSet, rset_nmem, kc);
2317 rset_end_tag = xpath_trunc(zh, stream, '0',
2318 xpath_rev, 2, curAttributeSet, rset_nmem, kc);
2320 rset = rsbetween_create(rset_nmem, kc, kc->scope,
2321 rset_start_tag, rset,
2322 rset_end_tag, rset_attr);
2331 static ZEBRA_RES rpn_search_APT(ZebraHandle zh, Z_AttributesPlusTerm *zapt,
2332 oid_value attributeSet, NMEM stream,
2333 Z_SortKeySpecList *sort_sequence,
2334 int num_bases, char **basenames,
2337 struct rset_key_control *kc)
2339 ZEBRA_RES res = ZEBRA_OK;
2341 char *search_type = NULL;
2342 char rank_type[128];
2345 char termz[IT_MAX_WORD+1];
2348 struct xpath_location_step xpath[10];
2352 log_level_rpn = yaz_log_module_level("rpn");
2355 zebra_maps_attr(zh->reg->zebra_maps, zapt, ®_id, &search_type,
2356 rank_type, &complete_flag, &sort_flag);
2358 yaz_log(YLOG_DEBUG, "reg_id=%c", reg_id);
2359 yaz_log(YLOG_DEBUG, "complete_flag=%d", complete_flag);
2360 yaz_log(YLOG_DEBUG, "search_type=%s", search_type);
2361 yaz_log(YLOG_DEBUG, "rank_type=%s", rank_type);
2363 if (zapt_term_to_utf8(zh, zapt, termz) == ZEBRA_FAIL)
2367 return rpn_sort_spec(zh, zapt, attributeSet, stream, sort_sequence,
2368 rank_type, rset_nmem, rset, kc);
2369 /* consider if an X-Path query is used */
2370 xpath_len = parse_xpath(zh, zapt, attributeSet, xpath, 10, stream);
2373 xpath_use = 1016; /* searching for element by default */
2374 if (xpath[xpath_len-1].part[0] == '@')
2375 xpath_use = 1015; /* last step an attribute .. */
2378 /* search using one of the various search type strategies
2379 termz is our UTF-8 search term
2380 attributeSet is top-level default attribute set
2381 stream is ODR for search
2382 reg_id is the register type
2383 complete_flag is 1 for complete subfield, 0 for incomplete
2384 xpath_use is use-attribute to be used for X-Path search, 0 for none
2386 if (!strcmp(search_type, "phrase"))
2388 res = rpn_search_APT_phrase(zh, zapt, termz, attributeSet, stream,
2389 reg_id, complete_flag, rank_type,
2391 num_bases, basenames, rset_nmem,
2394 else if (!strcmp(search_type, "and-list"))
2396 res = rpn_search_APT_and_list(zh, zapt, termz, attributeSet, stream,
2397 reg_id, complete_flag, rank_type,
2399 num_bases, basenames, rset_nmem,
2402 else if (!strcmp(search_type, "or-list"))
2404 res = rpn_search_APT_or_list(zh, zapt, termz, attributeSet, stream,
2405 reg_id, complete_flag, rank_type,
2407 num_bases, basenames, rset_nmem,
2410 else if (!strcmp(search_type, "local"))
2412 res = rpn_search_APT_local(zh, zapt, termz, attributeSet, stream,
2413 rank_type, rset_nmem, rset, kc);
2415 else if (!strcmp(search_type, "numeric"))
2417 res = rpn_search_APT_numeric(zh, zapt, termz, attributeSet, stream,
2418 reg_id, complete_flag, rank_type,
2420 num_bases, basenames, rset_nmem,
2425 zebra_setError(zh, YAZ_BIB1_UNSUPP_STRUCTURE_ATTRIBUTE, 0);
2428 if (res != ZEBRA_OK)
2432 return rpn_search_xpath(zh, attributeSet, num_bases, basenames,
2433 stream, rank_type, *rset,
2434 xpath_len, xpath, rset_nmem, rset, kc);
2437 static ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
2438 oid_value attributeSet,
2439 NMEM stream, NMEM rset_nmem,
2440 Z_SortKeySpecList *sort_sequence,
2441 int num_bases, char **basenames,
2442 RSET **result_sets, int *num_result_sets,
2443 Z_Operator *parent_op,
2444 struct rset_key_control *kc);
2446 ZEBRA_RES rpn_search_top(ZebraHandle zh, Z_RPNStructure *zs,
2447 oid_value attributeSet,
2448 NMEM stream, NMEM rset_nmem,
2449 Z_SortKeySpecList *sort_sequence,
2450 int num_bases, char **basenames,
2453 RSET *result_sets = 0;
2454 int num_result_sets = 0;
2456 struct rset_key_control *kc = zebra_key_control_create(zh);
2458 res = rpn_search_structure(zh, zs, attributeSet,
2461 num_bases, basenames,
2462 &result_sets, &num_result_sets,
2463 0 /* no parent op */,
2465 if (res != ZEBRA_OK)
2468 for (i = 0; i<num_result_sets; i++)
2469 rset_delete(result_sets[i]);
2474 assert(num_result_sets == 1);
2475 assert(result_sets);
2476 assert(*result_sets);
2477 *result_set = *result_sets;
2483 ZEBRA_RES rpn_search_structure(ZebraHandle zh, Z_RPNStructure *zs,
2484 oid_value attributeSet,
2485 NMEM stream, NMEM rset_nmem,
2486 Z_SortKeySpecList *sort_sequence,
2487 int num_bases, char **basenames,
2488 RSET **result_sets, int *num_result_sets,
2489 Z_Operator *parent_op,
2490 struct rset_key_control *kc)
2492 *num_result_sets = 0;
2493 if (zs->which == Z_RPNStructure_complex)
2496 Z_Operator *zop = zs->u.complex->roperator;
2497 RSET *result_sets_l = 0;
2498 int num_result_sets_l = 0;
2499 RSET *result_sets_r = 0;
2500 int num_result_sets_r = 0;
2502 res = rpn_search_structure(zh, zs->u.complex->s1,
2503 attributeSet, stream, rset_nmem,
2505 num_bases, basenames,
2506 &result_sets_l, &num_result_sets_l,
2508 if (res != ZEBRA_OK)
2511 for (i = 0; i<num_result_sets_l; i++)
2512 rset_delete(result_sets_l[i]);
2515 res = rpn_search_structure(zh, zs->u.complex->s2,
2516 attributeSet, stream, rset_nmem,
2518 num_bases, basenames,
2519 &result_sets_r, &num_result_sets_r,
2521 if (res != ZEBRA_OK)
2524 for (i = 0; i<num_result_sets_l; i++)
2525 rset_delete(result_sets_l[i]);
2526 for (i = 0; i<num_result_sets_r; i++)
2527 rset_delete(result_sets_r[i]);
2531 /* make a new list of result for all children */
2532 *num_result_sets = num_result_sets_l + num_result_sets_r;
2533 *result_sets = nmem_malloc(stream, *num_result_sets *
2534 sizeof(**result_sets));
2535 memcpy(*result_sets, result_sets_l,
2536 num_result_sets_l * sizeof(**result_sets));
2537 memcpy(*result_sets + num_result_sets_l, result_sets_r,
2538 num_result_sets_r * sizeof(**result_sets));
2540 if (!parent_op || parent_op->which != zop->which
2541 || (zop->which != Z_Operator_and &&
2542 zop->which != Z_Operator_or))
2544 /* parent node different from this one (or non-present) */
2545 /* we must combine result sets now */
2549 case Z_Operator_and:
2550 rset = rsmulti_and_create(rset_nmem, kc,
2552 *num_result_sets, *result_sets);
2555 rset = rsmulti_or_create(rset_nmem, kc,
2556 kc->scope, 0, /* termid */
2557 *num_result_sets, *result_sets);
2559 case Z_Operator_and_not:
2560 rset = rsbool_create_not(rset_nmem, kc,
2565 case Z_Operator_prox:
2566 if (zop->u.prox->which != Z_ProximityOperator_known)
2569 YAZ_BIB1_UNSUPP_PROX_UNIT_CODE,
2573 if (*zop->u.prox->u.known != Z_ProxUnit_word)
2575 zebra_setError_zint(zh,
2576 YAZ_BIB1_UNSUPP_PROX_UNIT_CODE,
2577 *zop->u.prox->u.known);
2582 rset = rsprox_create(rset_nmem, kc,
2584 *num_result_sets, *result_sets,
2585 *zop->u.prox->ordered,
2586 (!zop->u.prox->exclusion ?
2587 0 : *zop->u.prox->exclusion),
2588 *zop->u.prox->relationType,
2589 *zop->u.prox->distance );
2593 zebra_setError(zh, YAZ_BIB1_OPERATOR_UNSUPP, 0);
2596 *num_result_sets = 1;
2597 *result_sets = nmem_malloc(stream, *num_result_sets *
2598 sizeof(**result_sets));
2599 (*result_sets)[0] = rset;
2602 else if (zs->which == Z_RPNStructure_simple)
2607 if (zs->u.simple->which == Z_Operand_APT)
2609 yaz_log(YLOG_DEBUG, "rpn_search_APT");
2610 res = rpn_search_APT(zh, zs->u.simple->u.attributesPlusTerm,
2611 attributeSet, stream, sort_sequence,
2612 num_bases, basenames, rset_nmem, &rset,
2614 if (res != ZEBRA_OK)
2617 else if (zs->u.simple->which == Z_Operand_resultSetId)
2619 yaz_log(YLOG_DEBUG, "rpn_search_ref");
2620 rset = resultSetRef(zh, zs->u.simple->u.resultSetId);
2624 YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
2625 zs->u.simple->u.resultSetId);
2632 zebra_setError(zh, YAZ_BIB1_UNSUPP_SEARCH, 0);
2635 *num_result_sets = 1;
2636 *result_sets = nmem_malloc(stream, *num_result_sets *
2637 sizeof(**result_sets));
2638 (*result_sets)[0] = rset;
2642 zebra_setError(zh, YAZ_BIB1_UNSUPP_SEARCH, 0);
2648 struct scan_info_entry {
2654 struct scan_info_entry *list;
2660 static int scan_handle (char *name, const char *info, int pos, void *client)
2662 int len_prefix, idx;
2663 struct scan_info *scan_info = (struct scan_info *) client;
2665 len_prefix = strlen(scan_info->prefix);
2666 if (memcmp (name, scan_info->prefix, len_prefix))
2669 idx = scan_info->after - pos + scan_info->before;
2675 scan_info->list[idx].term = (char *)
2676 odr_malloc(scan_info->odr, strlen(name + len_prefix)+1);
2677 strcpy(scan_info->list[idx].term, name + len_prefix);
2678 assert (*info == sizeof(ISAM_P));
2679 memcpy (&scan_info->list[idx].isam_p, info+1, sizeof(ISAM_P));
2683 void zebra_term_untrans_iconv(ZebraHandle zh, NMEM stream, int reg_type,
2684 char **dst, const char *src)
2686 char term_src[IT_MAX_WORD];
2687 char term_dst[IT_MAX_WORD];
2689 zebra_term_untrans (zh, reg_type, term_src, src);
2691 if (zh->iconv_from_utf8 != 0)
2694 char *inbuf = term_src;
2695 size_t inleft = strlen(term_src);
2696 char *outbuf = term_dst;
2697 size_t outleft = sizeof(term_dst)-1;
2700 ret = yaz_iconv (zh->iconv_from_utf8, &inbuf, &inleft,
2702 if (ret == (size_t)(-1))
2705 len = outbuf - term_dst;
2706 *dst = nmem_malloc(stream, len + 1);
2708 memcpy (*dst, term_dst, len);
2712 *dst = nmem_strdup(stream, term_src);
2715 static void count_set (RSET r, int *count)
2722 yaz_log(YLOG_DEBUG, "count_set");
2725 rfd = rset_open (r, RSETF_READ);
2726 while (rset_read (rfd, &key,0 /* never mind terms */))
2728 if (key.mem[0] != psysno)
2730 psysno = key.mem[0];
2736 yaz_log(YLOG_DEBUG, "%d keys, %d records", kno, *count);
2739 ZEBRA_RES rpn_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
2740 oid_value attributeset,
2741 int num_bases, char **basenames,
2742 int *position, int *num_entries, ZebraScanEntry **list,
2743 int *is_partial, RSET limit_set, int return_zero)
2746 int pos = *position;
2747 int num = *num_entries;
2751 char termz[IT_MAX_WORD+20];
2754 const char *use_string = 0;
2755 struct scan_info *scan_info_array;
2756 ZebraScanEntry *glist;
2757 int ords[32], ord_no = 0;
2760 int bases_ok = 0; /* no of databases with OK attribute */
2761 int errCode = 0; /* err code (if any is not OK) */
2762 char *errString = 0; /* addinfo */
2765 char *search_type = NULL;
2766 char rank_type[128];
2769 NMEM rset_nmem = NULL;
2770 struct rset_key_control *kc = 0;
2775 if (attributeset == VAL_NONE)
2776 attributeset = VAL_BIB1;
2781 int termset_value_numeric;
2782 const char *termset_value_string;
2783 attr_init(&termset, zapt, 8);
2784 termset_value_numeric =
2785 attr_find_ex(&termset, NULL, &termset_value_string);
2786 if (termset_value_numeric != -1)
2789 const char *termset_name = 0;
2791 if (termset_value_numeric != -2)
2794 sprintf(resname, "%d", termset_value_numeric);
2795 termset_name = resname;
2798 termset_name = termset_value_string;
2800 limit_set = resultSetRef (zh, termset_name);
2804 yaz_log(YLOG_DEBUG, "position = %d, num = %d set=%d",
2805 pos, num, attributeset);
2807 attr_init(&use, zapt, 1);
2808 use_value = attr_find_ex(&use, &attributeset, &use_string);
2810 if (zebra_maps_attr(zh->reg->zebra_maps, zapt, ®_id, &search_type,
2811 rank_type, &complete_flag, &sort_flag))
2814 zebra_setError(zh, YAZ_BIB1_UNSUPP_ATTRIBUTE_TYPE, 0);
2817 yaz_log(YLOG_DEBUG, "use_value = %d", use_value);
2819 if (use_value == -1)
2821 for (base_no = 0; base_no < num_bases && ord_no < 32; base_no++)
2823 data1_local_attribute *local_attr;
2827 if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
2829 zebra_setError(zh, YAZ_BIB1_DATABASE_UNAVAILABLE,
2830 basenames[base_no]);
2836 (ord = zebraExplain_lookup_attr_str(zh->reg->zei,
2839 /* we have a match for a raw string attribute */
2841 ords[ord_no++] = ord;
2842 attp.local_attributes = 0; /* no more attributes */
2848 if ((r = att_getentbyatt (zh, &attp, attributeset, use_value,
2851 yaz_log(YLOG_DEBUG, "att_getentbyatt fail. set=%d use=%d",
2852 attributeset, use_value);
2855 errCode = YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
2857 zebra_setError(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
2860 zebra_setError_zint(zh, YAZ_BIB1_UNSUPP_USE_ATTRIBUTE,
2865 zebra_setError(zh, YAZ_BIB1_UNSUPP_ATTRIBUTE_SET, 0);
2871 for (local_attr = attp.local_attributes; local_attr && ord_no < 32;
2872 local_attr = local_attr->next)
2874 ord = zebraExplain_lookup_attr_su(zh->reg->zei,
2875 attp.attset_ordinal,
2878 ords[ord_no++] = ord;
2881 if (!bases_ok && errCode)
2883 zebra_setError(zh, errCode, errString);
2892 /* prepare dictionary scanning */
2904 yaz_log(YLOG_DEBUG, "rpn_scan pos=%d num=%d before=%d "
2905 "after=%d before+after=%d",
2906 pos, num, before, after, before+after);
2907 scan_info_array = (struct scan_info *)
2908 odr_malloc(stream, ord_no * sizeof(*scan_info_array));
2909 for (i = 0; i < ord_no; i++)
2911 int j, prefix_len = 0;
2912 int before_tmp = before, after_tmp = after;
2913 struct scan_info *scan_info = scan_info_array + i;
2914 struct rpn_char_map_info rcmi;
2916 rpn_char_map_prepare (zh->reg, reg_id, &rcmi);
2918 scan_info->before = before;
2919 scan_info->after = after;
2920 scan_info->odr = stream;
2922 scan_info->list = (struct scan_info_entry *)
2923 odr_malloc(stream, (before+after) * sizeof(*scan_info->list));
2924 for (j = 0; j<before+after; j++)
2925 scan_info->list[j].term = NULL;
2927 prefix_len += key_SU_encode (ords[i], termz + prefix_len);
2928 termz[prefix_len++] = reg_id;
2929 termz[prefix_len] = 0;
2930 strcpy(scan_info->prefix, termz);
2932 if (trans_scan_term(zh, zapt, termz+prefix_len, reg_id) == ZEBRA_FAIL)
2935 dict_scan(zh->reg->dict, termz, &before_tmp, &after_tmp,
2936 scan_info, scan_handle);
2938 glist = (ZebraScanEntry *)
2939 odr_malloc(stream, (before+after)*sizeof(*glist));
2941 rset_nmem = nmem_create();
2942 kc = zebra_key_control_create(zh);
2944 /* consider terms after main term */
2945 for (i = 0; i < ord_no; i++)
2949 for (i = 0; i<after; i++)
2952 const char *mterm = NULL;
2955 int lo = i + pos-1; /* offset in result list */
2957 /* find: j0 is the first of the minimal values */
2958 for (j = 0; j < ord_no; j++)
2960 if (ptr[j] < before+after && ptr[j] >= 0 &&
2961 (tst = scan_info_array[j].list[ptr[j]].term) &&
2962 (!mterm || strcmp (tst, mterm) < 0))
2969 break; /* no value found, stop */
2971 /* get result set for first one , but only if it's within bounds */
2974 /* get result set for first term */
2975 zebra_term_untrans_iconv(zh, stream->mem, reg_id,
2976 &glist[lo].term, mterm);
2977 rset = rset_trunc(zh, &scan_info_array[j0].list[ptr[j0]].isam_p, 1,
2978 glist[lo].term, strlen(glist[lo].term),
2979 NULL, 0, zapt->term->which, rset_nmem,
2982 ptr[j0]++; /* move index for this set .. */
2983 /* get result set for remaining scan terms */
2984 for (j = j0+1; j<ord_no; j++)
2986 if (ptr[j] < before+after && ptr[j] >= 0 &&
2987 (tst = scan_info_array[j].list[ptr[j]].term) &&
2988 !strcmp (tst, mterm))
2997 zh, &scan_info_array[j].list[ptr[j]].isam_p, 1,
2999 strlen(glist[lo].term), NULL, 0,
3000 zapt->term->which,rset_nmem,
3002 rset = rsmulti_or_create(rset_nmem, kc,
3003 kc->scope, 0 /* termid */,
3011 /* merge with limit_set if given */
3016 rsets[1] = rset_dup(limit_set);
3018 rset = rsmulti_and_create(rset_nmem, kc,
3023 count_set(rset, &glist[lo].occurrences);
3029 *num_entries -= (after-i);
3031 if (*num_entries < 0)
3034 nmem_destroy(rset_nmem);
3039 /* consider terms before main term */
3040 for (i = 0; i<ord_no; i++)
3043 for (i = 0; i<before; i++)
3046 const char *mterm = NULL;
3049 int lo = before-1-i; /* offset in result list */
3051 for (j = 0; j <ord_no; j++)
3053 if (ptr[j] < before && ptr[j] >= 0 &&
3054 (tst = scan_info_array[j].list[before-1-ptr[j]].term) &&
3055 (!mterm || strcmp (tst, mterm) > 0))
3064 zebra_term_untrans_iconv(zh, stream->mem, reg_id,
3065 &glist[lo].term, mterm);
3068 (zh, &scan_info_array[j0].list[before-1-ptr[j0]].isam_p, 1,
3069 glist[lo].term, strlen(glist[lo].term),
3070 NULL, 0, zapt->term->which, rset_nmem,
3075 for (j = j0+1; j<ord_no; j++)
3077 if (ptr[j] < before && ptr[j] >= 0 &&
3078 (tst = scan_info_array[j].list[before-1-ptr[j]].term) &&
3079 !strcmp (tst, mterm))
3084 rsets[1] = rset_trunc(
3086 &scan_info_array[j].list[before-1-ptr[j]].isam_p, 1,
3088 strlen(glist[lo].term), NULL, 0,
3089 zapt->term->which, rset_nmem,
3091 rset = rsmulti_or_create(rset_nmem, kc,
3092 kc->scope, 0 /* termid */, 2, rsets);
3101 rsets[1] = rset_dup(limit_set);
3103 rset = rsmulti_and_create(rset_nmem, kc,
3104 kc->scope, 2, rsets);
3106 count_set (rset, &glist[lo].occurrences);
3110 nmem_destroy(rset_nmem);
3117 if (*num_entries <= 0)
3124 *list = glist + i; /* list is set to first 'real' entry */
3126 yaz_log(YLOG_DEBUG, "position = %d, num_entries = %d",
3127 *position, *num_entries);