Beginnings for RPN to CQL transform.
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 28 Apr 2008 09:53:50 +0000 (11:53 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 28 Apr 2008 09:53:50 +0000 (11:53 +0200)
include/yaz/Makefile.am
include/yaz/cql.h
include/yaz/rpn2cql.h [new file with mode: 0644]
src/Makefile.am
src/cqltransform.c
src/rpn2cql.c [new file with mode: 0644]
util/cql2pqf.c
win/makefile

index 6e0e1b5..cc34d34 100644 (file)
@@ -3,7 +3,7 @@
 
 noinst_HEADERS = icu_I18N.h
 
-pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h comstack.h \
+pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \
  diagbib1.h diagsrw.h diagsru_update.h sortspec.h log.h logrpn.h marcdisp.h \
  nmem.h nmem_xml.h odr.h \
  options.h otherinfo.h pquery.h prt-ext.h querytowrbuf.h \
index 859519f..bf88187 100644 (file)
@@ -300,6 +300,14 @@ int cql_transform_buf(cql_transform_t ct,
 YAZ_EXPORT
 int cql_transform_error(cql_transform_t ct, const char **addinfo);
 
+/** \brief sets error and addinfo for transform
+    \param ct CQL transform handle
+    \param error error code
+    \param addinfo additional info
+ */
+YAZ_EXPORT
+void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo);
+
 /** \brief returns the CQL message corresponding to a given error code.
     \param code error code
     \returns text message
diff --git a/include/yaz/rpn2cql.h b/include/yaz/rpn2cql.h
new file mode 100644 (file)
index 0000000..90798db
--- /dev/null
@@ -0,0 +1,64 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2008 Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Index Data nor the names of its contributors
+ *       may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file
+    \brief Header for RPN to CQL tranform
+*/
+
+#ifndef RPN2CQL_H_INCLUDED
+#define RPN2CQL_H_INCLUDED
+#include <yaz/z-core.h>
+#include <yaz/cql.h>
+
+YAZ_BEGIN_CDECL
+
+/** \brief transforms PQF given a CQL tree (from FILE)
+    \param ct CQL transform handle
+    \param pr print function
+    \param client_data opaque data to be passed to print handler
+    \param q RPN Query
+    \retval 0 success
+    \retval !=0 failure (error code)
+ */
+YAZ_EXPORT
+int cql_transform_rpn2cql(cql_transform_t ct,
+                          void (*pr)(const char *buf, void *client_data),
+                          void *client_data,
+                          Z_RPNQuery *q);
+
+YAZ_END_CDECL
+
+#endif
+/* CQL_H_INCLUDED */
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 983ab68..90bce9e 100644 (file)
@@ -88,7 +88,7 @@ libyaz_la_SOURCES=version.c options.c log.c \
   grs1disp.c zgdu.c soap.c srw.c srwutil.c \
   opacdisp.c cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \
   cclqfile.c cclstr.c cclxmlconfig.c ccl_stop_words.c \
-  cql.y cqlstdio.c cqltransform.c cqlutil.c xcqlutil.c cqlstring.c \
+  cql.y cqlstdio.c cqltransform.c cqlutil.c xcqlutil.c cqlstring.c rpn2cql.c \
   cqlstrer.c querytowrbuf.c \
   tcpdchk.c \
   test.c timing.c \
index 59b74b9..218fd63 100644 (file)
@@ -710,6 +710,14 @@ int cql_transform_error(cql_transform_t ct, const char **addinfo)
     *addinfo = ct->addinfo;
     return ct->error;
 }
+
+void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo)
+{
+    xfree(ct->addinfo);
+    ct->addinfo = addinfo ? xstrdup(addinfo) : 0;
+    ct->error = error;
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
diff --git a/src/rpn2cql.c b/src/rpn2cql.c
new file mode 100644 (file)
index 0000000..3e581a4
--- /dev/null
@@ -0,0 +1,127 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2008 Index Data
+ * See the file LICENSE for details.
+ */
+
+/**
+ * \file
+ * \brief Implements RPN to CQL conversion
+ *
+ * Evaluation order of rules:
+ *
+ * always
+ * relation
+ * structure
+ * position
+ * truncation
+ * index
+ * relationModifier
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <yaz/rpn2cql.h>
+#include <yaz/xmalloc.h>
+#include <yaz/diagbib1.h>
+#include <yaz/z-core.h>
+#include <yaz/wrbuf.h>
+
+static int rpn2cql_simple(cql_transform_t ct,
+                          void (*pr)(const char *buf, void *client_data),
+                          void *client_data,
+                          Z_Operand *q)
+{
+    int ret = 0;
+    if (q->which != Z_Operand_APT)
+    {
+        ret = -1;
+        cql_transform_set_error(ct, YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM, 0);
+    }
+    else
+    {
+        Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
+        Z_Term *term = apt->term;
+        Z_AttributeList *attributes = apt->attributes;
+        WRBUF w = wrbuf_alloc();
+
+        switch(term->which)
+        {
+        case Z_Term_general:
+            wrbuf_write(w, (const char *) term->u.general->buf, term->u.general->len);
+            break;
+        case Z_Term_numeric:
+            wrbuf_printf(w, "%d", *term->u.numeric);
+            break;
+        case Z_Term_characterString:
+            wrbuf_puts(w, term->u.characterString);
+            break;
+        default:
+            ret = -1;
+            cql_transform_set_error(ct, YAZ_BIB1_TERM_TYPE_UNSUPP, 0);
+        }
+        if (ret == 0)
+            pr(wrbuf_cstr(w), client_data);
+        wrbuf_destroy(w);
+    }
+    return ret;
+}
+
+static int rpn2cql_structure(cql_transform_t ct,
+                             void (*pr)(const char *buf, void *client_data),
+                             void *client_data,
+                             Z_RPNStructure *q, int nested)
+{
+    if (q->which == Z_RPNStructure_simple)
+        return rpn2cql_simple(ct, pr, client_data, q->u.simple);
+    else
+    {
+        Z_Operator *op = q->u.complex->roperator;
+        int r;
+
+        if (nested)
+            pr("(", client_data);
+
+        r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1);
+        if (r)
+            return r;
+        switch(op->which)
+        {
+        case  Z_Operator_and:
+            pr(" and ", client_data);
+            break;
+        case  Z_Operator_or:
+            pr(" or ", client_data);
+            break;
+        case  Z_Operator_and_not:
+            pr(" not ", client_data);
+            break;
+        case  Z_Operator_prox:
+            cql_transform_set_error(ct, YAZ_BIB1_UNSUPP_SEARCH, 0);
+            return -1;
+        }
+        r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1);
+        if (nested)
+            pr(")", client_data);
+        return r;
+    }
+}
+
+int cql_transform_rpn2cql(cql_transform_t ct,
+                          void (*pr)(const char *buf, void *client_data),
+                          void *client_data,
+                          Z_RPNQuery *q)
+{
+    cql_transform_set_error(ct, 0, 0);
+    return rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0);
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index ac2a457..55bea5d 100644 (file)
@@ -6,28 +6,28 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#include <yaz/cql.h>
+#include <yaz/rpn2cql.h>
+#include <yaz/pquery.h>
 #include <yaz/options.h>
 
 static void usage(void)
 {
-    fprintf (stderr, "usage\n cql2pqf [-n <n>] <properties> [<query>]\n");
-    exit (1);
+    fprintf(stderr, "usage\n cql2pqf [-n <n>] [-r] <properties> [<query>]\n");
+    exit(1);
 }
 
 int main(int argc, char **argv)
 {
     cql_transform_t ct;
-    int r = 0;
     int i, iterations = 1;
-    CQL_parser cp = cql_parser_create();
     char *query = 0;
     char *fname = 0;
+    int reverse = 0;
 
     int ret;
     char *arg;
 
-    while ((ret = options("n:", argv, argc, &arg)) != -2)
+    while ((ret = options("n:r", argv, argc, &arg)) != -2)
     {
         switch (ret)
         {
@@ -37,6 +37,8 @@ int main(int argc, char **argv)
             else
                 query = arg;
             break;
+        case 'r':
+            reverse = 1;
         case 'n':
             iterations = atoi(arg);
             break;
@@ -49,40 +51,76 @@ int main(int argc, char **argv)
     ct = cql_transform_open_fname(fname);
     if (!ct)
     {
-        fprintf (stderr, "failed to read properties %s\n", fname);
-        exit (1);
+        fprintf(stderr, "failed to read properties %s\n", fname);
+        exit(1);
     }
 
-    if (query)
+    if (reverse)
     {
-        for (i = 0; i<iterations; i++)
-            r = cql_parser_string(cp, query);
+        if (!query)
+            usage();
+        else
+        {
+            ODR odr = odr_createmem(ODR_ENCODE);
+            YAZ_PQF_Parser pp = yaz_pqf_create();
+            Z_RPNQuery *rpn = yaz_pqf_parse(pp, odr, query);
+            if (!rpn)
+            {
+                fprintf(stderr, "PQF syntax error\n");
+            }
+            else 
+            {
+                int ret = cql_transform_rpn2cql(ct, cql_fputs, stdout, rpn);
+                
+                if (ret)
+                {
+                    const char *addinfo;
+                    int r = cql_transform_error(ct, &addinfo);
+                    printf("Transform error %d %s\n", r, addinfo ? addinfo : "");
+                }
+                else
+                    printf("\n");
+            }
+            yaz_pqf_destroy(pp);
+            odr_destroy(odr);
+        }
     }
     else
-        r = cql_parser_stdio(cp, stdin);
-
-    if (r)
-        fprintf (stderr, "Syntax error\n");
-    else
     {
-        r = cql_transform_FILE(ct, cql_parser_result(cp), stdout);
-        printf("\n");
-        if (r)
+        CQL_parser cp = cql_parser_create();
+        int r = 0;
+        
+        if (query)
         {
-            const char *addinfo;
-            cql_transform_error(ct, &addinfo);
-            printf ("Transform error %d %s\n", r, addinfo ? addinfo : "");
+            for (i = 0; i<iterations; i++)
+                r = cql_parser_string(cp, query);
         }
         else
+            r = cql_parser_stdio(cp, stdin);
+        
+        if (r)
+            fprintf(stderr, "Syntax error\n");
+        else
         {
-            FILE *null = fopen("/dev/null", "w");
-            for (i = 1; i<iterations; i++)
-                cql_transform_FILE(ct, cql_parser_result(cp), null);
-            fclose(null);
+            r = cql_transform_FILE(ct, cql_parser_result(cp), stdout);
+            printf("\n");
+            if (r)
+            {
+                const char *addinfo;
+                r = cql_transform_error(ct, &addinfo);
+                printf("Transform error %d %s\n", r, addinfo ? addinfo : "");
+            }
+            else
+            {
+                FILE *null = fopen("/dev/null", "w");
+                for (i = 1; i<iterations; i++)
+                    cql_transform_FILE(ct, cql_parser_result(cp), null);
+                fclose(null);
+            }
         }
+        cql_parser_destroy(cp);
     }
     cql_transform_close(ct);
-    cql_parser_destroy(cp);
     return 0;
 }
 /*
index ecfce48..b4cd961 100644 (file)
@@ -479,6 +479,7 @@ MISC_OBJS= \
    $(OBJDIR)\cqltransform.obj \
    $(OBJDIR)\cqlutil.obj \
    $(OBJDIR)\cqlstrer.obj \
+   $(OBJDIR)\rpn2cql.obj \
    $(OBJDIR)\xcqlutil.obj \
    $(OBJDIR)\elementset.obj \
    $(OBJDIR)\timing.obj \