Extend MARC-8 to handle ESC-G0 EACC. Fix conversion order for MARCXML
[yaz-moved-to-github.git] / src / xcqlutil.c
1 /* $Id: xcqlutil.c,v 1.3 2004-03-15 21:39:06 adam Exp $
2    Copyright (C) 2002-2004
3    Index Data Aps
4
5 This file is part of the YAZ toolkit.
6
7 See the file LICENSE.
8 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12
13 #include <yaz/cql.h>
14
15 static void pr_n(const char *buf, 
16                 void (*pr)(const char *buf, void *client_data),
17                 void *client_data, int n)
18 {
19     int i;
20     for (i = 0; i<n; i++)
21         (*pr)(" ", client_data);
22     (*pr)(buf, client_data);
23 }
24
25 static void pr_cdata(const char *buf,
26                      void (*pr)(const char *buf, void *client_data),
27                      void *client_data)
28 {
29     const char *src = buf;
30     char bf[2];
31     while (*src)
32     {
33         switch(*src)
34         {
35         case '&':
36             (*pr)("&amp;", client_data);
37             break;
38         case '<':
39             (*pr)("&lt;", client_data);
40             break;
41         case '>':
42             (*pr)("&gt;", client_data);
43             break;
44         default:
45             bf[0] = *src;
46             bf[1] = 0;
47             (*pr)(bf, client_data);
48         }
49         src++;
50     }
51 }
52                     
53 static void prefixes(struct cql_node *cn,
54                      void (*pr)(const char *buf, void *client_data),
55                      void *client_data, int level)
56 {
57     int head = 0;
58     if (cn->u.st.index_uri)
59     {
60         pr_n("<prefixes>\n", pr, client_data, level);
61         head = 1;
62
63         pr_n("<prefix>\n", pr, client_data, level+2);
64         pr_n("<identifier>", pr, client_data, level+4);
65         pr_cdata(cn->u.st.index_uri, pr, client_data);
66         pr_n("</identifier>\n", pr, client_data, 0);
67         pr_n("</prefix>\n", pr, client_data, level+2);
68     }
69     if (cn->u.st.relation_uri && cn->u.st.relation)
70     {
71         if (!head)
72             pr_n("<prefixes>\n", pr, client_data, level);
73         pr_n("<prefix>\n", pr, client_data, level+2);
74         pr_n("<name>", pr, client_data, level+4);
75         pr_cdata("rel", pr, client_data);
76         pr_n("</name>\n", pr, client_data, 0);
77         pr_n("<identifier>", pr, client_data, level+4);
78         pr_cdata(cn->u.st.relation_uri, pr, client_data);
79         pr_n("</identifier>\n", pr, client_data, 0);
80         pr_n("</prefix>\n", pr, client_data, level+2);
81     }
82     if (head)
83         pr_n("</prefixes>\n", pr, client_data, level);
84 }
85                      
86 static void cql_to_xml_mod(struct cql_node *m,
87                            void (*pr)(const char *buf, void *client_data),
88                            void *client_data, int level)
89 {
90     if (m)
91     {
92         pr_n("<modifiers>\n", pr, client_data, level);
93         for (; m; m = m->u.st.modifiers)
94         {
95             pr_n("<modifier>\n", pr, client_data, level+2);
96             pr_n("<type>", pr, client_data, level+4);
97             pr_cdata(m->u.st.index, pr, client_data);
98             pr_n("</type>\n", pr, client_data, 0);
99             if (m->u.st.relation)
100             {
101                 pr_n("<relation>", pr, client_data, level+4);
102                 pr_cdata(m->u.st.relation, pr, client_data);
103                 pr_n("</relation>\n", pr, client_data, 0);
104             }
105             if (m->u.st.term)
106             {
107                 pr_n("<value>", pr, client_data, level+4);
108                 pr_cdata(m->u.st.term, pr, client_data);
109                 pr_n("</value>\n", pr, client_data, 0);
110             }
111             pr_n("</modifier>\n", pr, client_data, level+2);
112         }
113         pr_n("</modifiers>\n", pr, client_data, level);
114     }
115 }
116
117 static void cql_to_xml_r(struct cql_node *cn,
118                          void (*pr)(const char *buf, void *client_data),
119                          void *client_data, int level)
120 {
121     if (!cn)
122         return;
123     switch (cn->which)
124     {
125     case CQL_NODE_ST:
126         pr_n("<searchClause>\n", pr, client_data, level);
127         prefixes(cn, pr, client_data, level+2);
128         if (cn->u.st.index)
129         {
130             pr_n("<index>", pr, client_data, level+2);
131             pr_cdata(cn->u.st.index, pr, client_data);
132             pr_n("</index>\n", pr, client_data, 0);
133         }
134         if (cn->u.st.relation)
135         {
136             pr_n("<relation>\n", pr, client_data, level+2);
137             pr_n("<value>", pr, client_data, level+4);
138             if (cn->u.st.relation_uri)
139                 pr_cdata("rel.", pr, client_data);
140             pr_cdata(cn->u.st.relation, pr, client_data);
141             pr_n("</value>\n", pr, client_data, 0);
142
143             if (cn->u.st.relation_uri)
144             {
145                 pr_n("<identifier>", pr, client_data, level+4);
146                 pr_cdata(cn->u.st.relation_uri, pr, client_data);
147                 pr_n("</identifier>\n", pr, client_data, 0);
148             }
149             cql_to_xml_mod(cn->u.st.modifiers,
150                            pr, client_data, level+4);
151
152             pr_n("</relation>\n", pr, client_data, level+2);
153         }
154         if (cn->u.st.term)
155         {
156             pr_n("<term>", pr, client_data, level+2);
157             pr_cdata(cn->u.st.term, pr, client_data);
158             pr_n("</term>\n", pr, client_data, 0);
159         }
160         pr_n("</searchClause>\n", pr, client_data, level);
161         break;
162     case CQL_NODE_BOOL:
163         pr_n("<triple>\n", pr, client_data, level);
164         if (cn->u.boolean.value)
165         {
166             pr_n("<boolean>\n", pr, client_data, level+2);
167
168             pr_n("<value>", pr, client_data, level+4);
169             pr_cdata(cn->u.boolean.value, pr, client_data);
170             pr_n("</value>\n", pr, client_data, 0);
171
172             cql_to_xml_mod(cn->u.boolean.modifiers,
173                            pr, client_data, level+4);
174
175             pr_n("</boolean>\n", pr, client_data, level+2);
176         }
177         if (cn->u.boolean.left)
178         {
179             printf ("%*s<leftOperand>\n", level+2, "");
180             cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4);
181             printf ("%*s</leftOperand>\n", level+2, "");
182         }
183         if (cn->u.boolean.right)
184         {
185             printf ("%*s<rightOperand>\n", level+2, "");
186             cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4);
187             printf ("%*s</rightOperand>\n", level+2, "");
188         }
189         pr_n("</triple>\n", pr, client_data, level);
190     }
191 }
192
193 void cql_to_xml(struct cql_node *cn, 
194                 void (*pr)(const char *buf, void *client_data),
195                 void *client_data)
196 {
197     cql_to_xml_r(cn, pr, client_data, 0);
198 }
199
200 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
201 {
202     cql_to_xml(cn, cql_fputs, f);
203 }
204
205 void cql_buf_write_handler (const char *b, void *client_data)
206 {
207     struct cql_buf_write_info *info = (struct cql_buf_write_info *)client_data;
208     int l = strlen(b);
209     if (info->off < 0 || (info->off + l >= info->max))
210     {
211         info->off = -1;
212         return;
213     }
214     memcpy (info->buf + info->off, b, l);
215     info->off += l;
216 }
217
218 int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
219 {
220     struct cql_buf_write_info info;
221     info.off = 0;
222     info.max = max;
223     info.buf = out;
224     cql_to_xml(cn, cql_buf_write_handler, &info);
225     if (info.off >= 0)
226         info.buf[info.off] = '\0';
227     return info.off;
228 }
229