+static struct ccl_rpn_node *ccl_term_multi_use(CCL_parser cclp,
+ struct ccl_token *lookahead0,
+ ccl_qualifier_t *qa,
+ size_t no,
+ int is_phrase,
+ int auto_group)
+{
+ struct ccl_rpn_node *p = 0;
+ int i;
+ for (i = 0; qa && qa[i]; i++)
+ {
+ struct ccl_rpn_attr *attr;
+ for (attr = ccl_qual_get_attr(qa[i]); attr; attr = attr->next)
+ if (attr->type == 1 && i == 0)
+ {
+ struct ccl_rpn_node *tmp2;
+ tmp2 = ccl_term_one_use(cclp, lookahead0,
+ attr, qa, no,
+ is_phrase, auto_group);
+ if (!tmp2)
+ {
+ ccl_rpn_delete(p);
+ return 0;
+ }
+ p = ccl_rpn_node_mkbool(p, tmp2, CCL_RPN_OR);
+ }
+ }
+ if (!p)
+ p = ccl_term_one_use(cclp, lookahead0,
+ 0 /* attr: no use */, qa, no,
+ is_phrase, auto_group);
+ return p;
+}
+
+static struct ccl_rpn_node *split_recur(CCL_parser cclp, ccl_qualifier_t *qa,
+ struct ccl_token **ar, size_t sz,
+ size_t sub_len)
+{
+ size_t l;
+ struct ccl_rpn_node *p_top = 0;
+ assert(sz > 0);
+ for (l = 1; l <= sz && l <= sub_len; l++)
+ {
+ struct ccl_rpn_node *p2 = ccl_term_multi_use(cclp, ar[0],
+ qa, l,
+ l > 1,
+ /* auto_group */0);
+ if (!p2)
+ {
+ ccl_rpn_delete(p_top);
+ return 0;
+ }
+ if (sz > l)
+ {
+ struct ccl_rpn_node *p1 = split_recur(cclp, qa, ar + l, sz - l,
+ sub_len);
+ if (!p1)
+ {
+ ccl_rpn_delete(p2);
+ return 0;
+ }
+ p2 = ccl_rpn_node_mkbool(p2, p1, CCL_RPN_AND);
+ }
+ p_top = ccl_rpn_node_mkbool(p_top, p2, CCL_RPN_OR);
+ }
+ assert(p_top);
+ return p_top;
+}
+
+static struct ccl_rpn_node *search_term_split_list(CCL_parser cclp,
+ ccl_qualifier_t *qa,
+ int *term_list, int multi)
+{
+ struct ccl_rpn_node *p;
+ struct ccl_token **ar;
+ struct ccl_token *lookahead = cclp->look_token;
+ size_t i, sz, sub_len;
+ for (sz = 0; is_term_ok(lookahead->kind, term_list); sz++)
+ lookahead = lookahead->next;
+ if (sz == 0)
+ {
+ cclp->error_code = CCL_ERR_TERM_EXPECTED;
+ return 0;
+ }
+ ar = (struct ccl_token **) xmalloc(sizeof(*lookahead) * sz);
+ lookahead = cclp->look_token;
+ for (i = 0; is_term_ok(lookahead->kind, term_list); i++)
+ {
+ ar[i] = lookahead;
+ lookahead = lookahead->next;
+ }
+ /* choose sub phrase carefully to avoid huge expansions */
+ if (sz >= 7)
+ sub_len = 1;
+ else if (sz >= 5)
+ sub_len = 2;
+ else
+ sub_len = 3;
+ p = split_recur(cclp, qa, ar, sz, sub_len);
+ xfree(ar);
+ for (i = 0; i < sz; i++)
+ ADVANCE;
+ return p;
+}
+