X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fcql2ccl.c;h=d08536f20c17a3c13716f104b01b2ccc8bbf85f5;hp=5f2011b4fee925d499ee8eab1d5c2d97b8a32185;hb=d1b8a1c1647ebb00401f6b6e8f992cca7480b5f9;hpb=2cf1b669768e41118f6937dd0afab37c8ed586a8 diff --git a/src/cql2ccl.c b/src/cql2ccl.c index 5f2011b..d08536f 100644 --- a/src/cql2ccl.c +++ b/src/cql2ccl.c @@ -1,10 +1,10 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2011 Index Data + * Copyright (C) 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 @@ -16,26 +16,74 @@ #include -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) { @@ -73,71 +121,113 @@ static int node(struct cql_node *cn, /* 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) { @@ -156,7 +246,7 @@ static int cql_to_ccl_r(struct cql_node *cn, 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) { @@ -168,7 +258,20 @@ void cql_to_ccl_stdio(struct cql_node *cn, FILE *f) 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: