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