Fix.
[yaz-moved-to-github.git] / zutil / yaz-ccl.c
1 /*
2  * Copyright (c) 1996-2001, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Log: yaz-ccl.c,v $
6  * Revision 1.13  2001-05-09 23:31:35  adam
7  * String attribute values for PQF. Proper C-backslash escaping for PQF.
8  *
9  * Revision 1.12  2001/03/07 13:24:40  adam
10  * Member and_not in Z_Operator is kept for backwards compatibility.
11  * Added support for definition of CCL operators in field spec file.
12  *
13  * Revision 1.11  2001/02/21 13:46:54  adam
14  * C++ fixes.
15  *
16  * Revision 1.10  2001/02/20 11:23:50  adam
17  * Updated ccl_pquery to consider local attribute set too.
18  *
19  * Revision 1.9  2000/11/27 14:16:55  adam
20  * Fixed bug in ccl_rpn_simple regarding resultSetId's.
21  *
22  * Revision 1.8  2000/11/16 13:03:13  adam
23  * Function ccl_rpn_query sets attributeSet to Bib-1.
24  *
25  * Revision 1.7  2000/11/16 09:58:02  adam
26  * Implemented local AttributeSet setting for CCL field maps.
27  *
28  * Revision 1.6  2000/02/02 15:13:23  adam
29  * Minor change.
30  *
31  * Revision 1.5  2000/01/31 13:15:22  adam
32  * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
33  * that some characters are not surrounded by spaces in resulting term.
34  * ILL-code updates.
35  *
36  * Revision 1.4  1999/12/20 15:20:13  adam
37  * Implemented ccl_pquery to convert from CCL tree to prefix query.
38  *
39  * Revision 1.3  1999/11/30 13:47:12  adam
40  * Improved installation. Moved header files to include/yaz.
41  *
42  * Revision 1.2  1999/06/16 12:00:08  adam
43  * Added proximity.
44  *
45  * Revision 1.1  1999/06/08 10:12:43  adam
46  * Moved file to be part of zutil (instead of util).
47  *
48  * Revision 1.13  1998/03/31 15:13:20  adam
49  * Development towards compiled ASN.1.
50  *
51  * Revision 1.12  1998/02/11 11:53:36  adam
52  * Changed code so that it compiles as C++.
53  *
54  * Revision 1.11  1997/11/24 11:33:57  adam
55  * Using function odr_nullval() instead of global ODR_NULLVAL when
56  * appropriate.
57  *
58  * Revision 1.10  1997/09/29 08:58:25  adam
59  * Fixed conversion of trees so that true copy is made.
60  *
61  * Revision 1.9  1997/06/23 10:31:25  adam
62  * Added ODR argument to ccl_rpn_query and ccl_scan_query.
63  *
64  * Revision 1.8  1996/10/29 13:36:27  adam
65  * Added header.
66  *
67  */
68
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72
73 #include <yaz/yaz-ccl.h>
74
75 static Z_RPNStructure *ccl_rpn_structure (ODR o, struct ccl_rpn_node *p);
76
77 static Z_AttributesPlusTerm *ccl_rpn_term (ODR o, struct ccl_rpn_node *p)
78 {
79     struct ccl_rpn_attr *attr;
80     int num = 0;
81     Z_AttributesPlusTerm *zapt;
82     Odr_oct *term_octet;
83     Z_Term *term;
84     Z_AttributeElement **elements;
85
86     zapt = (Z_AttributesPlusTerm *)odr_malloc (o, sizeof(*zapt));
87
88     term_octet = (Odr_oct *)odr_malloc (o, sizeof(*term_octet));
89
90     term = (Z_Term *)odr_malloc (o, sizeof(*term));
91
92     for (attr = p->u.t.attr_list; attr; attr = attr->next)
93         num++;
94     if (!num)
95         elements = (Z_AttributeElement**)odr_nullval();
96     else
97     {
98         int i = 0;
99         elements = (Z_AttributeElement **)
100             odr_malloc (o, num*sizeof(*elements));
101         for (attr = p->u.t.attr_list; attr; attr = attr->next, i++)
102         {
103             elements[i] = (Z_AttributeElement *)
104                 odr_malloc (o, sizeof(**elements));
105             elements[i]->attributeType =
106                 (int *)odr_malloc(o, sizeof(int));
107             *elements[i]->attributeType = attr->type;
108             elements[i]->attributeSet = 0;
109             if (attr->set && *attr->set)
110             {
111                 int value = oid_getvalbyname (attr->set);
112
113                 if (value != VAL_NONE)
114                 {
115                     int oid[OID_SIZE];
116                     struct oident ident;
117
118                     ident.oclass = CLASS_ATTSET;
119                     ident.proto = PROTO_Z3950;
120                     ident.value = (oid_value) value;
121                     elements[i]->attributeSet =
122                         odr_oiddup (o, oid_ent_to_oid (&ident, oid));
123                 }
124             }
125             elements[i]->which = Z_AttributeValue_numeric;
126             elements[i]->value.numeric =
127                 (int *)odr_malloc (o, sizeof(int));
128             *elements[i]->value.numeric = attr->value;
129         }
130     }
131 #ifdef ASN_COMPILED
132     zapt->attributes = (Z_AttributeList *)
133         odr_malloc (o, sizeof(*zapt->attributes));
134     zapt->attributes->num_attributes = num;
135     zapt->attributes->attributes = elements;
136 #else
137     zapt->num_attributes = num;
138     zapt->attributeList = elements;
139 #endif    
140     zapt->term = term;
141     term->which = Z_Term_general;
142     term->u.general = term_octet;
143     term_octet->len = term_octet->size = strlen (p->u.t.term);
144     term_octet->buf = (unsigned char *)odr_malloc (o, term_octet->len+1);
145     strcpy ((char*) term_octet->buf, p->u.t.term);
146     return zapt;
147 }
148
149 static Z_Operand *ccl_rpn_simple (ODR o, struct ccl_rpn_node *p)
150 {
151     Z_Operand *zo;
152
153     zo = (Z_Operand *)odr_malloc (o, sizeof(*zo));
154
155     switch (p->kind)
156     {
157     case CCL_RPN_TERM:
158         zo->which = Z_Operand_APT;
159         zo->u.attributesPlusTerm = ccl_rpn_term (o, p);
160         break;
161     case CCL_RPN_SET:
162         zo->which = Z_Operand_resultSetId;
163         zo->u.resultSetId = odr_strdup (o, p->u.setname);
164         break;
165     default:
166         return 0;
167     }
168     return zo;
169 }
170
171 static Z_Complex *ccl_rpn_complex (ODR o, struct ccl_rpn_node *p)
172 {
173     Z_Complex *zc;
174     Z_Operator *zo;
175
176     zc = (Z_Complex *)odr_malloc (o, sizeof(*zc));
177     zo = (Z_Operator *)odr_malloc (o, sizeof(*zo));
178
179     zc->roperator = zo;
180     switch (p->kind)
181     {
182     case CCL_RPN_AND:
183         zo->which = Z_Operator_and;
184         zo->u.and_not = odr_nullval();
185         break;
186     case CCL_RPN_OR:
187         zo->which = Z_Operator_or;
188         zo->u.and_not = odr_nullval();
189         break;
190     case CCL_RPN_NOT:
191         zo->which = Z_Operator_and_not;
192         zo->u.and_not = odr_nullval();
193         break;
194     case CCL_RPN_PROX:
195         zo->which = Z_Operator_prox;
196         zo->u.prox = (Z_ProximityOperator *)
197             odr_malloc (o, sizeof(*zo->u.prox));
198         zo->u.prox->exclusion = 0;
199
200         zo->u.prox->distance = (int *)
201             odr_malloc (o, sizeof(*zo->u.prox->distance));
202         *zo->u.prox->distance = 2;
203
204         zo->u.prox->ordered = (bool_t *)
205             odr_malloc (o, sizeof(*zo->u.prox->ordered));
206         *zo->u.prox->ordered = 0;
207
208         zo->u.prox->relationType = (int *)
209             odr_malloc (o, sizeof(*zo->u.prox->relationType));
210 #ifdef ASN_COMPILED
211         *zo->u.prox->relationType = Z_ProximityOperator_Prox_lessThan;
212         zo->u.prox->which = Z_ProximityOperator_known;
213         zo->u.prox->u.known = 
214             (Z_ProxUnit *) odr_malloc (o, sizeof(*zo->u.prox->u.known));
215         *zo->u.prox->u.known = Z_ProxUnit_word;
216 #else
217         *zo->u.prox->relationType = Z_Prox_lessThan;
218         zo->u.prox->which = Z_ProxCode_known;
219         zo->u.prox->proximityUnitCode = (int*)
220             odr_malloc (o, sizeof(*zo->u.prox->proximityUnitCode));
221         *zo->u.prox->proximityUnitCode = Z_ProxUnit_word;
222 #endif
223         break;
224     default:
225         return 0;
226     }
227     zc->s1 = ccl_rpn_structure (o, p->u.p[0]);
228     zc->s2 = ccl_rpn_structure (o, p->u.p[1]);
229     return zc;
230 }
231
232 static Z_RPNStructure *ccl_rpn_structure (ODR o, struct ccl_rpn_node *p)
233 {
234     Z_RPNStructure *zs;
235
236     zs = (Z_RPNStructure *)odr_malloc (o, sizeof(*zs));
237     switch (p->kind)
238     {
239     case CCL_RPN_AND:
240     case CCL_RPN_OR:
241     case CCL_RPN_NOT:
242     case CCL_RPN_PROX:
243         zs->which = Z_RPNStructure_complex;
244         zs->u.complex = ccl_rpn_complex (o, p);
245         break;
246     case CCL_RPN_TERM:
247     case CCL_RPN_SET:
248         zs->which = Z_RPNStructure_simple;
249         zs->u.simple = ccl_rpn_simple (o, p);
250         break;
251     default:
252         return 0;
253     }
254     return zs;
255 }
256
257 Z_RPNQuery *ccl_rpn_query (ODR o, struct ccl_rpn_node *p)
258 {
259     Z_RPNQuery *zq;
260     oident bib1;
261     int oid[OID_SIZE];
262     bib1.proto = PROTO_Z3950;
263     bib1.oclass = CLASS_ATTSET;
264     bib1.value = VAL_BIB1;
265
266     zq = (Z_RPNQuery *)odr_malloc (o, sizeof(*zq));
267     zq->attributeSetId = odr_oiddup (o, oid_ent_to_oid (&bib1, oid));
268     zq->RPNStructure = ccl_rpn_structure (o, p);
269     return zq;
270 }
271
272 Z_AttributesPlusTerm *ccl_scan_query (ODR o, struct ccl_rpn_node *p)
273 {
274     if (p->kind != CCL_RPN_TERM)
275         return NULL;
276     return ccl_rpn_term (o, p);
277 }
278
279 static void ccl_pquery_complex (WRBUF w, struct ccl_rpn_node *p)
280 {
281     switch (p->kind)
282     {
283     case CCL_RPN_AND:
284         wrbuf_puts (w, "@and ");
285         break;
286     case CCL_RPN_OR:
287         wrbuf_puts(w, "@or ");
288         break;
289     case CCL_RPN_NOT:
290         wrbuf_puts(w, "@not ");
291         break;
292     case CCL_RPN_PROX:
293         wrbuf_puts(w, "@prox 0 2 0 1 known 2 ");
294         break;
295     default:
296         wrbuf_puts(w, "@ bad op (unknown) ");
297     };
298     ccl_pquery(w, p->u.p[0]);
299     ccl_pquery(w, p->u.p[1]);
300 }
301         
302 void ccl_pquery (WRBUF w, struct ccl_rpn_node *p)
303 {
304     struct ccl_rpn_attr *att;
305     const char *cp;
306
307     switch (p->kind)
308     {
309     case CCL_RPN_AND:
310     case CCL_RPN_OR:
311     case CCL_RPN_NOT:
312     case CCL_RPN_PROX:
313         ccl_pquery_complex (w, p);
314         break;
315     case CCL_RPN_SET:
316         wrbuf_puts (w, "@set ");
317         wrbuf_puts (w, p->u.setname);
318         wrbuf_puts (w, " ");
319         break;
320     case CCL_RPN_TERM:
321         for (att = p->u.t.attr_list; att; att = att->next)
322         {
323             char tmpattr[128];
324             wrbuf_puts (w, "@attr ");
325             if (att->set)
326             {
327                 wrbuf_puts (w, att->set);
328                 wrbuf_puts (w, " ");
329             }
330             sprintf(tmpattr, "%d=%d ", att->type, att->value);
331             wrbuf_puts (w, tmpattr);
332         }
333         for (cp = p->u.t.term; *cp; cp++)
334         {
335             if (*cp == ' ' || *cp == '\\')
336                 wrbuf_putc (w, '\\');
337             wrbuf_putc (w, *cp);
338         }
339         wrbuf_puts (w, " ");
340         break;
341     }
342 }