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