Link SSL with libyaz.la and yaz-client only.
[yaz-moved-to-github.git] / src / pquery.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2008 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file pquery.c
7  * \brief Implements PQF parsing
8  */
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13
14 #include <yaz/proto.h>
15 #include <yaz/oid_db.h>
16 #include <yaz/pquery.h>
17
18 struct yaz_pqf_parser {
19     const char *query_buf;
20     const char *query_ptr;
21     const char *lex_buf;
22     size_t lex_len;
23     int query_look;
24     char *left_sep;
25     char *right_sep;
26     int escape_char;
27     int term_type;
28     int external_type;
29     int error;
30 };
31
32 static Z_RPNStructure *rpn_structure(struct yaz_pqf_parser *li, ODR o,
33                                      int num_attr, int max_attr, 
34                                      int *attr_list, char **attr_clist,
35                                      Odr_oid **attr_set);
36
37 static Odr_oid *query_oid_getvalbyname(struct yaz_pqf_parser *li, ODR o)
38 {
39     char buf[32];
40
41     if (li->lex_len >= sizeof(buf)-1)
42         return 0;
43     memcpy (buf, li->lex_buf, li->lex_len);
44     buf[li->lex_len] = '\0';
45     return yaz_string_to_oid_odr(yaz_oid_std(), CLASS_ATTSET, buf, o);
46 }
47
48 static int compare_term(struct yaz_pqf_parser *li, const char *src,
49                         size_t off)
50 {
51     size_t len=strlen(src);
52     
53     if (li->lex_len == len+off && !memcmp (li->lex_buf+off, src, len-off))
54         return 1;
55     return 0;
56 }
57
58 static int query_token(struct yaz_pqf_parser *li)
59 {
60     int sep_char = ' ';
61     const char *sep_match;
62     const char **qptr = &li->query_ptr;
63
64     while (**qptr == ' ')
65         (*qptr)++;
66     if (**qptr == '\0')
67         return 0;
68     li->lex_len = 0;
69     if ((sep_match = strchr (li->left_sep, **qptr)))
70     {
71         sep_char = li->right_sep[sep_match - li->left_sep];
72         ++(*qptr);
73     }
74     li->lex_buf = *qptr;
75    
76     if (**qptr == li->escape_char && isdigit (((const unsigned char *) *qptr)[1]))
77     {
78         ++(li->lex_len);
79         ++(*qptr);
80         return 'l';
81     }
82     while (**qptr && **qptr != sep_char)
83     {
84         if (**qptr == '\\')
85         {
86             ++(li->lex_len);
87             ++(*qptr);
88         }
89         ++(li->lex_len);
90         ++(*qptr);
91     }
92     if (**qptr)
93         ++(*qptr);
94     if (sep_char == ' ' &&
95         li->lex_len >= 1 && li->lex_buf[0] == li->escape_char)
96     {
97         if (compare_term (li, "and", 1))
98             return 'a';
99         if (compare_term (li, "or", 1))
100             return 'o';
101         if (compare_term (li, "not", 1))
102             return 'n';
103         if (compare_term (li, "attr", 1))
104             return 'l';
105         if (compare_term (li, "set", 1))
106             return 's';
107         if (compare_term (li, "attrset", 1))
108             return 'r';
109         if (compare_term (li, "prox", 1))
110             return 'p';
111         if (compare_term (li, "term", 1))
112             return 'y';
113     }
114     return 't';
115 }
116
117 static int lex(struct yaz_pqf_parser *li)
118 {
119     return li->query_look = query_token(li);
120 }
121
122 static int escape_string(char *out_buf, const char *in, int len)
123 {
124
125     char *out = out_buf;
126     while (--len >= 0)
127         if (*in == '\\' && len > 0)
128         {
129             --len;
130             switch (*++in)
131             {
132             case 't':
133                 *out++ = '\t';
134                 break;
135             case 'n':
136                 *out++ = '\n';
137                 break;
138             case 'r':
139                 *out++ = '\r';
140                 break;
141             case 'f':
142                 *out++ = '\f';
143                 break;
144             case 'x':
145                 if (len > 1)
146                 {
147                     char s[4];
148                     int n = 0;
149                     s[0] = *++in;
150                     s[1] = *++in;
151                     s[2] = '\0';
152                     len = len - 2;
153                     sscanf (s, "%x", &n);
154                     *out++ = n;
155                 }
156                 break;
157             case '0':
158             case '1':
159             case '2':
160             case '3':
161                 if (len > 1)
162                 {
163                     char s[4];
164                     int n = 0;
165                     s[0] = *in;
166                     s[1] = *++in;                   
167                     s[2] = *++in;
168                     s[3] = '\0';
169                     len = len - 2;
170                     sscanf (s, "%o", &n);
171                     *out++ = n;
172                 }
173                 break;
174             default:
175                 *out++ = *in;
176                 break;
177             }
178             in++;
179         }
180         else
181             *out++ = *in++;
182     return out - out_buf;
183 }
184
185 static int p_query_parse_attr(struct yaz_pqf_parser *li, ODR o,
186                               int num_attr, int *attr_list,
187                               char **attr_clist, Odr_oid **attr_set)
188 {
189     const char *cp;
190
191     if (!(cp = strchr (li->lex_buf, '=')) ||
192         (size_t) (cp-li->lex_buf) > li->lex_len)
193     {
194         attr_set[num_attr] = query_oid_getvalbyname (li, o);
195         if (attr_set[num_attr] == 0)
196         {
197             li->error = YAZ_PQF_ERROR_ATTSET;
198             return 0;
199         }
200         if (!lex (li))
201         {
202             li->error = YAZ_PQF_ERROR_MISSING;
203             return 0;
204         }
205         if (!(cp = strchr (li->lex_buf, '=')))
206         {
207             li->error = YAZ_PQF_ERROR_BADATTR;
208             return 0;
209         }
210     }
211     else 
212     {
213         if (num_attr > 0)
214             attr_set[num_attr] = attr_set[num_attr-1];
215         else
216             attr_set[num_attr] = 0;
217     }
218     if (*li->lex_buf < '0' || *li->lex_buf > '9')
219     {
220         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
221         return 0;
222     }
223     attr_list[2*num_attr] = atoi(li->lex_buf);
224     cp++;
225     if (*cp >= '0' && *cp <= '9')
226     {
227         attr_list[2*num_attr+1] = atoi (cp);
228         attr_clist[num_attr] = 0;
229     }
230     else
231     {
232         int len = li->lex_len - (cp - li->lex_buf);
233         attr_list[2*num_attr+1] = 0;
234         attr_clist[num_attr] = (char *) odr_malloc (o, len+1);
235         len = escape_string(attr_clist[num_attr], cp, len);
236         attr_clist[num_attr][len] = '\0';
237     }
238     return 1;
239 }
240
241 static Z_AttributesPlusTerm *rpn_term(struct yaz_pqf_parser *li, ODR o,
242                                       int num_attr, int *attr_list,
243                                       char **attr_clist, Odr_oid **attr_set)
244 {
245     Z_AttributesPlusTerm *zapt;
246     Odr_oct *term_octet;
247     Z_Term *term;
248     Z_AttributeElement **elements;
249
250     zapt = (Z_AttributesPlusTerm *)odr_malloc (o, sizeof(*zapt));
251     term_octet = (Odr_oct *)odr_malloc (o, sizeof(*term_octet));
252     term = (Z_Term *)odr_malloc (o, sizeof(*term));
253
254     if (!num_attr)
255         elements = (Z_AttributeElement**)odr_nullval();
256     else
257     {
258         int i, k = 0;
259         int *attr_tmp;
260
261         elements = (Z_AttributeElement**)
262             odr_malloc (o, num_attr * sizeof(*elements));
263
264         attr_tmp = (int *)odr_malloc (o, num_attr * 2 * sizeof(int));
265         memcpy (attr_tmp, attr_list, num_attr * 2 * sizeof(int));
266         for (i = num_attr; --i >= 0; )
267         {
268             int j;
269             for (j = i+1; j<num_attr; j++)
270                 if (attr_tmp[2*j] == attr_tmp[2*i])
271                     break;
272             if (j < num_attr)
273                 continue;
274             elements[k] =
275                 (Z_AttributeElement*)odr_malloc (o,sizeof(**elements));
276             elements[k]->attributeType = &attr_tmp[2*i];
277             elements[k]->attributeSet = attr_set[i];
278
279             if (attr_clist[i])
280             {
281                 elements[k]->which = Z_AttributeValue_complex;
282                 elements[k]->value.complex = (Z_ComplexAttribute *)
283                     odr_malloc (o, sizeof(Z_ComplexAttribute));
284                 elements[k]->value.complex->num_list = 1;
285                 elements[k]->value.complex->list =
286                     (Z_StringOrNumeric **)
287                     odr_malloc (o, 1 * sizeof(Z_StringOrNumeric *));
288                 elements[k]->value.complex->list[0] =
289                     (Z_StringOrNumeric *)
290                     odr_malloc (o, sizeof(Z_StringOrNumeric));
291                 elements[k]->value.complex->list[0]->which =
292                     Z_StringOrNumeric_string;
293                 elements[k]->value.complex->list[0]->u.string =
294                     attr_clist[i];
295                 elements[k]->value.complex->semanticAction = (int **)
296                     odr_nullval();
297                 elements[k]->value.complex->num_semanticAction = 0;
298             }
299             else
300             {
301                 elements[k]->which = Z_AttributeValue_numeric;
302                 elements[k]->value.numeric = &attr_tmp[2*i+1];
303             }
304             k++;
305         }
306         num_attr = k;
307     }
308     zapt->attributes = (Z_AttributeList *)
309         odr_malloc (o, sizeof(*zapt->attributes));
310     zapt->attributes->num_attributes = num_attr;
311     zapt->attributes->attributes = elements;
312
313     zapt->term = term;
314
315     term_octet->buf = (unsigned char *)odr_malloc (o, 1 + li->lex_len);
316     term_octet->size = term_octet->len =
317         escape_string ((char *) (term_octet->buf), li->lex_buf, li->lex_len);
318     term_octet->buf[term_octet->size] = 0;  /* null terminate */
319     
320     switch (li->term_type)
321     {
322     case Z_Term_general:
323         term->which = Z_Term_general;
324         term->u.general = term_octet;
325         break;
326     case Z_Term_characterString:
327         term->which = Z_Term_characterString;
328         term->u.characterString = (char*) term_octet->buf; 
329                                     /* null terminated above */
330         break;
331     case Z_Term_numeric:
332         term->which = Z_Term_numeric;
333         term->u.numeric = odr_intdup (o, atoi((char*) (term_octet->buf)));
334         break;
335     case Z_Term_null:
336         term->which = Z_Term_null;
337         term->u.null = odr_nullval();
338         break;
339     case Z_Term_external:
340         term->which = Z_Term_external;
341         term->u.external = 0;
342         break;
343     default:
344         term->which = Z_Term_null;
345         term->u.null = odr_nullval();
346         break;
347     }
348     return zapt;
349 }
350
351 static Z_Operand *rpn_simple(struct yaz_pqf_parser *li, ODR o,
352                              int num_attr, int *attr_list, char **attr_clist,
353                              Odr_oid **attr_set)
354 {
355     Z_Operand *zo;
356
357     zo = (Z_Operand *)odr_malloc (o, sizeof(*zo));
358     switch (li->query_look)
359     {
360     case 't':
361         zo->which = Z_Operand_APT;
362         if (!(zo->u.attributesPlusTerm =
363               rpn_term(li, o, num_attr, attr_list, attr_clist, attr_set)))
364             return 0;
365         lex (li);
366         break;
367     case 's':
368         lex (li);
369         if (!li->query_look)
370         {
371             li->error = YAZ_PQF_ERROR_MISSING;
372             return 0;
373         }
374         zo->which = Z_Operand_resultSetId;
375         zo->u.resultSetId = (char *)odr_malloc (o, li->lex_len+1);
376         memcpy (zo->u.resultSetId, li->lex_buf, li->lex_len);
377         zo->u.resultSetId[li->lex_len] = '\0';
378         lex (li);
379         break;
380     default:
381         /* we're only called if one of the above types are seens so
382            this shouldn't happen */
383         li->error = YAZ_PQF_ERROR_INTERNAL;
384         return 0;
385     }
386     return zo;
387 }
388
389 static Z_ProximityOperator *rpn_proximity (struct yaz_pqf_parser *li, ODR o)
390 {
391     Z_ProximityOperator *p = (Z_ProximityOperator *)odr_malloc (o, sizeof(*p));
392
393     if (!lex (li))
394     {
395         li->error = YAZ_PQF_ERROR_MISSING;
396         return NULL;
397     }
398     if (*li->lex_buf == '1')
399         p->exclusion = odr_intdup (o, 1);
400     else if (*li->lex_buf == '0')
401         p->exclusion = odr_intdup (o, 0);
402     else if (*li->lex_buf == 'v' || *li->lex_buf == 'n')
403         p->exclusion = NULL;
404     else
405     {
406         li->error = YAZ_PQF_ERROR_PROXIMITY;
407         return NULL;
408     }
409
410     if (!lex (li))
411     {
412         li->error = YAZ_PQF_ERROR_MISSING;
413         return NULL;
414     }
415     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
416         p->distance = odr_intdup (o, atoi (li->lex_buf));
417     else
418     {
419         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
420         return NULL;
421     }
422
423     if (!lex (li))
424     {
425         li->error = YAZ_PQF_ERROR_MISSING;
426         return NULL;
427     }
428     if (*li->lex_buf == '1')
429         p->ordered = odr_intdup (o, 1);
430     else if (*li->lex_buf == '0')
431         p->ordered = odr_intdup (o, 0);
432     else
433     {
434         li->error = YAZ_PQF_ERROR_PROXIMITY;
435         return NULL;
436     }
437     
438     if (!lex (li))
439     {
440         li->error = YAZ_PQF_ERROR_MISSING;
441         return NULL;
442     }
443     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
444         p->relationType = odr_intdup (o, atoi (li->lex_buf));
445     else
446     {
447         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
448         return NULL;
449     }
450
451     if (!lex (li))
452     {
453         li->error = YAZ_PQF_ERROR_MISSING;
454         return NULL;
455     }
456     if (*li->lex_buf == 'k')
457         p->which = Z_ProximityOperator_known;
458     else if (*li->lex_buf == 'p')
459         p->which = Z_ProximityOperator_private;
460     else
461         p->which = atoi (li->lex_buf);
462
463     if (p->which != Z_ProximityOperator_known
464         && p->which != Z_ProximityOperator_private)
465     {
466         li->error = YAZ_PQF_ERROR_PROXIMITY;
467         return NULL;
468     }
469
470     if (!lex (li))
471     {
472         li->error = YAZ_PQF_ERROR_MISSING;
473         return NULL;
474     }
475     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
476         p->u.known = odr_intdup (o, atoi(li->lex_buf));
477     else
478     {
479         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
480         return NULL;
481     }
482     return p;
483 }
484
485 static Z_Complex *rpn_complex(struct yaz_pqf_parser *li, ODR o,
486                               int num_attr, int max_attr, 
487                               int *attr_list, char **attr_clist,
488                               Odr_oid **attr_set)
489 {
490     Z_Complex *zc;
491     Z_Operator *zo;
492
493     zc = (Z_Complex *)odr_malloc (o, sizeof(*zc));
494     zo = (Z_Operator *)odr_malloc (o, sizeof(*zo));
495     zc->roperator = zo;
496     switch (li->query_look)
497     {
498     case 'a':
499         zo->which = Z_Operator_and;
500         zo->u.op_and = odr_nullval();
501         break;
502     case 'o':
503         zo->which = Z_Operator_or;
504         zo->u.op_or = odr_nullval();
505         break;
506     case 'n':
507         zo->which = Z_Operator_and_not;
508         zo->u.and_not = odr_nullval();
509         break;
510     case 'p':
511         zo->which = Z_Operator_prox;
512         zo->u.prox = rpn_proximity (li, o);
513         if (!zo->u.prox)
514             return NULL;
515         break;
516     default:
517         /* we're only called if one of the above types are seens so
518            this shouldn't happen */
519         li->error = YAZ_PQF_ERROR_INTERNAL;
520         return NULL;
521     }
522     lex (li);
523     if (!(zc->s1 =
524           rpn_structure(li, o, num_attr, max_attr, attr_list,
525                         attr_clist, attr_set)))
526         return NULL;
527     if (!(zc->s2 =
528           rpn_structure(li, o, num_attr, max_attr, attr_list,
529                         attr_clist, attr_set)))
530         return NULL;
531     return zc;
532 }
533
534 static void rpn_term_type(struct yaz_pqf_parser *li, ODR o)
535 {
536     if (!li->query_look)
537         return ;
538     if (compare_term (li, "general", 0))
539         li->term_type = Z_Term_general;
540     else if (compare_term (li, "numeric", 0))
541         li->term_type = Z_Term_numeric;
542     else if (compare_term (li, "string", 0))
543         li->term_type = Z_Term_characterString;
544     else if (compare_term (li, "oid", 0))
545         li->term_type = Z_Term_oid;
546     else if (compare_term (li, "datetime", 0))
547         li->term_type = Z_Term_dateTime;
548     else if (compare_term (li, "null", 0))
549         li->term_type = Z_Term_null;
550 #if 0
551     else if (compare_term(li, "range", 0))
552     {
553         /* prepare for external: range search .. */
554         li->term_type = Z_Term_external;
555         li->external_type = VAL_MULTISRCH2;
556     }
557 #endif
558     lex (li);
559 }
560                            
561 static Z_RPNStructure *rpn_structure(struct yaz_pqf_parser *li, ODR o,
562                                      int num_attr, int max_attr, 
563                                      int *attr_list,
564                                      char **attr_clist,
565                                      Odr_oid **attr_set)
566 {
567     Z_RPNStructure *sz;
568
569     sz = (Z_RPNStructure *)odr_malloc (o, sizeof(*sz));
570     switch (li->query_look)
571     {
572     case 'a':
573     case 'o':
574     case 'n':
575     case 'p':
576         sz->which = Z_RPNStructure_complex;
577         if (!(sz->u.complex =
578               rpn_complex (li, o, num_attr, max_attr, attr_list,
579                            attr_clist, attr_set)))
580             return NULL;
581         break;
582     case 't':
583     case 's':
584         sz->which = Z_RPNStructure_simple;
585         if (!(sz->u.simple =
586               rpn_simple (li, o, num_attr, attr_list,
587                           attr_clist, attr_set)))
588             return NULL;
589         break;
590     case 'l':
591         lex (li);
592         if (!li->query_look)
593         {
594             li->error = YAZ_PQF_ERROR_MISSING;
595             return 0;
596         }
597         if (num_attr >= max_attr)
598         {
599             li->error = YAZ_PQF_ERROR_TOOMANY;
600             return 0;
601         }
602         if (!p_query_parse_attr(li, o, num_attr, attr_list,
603                                 attr_clist, attr_set))
604             return 0;
605         num_attr++;
606         lex (li);
607         return
608             rpn_structure (li, o, num_attr, max_attr, attr_list,
609                            attr_clist,  attr_set);
610     case 'y':
611         lex (li);
612         rpn_term_type (li, o);
613         return
614             rpn_structure (li, o, num_attr, max_attr, attr_list,
615                            attr_clist, attr_set);
616     case 0:                /* operator/operand expected! */
617         li->error = YAZ_PQF_ERROR_MISSING;
618         return 0;
619     }
620     return sz;
621 }
622
623 Z_RPNQuery *p_query_rpn_mk(ODR o, struct yaz_pqf_parser *li, const char *qbuf)
624 {
625     Z_RPNQuery *zq;
626     int attr_array[1024];
627     char *attr_clist[512];
628     Odr_oid *attr_set[512];
629     Odr_oid *top_set = 0;
630
631     zq = (Z_RPNQuery *)odr_malloc (o, sizeof(*zq));
632     lex (li);
633     if (li->query_look == 'r')
634     {
635         lex (li);
636         top_set = query_oid_getvalbyname(li, o);
637         if (!top_set)
638         {
639             li->error = YAZ_PQF_ERROR_ATTSET;
640             return NULL;
641         }
642         lex (li);
643     }
644     if (!top_set)
645     {
646         top_set = odr_oiddup(o, yaz_oid_attset_bib_1);
647     }
648
649     zq->attributeSetId = top_set;
650
651     if (!zq->attributeSetId)
652     {
653         li->error = YAZ_PQF_ERROR_ATTSET;
654         return 0;
655     }
656
657     if (!(zq->RPNStructure = rpn_structure(li, o, 0, 512,
658                                            attr_array, attr_clist, attr_set)))
659         return 0;
660     if (li->query_look)
661     {
662         li->error = YAZ_PQF_ERROR_EXTRA;
663         return 0;
664     }
665     return zq;
666 }
667
668 Z_RPNQuery *p_query_rpn(ODR o, const char *qbuf)
669 {
670     struct yaz_pqf_parser li;
671
672     li.error = 0;
673     li.left_sep = "{\"";
674     li.right_sep = "}\"";
675     li.escape_char = '@';
676     li.term_type = Z_Term_general;
677     li.query_buf = li.query_ptr = qbuf;
678     li.lex_buf = 0;
679     return p_query_rpn_mk(o, &li, qbuf);
680 }
681
682
683 Z_AttributesPlusTerm *p_query_scan_mk(struct yaz_pqf_parser *li,
684                                       ODR o, oid_proto proto,
685                                       Odr_oid **attributeSetP,
686                                       const char *qbuf)
687 {
688     int attr_list[1024];
689     char *attr_clist[512];
690     Odr_oid *attr_set[512];
691     int num_attr = 0;
692     int max_attr = 512;
693     Odr_oid *top_set = 0;
694     Z_AttributesPlusTerm *apt;
695
696     lex (li);
697     if (li->query_look == 'r')
698     {
699         lex (li);
700         top_set = query_oid_getvalbyname(li, o);
701         if (!top_set)
702         {
703             li->error = YAZ_PQF_ERROR_ATTSET;
704             return NULL;
705         }
706         lex (li);
707     }
708     if (!top_set)
709     {
710         top_set = odr_oiddup(o, yaz_oid_attset_bib_1);
711     }
712     *attributeSetP = top_set;
713
714     while (1)
715     {
716         if (li->query_look == 'l')
717         {
718             lex (li);
719             if (!li->query_look)
720             {
721                 li->error = YAZ_PQF_ERROR_MISSING;
722                 return 0;
723             }
724             if (num_attr >= max_attr)
725             {
726                 li->error = YAZ_PQF_ERROR_TOOMANY;
727                 return 0;
728             }
729             if (!p_query_parse_attr(li, o, num_attr, attr_list,
730                                     attr_clist, attr_set))
731                 return 0;
732             num_attr++;
733             lex (li);
734         }
735         else if (li->query_look == 'y')
736         {
737             lex (li);
738             rpn_term_type (li, o);
739         }
740         else
741             break;
742     }
743     if (!li->query_look)
744     {
745         li->error = YAZ_PQF_ERROR_MISSING;
746         return 0;
747     }
748     apt = rpn_term(li, o, num_attr, attr_list, attr_clist, attr_set);
749
750     lex (li);
751
752     if (li->query_look != 0)
753     {
754         li->error = YAZ_PQF_ERROR_EXTRA;
755         return 0;
756     }
757     return apt;
758 }
759
760 Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
761                                     Odr_oid **attributeSetP,
762                                     const char *qbuf)
763 {
764     struct yaz_pqf_parser li;
765
766     li.error = 0;
767     li.left_sep = "{\"";
768     li.right_sep = "}\"";
769     li.escape_char = '@';
770     li.term_type = Z_Term_general;
771     li.query_buf = li.query_ptr = qbuf;
772     li.lex_buf = 0;
773
774     return p_query_scan_mk (&li, o, proto, attributeSetP, qbuf);
775 }
776
777 YAZ_PQF_Parser yaz_pqf_create (void)
778 {
779     YAZ_PQF_Parser p = (YAZ_PQF_Parser) xmalloc (sizeof(*p));
780
781     p->error = 0;
782     p->left_sep = "{\"";
783     p->right_sep = "}\"";
784     p->escape_char = '@';
785     p->term_type = Z_Term_general;
786
787     return p;
788 }
789
790 void yaz_pqf_destroy(YAZ_PQF_Parser p)
791 {
792     xfree (p);
793 }
794
795 Z_RPNQuery *yaz_pqf_parse(YAZ_PQF_Parser p, ODR o, const char *qbuf)
796 {
797     if (!p)
798         return 0;
799     p->query_buf = p->query_ptr = qbuf;
800     p->lex_buf = 0;
801     return p_query_rpn_mk (o, p, qbuf);
802 }
803
804 Z_AttributesPlusTerm *yaz_pqf_scan(YAZ_PQF_Parser p, ODR o,
805                                    Odr_oid **attributeSetP,
806                                    const char *qbuf)
807 {
808     if (!p)
809         return 0;
810     p->query_buf = p->query_ptr = qbuf;
811     p->lex_buf = 0;
812     return p_query_scan_mk (p, o, PROTO_Z3950, attributeSetP, qbuf);
813 }
814
815 int yaz_pqf_error (YAZ_PQF_Parser p, const char **msg, size_t *off)
816 {
817     switch (p->error)
818     {
819     case YAZ_PQF_ERROR_NONE:
820         *msg = "no error"; break;
821     case YAZ_PQF_ERROR_EXTRA:
822         *msg = "extra token"; break;
823     case YAZ_PQF_ERROR_MISSING:
824         *msg = "missing token"; break;
825     case YAZ_PQF_ERROR_ATTSET:
826         *msg = "unknown attribute set"; break;
827     case YAZ_PQF_ERROR_TOOMANY:
828         *msg = "too many attributes"; break;
829     case YAZ_PQF_ERROR_BADATTR:
830         *msg = "bad attribute specification"; break;
831     case YAZ_PQF_ERROR_INTERNAL:
832         *msg = "internal error"; break;
833     case YAZ_PQF_ERROR_PROXIMITY:
834         *msg = "proximity error"; break;
835     case YAZ_PQF_ERROR_BAD_INTEGER:
836         *msg = "bad integer"; break;
837     default:
838         *msg = "unknown error"; break;
839     }
840     *off = p->query_ptr - p->query_buf;
841     return p->error;
842 }
843 /*
844  * Local variables:
845  * c-basic-offset: 4
846  * indent-tabs-mode: nil
847  * End:
848  * vim: shiftwidth=4 tabstop=8 expandtab
849  */
850