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