root/trunk/gsdl/packages/yaz/zutil/pquery.c @ 1343

Revision 1343, 17.5 KB (checked in by johnmcp, 20 years ago)

Added the YAZ toolkit source to the packages directory (for z39.50 stuff)

  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (c) 1995-1998, Index Data.
3 * See the file LICENSE for details.
4 * Sebastian Hammer, Adam Dickmeiss
5 *
6 * $Log$
7 * Revision 1.1  2000/08/03 03:12:37  johnmcp
8 * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
9 *
10 * Revision 1.4  1999/12/21 16:25:20  adam
11 * Fixed handling of default/inherited attributes.
12 *
13 * Revision 1.3  1999/12/20 15:20:13  adam
14 * Implemented ccl_pquery to convert from CCL tree to prefix query.
15 *
16 * Revision 1.2  1999/11/30 13:47:12  adam
17 * Improved installation. Moved header files to include/yaz.
18 *
19 * Revision 1.1  1999/06/08 10:10:16  adam
20 * New sub directory zutil. Moved YAZ Compiler to be part of YAZ tree.
21 *
22 * Revision 1.22  1999/04/20 09:56:49  adam
23 * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
24 * Modified all encoders/decoders to reflect this change.
25 *
26 * Revision 1.21  1998/10/13 16:03:37  adam
27 * Better checking for invalid OID's in p_query_rpn.
28 *
29 * Revision 1.20  1998/03/31 15:13:20  adam
30 * Development towards compiled ASN.1.
31 *
32 * Revision 1.19  1998/03/05 08:09:03  adam
33 * Minor change to make C++ happy.
34 *
35 * Revision 1.18  1998/02/11 11:53:36  adam
36 * Changed code so that it compiles as C++.
37 *
38 * Revision 1.17  1997/11/24 11:33:57  adam
39 * Using function odr_nullval() instead of global ODR_NULLVAL when
40 * appropriate.
41 *
42 * Revision 1.16  1997/09/29 13:19:00  adam
43 * Added function, oid_ent_to_oid, to replace the function
44 * oid_getoidbyent, which is not thread safe.
45 *
46 * Revision 1.15  1997/09/29 07:13:43  adam
47 * Changed type of a few variables to avoid warnings.
48 *
49 * Revision 1.14  1997/09/22 12:33:41  adam
50 * Fixed bug introduced by previous commit.
51 *
52 * Revision 1.13  1997/09/17 12:10:42  adam
53 * YAZ version 1.4.
54 *
55 * Revision 1.12  1997/09/01 08:54:13  adam
56 * New windows NT/95 port using MSV5.0. Made prefix query handling
57 * thread safe. The function options ignores empty arguments when met.
58 *
59 * Revision 1.11  1996/11/11 13:15:29  adam
60 * Added proximity operator.
61 *
62 * Revision 1.10  1996/08/12 14:10:35  adam
63 * New function p_query_attset to define default attribute set.
64 *
65 * Revision 1.9  1996/03/15  11:03:46  adam
66 * Attribute set can be set globally for a query with the @attrset
67 * operator. The @attr operator has an optional attribute-set specifier
68 * that sets the attribute set locally.
69 *
70 * Revision 1.8  1996/01/02  11:46:56  quinn
71 * Changed 'operator' to 'roperator' to avoid C++ conflict.
72 *
73 * Revision 1.7  1995/09/29  17:12:36  quinn
74 * Smallish
75 *
76 * Revision 1.6  1995/09/27  15:03:03  quinn
77 * Modified function heads & prototypes.
78 *
79 * Revision 1.5  1995/06/15  12:31:02  quinn
80 * *** empty log message ***
81 *
82 * Revision 1.4  1995/06/15  07:45:19  quinn
83 * Moving to v3.
84 *
85 * Revision 1.3  1995/06/14  11:06:35  adam
86 * Bug fix: Attributes wasn't interpreted correctly!
87 *
88 * Revision 1.2  1995/05/26  08:56:11  adam
89 * New function: p_query_scan.
90 *
91 * Revision 1.1  1995/05/22  15:31:49  adam
92 * New function, p_query_rpn, to convert from prefix (ascii) to rpn (asn).
93 *
94 */
95
96#include <stdio.h>
97#include <string.h>
98#include <stdlib.h>
99
100#include <yaz/proto.h>
101#include <yaz/oid.h>
102#include <yaz/pquery.h>
103
104static oid_value p_query_dfset = VAL_NONE;
105
106struct lex_info {
107    const char *query_buf;
108    const char *lex_buf;
109    size_t lex_len;
110    int query_look;
111    char *left_sep;
112    char *right_sep;
113    int escape_char;
114    int term_type;
115};
116
117static Z_RPNStructure *rpn_structure (struct lex_info *li, ODR o, oid_proto,
118                                      int num_attr, int max_attr,
119                                      int *attr_list, oid_value *attr_set);
120
121static enum oid_value query_oid_getvalbyname (struct lex_info *li)
122{
123    enum oid_value value;
124    char buf[32];
125
126    if (li->lex_len > 31)
127        return VAL_NONE;
128    memcpy (buf, li->lex_buf, li->lex_len);
129    buf[li->lex_len] = '\0';
130    value = oid_getvalbyname (buf);
131    return value;
132}
133
134static int compare_term (struct lex_info *li, const char *src, size_t off)
135{
136    size_t len=strlen(src);
137
138    if (li->lex_len == len+off && !memcmp (li->lex_buf+off, src, len-off))
139    return 1;
140    return 0;
141}
142
143static int query_token (struct lex_info *li)
144{
145    const char *sep_match;
146    const char **qptr = &li->query_buf;
147
148    while (**qptr == ' ')
149        (*qptr)++;
150    if (**qptr == '\0')
151        return 0;
152    li->lex_len = 0;
153    if ((sep_match = strchr (li->left_sep, **qptr)))
154    {
155        int sep_index = sep_match - li->left_sep;
156       
157        ++(*qptr);
158        li->lex_buf = *qptr;
159        while (**qptr && **qptr != li->right_sep[sep_index])
160        {
161            ++(li->lex_len);
162            ++(*qptr);
163        }
164        if (**qptr)
165            ++(*qptr);
166    }
167    else
168    {
169        li->lex_buf = *qptr;
170        while (**qptr && **qptr != ' ')
171        {
172            ++(li->lex_len);
173            ++(*qptr);
174        }
175    }
176    if (li->lex_len >= 1 && li->lex_buf[0] == li->escape_char)
177    {
178    if (compare_term (li, "and", 1))
179        return 'a';
180        if (compare_term (li, "or", 1))
181            return 'o';
182        if (compare_term (li, "not", 1))
183            return 'n';
184        if (compare_term (li, "attr", 1))
185            return 'l';
186        if (compare_term (li, "set", 1))
187            return 's';
188        if (compare_term (li, "attrset", 1))
189            return 'r';
190        if (compare_term (li, "prox", 1))
191            return 'p';
192        if (compare_term (li, "term", 1))
193            return 'y';
194    }
195    return 't';
196}
197
198static int lex (struct lex_info *li)
199{
200    return li->query_look = query_token (li);
201}
202
203static Z_AttributesPlusTerm *rpn_term (struct lex_info *li, ODR o,
204                                       oid_proto proto,
205                                       int num_attr, int *attr_list,
206                                       oid_value *attr_set)
207{
208    Z_AttributesPlusTerm *zapt;
209    Odr_oct *term_octet;
210    Z_Term *term;
211    Z_AttributeElement **elements;
212
213    zapt = (Z_AttributesPlusTerm *)odr_malloc (o, sizeof(*zapt));
214    term_octet = (Odr_oct *)odr_malloc (o, sizeof(*term_octet));
215    term = (Z_Term *)odr_malloc (o, sizeof(*term));
216
217    if (!num_attr)
218        elements = (Z_AttributeElement**)odr_nullval();
219    else
220    {
221        int i, k = 0;
222        int *attr_tmp;
223
224        elements = (Z_AttributeElement**)
225        odr_malloc (o, num_attr * sizeof(*elements));
226
227        attr_tmp = (int *)odr_malloc (o, num_attr * 2 * sizeof(int));
228        memcpy (attr_tmp, attr_list, num_attr * 2 * sizeof(int));
229        for (i = num_attr; --i >= 0; )
230        {
231            int j;
232            for (j = i+1; j<num_attr; j++)
233                if (attr_tmp[2*j] == attr_tmp[2*i])
234                    break;
235            if (j < num_attr)
236                continue;
237            elements[k] =
238                (Z_AttributeElement*)odr_malloc (o,sizeof(**elements));
239            elements[k]->attributeType = &attr_tmp[2*i];
240            if (attr_set[i] == VAL_NONE)
241                elements[k]->attributeSet = 0;
242            else
243            {
244                oident attrid;
245                int oid[OID_SIZE];
246       
247                attrid.proto = PROTO_Z3950;
248                attrid.oclass = CLASS_ATTSET;
249                attrid.value = attr_set[i];
250                   
251                elements[k]->attributeSet =
252            odr_oiddup (o, oid_ent_to_oid (&attrid, oid));
253            }
254        elements[k]->which = Z_AttributeValue_numeric;
255        elements[k]->value.numeric = &attr_tmp[2*i+1];
256            k++;
257        }
258        num_attr = k;
259    }
260#ifdef ASN_COMPILED
261    zapt->attributes = (Z_AttributeList *)
262    odr_malloc (o, sizeof(*zapt->attributes));
263    zapt->attributes->num_attributes = num_attr;
264    zapt->attributes->attributes = elements;
265#else
266    zapt->num_attributes = num_attr;
267    zapt->attributeList = elements;
268#endif   
269
270    zapt->term = term;
271    term->which = Z_Term_general;
272    term->u.general = term_octet;
273    term_octet->buf = (unsigned char *)odr_malloc (o, li->lex_len);
274    term_octet->size = term_octet->len = li->lex_len;
275    memcpy (term_octet->buf, li->lex_buf, li->lex_len);
276    return zapt;
277}
278
279static Z_Operand *rpn_simple (struct lex_info *li, ODR o, oid_proto proto,
280                              int num_attr, int *attr_list,
281                              oid_value *attr_set)
282{
283    Z_Operand *zo;
284
285    zo = (Z_Operand *)odr_malloc (o, sizeof(*zo));
286    switch (li->query_look)
287    {
288    case 't':
289        zo->which = Z_Operand_APT;
290        if (!(zo->u.attributesPlusTerm =
291              rpn_term (li, o, proto, num_attr, attr_list, attr_set)))
292            return NULL;
293        lex (li);
294        break;
295    case 's':
296        lex (li);
297        if (!li->query_look)
298            return NULL;
299        zo->which = Z_Operand_resultSetId;
300        zo->u.resultSetId = (char *)odr_malloc (o, li->lex_len+1);
301        memcpy (zo->u.resultSetId, li->lex_buf, li->lex_len);
302        zo->u.resultSetId[li->lex_len] = '\0';
303        lex (li);
304        break;
305    default:
306        return NULL;
307    }
308    return zo;
309}
310
311static Z_ProximityOperator *rpn_proximity (struct lex_info *li, ODR o)
312{
313    Z_ProximityOperator *p = (Z_ProximityOperator *)odr_malloc (o, sizeof(*p));
314
315    if (!lex (li))
316        return NULL;
317    if (*li->lex_buf == '1')
318    {
319        p->exclusion = (int *)odr_malloc (o, sizeof(*p->exclusion));
320        *p->exclusion = 1;
321    }
322    else if (*li->lex_buf == '0')
323    {
324        p->exclusion = (int *)odr_malloc (o, sizeof(*p->exclusion));
325        *p->exclusion = 0;
326    }
327    else
328        p->exclusion = NULL;
329
330    if (!lex (li))
331        return NULL;
332    p->distance = (int *)odr_malloc (o, sizeof(*p->distance));
333    *p->distance = atoi (li->lex_buf);
334
335    if (!lex (li))
336        return NULL;
337    p->ordered = (int *)odr_malloc (o, sizeof(*p->ordered));
338    *p->ordered = atoi (li->lex_buf);
339   
340    if (!lex (li))
341        return NULL;
342    p->relationType = (int *)odr_malloc (o, sizeof(*p->relationType));
343    *p->relationType = atoi (li->lex_buf);
344
345    if (!lex (li))
346        return NULL;
347    if (*li->lex_buf == 'k')
348        p->which = 0;
349    else if (*li->lex_buf == 'p')
350        p->which = 1;
351    else
352        p->which = atoi (li->lex_buf);
353
354    if (!lex (li))
355        return NULL;
356#ifdef ASN_COMPILED
357    p->which = Z_ProximityOperator_known;
358    p->u.known = (int *)odr_malloc (o, sizeof(*p->u.known));
359    *p->u.known = atoi (li->lex_buf);
360#else
361    p->proximityUnitCode = (int *)odr_malloc (o, sizeof(*p->proximityUnitCode));
362    *p->proximityUnitCode = atoi (li->lex_buf);
363#endif
364    return p;
365}
366
367static Z_Complex *rpn_complex (struct lex_info *li, ODR o, oid_proto proto,
368                               int num_attr, int max_attr,
369                               int *attr_list, oid_value *attr_set)
370{
371    Z_Complex *zc;
372    Z_Operator *zo;
373
374    zc = (Z_Complex *)odr_malloc (o, sizeof(*zc));
375    zo = (Z_Operator *)odr_malloc (o, sizeof(*zo));
376    zc->roperator = zo;
377    switch (li->query_look)
378    {
379    case 'a':
380        zo->which = Z_Operator_and;
381        zo->u.and = odr_nullval();
382        break;
383    case 'o':
384        zo->which = Z_Operator_or;
385        zo->u.and = odr_nullval();
386        break;
387    case 'n':
388        zo->which = Z_Operator_and_not;
389        zo->u.and = odr_nullval();
390        break;
391    case 'p':
392        zo->which = Z_Operator_prox;
393        zo->u.prox = rpn_proximity (li, o);
394        if (!zo->u.prox)
395            return NULL;
396        break;
397    default:
398        return NULL;
399    }
400    lex (li);
401    if (!(zc->s1 =
402          rpn_structure (li, o, proto, num_attr, max_attr, attr_list,
403                         attr_set)))
404        return NULL;
405    if (!(zc->s2 =
406          rpn_structure (li, o, proto, num_attr, max_attr, attr_list,
407                         attr_set)))
408        return NULL;
409    return zc;
410}
411
412static Z_RPNStructure *rpn_structure (struct lex_info *li, ODR o,
413                                      oid_proto proto,
414                                      int num_attr, int max_attr,
415                                      int *attr_list, oid_value *attr_set)
416{
417    Z_RPNStructure *sz;
418    const char *cp;
419
420    sz = (Z_RPNStructure *)odr_malloc (o, sizeof(*sz));
421    switch (li->query_look)
422    {
423    case 'a':
424    case 'o':
425    case 'n':
426    case 'p':
427        sz->which = Z_RPNStructure_complex;
428        if (!(sz->u.complex =
429              rpn_complex (li, o, proto, num_attr, max_attr, attr_list,
430                           attr_set)))
431            return NULL;
432        break;
433    case 't':
434    case 's':
435        sz->which = Z_RPNStructure_simple;
436        if (!(sz->u.simple =
437              rpn_simple (li, o, proto, num_attr, attr_list,
438                          attr_set)))
439            return NULL;
440        break;
441    case 'l':
442        lex (li);
443        if (!li->query_look)
444            return NULL;
445        if (num_attr >= max_attr)
446            return NULL;
447        if (!(cp = strchr (li->lex_buf, '=')) ||
448            (size_t) (cp-li->lex_buf) > li->lex_len)
449        {
450            attr_set[num_attr] = query_oid_getvalbyname (li);
451        if (attr_set[num_attr] == VAL_NONE)
452        return NULL;
453            lex (li);
454
455            if (!(cp = strchr (li->lex_buf, '=')))
456                return NULL;
457        }
458        else
459        {
460            if (num_attr > 0)
461                attr_set[num_attr] = attr_set[num_attr-1];
462            else
463                attr_set[num_attr] = VAL_NONE;
464        }
465    attr_list[2*num_attr] = atoi(li->lex_buf);
466    attr_list[2*num_attr+1] = atoi (cp+1);
467    num_attr++;
468        lex (li);
469        return
470            rpn_structure (li, o, proto, num_attr, max_attr, attr_list,
471                           attr_set);
472    case 'y':
473    lex (li);
474    if (!li->query_look)
475        return NULL;
476    if (compare_term (li, "general", 0))
477        li->term_type = Z_Term_general;
478    else if (compare_term (li, "numeric", 0))
479        li->term_type = Z_Term_numeric;
480    else if (compare_term (li, "string", 0))
481        li->term_type = Z_Term_characterString;
482    else if (compare_term (li, "oid", 0))
483        li->term_type = Z_Term_oid;
484    else if (compare_term (li, "datetime", 0))
485        li->term_type = Z_Term_dateTime;
486    else if (compare_term (li, "null", 0))
487        li->term_type = Z_Term_null;
488    lex (li);
489        return
490            rpn_structure (li, o, proto, num_attr, max_attr, attr_list,
491                           attr_set);
492    case 0:                /* operator/operand expected! */
493        return NULL;
494    }
495    return sz;
496}
497
498Z_RPNQuery *p_query_rpn_mk (ODR o, struct lex_info *li, oid_proto proto,
499                            const char *qbuf)
500{
501    Z_RPNQuery *zq;
502    int attr_array[1024];
503    oid_value attr_set[512];
504    oid_value topSet = VAL_NONE;
505    oident oset;
506    int oid[OID_SIZE];
507
508    zq = (Z_RPNQuery *)odr_malloc (o, sizeof(*zq));
509    lex (li);
510    if (li->query_look == 'r')
511    {
512        lex (li);
513        topSet = query_oid_getvalbyname (li);
514        if (topSet == VAL_NONE)
515            return NULL;
516
517        lex (li);
518    }
519    if (topSet == VAL_NONE)
520        topSet = p_query_dfset;
521    if (topSet == VAL_NONE)
522        topSet = VAL_BIB1;
523    oset.proto = proto;
524    oset.oclass = CLASS_ATTSET;
525    oset.value = topSet;
526
527    if (!oid_ent_to_oid (&oset, oid))
528    return NULL;
529    zq->attributeSetId = odr_oiddup (o, oid);
530
531    if (!(zq->RPNStructure = rpn_structure (li, o, proto, 0, 512,
532                                            attr_array, attr_set)))
533        return NULL;
534    return zq;
535}
536
537Z_RPNQuery *p_query_rpn (ODR o, oid_proto proto,
538                         const char *qbuf)
539{
540    struct lex_info li;
541   
542    li.left_sep = "{\"";
543    li.right_sep = "}\"";
544    li.escape_char = '@';
545    li.term_type = Z_Term_general;
546    li.query_buf = qbuf;
547    return p_query_rpn_mk (o, &li, proto, qbuf);
548}
549
550Z_AttributesPlusTerm *p_query_scan_mk (struct lex_info *li,
551                                       ODR o, oid_proto proto,
552                                       Odr_oid **attributeSetP,
553                                       const char *qbuf)
554{
555    int attr_list[1024];
556    oid_value attr_set[512];
557    int num_attr = 0;
558    int max_attr = 512;
559    const char *cp;
560    oid_value topSet = VAL_NONE;
561    oident oset;
562    int oid[OID_SIZE];
563
564    lex (li);
565    if (li->query_look == 'r')
566    {
567        lex (li);
568        topSet = query_oid_getvalbyname (li);
569
570        lex (li);
571    }
572    if (topSet == VAL_NONE)
573        topSet = p_query_dfset;
574    if (topSet == VAL_NONE)
575        topSet = VAL_BIB1;
576    oset.proto = proto;
577    oset.oclass = CLASS_ATTSET;
578    oset.value = topSet;
579
580    *attributeSetP = odr_oiddup (o, oid_ent_to_oid (&oset, oid));
581
582    while (li->query_look == 'l')
583    {
584        lex (li);
585        if (!li->query_look)
586            return NULL;
587        if (num_attr >= max_attr)
588            return NULL;
589
590        if (!(cp = strchr (li->lex_buf, '=')) ||
591            (size_t) (cp-li->lex_buf) > li->lex_len)
592        {
593            attr_set[num_attr] = query_oid_getvalbyname (li);
594            lex (li);
595
596            if (!(cp = strchr (li->lex_buf, '=')))
597                return NULL;
598        }
599        else
600        {
601            if (num_attr > 0)
602                attr_set[num_attr] = attr_set[num_attr-1];
603            else
604                attr_set[num_attr] = VAL_NONE;
605        }
606        attr_list[2*num_attr] = atoi (li->lex_buf);
607        attr_list[2*num_attr+1] = atoi (cp+1);
608        num_attr++;
609        lex (li);
610    }
611    if (!li->query_look)
612        return NULL;
613    return rpn_term (li, o, proto, num_attr, attr_list, attr_set);
614}
615
616Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
617                                    Odr_oid **attributeSetP,
618                                    const char *qbuf)
619{
620    struct lex_info li;
621
622    li.left_sep = "{\"";
623    li.right_sep = "}\"";
624    li.escape_char = '@';
625    li.term_type = Z_Term_general;
626    li.query_buf = qbuf;
627
628    return p_query_scan_mk (&li, o, proto, attributeSetP, qbuf);
629}
630
631int p_query_attset (const char *arg)
632{
633    p_query_dfset = oid_getvalbyname (arg);
634    return (p_query_dfset == VAL_NONE) ? -1 : 0;
635}
636
Note: See TracBrowser for help on using the browser.