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