+struct scan_info_entry {
+ char *term;
+ ISAM_P isam_p;
+};
+
+struct scan_info {
+ struct scan_info_entry *list;
+ ODR odr;
+ int before, after;
+ char prefix[20];
+};
+
+static int scan_handle (char *name, const char *info, int pos, void *client)
+{
+ int len_prefix, idx;
+ struct scan_info *scan_info = client;
+
+ len_prefix = strlen(scan_info->prefix);
+ if (memcmp (name, scan_info->prefix, len_prefix))
+ return 1;
+ if (pos > 0)
+ idx = scan_info->after - pos + scan_info->before;
+ else
+ idx = - pos - 1;
+ scan_info->list[idx].term = odr_malloc (scan_info->odr,
+ strlen(name + len_prefix)+1);
+ strcpy (scan_info->list[idx].term, name + len_prefix);
+ assert (*info == sizeof(ISAM_P));
+ memcpy (&scan_info->list[idx].isam_p, info+1, sizeof(ISAM_P));
+ return 0;
+}
+
+
+static void scan_term_untrans (ODR odr, char **dstp, const char *src)
+{
+ char *dst = odr_malloc (odr, strlen(src)*2+1);
+ *dstp = dst;
+
+ while (*src)
+ {
+ const char *cp = map_chrs_output (&src);
+ while (*cp)
+ *dst++ = *cp++;
+ }
+ *dst = '\0';
+}
+
+int rpn_scan (ZServerInfo *zi, Z_AttributesPlusTerm *zapt,
+ oid_value attributeset,
+ int num_bases, char **basenames,
+ int *position, int *num_entries, struct scan_entry **list,
+ int *status)
+{
+ int i;
+ int pos = *position;
+ int num = *num_entries;
+ int before;
+ int after;
+ int base_no;
+ char termz[IT_MAX_WORD+20];
+ AttrType use;
+ int use_value;
+ AttrType completeness;
+ int completeness_value;
+ struct scan_info *scan_info_array;
+ struct scan_entry *glist;
+ int ords[32], ord_no = 0;
+ int ptr[32];
+
+ logf (LOG_DEBUG, "scan, position = %d, num = %d", pos, num);
+
+ if (attributeset == VAL_NONE)
+ attributeset = VAL_BIB1;
+
+ attr_init (&use, zapt, 1);
+ use_value = attr_find (&use, &attributeset);
+ logf (LOG_DEBUG, "use value %d", use_value);
+
+ attr_init (&completeness, zapt, 6);
+ completeness_value = attr_find (&completeness, NULL);
+ logf (LOG_DEBUG, "completeness value %d", completeness_value);
+
+ if (use_value == -1)
+ use_value = 1016;
+ for (base_no = 0; base_no < num_bases && ord_no < 32; base_no++)
+ {
+ attent *attp;
+ data1_local_attribute *local_attr;
+
+ attp = att_getentbyatt (attributeset, use_value);
+ if (!attp)
+ {
+ logf (LOG_DEBUG, "att_getentbyatt fail. set=%d use=%d",
+ attributeset, use_value);
+ return zi->errCode = 114;
+ }
+ if (zebTargetInfo_curDatabase (zi->zti, basenames[base_no]))
+ {
+ zi->errString = basenames[base_no];
+ return zi->errCode = 109; /* Database unavailable */
+ }
+ for (local_attr = attp->local_attributes; local_attr && ord_no < 32;
+ local_attr = local_attr->next)
+ {
+ int ord;
+
+ ord = zebTargetInfo_lookupSU (zi->zti, attp->attset_ordinal,
+ local_attr->local);
+ if (ord > 0)
+ ords[ord_no++] = ord;
+ }
+ }
+ if (ord_no == 0)
+ return zi->errCode = 113;
+ before = pos-1;
+ after = 1+num-pos;
+ scan_info_array = odr_malloc (zi->odr, ord_no * sizeof(*scan_info_array));
+ for (i = 0; i < ord_no; i++)
+ {
+ int j, prefix_len = 0;
+ int before_tmp = before, after_tmp = after;
+ struct scan_info *scan_info = scan_info_array + i;
+
+ scan_info->before = before;
+ scan_info->after = after;
+ scan_info->odr = zi->odr;
+
+ scan_info->list = odr_malloc (zi->odr, (before+after)*
+ sizeof(*scan_info->list));
+ for (j = 0; j<before+after; j++)
+ scan_info->list[j].term = NULL;
+ termz[prefix_len++] = ords[i];
+ termz[prefix_len++] =
+ (completeness_value==2 || completeness_value==3) ? 'p': 'w';
+ termz[prefix_len] = 0;
+ strcpy (scan_info->prefix, termz);
+
+ trans_scan_term (zi, zapt, termz+prefix_len);
+
+ dict_scan (zi->dict, termz, &before_tmp, &after_tmp, scan_info,
+ scan_handle);
+ }
+ glist = odr_malloc (zi->odr, (before+after)*sizeof(*glist));
+ for (i = 0; i < ord_no; i++)
+ ptr[i] = before;
+
+ *status = BEND_SCAN_SUCCESS;
+ for (i = 0; i<after; i++)
+ {
+ int j, j0 = -1;
+ const char *mterm = NULL;
+ const char *tst;
+ RSET rset;
+
+ for (j = 0; j < ord_no; j++)
+ {
+ if (ptr[j] < before+after &&
+ (tst=scan_info_array[j].list[ptr[j]].term) &&
+ (!mterm || strcmp (tst, mterm) < 0))
+ {
+ j0 = j;
+ mterm = tst;
+ }
+ }
+ if (j0 == -1)
+ break;
+ scan_term_untrans (zi->odr, &glist[i+before].term, mterm);
+ rset = rset_trunc (zi, &scan_info_array[j0].list[ptr[j0]].isam_p, 1);
+
+ ptr[j0]++;
+ for (j = j0+1; j<ord_no; j++)
+ {
+ if (ptr[j] < before+after &&
+ (tst=scan_info_array[j].list[ptr[j]].term) &&
+ !strcmp (tst, mterm))
+ {
+ rset_bool_parms bool_parms;
+ RSET rset2;
+
+ rset2 =
+ rset_trunc (zi, &scan_info_array[j].list[ptr[j]].isam_p, 1);
+
+ bool_parms.key_size = sizeof(struct it_key);
+ bool_parms.cmp = key_compare_it;
+ bool_parms.rset_l = rset;
+ bool_parms.rset_r = rset2;
+
+ rset = rset_create (rset_kind_or, &bool_parms);
+
+ ptr[j]++;
+ }
+ }
+ count_set (rset, &glist[i+before].occurrences);
+ rset_delete (rset);
+ }
+ if (i < after)
+ {
+ *num_entries -= (after-i);
+ *status = BEND_SCAN_PARTIAL;
+ }
+
+ for (i = 0; i<ord_no; i++)
+ ptr[i] = 0;
+
+ for (i = 0; i<before; i++)
+ {
+ int j, j0 = -1;
+ const char *mterm = NULL;
+ const char *tst;
+ RSET rset;
+
+ for (j = 0; j <ord_no; j++)
+ {
+ if (ptr[j] < before &&
+ (tst=scan_info_array[j].list[before-1-ptr[j]].term) &&
+ (!mterm || strcmp (tst, mterm) > 0))
+ {
+ j0 = j;
+ mterm = tst;
+ }
+ }
+ if (j0 == -1)
+ break;
+
+ scan_term_untrans (zi->odr, &glist[before-1-i].term, mterm);
+
+ rset = rset_trunc
+ (zi, &scan_info_array[j0].list[before-1-ptr[j0]].isam_p, 1);
+
+ ptr[j0]++;
+
+ for (j = j0+1; j<ord_no; j++)
+ {
+ if (ptr[j] < before &&
+ (tst=scan_info_array[j].list[before-1-ptr[j]].term) &&
+ !strcmp (tst, mterm))
+ {
+ rset_bool_parms bool_parms;
+ RSET rset2;
+
+ rset2 = rset_trunc (zi,
+ &scan_info_array[j].list[before-1-ptr[j]].isam_p, 1);
+
+ bool_parms.key_size = sizeof(struct it_key);
+ bool_parms.cmp = key_compare_it;
+ bool_parms.rset_l = rset;
+ bool_parms.rset_r = rset2;
+
+ rset = rset_create (rset_kind_or, &bool_parms);
+
+ ptr[j]++;
+ }
+ }
+ count_set (rset, &glist[before-1-i].occurrences);
+ rset_delete (rset);
+ }
+ i = before-i;
+ if (i)
+ {
+ *status = BEND_SCAN_PARTIAL;
+ *position -= i;
+ *num_entries -= i;
+ }
+ *list = glist + i; /* list is set to first 'real' entry */
+
+ logf (LOG_DEBUG, "position = %d, num_entries = %d",
+ *position, *num_entries);
+ if (zi->errCode)
+ logf (LOG_DEBUG, "scan error: %d", zi->errCode);
+ return zi->errCode;
+}
+