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