/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2011 Index Data
+ * Copyright (C) 1995-2013 Index Data
* See the file LICENSE for details.
*/
/**
- * \file xcqlutil.c
- * \brief Implements CQL to XCQL conversion.
+ * \file cql2ccl.c
+ * \brief Implements CQL to CCL conversion.
*/
#if HAVE_CONFIG_H
#include <config.h>
#include <yaz/cql.h>
-static int cql_to_ccl_r(struct cql_node *cn,
+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)
+static void pr_term(const char **cpp, int stop_at_space,
+ void (*pr)(const char *buf, void *client_data),
+ void *client_data)
{
- while (cn)
+ const char *cp;
+ int quote_mode = 0;
+ for (cp = *cpp; *cp; cp++)
{
- 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;
+ char x[4];
+
+ if (*cp == '\\' && cp[1])
+ {
+ if (!quote_mode)
+ {
+ pr("\"", client_data);
+ quote_mode = 1;
+ }
+ cp++;
+ if (*cp == '\"' || *cp == '\\')
+ pr("\\", client_data);
+ 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 (*cp == ' ' && stop_at_space)
+ break;
+ 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 (cp == *cpp)
+ pr("\"\"", client_data);
+ *cpp = cp;
}
-static int node(struct cql_node *cn,
+static int node(struct cql_node *cn,
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
/* 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
+ for (; cn; cn = cn->u.st.extra_terms)
{
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);
+ if (!split_op)
+ ccl_rel = 0;
}
- while (*cp && *cp != ' ')
- {
- char x[2];
- x[0] = *cp;
- x[1] = '\0';
- pr(x, client_data);
- cp++;
- }
+ pr_term(&cp, split_op ? 1 : 0, pr, client_data);
while (*cp == ' ')
cp++;
if (*cp == '\0')
break;
pr(" ", client_data);
- pr(split_op, client_data);
- pr(" ", client_data);
+ if (split_op)
+ {
+ pr(split_op, client_data);
+ pr(" ", client_data);
+ }
+ }
+ if (cn->u.st.extra_terms)
+ {
+ pr(" ", client_data);
+ if (split_op)
+ {
+ pr(split_op, client_data);
+ pr(" ", client_data);
+ }
}
- return -1;
}
return 0;
}
-static int bool(struct cql_node *cn,
+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);
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);
+
+ pr(") ", 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);
pr(")", client_data);
return r;
}
-static int cql_to_ccl_r(struct cql_node *cn,
+static int cql_to_ccl_r(struct cql_node *cn,
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
return -1;
}
-int cql_to_ccl(struct cql_node *cn,
+int cql_to_ccl(struct cql_node *cn,
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
cql_to_ccl(cn, cql_fputs, f);
}
-
+int cql_to_ccl_buf(struct cql_node *cn, char *out, int max)
+{
+ struct cql_buf_write_info info;
+ int r;
+ info.off = 0;
+ info.max = max;
+ info.buf = out;
+ r = cql_to_ccl(cn, cql_buf_write_handler, &info);
+ if (info.off >= 0)
+ info.buf[info.off] = '\0';
+ else
+ return -2; /* buffer overflow */
+ return r;
+}
/*
* Local variables: