90ee5d647637ebb64e93850b1a4ec9eb6ea22403
[yaz-moved-to-github.git] / src / cql2ccl.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file xcqlutil.c
7  * \brief Implements CQL to XCQL conversion.
8  */
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
19 static int cql_to_ccl_r(struct cql_node *cn, 
20                         void (*pr)(const char *buf, void *client_data),
21                         void *client_data);
22
23 static void pr_term(struct cql_node *cn,
24                 void (*pr)(const char *buf, void *client_data),
25                 void *client_data)
26 {
27     while (cn)
28     {
29         pr("\"", client_data);
30         pr(cn->u.st.term, client_data);
31         pr("\"", client_data);
32         if (cn->u.st.extra_terms)
33             pr(" ", client_data);
34         cn = cn->u.st.extra_terms;
35     }
36 }
37
38 static int node(struct cql_node *cn, 
39                 void (*pr)(const char *buf, void *client_data),
40                 void *client_data)
41 {
42     const char *ccl_field = 0;
43     const char *split_op = 0;
44     const char *ccl_rel = 0;
45     const char *rel = cn->u.st.relation;
46
47     if (cn->u.st.index && strcmp(cn->u.st.index,
48                                  "cql.serverChoice"))
49         ccl_field = cn->u.st.index;
50
51     if (!rel)
52         ;
53     else if (!strcmp(rel, "<") || !strcmp(rel, "<=")
54              || !strcmp(rel, ">") || !strcmp(rel, ">=")
55              || !strcmp(rel, "<>") || !strcmp(rel, "="))
56         ccl_rel = rel;
57     else if (!strcmp(rel, "all"))
58     {
59         ccl_rel = "=";
60         split_op = "and";
61     }
62     else if (!strcmp(rel, "any"))
63     {
64         ccl_rel = "=";
65         split_op = "or";
66     }
67     else if (!strcmp(rel, "==") || !strcmp(rel, "adj"))
68     {
69         ccl_rel = "=";
70     }
71     else
72     {
73         /* unsupported relation */
74         return -1;
75     }
76     if (!split_op)
77     {
78         if (ccl_field && ccl_rel)
79         {
80             pr(ccl_field, client_data);
81             pr(ccl_rel, client_data);
82         }
83         pr_term(cn, pr, client_data);
84     }
85     else
86     {
87         const char *cp = cn->u.st.term;
88         
89         while (1)
90         {
91             if (*cp == '\0')
92                 break;
93             if (ccl_field && ccl_rel)
94             {
95                 pr(ccl_field, client_data);
96                 pr(ccl_rel, client_data);
97             }
98             while (*cp && *cp != ' ')
99             {
100                 char x[2];
101                 x[0] = *cp;
102                 x[1] = '\0';
103                 pr(x, client_data);
104                 cp++;
105             }
106             while (*cp == ' ')
107                 cp++;
108             if (*cp == '\0')
109                 break;
110             pr(" ", client_data);
111             pr(split_op, client_data);
112             pr(" ", client_data);            
113         }
114         return -1;
115     }
116     return 0;
117 }
118
119
120 static int bool(struct cql_node *cn, 
121                 void (*pr)(const char *buf, void *client_data),
122                 void *client_data)
123 {
124     int r;
125
126     pr("(", client_data);
127     r = cql_to_ccl_r(cn->u.boolean.left, pr, client_data);
128     if (r)
129         return r;
130     
131     pr(" ", client_data);
132     pr(cn->u.boolean.value, client_data);
133     pr(" ", client_data);
134
135     r = cql_to_ccl_r(cn->u.boolean.right, pr, client_data);
136     pr(")", client_data);
137     return r;
138 }
139
140 static int cql_to_ccl_r(struct cql_node *cn, 
141                         void (*pr)(const char *buf, void *client_data),
142                         void *client_data)
143 {
144     if (!cn)
145         return -1;
146
147     switch (cn->which)
148     {
149     case CQL_NODE_ST:
150         return node(cn, pr, client_data);
151     case CQL_NODE_BOOL:
152         return bool(cn, pr, client_data);
153     case CQL_NODE_SORT:
154         return cql_to_ccl_r(cn->u.sort.search, pr, client_data);
155     }
156     return -1;
157 }
158
159 int cql_to_ccl(struct cql_node *cn, 
160                void (*pr)(const char *buf, void *client_data),
161                void *client_data)
162 {
163     return cql_to_ccl_r(cn, pr, client_data);
164 }
165
166 void cql_to_ccl_stdio(struct cql_node *cn, FILE *f)
167 {
168     cql_to_ccl(cn, cql_fputs, f);
169 }
170
171 int cql_to_ccl_buf(struct cql_node *cn, char *out, int max)
172 {
173     struct cql_buf_write_info info;
174     info.off = 0;
175     info.max = max;
176     info.buf = out;
177     cql_to_ccl(cn, cql_buf_write_handler, &info);
178     if (info.off >= 0)
179         info.buf[info.off] = '\0';
180     return info.off;
181 }
182
183 /*
184  * Local variables:
185  * c-basic-offset: 4
186  * c-file-style: "Stroustrup"
187  * indent-tabs-mode: nil
188  * End:
189  * vim: shiftwidth=4 tabstop=8 expandtab
190  */
191