From: Adam Dickmeiss Date: Fri, 10 Jun 2011 11:40:39 +0000 (+0200) Subject: Add cql_to_ccl and cql_to_ccl_stdio. X-Git-Tag: v4.2.2~5 X-Git-Url: http://jsfdemo.indexdata.com/cgi-bin?a=commitdiff_plain;h=2cf1b669768e41118f6937dd0afab37c8ed586a8;p=yaz-moved-to-github.git Add cql_to_ccl and cql_to_ccl_stdio. These utilities makes a rough conversion from CQL parse tree (cql_node) to a CCL string. --- diff --git a/include/yaz/cql.h b/include/yaz/cql.h index 2ec9776..817e04b 100644 --- a/include/yaz/cql.h +++ b/include/yaz/cql.h @@ -243,6 +243,23 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f); YAZ_EXPORT int cql_to_xml_buf(struct cql_node *cn, char *out, int max); +/** \brief converts CQL tree to CCL and writes to user-defined stream + \param cn CQL node (tree) + \param pr print function + \param client_data data to be passed to pr function + */ +YAZ_EXPORT +int cql_to_ccl(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data); + +/** \brief converts CQL tree to CCL and writes to file + \param cn CQL node (tree) + \param f file handle + */ +YAZ_EXPORT +void cql_to_ccl_stdio(struct cql_node *cn, FILE *f); + /** \brief stream handle for file (used by cql_to_xml_stdio) */ YAZ_EXPORT void cql_fputs(const char *buf, void *client_data); diff --git a/src/Makefile.am b/src/Makefile.am index 31343c5..fc22046 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -95,7 +95,7 @@ libyaz_la_SOURCES=version.c options.c log.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_sortkeys.c rpn2cql.c \ + cql_sortkeys.c cql2ccl.c rpn2cql.c \ rpn2solr.c solrtransform.c \ cqlstrer.c querytowrbuf.c \ tcpdchk.c \ diff --git a/src/cql2ccl.c b/src/cql2ccl.c new file mode 100644 index 0000000..5f2011b --- /dev/null +++ b/src/cql2ccl.c @@ -0,0 +1,181 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2011 Index Data + * See the file LICENSE for details. + */ +/** + * \file xcqlutil.c + * \brief Implements CQL to XCQL conversion. + */ +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +static int cql_to_ccl_r(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data); + +static void pr_term(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + while (cn) + { + pr("\"", client_data); + pr(cn->u.st.term, client_data); + pr("\"", client_data); + if (cn->u.st.extra_terms) + pr(" ", client_data); + cn = cn->u.st.extra_terms; + } +} + +static int node(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + const char *ccl_field = 0; + const char *split_op = 0; + const char *ccl_rel = 0; + const char *rel = cn->u.st.relation; + + if (cn->u.st.index && strcmp(cn->u.st.index, + "cql.serverChoice")) + ccl_field = cn->u.st.index; + + if (!rel) + ; + else if (!strcmp(rel, "<") || !strcmp(rel, "<=") + || !strcmp(rel, ">") || !strcmp(rel, ">=") + || !strcmp(rel, "<>") || !strcmp(rel, "=")) + ccl_rel = rel; + else if (!strcmp(rel, "all")) + { + ccl_rel = "="; + split_op = "and"; + } + else if (!strcmp(rel, "any")) + { + ccl_rel = "="; + split_op = "or"; + } + else if (!strcmp(rel, "==") || !strcmp(rel, "adj")) + { + ccl_rel = "="; + } + else + { + /* unsupported relation */ + return -1; + } + if (!split_op) + { + if (ccl_field && ccl_rel) + { + pr(ccl_field, client_data); + pr(ccl_rel, client_data); + } + pr_term(cn, pr, client_data); + } + else + { + const char *cp = cn->u.st.term; + + while (1) + { + if (*cp == '\0') + break; + if (ccl_field && ccl_rel) + { + pr(ccl_field, client_data); + pr(ccl_rel, client_data); + } + while (*cp && *cp != ' ') + { + char x[2]; + x[0] = *cp; + x[1] = '\0'; + pr(x, client_data); + cp++; + } + while (*cp == ' ') + cp++; + if (*cp == '\0') + break; + pr(" ", client_data); + pr(split_op, client_data); + pr(" ", client_data); + } + return -1; + } + return 0; +} + + +static int bool(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + int r; + + pr("(", client_data); + r = cql_to_ccl_r(cn->u.boolean.left, pr, client_data); + if (r) + return r; + + pr(" ", client_data); + pr(cn->u.boolean.value, client_data); + pr(" ", client_data); + + r = cql_to_ccl_r(cn->u.boolean.right, pr, client_data); + pr(")", client_data); + return r; +} + +static int cql_to_ccl_r(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + if (!cn) + return -1; + + switch (cn->which) + { + case CQL_NODE_ST: + return node(cn, pr, client_data); + case CQL_NODE_BOOL: + return bool(cn, pr, client_data); + case CQL_NODE_SORT: + return cql_to_ccl_r(cn->u.sort.search, pr, client_data); + } + return -1; +} + +int cql_to_ccl(struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + return cql_to_ccl_r(cn, pr, client_data); +} + +void cql_to_ccl_stdio(struct cql_node *cn, FILE *f) +{ + cql_to_ccl(cn, cql_fputs, f); +} + + + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +