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