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