YAZ 5.37.0
cql2ccl.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include <stdlib.h>
14#include <string.h>
15#include <stdio.h>
16
17#include <yaz/cql.h>
18#include <yaz/snprintf.h>
19
20static int cql_to_ccl_r(struct cql_node *cn,
21 void (*pr)(const char *buf, void *client_data),
22 void *client_data);
23
24static void pr_term(const char **cpp, int stop_at_space,
25 void (*pr)(const char *buf, void *client_data),
26 void *client_data)
27{
28 const char *cp;
29 int quote_mode = 0;
30 for (cp = *cpp; *cp; cp++)
31 {
32 char x[4];
33
34 if (*cp == '\\' && cp[1])
35 {
36 if (!quote_mode)
37 {
38 pr("\"", client_data);
39 quote_mode = 1;
40 }
41 cp++;
42 if (*cp == '\"' || *cp == '\\')
43 pr("\\", client_data);
44 x[0] = *cp;
45 x[1] = '\0';
46 pr(x, client_data);
47 }
48 else if (*cp == '*')
49 {
50 if (quote_mode)
51 {
52 pr("\"", client_data);
53 quote_mode = 0;
54 }
55 pr("?", client_data);
56 }
57 else if (*cp == '?')
58 {
59 if (quote_mode)
60 {
61 pr("\"", client_data);
62 quote_mode = 0;
63 }
64 pr("#", client_data);
65 }
66 else if (*cp == ' ' && stop_at_space)
67 break;
68 else
69 {
70 if (!quote_mode)
71 {
72 pr("\"", client_data);
73 quote_mode = 1;
74 }
75 x[0] = *cp;
76 x[1] = '\0';
77 pr(x, client_data);
78 }
79 }
80 if (quote_mode)
81 pr("\"", client_data);
82 if (cp == *cpp)
83 pr("\"\"", client_data);
84 *cpp = cp;
85}
86
87static int node_st(struct cql_node *cn,
88 void (*pr)(const char *buf, void *client_data),
89 void *client_data)
90{
91 const char *ccl_field = 0;
92 const char *split_op = 0;
93 const char *ccl_rel = 0;
94 const char *rel = cn->u.st.relation;
95
96 if (cn->u.st.index && cql_strcmp(cn->u.st.index,
97 "cql.serverChoice"))
98 ccl_field = cn->u.st.index;
99
100 if (!rel)
101 ;
102 else if (!strcmp(rel, "<") || !strcmp(rel, "<=")
103 || !strcmp(rel, ">") || !strcmp(rel, ">=")
104 || !strcmp(rel, "<>") || !strcmp(rel, "="))
105 ccl_rel = rel;
106 else if (!cql_strcmp(rel, "all"))
107 {
108 ccl_rel = "=";
109 split_op = "and";
110 }
111 else if (!cql_strcmp(rel, "any"))
112 {
113 ccl_rel = "=";
114 split_op = "or";
115 }
116 else if (!strcmp(rel, "==") || !cql_strcmp(rel, "adj"))
117 {
118 ccl_rel = "=";
119 }
120 else
121 {
122 /* unsupported relation */
123 return -1;
124 }
125 for (; cn; cn = cn->u.st.extra_terms)
126 {
127 const char *cp = cn->u.st.term;
128 while (1)
129 {
130 if (ccl_field && ccl_rel)
131 {
132 pr(ccl_field, client_data);
133 pr(ccl_rel, client_data);
134 if (!split_op)
135 ccl_rel = 0;
136 }
137 pr_term(&cp, split_op ? 1 : 0, pr, client_data);
138 while (*cp == ' ')
139 cp++;
140 if (*cp == '\0')
141 break;
142 pr(" ", client_data);
143 if (split_op)
144 {
145 pr(split_op, client_data);
146 pr(" ", client_data);
147 }
148 }
149 if (cn->u.st.extra_terms)
150 {
151 pr(" ", client_data);
152 if (split_op)
153 {
154 pr(split_op, client_data);
155 pr(" ", client_data);
156 }
157 }
158 }
159 return 0;
160}
161
162
163static int node_bool(struct cql_node *cn,
164 void (*pr)(const char *buf, void *client_data),
165 void *client_data)
166{
167 char *value = cn->u.boolean.value;
168 int r;
169
170 pr("(", client_data);
171 r = cql_to_ccl_r(cn->u.boolean.left, pr, client_data);
172 if (r)
173 return r;
174
175 pr(") ", client_data);
176
177 if (cql_strcmp(value, "prox"))
178 { /* not proximity. assuming boolean */
179 pr(value, client_data);
180 }
181 else
182 {
183 struct cql_node *n = cn->u.boolean.modifiers;
184 int ordered = 0;
185 int distance = 1;
186 for (; n ; n = n->u.st.modifiers)
187 if (n->which == CQL_NODE_ST)
188 {
189 if (!cql_strcmp(n->u.st.index, "unit"))
190 {
191 if (!cql_strcmp(n->u.st.term, "word"))
192 ;
193 else
194 return -1;
195 }
196 else if (!cql_strcmp(n->u.st.index, "distance"))
197 {
198 if (!strcmp(n->u.st.relation, "<="))
199 distance = atoi(n->u.st.term);
200 else if (!strcmp(n->u.st.relation, "<"))
201 distance = atoi(n->u.st.term) - 1;
202 else
203 return -1;
204 }
205 else if (!cql_strcmp(n->u.st.index, "unordered"))
206 {
207 ordered = 0;
208 }
209 else if (!cql_strcmp(n->u.st.index, "ordered"))
210 {
211 ordered = 1;
212 }
213 else
214 return -1;
215 }
216 pr(ordered ? "!" : "%", client_data);
217 if (distance != 1)
218 {
219 char x[40];
220 yaz_snprintf(x, sizeof x, "%d", distance);
221 pr(x, client_data);
222 }
223 }
224 pr(" (", client_data);
225
226 r = cql_to_ccl_r(cn->u.boolean.right, pr, client_data);
227 pr(")", client_data);
228 return r;
229}
230
231static int cql_to_ccl_r(struct cql_node *cn,
232 void (*pr)(const char *buf, void *client_data),
233 void *client_data)
234{
235 if (!cn)
236 return -1;
237
238 switch (cn->which)
239 {
240 case CQL_NODE_ST:
241 return node_st(cn, pr, client_data);
242 case CQL_NODE_BOOL:
243 return node_bool(cn, pr, client_data);
244 case CQL_NODE_SORT:
245 return cql_to_ccl_r(cn->u.sort.search, pr, client_data);
246 }
247 return -1;
248}
249
250int cql_to_ccl(struct cql_node *cn,
251 void (*pr)(const char *buf, void *client_data),
252 void *client_data)
253{
254 return cql_to_ccl_r(cn, pr, client_data);
255}
256
257void cql_to_ccl_stdio(struct cql_node *cn, FILE *f)
258{
259 cql_to_ccl(cn, cql_fputs, f);
260}
261
262int cql_to_ccl_buf(struct cql_node *cn, char *out, int max)
263{
264 struct cql_buf_write_info info;
265 int r;
266 info.off = 0;
267 info.max = max;
268 info.buf = out;
269 r = cql_to_ccl(cn, cql_buf_write_handler, &info);
270 if (info.off >= 0)
271 info.buf[info.off] = '\0';
272 else
273 return -2; /* buffer overflow */
274 return r;
275}
276
277/*
278 * Local variables:
279 * c-basic-offset: 4
280 * c-file-style: "Stroustrup"
281 * indent-tabs-mode: nil
282 * End:
283 * vim: shiftwidth=4 tabstop=8 expandtab
284 */
285
static void pr_term(const char **cpp, int stop_at_space, void(*pr)(const char *buf, void *client_data), void *client_data)
Definition cql2ccl.c:24
int cql_to_ccl(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
converts CQL tree to CCL and writes to user-defined stream
Definition cql2ccl.c:250
static int cql_to_ccl_r(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
Definition cql2ccl.c:231
static int node_st(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
Definition cql2ccl.c:87
static int node_bool(struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
Definition cql2ccl.c:163
int cql_to_ccl_buf(struct cql_node *cn, char *out, int max)
converts CQL tree to CCL and writes result to buffer
Definition cql2ccl.c:262
void cql_to_ccl_stdio(struct cql_node *cn, FILE *f)
converts CQL tree to CCL and writes to file
Definition cql2ccl.c:257
Header with public definitions about CQL.
#define CQL_NODE_SORT
Node type: sortby single spec.
Definition cql.h:115
#define CQL_NODE_ST
Node type: search term.
Definition cql.h:111
#define CQL_NODE_BOOL
Node type: boolean.
Definition cql.h:113
int cql_strcmp(const char *s1, const char *s2)
compares two CQL strings (ala strcmp)
Definition cqlutil.c:194
void cql_fputs(const char *buf, void *client_data)
stream handle for file (used by cql_to_xml_stdio)
Definition cqlutil.c:18
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Definition snprintf.c:31
Header for config file reading utilities.
Structure used by cql_buf_write_handler.
Definition cql.h:170
CQL parse tree (node).
Definition cql.h:119
struct cql_node::@103257335133214234142137075341003020020243260314::@231337216262210265241053375071103126222160053350 st
struct cql_node * right
Definition cql.h:147
char * value
Definition cql.h:143
struct cql_node * search
Definition cql.h:159
union cql_node::@103257335133214234142137075341003020020243260314 u
struct cql_node * extra_terms
Definition cql.h:138
struct cql_node::@103257335133214234142137075341003020020243260314::@240210333203360145104277071333350273146264012233 boolean
struct cql_node * modifiers
Definition cql.h:136
int which
Definition cql.h:121
char * relation
Definition cql.h:132
struct cql_node::@103257335133214234142137075341003020020243260314::@115152140343061015107127141216014153002063077012 sort
char * index
Definition cql.h:126
struct cql_node * left
Definition cql.h:145
char * term
Definition cql.h:130
void cql_buf_write_handler(const char *b, void *client_data)
Handler for cql_buf_write_info.
Definition xcqlutil.c:251