Better diagnostics.
[yaz-moved-to-github.git] / util / pquery.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: pquery.c,v $
7  * Revision 1.2  1995-05-26 08:56:11  adam
8  * New function: p_query_scan.
9  *
10  * Revision 1.1  1995/05/22  15:31:49  adam
11  * New function, p_query_rpn, to convert from prefix (ascii) to rpn (asn).
12  *
13  */
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18
19 #include <proto.h>
20 #include <oid.h>
21
22 #include <pquery.h>
23
24 static const char *query_buf;
25 static const char *query_lex_buf;
26 static int query_lex_len;
27 static int query_look = 0;
28 static char *left_sep = "{\"";
29 static char *right_sep = "}\"";
30 static int escape_char = '@';
31
32 static Z_RPNStructure *rpn_structure (ODR o, int num_attr, int max_attr, 
33                                       int *attr_list);
34
35 static int query_token (const char **qptr, const char **lex_buf, int *lex_len)
36 {
37     const char *sep_match;
38
39     while (**qptr == ' ')
40         (*qptr)++;
41     if (**qptr == '\0')
42         return 0;
43     *lex_len = 0;
44     if ((sep_match = strchr (left_sep, **qptr)))
45     {
46         int sep_index = sep_match - left_sep;
47         
48         ++(*qptr);
49         *lex_buf = *qptr;
50         while (**qptr && **qptr != right_sep[sep_index])
51         {
52             ++(*lex_len);
53             ++(*qptr);
54         }
55         if (**qptr)
56             ++(*qptr);
57     }
58     else
59     {
60         *lex_buf = *qptr;
61         while (**qptr && **qptr != ' ')
62         {
63             ++(*lex_len);
64             ++(*qptr);
65         }
66     }
67     if (*lex_len >= 1 && (*lex_buf)[0] == escape_char)
68     {
69         if (*lex_len == 4 && !memcmp (*lex_buf+1, "and", 3))
70             return 'a';
71         if (*lex_len == 3 && !memcmp (*lex_buf+1, "or", 2))
72             return 'o';
73         if (*lex_len == 4 && !memcmp (*lex_buf+1, "not", 3))
74             return 'n';
75         if (*lex_len == 5 && !memcmp (*lex_buf+1, "attr", 4))
76             return 'l';
77         if (*lex_len == 4 && !memcmp (*lex_buf+1, "set", 3))
78             return 's';
79     }
80     return 't';
81 }
82
83 static int lex (void)
84 {
85     return query_look = 
86         query_token (&query_buf, &query_lex_buf, &query_lex_len);
87 }
88
89 static Z_AttributesPlusTerm *rpn_term (ODR o, int num_attr, int *attr_list)
90 {
91     Z_AttributesPlusTerm *zapt;
92     Odr_oct *term_octet;
93     Z_Term *term;
94
95     zapt = odr_malloc (o, sizeof(*zapt));
96     term_octet = odr_malloc (o, sizeof(*term_octet));
97     term = odr_malloc (o, sizeof(*term));
98
99     zapt->num_attributes = num_attr;
100     if (num_attr)
101     {
102         int i;
103         zapt->attributeList = odr_malloc (o, num_attr * 
104                                           sizeof(*zapt->attributeList));
105         for (i = 0; i < num_attr; i++)
106         {
107             zapt->attributeList[i] =
108                 odr_malloc (o,sizeof(**zapt->attributeList));
109             zapt->attributeList[i]->attributeType = &attr_list[2*i];
110             zapt->attributeList[i]->attributeValue = &attr_list[2*i+1];
111         }
112     }
113     else
114         zapt->attributeList = ODR_NULLVAL;
115     zapt->term = term;
116     term->which = Z_Term_general;
117     term->u.general = term_octet;
118     term_octet->buf = odr_malloc (o, query_lex_len);
119     term_octet->size = term_octet->len = query_lex_len;
120     memcpy (term_octet->buf, query_lex_buf, query_lex_len);
121     return zapt;
122 }
123
124 static Z_Operand *rpn_simple (ODR o, int num_attr, int *attr_list)
125 {
126     Z_Operand *zo;
127
128     zo = odr_malloc (o, sizeof(*zo));
129     switch (query_look)
130     {
131     case 't':
132         zo->which = Z_Operand_APT;
133         if (!(zo->u.attributesPlusTerm = rpn_term (o, num_attr, attr_list)))
134             return NULL;
135         lex ();
136         break;
137     case 's':
138         lex ();
139         if (!query_look)
140             return NULL;
141         zo->which = Z_Operand_resultSetId;
142         zo->u.resultSetId = odr_malloc (o, query_lex_len+1);
143         memcpy (zo->u.resultSetId, query_lex_buf, query_lex_len);
144         zo->u.resultSetId[query_lex_len] = '\0';
145         lex ();
146         break;
147     default:
148         return NULL;
149     }
150     return zo;
151 }
152
153 static Z_Complex *rpn_complex (ODR o, int num_attr, int max_attr, 
154                                int *attr_list)
155 {
156     Z_Complex *zc;
157     Z_Operator *zo;
158
159     zc = odr_malloc (o, sizeof(*zc));
160     zo = odr_malloc (o, sizeof(*zo));
161     zc->operator = zo;
162     switch (query_look)
163     {
164     case 'a':
165         zo->which = Z_Operator_and;
166         zo->u.and = ODR_NULLVAL;
167         break;
168     case 'o':
169         zo->which = Z_Operator_or;
170         zo->u.and = ODR_NULLVAL;
171         break;
172     case 'n':
173         zo->which = Z_Operator_and_not;
174         zo->u.and = ODR_NULLVAL;
175         break;
176     default:
177         return NULL;
178     }
179     lex ();
180     if (!(zc->s1 = rpn_structure (o, num_attr, max_attr, attr_list)))
181         return NULL;
182     if (!(zc->s2 = rpn_structure (o, num_attr, max_attr, attr_list)))
183         return NULL;
184     return zc;
185 }
186
187 static Z_RPNStructure *rpn_structure (ODR o, int num_attr, int max_attr, 
188                                       int *attr_list)
189 {
190     Z_RPNStructure *sz;
191     const char *cp;
192
193     sz = odr_malloc (o, sizeof(*sz));
194     switch (query_look)
195     {
196     case 'a':
197     case 'o':
198     case 'n':
199         sz->which = Z_RPNStructure_complex;
200         if (!(sz->u.complex = rpn_complex (o, num_attr, max_attr, attr_list)))
201             return NULL;
202         break;
203     case 't':
204     case 's':
205         sz->which = Z_RPNStructure_simple;
206         if (!(sz->u.simple = rpn_simple (o, num_attr, attr_list)))
207             return NULL;
208         break;
209     case 'l':
210         lex ();
211         if (!query_look)
212             return NULL;
213         if (!(cp = strchr (query_lex_buf, '=')))
214             return NULL;
215         if (num_attr >= max_attr)
216             return NULL;
217         attr_list[2*num_attr] = atoi (query_lex_buf);
218         attr_list[2*num_attr+1] = atoi (cp+1);
219         num_attr++;
220         lex ();
221         return rpn_structure (o, num_attr, max_attr, attr_list);
222     case 0:                /* operator/operand expected! */
223         return NULL;
224     }
225     return sz;
226 }
227
228 Z_RPNQuery *p_query_rpn (ODR o, const char *qbuf)
229 {
230     Z_RPNQuery *zq;
231     int attr_array[1024];
232
233     query_buf = qbuf;
234     zq = odr_malloc (o, sizeof(*zq));
235     zq->attributeSetId = NULL;
236     lex ();
237     if (!(zq->RPNStructure = rpn_structure (o, 0, 512, attr_array)))
238         return NULL;
239     return zq;
240 }
241
242 Z_AttributesPlusTerm *p_query_scan (ODR o, const char *qbuf)
243 {
244     int attr_list[1024];
245     int num_attr = 0;
246     int max_attr = 512;
247     const char *cp;
248
249     query_buf = qbuf;
250     while (lex() == 'l')
251     {
252         lex ();
253         if (!query_look)
254             return NULL;
255         if (!(cp = strchr (query_lex_buf, '=')))
256             return NULL;
257         if (num_attr >= max_attr)
258             return NULL;
259         attr_list[2*num_attr] = atoi (query_lex_buf);
260         attr_list[2*num_attr+1] = atoi (cp+1);
261         num_attr++;
262     }
263     if (!query_look)
264         return NULL;
265     return rpn_term (o, num_attr, attr_list);
266 }
267