CQL to RPN: term may be passed through verbatim
[yaz-moved-to-github.git] / src / cqltransform.c
index 3163775..b2422c9 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2011 Index Data
+ * Copyright (C) 1995-2012 Index Data
  * See the file LICENSE for details.
  */
 /**
@@ -616,9 +616,17 @@ static void emit_term(cql_transform_t ct,
 {
     int i;
     const char *ns = cn->u.st.index_uri;
-    int process_term = !has_modifier(cn, "regexp");
-    char *z3958_mem = 0;
+    int z3958_mode = 0;
+    int process_term = 1;
 
+    if (has_modifier(cn, "regexp"))
+        process_term = 0;
+    else if (cql_lookup_property(ct, "truncation", 0, "cql"))
+    {
+        process_term = 0;
+        cql_pr_attr(ct, "truncation", "cql", 0,
+                    pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP);
+    }
     assert(cn->which == CQL_NODE_ST);
 
     if (process_term && length > 0)
@@ -685,34 +693,12 @@ static void emit_term(cql_transform_t ct,
         }
         else if (first_wc)
         {
-            /* We have one or more wildcard characters, but not in a
-             * way that can be dealt with using only the standard
-             * left-, right- and both-truncation attributes.  We need
-             * to translate the pattern into a Z39.58-type pattern,
-             * which has been supported in BIB-1 since 1996.  If
-             * there's no configuration element for "truncation.z3958"
-             * we indicate this as error 28 "Masking character not
-             * supported".
-             */
-            int i;
+            z3958_mode = 1;
             cql_pr_attr(ct, "truncation", "z3958", 0,
                         pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP);
-            z3958_mem = (char *) xmalloc(length+1);
-            for (i = 0; i < length; i++)
-            {
-                if (i > 0 && term[i-1] == '\\')
-                    z3958_mem[i] = term[i];
-                else if (term[i] == '*')
-                    z3958_mem[i] = '?';
-                else if (term[i] == '?')
-                    z3958_mem[i] = '#';
-                else
-                    z3958_mem[i] = term[i];
-            }
-            z3958_mem[length] = '\0';
-            term = z3958_mem;
         }
-        else {
+        else
+        {
             /* No masking characters.  Use "truncation.none" if given. */
             cql_pr_attr(ct, "truncation", "none", 0,
                         pr, client_data, 0);
@@ -733,20 +719,47 @@ static void emit_term(cql_transform_t ct,
         }
     }
 
+    /* produce only \-sequences if:
+       1) the output is a Z39.58-trunc reserved character
+       2) the output is a PQF reserved character (\\, \")
+    */
     (*pr)("\"", client_data);
     for (i = 0; i < length; i++)
     {
-        /* pr(int) each character */
-        /* we do not need to deal with \-sequences because the
-           CQL and PQF terms have same \-format, bug #1988 */
-        char buf[2];
-
-        buf[0] = term[i];
-        buf[1] = '\0';
-        (*pr)(buf, client_data);
+        char x[3]; /* temp buffer */
+        if (i > 0 && term[i-1] == '\\')
+        {
+            if (term[i] == '\"' || term[i] == '\\')
+                pr("\\", client_data);
+            if (z3958_mode && strchr("#?", term[i]))
+                pr("\\\\", client_data); /* double \\ to survive PQF parse */
+            x[0] = term[i];
+            x[1] = '\0';
+            pr(x, client_data);
+        }
+        else if (z3958_mode && term[i] == '*')
+        {
+            pr("?", client_data);
+            /* avoid ?n sequences output (n=[0-9]) because that has
+               different semantics than just a single ? in Z39.58
+            */
+            if (i < length - 1 && yaz_isdigit(term[i+1]))
+                pr("\\\\", client_data); /* double \\ to survive PQF parse */
+        }
+        else if (z3958_mode && term[i] == '?')
+            pr("#", client_data);
+        else if (term[i] != '\\')
+        {
+            if (term[i] == '\"')
+                pr("\\", client_data);
+            if (z3958_mode && strchr("#?", term[i]))
+                pr("\\\\", client_data); /* double \\ to survive PQF parse */
+            x[0] = term[i];
+            x[1] = '\0';
+            pr(x, client_data);
+        }
     }
     (*pr)("\" ", client_data);
-    xfree(z3958_mem);
 }
 
 static void emit_terms(cql_transform_t ct,