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