More type casts. Modify CQL tree - bool is C++ reserved name.
[yaz-moved-to-github.git] / ccl / cclfind.c
index a7d19b5..8153a0e 100644 (file)
@@ -44,7 +44,7 @@
 /* CCL find (to rpn conversion)
  * Europagate, 1995
  *
- * $Id: cclfind.c,v 1.27 2001-11-27 22:38:50 adam Exp $
+ * $Id: cclfind.c,v 1.33 2003-02-14 18:49:22 adam Exp $
  *
  * Old Europagate log:
  *
@@ -160,7 +160,7 @@ static void strxcat (char *n, const char *src, int len)
  */
 static char *copy_token_name (struct ccl_token *tp)
 {
-    char *str = (char *)malloc (tp->len + 1);
+    char *str = (char *)xmalloc (tp->len + 1);
     ccl_assert (str);
     memcpy (str, tp->name, tp->len);
     str[tp->len] = '\0';
@@ -175,7 +175,7 @@ static char *copy_token_name (struct ccl_token *tp)
 static struct ccl_rpn_node *mk_node (int kind)
 {
     struct ccl_rpn_node *p;
-    p = (struct ccl_rpn_node *)malloc (sizeof(*p));
+    p = (struct ccl_rpn_node *)xmalloc (sizeof(*p));
     ccl_assert (p);
     p->kind = kind;
     return p;
@@ -199,24 +199,24 @@ void ccl_rpn_delete (struct ccl_rpn_node *rpn)
         ccl_rpn_delete (rpn->u.p[1]);
         break;
     case CCL_RPN_TERM:
-        free (rpn->u.t.term);
+        xfree (rpn->u.t.term);
         for (attr = rpn->u.t.attr_list; attr; attr = attr1)
         {
             attr1 = attr->next;
             if (attr->set)
-                free (attr->set);
-            free (attr);
+                xfree (attr->set);
+            xfree (attr);
         }
         break;
     case CCL_RPN_SET:
-        free (rpn->u.setname);
+        xfree (rpn->u.setname);
         break;
     case CCL_RPN_PROX:
         ccl_rpn_delete (rpn->u.p[0]);
         ccl_rpn_delete (rpn->u.p[1]);
         break;
     }
-    free (rpn);
+    xfree (rpn);
 }
 
 static struct ccl_rpn_node *find_spec (CCL_parser cclp,
@@ -245,11 +245,11 @@ static void add_attr (struct ccl_rpn_node *p, const char *set,
 {
     struct ccl_rpn_attr *n;
 
-    n = (struct ccl_rpn_attr *)malloc (sizeof(*n));
+    n = (struct ccl_rpn_attr *)xmalloc (sizeof(*n));
     ccl_assert (n);
     if (set)
     {
-        n->set = (char*) malloc (strlen(set)+1);
+        n->set = (char*) xmalloc (strlen(set)+1);
         strcpy (n->set, set);
     }
     else
@@ -417,7 +417,7 @@ static struct ccl_rpn_node *search_term_x (CCL_parser cclp,
         }
         
         /* make the RPN token */
-        p->u.t.term = (char *)malloc (len);
+        p->u.t.term = (char *)xmalloc (len);
         ccl_assert (p->u.t.term);
         p->u.t.term[0] = '\0';
         for (i = 0; i<no; i++)
@@ -592,7 +592,7 @@ static struct ccl_rpn_node *qualifiers2 (CCL_parser cclp,
             }
         }
         else if (cclp->look_token->len == 1 &&
-                 cclp->look_token->name[0] == '"')   /* = - term  ? */
+                 cclp->look_token->name[0] == '-')   /* = - term  ? */
         {
             ADVANCE;
             if (!(p = search_term (cclp, ap)))
@@ -627,22 +627,24 @@ static struct ccl_rpn_node *qualifiers2 (CCL_parser cclp,
 }
 
 /*
- * qualifiers: Parse CCL qualifiers and search terms. 
+ * qualifiers1: Parse CCL qualifiers and search terms. 
  * cclp:   CCL Parser
  * la:     Token pointer to RELATION token.
  * qa:     Qualifier attributes already applied.
  * return: pointer to node(s); NULL on error.
  */
-static struct ccl_rpn_node *qualifiers (CCL_parser cclp, struct ccl_token *la,
-                                        struct ccl_rpn_attr **qa)
+static struct ccl_rpn_node *qualifiers1 (CCL_parser cclp, struct ccl_token *la,
+                                         struct ccl_rpn_attr **qa)
 {
     struct ccl_token *lookahead = cclp->look_token;
     struct ccl_token *look_start = cclp->look_token;
     struct ccl_rpn_attr **ap;
     struct ccl_rpn_node *node = 0;
+    const char *field_str;
     int no = 0;
     int seq = 0;
     int i;
+    int mode_merge = 1;
 #if 0
     if (qa)
     {
@@ -656,62 +658,122 @@ static struct ccl_rpn_node *qualifiers (CCL_parser cclp, struct ccl_token *la,
     if (qa)
         for (i=0; qa[i]; i++)
             no++;
-    ap = (struct ccl_rpn_attr **)malloc ((no+1) * sizeof(*ap));
+    ap = (struct ccl_rpn_attr **)xmalloc ((no ? (no+1) : 2) * sizeof(*ap));
     ccl_assert (ap);
 
-    while (1)
+    field_str = ccl_qual_search_special(cclp->bibset, "field");
+    if (field_str)
+    {
+        if (!strcmp (field_str, "or"))
+            mode_merge = 0;
+        else if (!strcmp (field_str, "merge"))
+            mode_merge = 1;
+    }
+    if (!mode_merge)
     {
-        struct ccl_rpn_node *node_sub;
-        int found = 0;
+        /* consider each field separately and OR */
         lookahead = look_start;
-        for (i = 0; lookahead != la; i++)
+        while (lookahead != la)
         {
-            ap[i] = ccl_qual_search (cclp, lookahead->name,
-                                     lookahead->len, seq);
-            if (ap[i])
-                found++;
-            if (!ap[i] && seq > 0)
-                ap[i] = ccl_qual_search (cclp, lookahead->name,
-                                         lookahead->len, 0);
-            if (!ap[i])
+            ap[1] = 0;
+            seq = 0;
+            while ((ap[0] = ccl_qual_search (cclp, lookahead->name,
+                                             lookahead->len, seq)) != 0)
+            {
+                struct ccl_rpn_node *node_sub;
+                cclp->look_token = la;
+                
+                node_sub = qualifiers2(cclp, ap);
+                if (!node_sub)
+                {
+                    ccl_rpn_delete (node);
+                    xfree (ap);
+                    return 0;
+                }
+                if (node)
+                {
+                    struct ccl_rpn_node *node_this = mk_node(CCL_RPN_OR);
+                    node_this->u.p[0] = node;
+                    node_this->u.p[1] = node_sub;
+                    node = node_this;
+                }
+                else
+                    node = node_sub;
+                seq++;
+            }
+            if (seq == 0)
             {
                 cclp->look_token = lookahead;
                 cclp->error_code = CCL_ERR_UNKNOWN_QUAL;
-                free (ap);
+                xfree (ap);
                 return NULL;
             }
             lookahead = lookahead->next;
             if (lookahead->kind == CCL_TOK_COMMA)
                 lookahead = lookahead->next;
         }
-        if (qa)
-            while (*qa)
-                ap[i++] = *qa++;
-        ap[i] = NULL;
-
-        if (!found)
-            break;
-
-        cclp->look_token = lookahead;
-
-        node_sub = qualifiers2(cclp, ap);
-        if (!node_sub)
-        {
-            ccl_rpn_delete (node);
-            break;
-        }
-        if (node)
+    }
+    else
+    {
+        /* merge attributes from ALL fields - including inherited ones */
+        while (1)
         {
-            struct ccl_rpn_node *node_this = mk_node(CCL_RPN_OR);
-            node_this->u.p[0] = node;
-            node_this->u.p[1] = node_sub;
-            node = node_this;
+            struct ccl_rpn_node *node_sub;
+            int found = 0;
+            lookahead = look_start;
+            for (i = 0; lookahead != la; i++)
+            {
+                ap[i] = ccl_qual_search (cclp, lookahead->name,
+                                         lookahead->len, seq);
+                if (ap[i])
+                    found++;
+                if (!ap[i] && seq > 0)
+                    ap[i] = ccl_qual_search (cclp, lookahead->name,
+                                             lookahead->len, 0);
+                if (!ap[i])
+                {
+                    cclp->look_token = lookahead;
+                    cclp->error_code = CCL_ERR_UNKNOWN_QUAL;
+                    xfree (ap);
+                    return NULL;
+                }
+                lookahead = lookahead->next;
+                if (lookahead->kind == CCL_TOK_COMMA)
+                    lookahead = lookahead->next;
+            }
+            if (qa)
+            {
+                struct ccl_rpn_attr **qa0 = qa;
+                
+                while (*qa0)
+                    ap[i++] = *qa0++;
+            }
+            ap[i] = NULL;
+            
+            if (!found)
+                break;
+            
+            cclp->look_token = lookahead;
+            
+            node_sub = qualifiers2(cclp, ap);
+            if (!node_sub)
+            {
+                ccl_rpn_delete (node);
+                break;
+            }
+            if (node)
+            {
+                struct ccl_rpn_node *node_this = mk_node(CCL_RPN_OR);
+                node_this->u.p[0] = node;
+                node_this->u.p[1] = node_sub;
+                node = node_this;
+            }
+            else
+                node = node_sub;
+            seq++;
         }
-        else
-            node = node_sub;
-        seq++;
     }
-    free (ap);
+    xfree (ap);
     return node;
 }
 
@@ -726,7 +788,7 @@ static struct ccl_rpn_node *search_terms (CCL_parser cclp,
                                           struct ccl_rpn_attr **qa)
 {
     static int list[] = {
-        CCL_TOK_TERM, CCL_TOK_COMMA,CCL_TOK_EQ, CCL_TOK_REL, -1};
+        CCL_TOK_TERM, CCL_TOK_COMMA,CCL_TOK_EQ, CCL_TOK_REL, CCL_TOK_SET, -1};
     struct ccl_rpn_node *p1, *p2, *pn;
     p1 = search_term_x (cclp, qa, list, 1);
     if (!p1)
@@ -735,6 +797,16 @@ static struct ccl_rpn_node *search_terms (CCL_parser cclp,
     {
         if (KIND == CCL_TOK_PROX)
         {
+            struct ccl_rpn_node *p_prox = 0;
+            /* ! word order specified */
+            /* % word order not specified */
+            p_prox = mk_node(CCL_RPN_TERM);
+            p_prox->u.t.term = (char *) xmalloc(cclp->look_token->len);
+            memcpy(p_prox->u.t.term, cclp->look_token->name,
+                   cclp->look_token->len);
+            p_prox->u.t.term[cclp->look_token->len] = 0;
+            p_prox->u.t.attr_list = 0;
+
             ADVANCE;
             p2 = search_term_x (cclp, qa, list, 1);
             if (!p2)
@@ -745,6 +817,7 @@ static struct ccl_rpn_node *search_terms (CCL_parser cclp,
             pn = mk_node (CCL_RPN_PROX);
             pn->u.p[0] = p1;
             pn->u.p[1] = p2;
+            pn->u.p[2] = p_prox;
             p1 = pn;
         }
         else if (is_term_ok(KIND, list))
@@ -758,6 +831,7 @@ static struct ccl_rpn_node *search_terms (CCL_parser cclp,
             pn = mk_node (CCL_RPN_PROX);
             pn->u.p[0] = p1;
             pn->u.p[1] = p2;
+            pn->u.p[2] = 0;
             p1 = pn;
         }
         else
@@ -813,7 +887,7 @@ static struct ccl_rpn_node *search_elements (CCL_parser cclp,
     {
         lookahead = lookahead->next;
         if (lookahead->kind == CCL_TOK_REL || lookahead->kind == CCL_TOK_EQ)
-            return qualifiers (cclp, lookahead, qa);
+            return qualifiers1 (cclp, lookahead, qa);
         if (lookahead->kind != CCL_TOK_COMMA)
             break;
         lookahead = lookahead->next;
@@ -848,6 +922,7 @@ static struct ccl_rpn_node *search_elements (CCL_parser cclp,
                 struct ccl_rpn_node *node_this = mk_node(CCL_RPN_OR);
                 node_this->u.p[0] = node;
                 node_this->u.p[1] = node_sub;
+                node_this->u.p[2] = 0;
                 node = node_this;
             }
             else
@@ -886,6 +961,7 @@ static struct ccl_rpn_node *find_spec (CCL_parser cclp,
             pn = mk_node (CCL_RPN_AND);
             pn->u.p[0] = p1;
             pn->u.p[1] = p2;
+            pn->u.p[2] = 0;
             p1 = pn;
             continue;
         case CCL_TOK_OR:
@@ -899,6 +975,7 @@ static struct ccl_rpn_node *find_spec (CCL_parser cclp,
             pn = mk_node (CCL_RPN_OR);
             pn->u.p[0] = p1;
             pn->u.p[1] = p2;
+            pn->u.p[2] = 0;
             p1 = pn;
             continue;
         case CCL_TOK_NOT:
@@ -912,6 +989,7 @@ static struct ccl_rpn_node *find_spec (CCL_parser cclp,
             pn = mk_node (CCL_RPN_NOT);
             pn->u.p[0] = p1;
             pn->u.p[1] = p2;
+            pn->u.p[2] = 0;
             p1 = pn;
             continue;
         }