Added body-of-text to BIB-1 ANY and the WAIS profile
[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.9  1996-03-15 11:03:46  adam
8  * Attribute set can be set globally for a query with the @attrset
9  * operator. The @attr operator has an optional attribute-set specifier
10  * that sets the attribute set locally.
11  *
12  * Revision 1.8  1996/01/02  11:46:56  quinn
13  * Changed 'operator' to 'roperator' to avoid C++ conflict.
14  *
15  * Revision 1.7  1995/09/29  17:12:36  quinn
16  * Smallish
17  *
18  * Revision 1.6  1995/09/27  15:03:03  quinn
19  * Modified function heads & prototypes.
20  *
21  * Revision 1.5  1995/06/15  12:31:02  quinn
22  * *** empty log message ***
23  *
24  * Revision 1.4  1995/06/15  07:45:19  quinn
25  * Moving to v3.
26  *
27  * Revision 1.3  1995/06/14  11:06:35  adam
28  * Bug fix: Attributes wasn't interpreted correctly!
29  *
30  * Revision 1.2  1995/05/26  08:56:11  adam
31  * New function: p_query_scan.
32  *
33  * Revision 1.1  1995/05/22  15:31:49  adam
34  * New function, p_query_rpn, to convert from prefix (ascii) to rpn (asn).
35  *
36  */
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41
42 #include <proto.h>
43 #include <oid.h>
44
45 #include <pquery.h>
46
47 static const char *query_buf;
48 static const char *query_lex_buf;
49 static int query_lex_len;
50 static int query_look = 0;
51 static char *left_sep = "{\"";
52 static char *right_sep = "}\"";
53 static int escape_char = '@';
54
55 static Z_RPNStructure *rpn_structure (ODR o, oid_proto, 
56                                       int num_attr, int max_attr, 
57                                       int *attr_list, oid_value *attr_set);
58
59 static int query_oid_getvalbyname (void)
60 {
61     char buf[32];
62
63     if (query_lex_len > 31)
64         return VAL_NONE;
65     memcpy (buf, query_lex_buf, query_lex_len);
66     buf[query_lex_len] = '\0';
67     return oid_getvalbyname (buf);
68 }
69
70 static int query_token (const char **qptr, const char **lex_buf, int *lex_len)
71 {
72     const char *sep_match;
73
74     while (**qptr == ' ')
75         (*qptr)++;
76     if (**qptr == '\0')
77         return 0;
78     *lex_len = 0;
79     if ((sep_match = strchr (left_sep, **qptr)))
80     {
81         int sep_index = sep_match - left_sep;
82         
83         ++(*qptr);
84         *lex_buf = *qptr;
85         while (**qptr && **qptr != right_sep[sep_index])
86         {
87             ++(*lex_len);
88             ++(*qptr);
89         }
90         if (**qptr)
91             ++(*qptr);
92     }
93     else
94     {
95         *lex_buf = *qptr;
96         while (**qptr && **qptr != ' ')
97         {
98             ++(*lex_len);
99             ++(*qptr);
100         }
101     }
102     if (*lex_len >= 1 && (*lex_buf)[0] == escape_char)
103     {
104         if (*lex_len == 4 && !memcmp (*lex_buf+1, "and", 3))
105             return 'a';
106         if (*lex_len == 3 && !memcmp (*lex_buf+1, "or", 2))
107             return 'o';
108         if (*lex_len == 4 && !memcmp (*lex_buf+1, "not", 3))
109             return 'n';
110         if (*lex_len == 5 && !memcmp (*lex_buf+1, "attr", 4))
111             return 'l';
112         if (*lex_len == 4 && !memcmp (*lex_buf+1, "set", 3))
113             return 's';
114         if (*lex_len == 8 && !memcmp (*lex_buf+1, "attrset", 7))
115             return 'r';
116     }
117     return 't';
118 }
119
120 static int lex (void)
121 {
122     return query_look = 
123         query_token (&query_buf, &query_lex_buf, &query_lex_len);
124 }
125
126 static Z_AttributesPlusTerm *rpn_term (ODR o, oid_proto proto, 
127                                        int num_attr, int *attr_list,
128                                        oid_value *attr_set)
129 {
130     Z_AttributesPlusTerm *zapt;
131     Odr_oct *term_octet;
132     Z_Term *term;
133
134     zapt = odr_malloc (o, sizeof(*zapt));
135     term_octet = odr_malloc (o, sizeof(*term_octet));
136     term = odr_malloc (o, sizeof(*term));
137
138     zapt->num_attributes = num_attr;
139     if (num_attr)
140     {
141         int i;
142         int *attr_tmp;
143
144         zapt->attributeList = odr_malloc (o, num_attr * 
145                                           sizeof(*zapt->attributeList));
146
147         attr_tmp = odr_malloc (o, num_attr * 2 * sizeof(int));
148         memcpy (attr_tmp, attr_list, num_attr * 2 * sizeof(int));
149         for (i = 0; i < num_attr; i++)
150         {
151             zapt->attributeList[i] =
152                 odr_malloc (o,sizeof(**zapt->attributeList));
153             zapt->attributeList[i]->attributeType = &attr_tmp[2*i];
154 #ifdef Z_95
155             if (attr_set[i] == VAL_NONE)
156                 zapt->attributeList[i]->attributeSet = 0;
157             else
158             {
159                 oident attrid;
160
161                 attrid.proto = PROTO_Z3950;
162                 attrid.oclass = CLASS_ATTSET;
163                 attrid.value = attr_set[i];
164                    
165                 zapt->attributeList[i]->attributeSet = 
166                     odr_oiddup (o, oid_getoidbyent (&attrid));
167             }
168             zapt->attributeList[i]->which = Z_AttributeValue_numeric;
169             zapt->attributeList[i]->value.numeric = &attr_tmp[2*i+1];
170 #else
171             zapt->attributeList[i]->attributeValue = &attr_tmp[2*i+1];
172 #endif
173         }
174     }
175     else
176         zapt->attributeList = ODR_NULLVAL;
177     zapt->term = term;
178     term->which = Z_Term_general;
179     term->u.general = term_octet;
180     term_octet->buf = odr_malloc (o, query_lex_len);
181     term_octet->size = term_octet->len = query_lex_len;
182     memcpy (term_octet->buf, query_lex_buf, query_lex_len);
183     return zapt;
184 }
185
186 static Z_Operand *rpn_simple (ODR o, oid_proto proto,
187                               int num_attr, int *attr_list,
188                               oid_value *attr_set)
189 {
190     Z_Operand *zo;
191
192     zo = odr_malloc (o, sizeof(*zo));
193     switch (query_look)
194     {
195     case 't':
196         zo->which = Z_Operand_APT;
197         if (!(zo->u.attributesPlusTerm =
198               rpn_term (o, proto, num_attr, attr_list, attr_set)))
199             return NULL;
200         lex ();
201         break;
202     case 's':
203         lex ();
204         if (!query_look)
205             return NULL;
206         zo->which = Z_Operand_resultSetId;
207         zo->u.resultSetId = odr_malloc (o, query_lex_len+1);
208         memcpy (zo->u.resultSetId, query_lex_buf, query_lex_len);
209         zo->u.resultSetId[query_lex_len] = '\0';
210         lex ();
211         break;
212     default:
213         return NULL;
214     }
215     return zo;
216 }
217
218 static Z_Complex *rpn_complex (ODR o, oid_proto proto,
219                                int num_attr, int max_attr, 
220                                int *attr_list, oid_value *attr_set)
221 {
222     Z_Complex *zc;
223     Z_Operator *zo;
224
225     zc = odr_malloc (o, sizeof(*zc));
226     zo = odr_malloc (o, sizeof(*zo));
227     zc->roperator = zo;
228     switch (query_look)
229     {
230     case 'a':
231         zo->which = Z_Operator_and;
232         zo->u.and = ODR_NULLVAL;
233         break;
234     case 'o':
235         zo->which = Z_Operator_or;
236         zo->u.and = ODR_NULLVAL;
237         break;
238     case 'n':
239         zo->which = Z_Operator_and_not;
240         zo->u.and = ODR_NULLVAL;
241         break;
242     default:
243         return NULL;
244     }
245     lex ();
246     if (!(zc->s1 =
247           rpn_structure (o, proto, num_attr, max_attr, attr_list, attr_set)))
248         return NULL;
249     if (!(zc->s2 =
250           rpn_structure (o, proto, num_attr, max_attr, attr_list, attr_set)))
251         return NULL;
252     return zc;
253 }
254
255 static Z_RPNStructure *rpn_structure (ODR o, oid_proto proto, 
256                                       int num_attr, int max_attr, 
257                                       int *attr_list, oid_value *attr_set)
258 {
259     Z_RPNStructure *sz;
260     const char *cp;
261
262     sz = odr_malloc (o, sizeof(*sz));
263     switch (query_look)
264     {
265     case 'a':
266     case 'o':
267     case 'n':
268         sz->which = Z_RPNStructure_complex;
269         if (!(sz->u.complex =
270               rpn_complex (o, proto, num_attr, max_attr, attr_list, attr_set)))
271             return NULL;
272         break;
273     case 't':
274     case 's':
275         sz->which = Z_RPNStructure_simple;
276         if (!(sz->u.simple =
277               rpn_simple (o, proto, num_attr, attr_list, attr_set)))
278             return NULL;
279         break;
280     case 'l':
281         lex ();
282         if (!query_look)
283             return NULL;
284         if (num_attr >= max_attr)
285             return NULL;
286         if (!(cp = strchr (query_lex_buf, '=')) ||
287             (cp-query_lex_buf) > query_lex_len)
288         {
289             attr_set[num_attr] = query_oid_getvalbyname ();
290             lex ();
291
292             if (!(cp = strchr (query_lex_buf, '=')))
293                 return NULL;
294         }
295         else 
296         {
297             if (num_attr > 0)
298                 attr_set[num_attr] = attr_set[num_attr-1];
299             else
300                 attr_set[num_attr] = VAL_NONE;
301         }
302         attr_list[2*num_attr] = atoi (query_lex_buf);
303         attr_list[2*num_attr+1] = atoi (cp+1);
304         num_attr++;
305         lex ();
306         return
307             rpn_structure (o, proto, num_attr, max_attr, attr_list, attr_set);
308     case 0:                /* operator/operand expected! */
309         return NULL;
310     }
311     return sz;
312 }
313
314 Z_RPNQuery *p_query_rpn (ODR o, oid_proto proto, const char *qbuf)
315 {
316     Z_RPNQuery *zq;
317     int attr_array[1024];
318     oid_value attr_set[512];
319     oid_value topSet = VAL_NONE;
320     oident oset;
321
322     query_buf = qbuf;
323     zq = odr_malloc (o, sizeof(*zq));
324     lex ();
325     if (query_look == 'r')
326     {
327         lex ();
328         topSet = query_oid_getvalbyname ();
329         if (topSet == VAL_NONE)
330             return NULL;
331
332         lex ();
333     }
334     if (topSet == VAL_NONE)
335         topSet = VAL_BIB1;
336     oset.proto = proto;
337     oset.oclass = CLASS_ATTSET;
338     oset.value = topSet;
339
340     zq->attributeSetId = odr_oiddup (o, oid_getoidbyent (&oset));
341
342     if (!(zq->RPNStructure = rpn_structure (o, proto, 0, 512,
343                                             attr_array, attr_set)))
344         return NULL;
345     return zq;
346 }
347
348 Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
349                                     Odr_oid **attributeSetP,
350                                     const char *qbuf)
351 {
352     int attr_list[1024];
353     oid_value attr_set[512];
354     int num_attr = 0;
355     int max_attr = 512;
356     const char *cp;
357     oid_value topSet = VAL_NONE;
358     oident oset;
359
360     query_buf = qbuf;
361
362     lex ();
363     if (query_look == 'r')
364     {
365         lex ();
366         topSet = query_oid_getvalbyname ();
367
368         lex ();
369     }
370     if (topSet == VAL_NONE)
371         topSet = VAL_BIB1;
372     oset.proto = proto;
373     oset.oclass = CLASS_ATTSET;
374     oset.value = topSet;
375
376     *attributeSetP = odr_oiddup (o, oid_getoidbyent (&oset));
377
378     while (query_look == 'l')
379     {
380         lex ();
381         if (!query_look)
382             return NULL;
383         if (num_attr >= max_attr)
384             return NULL;
385
386         if (!(cp = strchr (query_lex_buf, '=')) ||
387             (cp-query_lex_buf) > query_lex_len)
388         {
389             attr_set[num_attr] = query_oid_getvalbyname ();
390             lex ();
391
392             if (!(cp = strchr (query_lex_buf, '=')))
393                 return NULL;
394         }
395         else
396         {
397             if (num_attr > 0)
398                 attr_set[num_attr] = attr_set[num_attr-1];
399             else
400                 attr_set[num_attr] = VAL_NONE;
401         }
402         attr_list[2*num_attr] = atoi (query_lex_buf);
403         attr_list[2*num_attr+1] = atoi (cp+1);
404         num_attr++;
405         lex ();
406     }
407     if (!query_look)
408         return NULL;
409     return rpn_term (o, proto, num_attr, attr_list, attr_set);
410 }
411