+ }
+ *term_tmp++ = ')';
+ *term_tmp = '\0';
+ break;
+ case 3:
+ case 102:
+ case -1:
+ yaz_log(log_level_rpn, "Relation =");
+ if (!term_100(zh->reg->zebra_maps, reg_type, term_sub,
+ term_component, space_split, term_dst))
+ return 0;
+ strcat(term_tmp, "(");
+ strcat(term_tmp, term_component);
+ strcat(term_tmp, ")");
+ break;
+ default:
+ *error_code = 117;
+ return 0;
+ }
+ return 1;
+}
+
+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);
+
+static ZEBRA_RES term_trunc(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,
+ const char *rank_type, int xpath_use,
+ NMEM rset_nmem,
+ RSET *rset)
+{
+ ZEBRA_RES res;
+ *rset = 0;
+ 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);
+ if (res != ZEBRA_OK)
+ return res;
+ if (!*term_sub) /* no more terms ? */
+ return res;
+ yaz_log(log_level_rpn, "term: %s", term_dst);
+ *rset = rset_trunc(zh, grep_info->isam_p_buf,
+ 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);
+ 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_dict[2*IT_MAX_WORD+4000];
+ int j, r, base_no;
+ AttrType truncation;
+ int truncation_value;
+ AttrType use;
+ int use_value;
+ const char *use_string = 0;
+ oid_value curAttributeSet = attributeSet;
+ const char *termp;
+ struct rpn_char_map_info rcmi;
+ 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 */
+
+ rpn_char_map_prepare (zh->reg, reg_type, &rcmi);
+ attr_init(&use, zapt, 1);
+ use_value = attr_find_ex(&use, &curAttributeSet, &use_string);
+ yaz_log(log_level_rpn, "string_term, use value %d", use_value);
+ attr_init(&truncation, zapt, 5);
+ truncation_value = attr_find(&truncation, NULL);
+ yaz_log(log_level_rpn, "truncation value %d", truncation_value);
+
+ if (use_value == -1) /* no attribute - assumy "any" */
+ use_value = 1016;
+ for (base_no = 0; base_no < num_bases; base_no++)
+ {
+ int ord = -1;
+ int attr_ok = 0;
+ int regex_range = 0;
+ int init_pos = 0;
+ attent attp;
+ data1_local_attribute id_xpath_attr;
+ data1_local_attribute *local_attr;
+ int max_pos, prefix_len = 0;
+ int relation_error;
+
+ termp = *term_sub;
+
+ if (zebraExplain_curDatabase (zh->reg->zei, basenames[base_no]))
+ {
+ zh->errCode = YAZ_BIB1_DATABASE_UNAVAILABLE;
+ zh->errString = basenames[base_no];
+ return ZEBRA_FAIL;
+ }
+ if (xpath_use > 0 && use_value == -2)
+ {
+ /* xpath mode and we have a string attribute */
+ attp.local_attributes = &id_xpath_attr;
+ attp.attset_ordinal = VAL_IDXPATH;
+ id_xpath_attr.next = 0;
+
+ use_value = xpath_use; /* xpath_use as use-attribute now */
+ id_xpath_attr.local = use_value;
+ }
+ else if (curAttributeSet == VAL_IDXPATH && use_value >= 0)
+ {
+ /* X-Path attribute, use numeric value directly */
+ attp.local_attributes = &id_xpath_attr;
+ attp.attset_ordinal = VAL_IDXPATH;
+ id_xpath_attr.next = 0;
+ id_xpath_attr.local = use_value;
+ }
+ else if (use_string &&
+ (ord = zebraExplain_lookup_attr_str(zh->reg->zei,
+ use_string)) >= 0)
+ {
+ /* we have a match for a raw string attribute */
+ char ord_buf[32];
+ int i, ord_len;
+
+ if (prefix_len)
+ term_dict[prefix_len++] = '|';
+ else
+ term_dict[prefix_len++] = '(';
+
+ ord_len = key_SU_encode (ord, ord_buf);
+ for (i = 0; i<ord_len; i++)
+ {
+ term_dict[prefix_len++] = 1;
+ term_dict[prefix_len++] = ord_buf[i];
+ }
+ attp.local_attributes = 0; /* no more attributes */
+ }
+ else
+ {
+ /* lookup in the .att files . Allow string as well */
+ if ((r = att_getentbyatt (zh, &attp, curAttributeSet, use_value,
+ use_string)))
+ {
+ yaz_log(YLOG_DEBUG, "att_getentbyatt fail. set=%d use=%d r=%d",
+ curAttributeSet, use_value, r);
+ 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);
+ else
+ errString = nmem_strdup_i (stream, use_value);
+ }
+ else
+ {
+ int oid[OID_SIZE];
+ struct oident oident;
+
+ oident.proto = PROTO_Z3950;
+ oident.oclass = CLASS_ATTSET;
+ oident.value = curAttributeSet;
+ oid_ent_to_oid (&oident, oid);
+
+ errCode = YAZ_BIB1_UNSUPP_ATTRIBUTE_SET;
+ errString = nmem_strdup(stream, oident.desc);
+ }
+ continue;