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