+
+ ++size;
+ ti->heapnum = 0;
+ ti->keysize = key_size;
+ ti->cmp = cmp;
+ ti->indx = xmalloc (size * sizeof(*ti->indx));
+ ti->heap = xmalloc (size * sizeof(*ti->heap));
+ ti->swapbuf = xmalloc (ti->keysize);
+ ti->tmpbuf = xmalloc (ti->keysize);
+ ti->buf = xmalloc (size * ti->keysize);
+ for (i = size; --i >= 0; )
+ ti->heap[i] = ti->buf + ti->keysize * i;
+ return ti;
+}
+
+static void heap_close (struct trunc_info *ti)
+{
+ xfree (ti->indx);
+ xfree (ti->heap);
+ xfree (ti->swapbuf);
+ xfree (ti->tmpbuf);
+ xfree (ti);
+}
+
+static RSET rset_trunc (ISAM isam, ISAM_P *isam_p, int from, int to,
+ int merge_chunk)
+{
+ logf (LOG_DEBUG, "rset_trunc, range=%d-%d", from, to-1);
+ if (to - from > merge_chunk)
+ {
+ return NULL;
+ }
+ else
+ {
+ ISPT *ispt;
+ int i;
+ struct trunc_info *ti;
+ RSET result;
+ RSFD rsfd;
+ rset_temp_parms parms;
+
+ ispt = xmalloc (sizeof(*ispt) * (to-from));
+ parms.key_size = sizeof (struct it_key);
+ result = rset_create (rset_kind_temp, &parms);
+ rsfd = rset_open (result, 1);
+
+ ti = heap_init (to-from, sizeof(struct it_key),
+ key_compare);
+ for (i = to-from; --i >= 0; )
+ {
+ ispt[i] = is_position (isam, isam_p[from+i]);
+ if (is_readkey (ispt[i], ti->tmpbuf))
+ heap_insert (ti, ti->tmpbuf, i);
+ }
+ while (ti->heapnum)
+ {
+ int n = ti->indx[1];
+
+ rset_write (result, rsfd, ti->heap[1]);
+ heap_delete (ti);
+ if (is_readkey (ispt[n], ti->tmpbuf))
+ heap_insert (ti, ti->tmpbuf, n);
+ }
+ for (i = to-from; --i >= 0; )
+ is_pt_free (ispt[i]);
+ rset_close (result, rsfd);
+ heap_close (ti);
+ xfree (ispt);
+ return result;
+ }
+}
+
+static ISAM_P *isam_p_buf = NULL;
+static int isam_p_size = 0;
+static int isam_p_indx;
+
+static void add_isam_p (const char *info)
+{
+ if (isam_p_indx == isam_p_size)
+ {
+ ISAM_P *new_isam_p_buf;
+
+ isam_p_size = 2*isam_p_size + 100;
+ new_isam_p_buf = xmalloc (sizeof(*new_isam_p_buf) *
+ isam_p_size);
+ if (isam_p_buf)
+ {
+ memcpy (new_isam_p_buf, isam_p_buf,
+ isam_p_indx * sizeof(*isam_p_buf));
+ xfree (isam_p_buf);
+ }
+ isam_p_buf = new_isam_p_buf;
+ }
+ assert (*info == sizeof(*isam_p_buf));
+ memcpy (isam_p_buf + isam_p_indx, info+1, sizeof(*isam_p_buf));
+ isam_p_indx++;
+}
+
+static int grep_handle (Dict_char *name, const char *info)
+{
+ logf (LOG_DEBUG, "dict name: %s", name);
+ add_isam_p (info);
+ return 0;
+}
+
+static int trunc_term (ZServerInfo *zi, Z_AttributesPlusTerm *zapt,
+ const char *term_sub, ISAM_P **isam_ps)
+{
+ char term_dict[2*IT_MAX_WORD+2];
+ int i, j;
+ const char *info;
+ AttrType truncation;
+ int truncation_value;
+ AttrType use;
+ int use_value;
+
+ attr_init (&use, zapt, 1);
+ use_value = attr_find (&use);
+ logf (LOG_DEBUG, "use value %d", use_value);
+ attr_init (&truncation, zapt, 5);
+ truncation_value = attr_find (&truncation);
+ logf (LOG_DEBUG, "truncation value %d", truncation_value);
+
+ if (use_value == -1)
+ use_value = 1016;
+ i = index_word_prefix (term_dict, 1, use_value);
+
+ switch (truncation_value)
+ {
+ case -1: /* not specified */
+ case 100: /* do not truncate */
+ strcat (term_dict, term_sub);
+ logf (LOG_DEBUG, "dict_lookup: %s", term_dict);
+ if ((info = dict_lookup (zi->wordDict, term_dict)))
+ add_isam_p (info);
+ break;
+ case 1: /* right truncation */
+ strcat (term_dict, term_sub);
+ strcat (term_dict, ".*");
+ dict_lookup_grep (zi->wordDict, term_dict, 0, grep_handle);
+ break;
+ case 2: /* left truncation */
+ case 3: /* left&right truncation */
+ zi->errCode = 120;
+ return -1;
+ case 101: /* process # in term */
+ for (j = strlen(term_dict), i = 0; term_sub[i] && i < 2; i++)
+ term_dict[j++] = term_sub[i];
+ for (; term_sub[i]; i++)
+ if (term_sub[i] == '#')
+ {
+ term_dict[j++] = '.';
+ term_dict[j++] = '*';
+ }
+ else
+ term_dict[j++] = term_sub[i];
+ term_dict[j] = '\0';
+ dict_lookup_grep (zi->wordDict, term_dict, 0, grep_handle);
+ break;
+ case 102: /* regular expression */
+ strcat (term_dict, term_sub);
+ dict_lookup_grep (zi->wordDict, term_dict, 0, grep_handle);
+ break;
+ }
+ *isam_ps = isam_p_buf;
+ logf (LOG_DEBUG, "%d positions", isam_p_indx);
+ return 0;
+}
+
+static void trans_term (ZServerInfo *zi, Z_AttributesPlusTerm *zapt,
+ char *termz)
+{
+ size_t i, sizez;