Member and_not in Z_Operator is kept for backwards compatibility.
[yaz-moved-to-github.git] / ccl / ccltoken.c
index 64a8279..b0e1b81 100644 (file)
  * Europagate, 1995
  *
  * $Log: ccltoken.c,v $
- * Revision 1.7  1997-09-01 08:48:12  adam
+ * Revision 1.16  2001-03-07 13:24:40  adam
+ * Member and_not in Z_Operator is kept for backwards compatibility.
+ * Added support for definition of CCL operators in field spec file.
+ *
+ * Revision 1.15  2000/05/01 09:36:50  adam
+ * Range operator only treated in ordered ranges so that minus (-) can be
+ * used for, say, the and-not operator.
+ *
+ * Revision 1.14  2000/03/14 09:06:11  adam
+ * Added POSIX threads support for frontend server.
+ *
+ * Revision 1.13  2000/02/08 10:39:53  adam
+ * Added a few functions to set name of operands, etc.
+ *
+ * Revision 1.12  2000/01/31 13:15:21  adam
+ * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
+ * that some characters are not surrounded by spaces in resulting term.
+ * ILL-code updates.
+ *
+ * Revision 1.11  1999/11/30 13:47:11  adam
+ * Improved installation. Moved header files to include/yaz.
+ *
+ * Revision 1.10  1998/07/07 15:49:41  adam
+ * Added braces to avoid warning.
+ *
+ * Revision 1.9  1998/02/11 11:53:33  adam
+ * Changed code so that it compiles as C++.
+ *
+ * Revision 1.8  1997/09/29 08:56:38  adam
+ * Changed CCL parser to be thread safe. New type, CCL_parser, declared
+ * and a create/destructers ccl_parser_create/ccl_parser/destory has
+ * been added.
+ *
+ * Revision 1.7  1997/09/01 08:48:12  adam
  * New windows NT/95 port using MSV5.0. Only a few changes made
  * to avoid warnings.
  *
  *
  */
 
-#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <assert.h>
-
-#include <ccl.h>
 
-const char *ccl_token_and = "and";
-const char *ccl_token_or = "or";
-const char *ccl_token_not = "not andnot";
-const char *ccl_token_set = "set";
-int ccl_case_sensitive = 1;
+#include <yaz/ccl.h>
 
 /*
  * token_cmp: Compare token with keyword(s)
@@ -110,16 +135,23 @@ int ccl_case_sensitive = 1;
  * return: 1 if token string matches one of the keywords in list;
  *         0 otherwise.
  */
-static int token_cmp (const char *kw, struct ccl_token *token)
+static int token_cmp (CCL_parser cclp, const char *kw, struct ccl_token *token)
 {
     const char *cp1 = kw;
     const char *cp2;
+    const char *aliases;
+    int case_sensitive = cclp->ccl_case_sensitive;
+
+    aliases = ccl_qual_search_special(cclp->bibset, "case");
+    if (aliases)
+       case_sensitive = atoi(aliases);
     if (!kw)
         return 0;
     while ((cp2 = strchr (cp1, ' ')))
     {
         if (token->len == (size_t) (cp2-cp1))
-            if (ccl_case_sensitive)
+        {
+            if (case_sensitive)
             {
                 if (!memcmp (cp1, token->name, token->len))
                     return 1;
@@ -129,9 +161,10 @@ static int token_cmp (const char *kw, struct ccl_token *token)
                 if (!ccl_memicmp (cp1, token->name, token->len))
                     return 1;
             }
+        }
        cp1 = cp2+1;
     }
-    if (ccl_case_sensitive)
+    if (case_sensitive)
         return token->len == strlen(cp1) 
             && !memcmp (cp1, token->name, token->len);
     return token->len == strlen(cp1) &&
@@ -156,14 +189,14 @@ struct ccl_token *ccl_token_simple (const char *command)
        }
        if (!first)
        {
-           first = last = malloc (sizeof (*first));
-           assert (first);
+           first = last = (struct ccl_token *)malloc (sizeof (*first));
+           ccl_assert (first);
            last->prev = NULL;
        }
        else
        {
-           last->next = malloc (sizeof(*first));
-           assert (last->next);
+           last->next = (struct ccl_token *)malloc (sizeof(*first));
+           ccl_assert (last->next);
            last->next->prev = last;
            last = last->next;
        }
@@ -199,12 +232,14 @@ struct ccl_token *ccl_token_simple (const char *command)
     return first;
 }
 
+
 /*
  * ccl_tokenize: tokenize CCL command string.
  * return: CCL token list.
  */
-struct ccl_token *ccl_tokenize (const char *command)
+struct ccl_token *ccl_parser_tokenize (CCL_parser cclp, const char *command)
 {
+    const char *aliases;
     const char *cp = command;
     struct ccl_token *first = NULL;
     struct ccl_token *last = NULL;
@@ -218,14 +253,14 @@ struct ccl_token *ccl_tokenize (const char *command)
        }
        if (!first)
        {
-           first = last = malloc (sizeof (*first));
-           assert (first);
+           first = last = (struct ccl_token *)malloc (sizeof (*first));
+           ccl_assert (first);
            last->prev = NULL;
        }
        else
        {
-           last->next = malloc (sizeof(*first));
-           assert (last->next);
+           last->next = (struct ccl_token *)malloc (sizeof(*first));
+           ccl_assert (last->next);
            last->next->prev = last;
            last = last->next;
        }
@@ -269,9 +304,6 @@ struct ccl_token *ccl_tokenize (const char *command)
            else
                last->kind = CCL_TOK_REL;
            break;
-       case '-':
-           last->kind = CCL_TOK_MINUS;
-           break;
        case '\"':
            last->kind = CCL_TOK_TERM;
            last->name = cp;
@@ -290,21 +322,48 @@ struct ccl_token *ccl_tokenize (const char *command)
                cp++;
                ++ last->len;
            }
-           if (token_cmp (ccl_token_and, last))
+           last->kind = CCL_TOK_TERM;
+
+           aliases = ccl_qual_search_special(cclp->bibset, "and");
+           if (!aliases)
+               aliases = cclp->ccl_token_and;
+           if (token_cmp (cclp, aliases, last))
                last->kind = CCL_TOK_AND;
-           else if (token_cmp (ccl_token_or, last))
+
+           aliases = ccl_qual_search_special(cclp->bibset, "or");
+           if (!aliases)
+               aliases = cclp->ccl_token_or;
+           if (token_cmp (cclp, aliases, last))
                last->kind = CCL_TOK_OR;
-            else if (token_cmp (ccl_token_not, last))
+
+           aliases = ccl_qual_search_special(cclp->bibset, "not");
+           if (!aliases)
+               aliases = cclp->ccl_token_not;
+            if (token_cmp (cclp, aliases, last))
                last->kind = CCL_TOK_NOT;
-           else if (token_cmp (ccl_token_set, last))
+
+           aliases = ccl_qual_search_special(cclp->bibset, "set");
+           if (!aliases)
+               aliases = cclp->ccl_token_set;
+
+           if (token_cmp (cclp, aliases, last))
                last->kind = CCL_TOK_SET;
-           else
-               last->kind = CCL_TOK_TERM;
        }
     }
     return first;
 }
 
+struct ccl_token *ccl_tokenize (const char *command)
+{
+    CCL_parser cclp = ccl_parser_create ();
+    struct ccl_token *list;
+
+    list = ccl_parser_tokenize (cclp, command);
+
+    ccl_parser_destroy (cclp);
+    return list;
+}
+
 /*
  * ccl_token_del: delete CCL tokens
  */
@@ -319,3 +378,85 @@ void ccl_token_del (struct ccl_token *list)
         list = list1;
     }
 }
+
+char *ccl_strdup (const char *str)
+{
+    int len = strlen(str);
+    char *p = (char*) malloc (len+1);
+    strcpy (p, str);
+    return p;
+}
+
+CCL_parser ccl_parser_create (void)
+{
+    CCL_parser p = (CCL_parser)malloc (sizeof(*p));
+    if (!p)
+       return p;
+    p->look_token = NULL;
+    p->error_code = 0;
+    p->error_pos = NULL;
+    p->bibset = NULL;
+
+    p->ccl_token_and = ccl_strdup("and");
+    p->ccl_token_or = ccl_strdup("or");
+    p->ccl_token_not = ccl_strdup("not andnot");
+    p->ccl_token_set = ccl_strdup("set");
+    p->ccl_case_sensitive = 1;
+
+    return p;
+}
+
+void ccl_parser_destroy (CCL_parser p)
+{
+    if (!p)
+       return;
+    free (p->ccl_token_and);
+    free (p->ccl_token_or);
+    free (p->ccl_token_not);
+    free (p->ccl_token_set);
+    free (p);
+}
+
+void ccl_parser_set_op_and (CCL_parser p, const char *op)
+{
+    if (p && op)
+    {
+       if (p->ccl_token_and)
+           free (p->ccl_token_and);
+       p->ccl_token_and = ccl_strdup (op);
+    }
+}
+
+void ccl_parser_set_op_or (CCL_parser p, const char *op)
+{
+    if (p && op)
+    {
+       if (p->ccl_token_or)
+           free (p->ccl_token_or);
+       p->ccl_token_or = ccl_strdup (op);
+    }
+}
+void ccl_parser_set_op_not (CCL_parser p, const char *op)
+{
+    if (p && op)
+    {
+       if (p->ccl_token_not)
+           free (p->ccl_token_not);
+       p->ccl_token_not = ccl_strdup (op);
+    }
+}
+void ccl_parser_set_op_set (CCL_parser p, const char *op)
+{
+    if (p && op)
+    {
+       if (p->ccl_token_set)
+           free (p->ccl_token_set);
+       p->ccl_token_set = ccl_strdup (op);
+    }
+}
+
+void ccl_parser_set_case (CCL_parser p, int case_sensitivity_flag)
+{
+    if (p)
+       p->ccl_case_sensitive = case_sensitivity_flag;
+}