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