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