cql2ccl: handle CQL \-sequences differently
[yaz-moved-to-github.git] / src / cql2ccl.c
index f427e7c..54b16e7 100644 (file)
@@ -26,18 +26,65 @@ static void pr_term(struct cql_node *cn,
 {
     while (cn)
     {
-        const char *cp;
-        cp = cn->u.st.term;
-        while (*cp)
+        if (! *cn->u.st.term) /* empty term special case */
+            pr("\"\"", client_data);
+        else
         {
-            char x[2];
-            if (*cp == '*')
-                x[0] = '?';
-            else
-                x[0] = *cp;
-            x[1] = 0;
-            pr(x, client_data);
-            cp++;
+            const char *cp;
+            int quote_mode = 0;
+            for (cp = cn->u.st.term; *cp; cp++)
+            {
+                char x[4];
+                
+                if (*cp == '\\' && cp[1])
+                {
+                    if (!quote_mode)
+                    {
+                        pr("\"", client_data);
+                        quote_mode = 1;
+                    }
+                    cp++;
+                    if (*cp == '\"' || *cp == '\\')
+                        pr("\\\"", client_data);
+                    else
+                    {
+                        x[0] = *cp;
+                        x[1] = '\0';
+                        pr(x, client_data);
+                    }
+                }
+                else if (*cp == '*')
+                {
+                    if (quote_mode)
+                    {
+                        pr("\"", client_data);
+                        quote_mode = 0;
+                    }
+                    pr("?", client_data);
+                }
+                else if (*cp == '?')
+                {
+                    if (quote_mode)
+                    {
+                        pr("\"", client_data);
+                        quote_mode = 0;
+                    }
+                    pr("#", client_data);
+                }
+                else
+                {
+                    if (!quote_mode)
+                    {
+                        pr("\"", client_data);
+                        quote_mode = 1;
+                    }
+                    x[0] = *cp;
+                    x[1] = '\0';
+                    pr(x, client_data);
+                }
+            }
+            if (quote_mode)
+                pr("\"", client_data);
         }
         if (cn->u.st.extra_terms)
             pr(" ", client_data);
@@ -133,6 +180,7 @@ static int bool(struct cql_node *cn,
                 void (*pr)(const char *buf, void *client_data),
                 void *client_data)
 {
+    char *value = cn->u.boolean.value;
     int r;
 
     pr("(", client_data);
@@ -141,7 +189,54 @@ static int bool(struct cql_node *cn,
         return r;
     
     pr(" ", client_data);
-    pr(cn->u.boolean.value, client_data);
+
+    if (strcmp(value, "prox"))
+    {   /* not proximity. assuming boolean */
+        pr(value, client_data);
+    }
+    else
+    {
+        struct cql_node *n = cn->u.boolean.modifiers;
+        int ordered = 0;
+        int distance = 1;
+        for (; n ; n = n->u.st.modifiers)
+            if (n->which == CQL_NODE_ST)
+            {
+                if (!strcmp(n->u.st.index, "unit"))
+                {
+                    if (!strcmp(n->u.st.term, "word"))
+                        ;
+                    else
+                        return -1;
+                }
+                else if (!strcmp(n->u.st.index, "distance"))
+                {
+                    if (!strcmp(n->u.st.relation, "<="))
+                        distance = atoi(n->u.st.term);
+                    else if (!strcmp(n->u.st.relation, "<"))
+                        distance = atoi(n->u.st.term) - 1;
+                    else
+                        return -1;
+                }
+                else if (!strcmp(n->u.st.index, "unordered"))
+                {
+                    ordered = 0;
+                }
+                else if (!strcmp(n->u.st.index, "ordered"))
+                {
+                    ordered = 1;
+                }
+                else
+                    return -1;
+            }
+        pr(ordered ? "!" : "%", client_data);
+        if (distance != 1)
+        {
+            char x[40];
+            sprintf(x, "%d", distance);
+            pr(x, client_data);
+        }
+    }
     pr(" ", client_data);
 
     r = cql_to_ccl_r(cn->u.boolean.right, pr, client_data);