Minor PQF encoding and decoding changes; reformat
[yaz-moved-to-github.git] / src / pquery.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 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                                      Odr_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, Odr_int *attr_list,
187                               char **attr_clist, Odr_oid **attr_set)
188 {
189     const char *cp;
190     size_t i;
191
192     if (!(cp = strchr(li->lex_buf, '=')) ||
193         (size_t) (cp-li->lex_buf) > li->lex_len)
194     {
195         attr_set[num_attr] = query_oid_getvalbyname(li, o);
196         if (attr_set[num_attr] == 0)
197         {
198             li->error = YAZ_PQF_ERROR_ATTSET;
199             return 0;
200         }
201         if (!lex(li))
202         {
203             li->error = YAZ_PQF_ERROR_MISSING;
204             return 0;
205         }
206         if (!(cp = strchr(li->lex_buf, '=')))
207         {
208             li->error = YAZ_PQF_ERROR_BADATTR;
209             return 0;
210         }
211     }
212     else 
213     {
214         if (num_attr > 0)
215             attr_set[num_attr] = attr_set[num_attr-1];
216         else
217             attr_set[num_attr] = 0;
218     }
219     if (*li->lex_buf < '0' || *li->lex_buf > '9')
220     {
221         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
222         return 0;
223     }
224     attr_list[2*num_attr] = odr_atoi(li->lex_buf);
225     cp++;
226
227     /* inspect value .. and make it a integer if it appears to be */
228     for (i = cp - li->lex_buf; i < li->lex_len; i++)
229         if (li->lex_buf[i] < '0' || li->lex_buf[i] > '9')
230         {
231             int len = li->lex_len - (cp - li->lex_buf);
232             attr_list[2*num_attr+1] = 0;
233             attr_clist[num_attr] = (char *) odr_malloc(o, len+1);
234             len = escape_string(attr_clist[num_attr], cp, len);
235             attr_clist[num_attr][len] = '\0';
236             return 1;
237         }
238     attr_list[2*num_attr+1] = odr_atoi(cp);
239     attr_clist[num_attr] = 0;
240     return 1;
241 }
242
243 static Z_AttributesPlusTerm *rpn_term(struct yaz_pqf_parser *li, ODR o,
244                                       int num_attr, Odr_int *attr_list,
245                                       char **attr_clist, Odr_oid **attr_set)
246 {
247     Z_AttributesPlusTerm *zapt;
248     Odr_oct *term_octet;
249     Z_Term *term;
250     Z_AttributeElement **elements;
251
252     zapt = (Z_AttributesPlusTerm *)odr_malloc(o, sizeof(*zapt));
253     term_octet = (Odr_oct *)odr_malloc(o, sizeof(*term_octet));
254     term = (Z_Term *)odr_malloc(o, sizeof(*term));
255
256     if (!num_attr)
257         elements = (Z_AttributeElement**)odr_nullval();
258     else
259     {
260         int i, k = 0;
261         Odr_int *attr_tmp;
262
263         elements = (Z_AttributeElement**)
264             odr_malloc (o, num_attr * sizeof(*elements));
265
266         attr_tmp = (Odr_int *)odr_malloc(o, num_attr * 2 * sizeof(*attr_tmp));
267         memcpy(attr_tmp, attr_list, num_attr * 2 * sizeof(*attr_tmp));
268         for (i = num_attr; --i >= 0; )
269         {
270             int j;
271             for (j = i+1; j<num_attr; j++)
272                 if (attr_tmp[2*j] == attr_tmp[2*i])
273                     break;
274             if (j < num_attr)
275                 continue;
276             elements[k] =
277                 (Z_AttributeElement*)odr_malloc(o,sizeof(**elements));
278             elements[k]->attributeType = &attr_tmp[2*i];
279             elements[k]->attributeSet = attr_set[i];
280
281             if (attr_clist[i])
282             {
283                 elements[k]->which = Z_AttributeValue_complex;
284                 elements[k]->value.complex = (Z_ComplexAttribute *)
285                     odr_malloc(o, sizeof(Z_ComplexAttribute));
286                 elements[k]->value.complex->num_list = 1;
287                 elements[k]->value.complex->list =
288                     (Z_StringOrNumeric **)
289                     odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
290                 elements[k]->value.complex->list[0] =
291                     (Z_StringOrNumeric *)
292                     odr_malloc(o, sizeof(Z_StringOrNumeric));
293                 elements[k]->value.complex->list[0]->which =
294                     Z_StringOrNumeric_string;
295                 elements[k]->value.complex->list[0]->u.string =
296                     attr_clist[i];
297                 elements[k]->value.complex->semanticAction = 0;
298                 elements[k]->value.complex->num_semanticAction = 0;
299             }
300             else
301             {
302                 elements[k]->which = Z_AttributeValue_numeric;
303                 elements[k]->value.numeric = &attr_tmp[2*i+1];
304             }
305             k++;
306         }
307         num_attr = k;
308     }
309     zapt->attributes = (Z_AttributeList *)
310         odr_malloc(o, sizeof(*zapt->attributes));
311     zapt->attributes->num_attributes = num_attr;
312     zapt->attributes->attributes = elements;
313
314     zapt->term = term;
315
316     term_octet->buf = (unsigned char *)odr_malloc(o, 1 + li->lex_len);
317     term_octet->size = term_octet->len =
318         escape_string((char *) (term_octet->buf), li->lex_buf, li->lex_len);
319     term_octet->buf[term_octet->size] = 0;  /* null terminate */
320     
321     switch (li->term_type)
322     {
323     case Z_Term_general:
324         term->which = Z_Term_general;
325         term->u.general = term_octet;
326         break;
327     case Z_Term_characterString:
328         term->which = Z_Term_characterString;
329         term->u.characterString = (char*) term_octet->buf; 
330         /* null terminated above */
331         break;
332     case Z_Term_numeric:
333         term->which = Z_Term_numeric;
334         term->u.numeric = odr_intdup(o, odr_atoi((const char*) term_octet->buf));
335         break;
336     case Z_Term_null:
337         term->which = Z_Term_null;
338         term->u.null = odr_nullval();
339         break;
340     case Z_Term_external:
341         term->which = Z_Term_external;
342         term->u.external = 0;
343         break;
344     default:
345         term->which = Z_Term_null;
346         term->u.null = odr_nullval();
347         break;
348     }
349     return zapt;
350 }
351
352 static Z_Operand *rpn_simple(struct yaz_pqf_parser *li, ODR o,
353                              int num_attr, Odr_int *attr_list,
354                              char **attr_clist,
355                              Odr_oid **attr_set)
356 {
357     Z_Operand *zo;
358
359     zo = (Z_Operand *)odr_malloc(o, sizeof(*zo));
360     switch (li->query_look)
361     {
362     case 't':
363         zo->which = Z_Operand_APT;
364         if (!(zo->u.attributesPlusTerm =
365               rpn_term(li, o, num_attr, attr_list, attr_clist, attr_set)))
366             return 0;
367         lex(li);
368         break;
369     case 's':
370         lex(li);
371         if (!li->query_look)
372         {
373             li->error = YAZ_PQF_ERROR_MISSING;
374             return 0;
375         }
376         zo->which = Z_Operand_resultSetId;
377         zo->u.resultSetId = (char *)odr_malloc(o, li->lex_len+1);
378         memcpy(zo->u.resultSetId, li->lex_buf, li->lex_len);
379         zo->u.resultSetId[li->lex_len] = '\0';
380         lex(li);
381         break;
382     default:
383         /* we're only called if one of the above types are seens so
384            this shouldn't happen */
385         li->error = YAZ_PQF_ERROR_INTERNAL;
386         return 0;
387     }
388     return zo;
389 }
390
391 static Z_ProximityOperator *rpn_proximity(struct yaz_pqf_parser *li, ODR o)
392 {
393     Z_ProximityOperator *p = (Z_ProximityOperator *)odr_malloc(o, sizeof(*p));
394
395     if (!lex(li))
396     {
397         li->error = YAZ_PQF_ERROR_MISSING;
398         return NULL;
399     }
400     if (*li->lex_buf == '1')
401         p->exclusion = odr_booldup(o, 1);
402     else if (*li->lex_buf == '0')
403         p->exclusion = odr_booldup(o, 0);
404     else if (*li->lex_buf == 'v' || *li->lex_buf == 'n')
405         p->exclusion = NULL;
406     else
407     {
408         li->error = YAZ_PQF_ERROR_PROXIMITY;
409         return NULL;
410     }
411
412     if (!lex(li))
413     {
414         li->error = YAZ_PQF_ERROR_MISSING;
415         return NULL;
416     }
417     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
418         p->distance = odr_intdup(o, odr_atoi(li->lex_buf));
419     else
420     {
421         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
422         return NULL;
423     }
424
425     if (!lex(li))
426     {
427         li->error = YAZ_PQF_ERROR_MISSING;
428         return NULL;
429     }
430     if (*li->lex_buf == '1')
431         p->ordered = odr_booldup(o, 1);
432     else if (*li->lex_buf == '0')
433         p->ordered = odr_booldup(o, 0);
434     else
435     {
436         li->error = YAZ_PQF_ERROR_PROXIMITY;
437         return NULL;
438     }
439     
440     if (!lex (li))
441     {
442         li->error = YAZ_PQF_ERROR_MISSING;
443         return NULL;
444     }
445     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
446         p->relationType = odr_intdup(o, odr_atoi(li->lex_buf));
447     else
448     {
449         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
450         return NULL;
451     }
452
453     if (!lex(li))
454     {
455         li->error = YAZ_PQF_ERROR_MISSING;
456         return NULL;
457     }
458     if (*li->lex_buf == 'k')
459         p->which = Z_ProximityOperator_known;
460     else if (*li->lex_buf == 'p')
461         p->which = Z_ProximityOperator_private;
462     else
463         p->which = atoi(li->lex_buf);
464
465     if (p->which != Z_ProximityOperator_known
466         && p->which != Z_ProximityOperator_private)
467     {
468         li->error = YAZ_PQF_ERROR_PROXIMITY;
469         return NULL;
470     }
471
472     if (!lex(li))
473     {
474         li->error = YAZ_PQF_ERROR_MISSING;
475         return NULL;
476     }
477     if (*li->lex_buf >= '0' && *li->lex_buf <= '9')
478         p->u.known = odr_intdup(o, odr_atoi(li->lex_buf));
479     else
480     {
481         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
482         return NULL;
483     }
484     return p;
485 }
486
487 static Z_Complex *rpn_complex(struct yaz_pqf_parser *li, ODR o,
488                               int num_attr, int max_attr, 
489                               Odr_int *attr_list, char **attr_clist,
490                               Odr_oid **attr_set)
491 {
492     Z_Complex *zc;
493     Z_Operator *zo;
494
495     zc = (Z_Complex *)odr_malloc(o, sizeof(*zc));
496     zo = (Z_Operator *)odr_malloc(o, sizeof(*zo));
497     zc->roperator = zo;
498     switch (li->query_look)
499     {
500     case 'a':
501         zo->which = Z_Operator_and;
502         zo->u.op_and = odr_nullval();
503         break;
504     case 'o':
505         zo->which = Z_Operator_or;
506         zo->u.op_or = odr_nullval();
507         break;
508     case 'n':
509         zo->which = Z_Operator_and_not;
510         zo->u.and_not = odr_nullval();
511         break;
512     case 'p':
513         zo->which = Z_Operator_prox;
514         zo->u.prox = rpn_proximity(li, o);
515         if (!zo->u.prox)
516             return NULL;
517         break;
518     default:
519         /* we're only called if one of the above types are seens so
520            this shouldn't happen */
521         li->error = YAZ_PQF_ERROR_INTERNAL;
522         return NULL;
523     }
524     lex(li);
525     if (!(zc->s1 =
526           rpn_structure(li, o, num_attr, max_attr, attr_list,
527                         attr_clist, attr_set)))
528         return NULL;
529     if (!(zc->s2 =
530           rpn_structure(li, o, num_attr, max_attr, attr_list,
531                         attr_clist, attr_set)))
532         return NULL;
533     return zc;
534 }
535
536 static void rpn_term_type(struct yaz_pqf_parser *li)
537 {
538     if (!li->query_look)
539         return ;
540     if (compare_term(li, "general", 0))
541         li->term_type = Z_Term_general;
542     else if (compare_term(li, "numeric", 0))
543         li->term_type = Z_Term_numeric;
544     else if (compare_term(li, "string", 0))
545         li->term_type = Z_Term_characterString;
546     else if (compare_term(li, "oid", 0))
547         li->term_type = Z_Term_oid;
548     else if (compare_term(li, "datetime", 0))
549         li->term_type = Z_Term_dateTime;
550     else if (compare_term(li, "null", 0))
551         li->term_type = Z_Term_null;
552 #if 0
553     else if (compare_term(li, "range", 0))
554     {
555         /* prepare for external: range search .. */
556         li->term_type = Z_Term_external;
557         li->external_type = VAL_MULTISRCH2;
558     }
559 #endif
560     lex(li);
561 }
562                            
563 static Z_RPNStructure *rpn_structure(struct yaz_pqf_parser *li, ODR o,
564                                      int num_attr, int max_attr, 
565                                      Odr_int *attr_list,
566                                      char **attr_clist,
567                                      Odr_oid **attr_set)
568 {
569     Z_RPNStructure *sz;
570
571     sz = (Z_RPNStructure *)odr_malloc(o, sizeof(*sz));
572     switch (li->query_look)
573     {
574     case 'a':
575     case 'o':
576     case 'n':
577     case 'p':
578         sz->which = Z_RPNStructure_complex;
579         if (!(sz->u.complex =
580               rpn_complex(li, o, num_attr, max_attr, attr_list,
581                           attr_clist, attr_set)))
582             return NULL;
583         break;
584     case 't':
585     case 's':
586         sz->which = Z_RPNStructure_simple;
587         if (!(sz->u.simple =
588               rpn_simple(li, o, num_attr, attr_list,
589                          attr_clist, attr_set)))
590             return NULL;
591         break;
592     case 'l':
593         lex(li);
594         if (!li->query_look)
595         {
596             li->error = YAZ_PQF_ERROR_MISSING;
597             return 0;
598         }
599         if (num_attr >= max_attr)
600         {
601             li->error = YAZ_PQF_ERROR_TOOMANY;
602             return 0;
603         }
604         if (!p_query_parse_attr(li, o, num_attr, attr_list,
605                                 attr_clist, attr_set))
606             return 0;
607         num_attr++;
608         lex(li);
609         return
610             rpn_structure(li, o, num_attr, max_attr, attr_list,
611                           attr_clist,  attr_set);
612     case 'y':
613         lex(li);
614         rpn_term_type(li);
615         return
616             rpn_structure(li, o, num_attr, max_attr, attr_list,
617                           attr_clist, attr_set);
618     case 0:                /* operator/operand expected! */
619         li->error = YAZ_PQF_ERROR_MISSING;
620         return 0;
621     }
622     return sz;
623 }
624
625 static Z_RPNQuery *p_query_rpn_mk(ODR o, struct yaz_pqf_parser *li)
626 {
627     Z_RPNQuery *zq;
628     Odr_int attr_array[1024];
629     char *attr_clist[512];
630     Odr_oid *attr_set[512];
631     Odr_oid *top_set = 0;
632
633     zq = (Z_RPNQuery *)odr_malloc(o, sizeof(*zq));
634     lex(li);
635     if (li->query_look == 'r')
636     {
637         lex(li);
638         top_set = query_oid_getvalbyname(li, o);
639         if (!top_set)
640         {
641             li->error = YAZ_PQF_ERROR_ATTSET;
642             return NULL;
643         }
644         lex(li);
645     }
646     if (!top_set)
647     {
648         top_set = odr_oiddup(o, yaz_oid_attset_bib_1);
649     }
650
651     zq->attributeSetId = top_set;
652
653     if (!zq->attributeSetId)
654     {
655         li->error = YAZ_PQF_ERROR_ATTSET;
656         return 0;
657     }
658
659     if (!(zq->RPNStructure = rpn_structure(li, o, 0, 512,
660                                            attr_array, attr_clist, attr_set)))
661         return 0;
662     if (li->query_look)
663     {
664         li->error = YAZ_PQF_ERROR_EXTRA;
665         return 0;
666     }
667     return zq;
668 }
669
670 Z_RPNQuery *p_query_rpn(ODR o, const char *qbuf)
671 {
672     struct yaz_pqf_parser li;
673
674     li.error = 0;
675     li.left_sep = "{\"";
676     li.right_sep = "}\"";
677     li.escape_char = '@';
678     li.term_type = Z_Term_general;
679     li.query_buf = li.query_ptr = qbuf;
680     li.lex_buf = 0;
681     return p_query_rpn_mk(o, &li);
682 }
683
684
685 static Z_AttributesPlusTerm *p_query_scan_mk(struct yaz_pqf_parser *li,
686                                              ODR o,
687                                              Odr_oid **attributeSetP)
688 {
689     Odr_int attr_list[1024];
690     char *attr_clist[512];
691     Odr_oid *attr_set[512];
692     int num_attr = 0;
693     int max_attr = 512;
694     Odr_oid *top_set = 0;
695     Z_AttributesPlusTerm *apt;
696
697     lex(li);
698     if (li->query_look == 'r')
699     {
700         lex(li);
701         top_set = query_oid_getvalbyname(li, o);
702         if (!top_set)
703         {
704             li->error = YAZ_PQF_ERROR_ATTSET;
705             return NULL;
706         }
707         lex(li);
708     }
709     if (!top_set)
710     {
711         top_set = odr_oiddup(o, yaz_oid_attset_bib_1);
712     }
713     *attributeSetP = top_set;
714
715     while (1)
716     {
717         if (li->query_look == 'l')
718         {
719             lex(li);
720             if (!li->query_look)
721             {
722                 li->error = YAZ_PQF_ERROR_MISSING;
723                 return 0;
724             }
725             if (num_attr >= max_attr)
726             {
727                 li->error = YAZ_PQF_ERROR_TOOMANY;
728                 return 0;
729             }
730             if (!p_query_parse_attr(li, o, num_attr, attr_list,
731                                     attr_clist, attr_set))
732                 return 0;
733             num_attr++;
734             lex(li);
735         }
736         else if (li->query_look == 'y')
737         {
738             lex(li);
739             rpn_term_type(li);
740         }
741         else
742             break;
743     }
744     if (!li->query_look)
745     {
746         li->error = YAZ_PQF_ERROR_MISSING;
747         return 0;
748     }
749     apt = rpn_term(li, o, num_attr, attr_list, attr_clist, attr_set);
750
751     lex(li);
752
753     if (li->query_look != 0)
754     {
755         li->error = YAZ_PQF_ERROR_EXTRA;
756         return 0;
757     }
758     return apt;
759 }
760
761 YAZ_PQF_Parser yaz_pqf_create(void)
762 {
763     YAZ_PQF_Parser p = (YAZ_PQF_Parser) xmalloc(sizeof(*p));
764
765     p->error = 0;
766     p->left_sep = "{\"";
767     p->right_sep = "}\"";
768     p->escape_char = '@';
769     p->term_type = Z_Term_general;
770
771     return p;
772 }
773
774 void yaz_pqf_destroy(YAZ_PQF_Parser p)
775 {
776     xfree(p);
777 }
778
779 Z_RPNQuery *yaz_pqf_parse(YAZ_PQF_Parser p, ODR o, const char *qbuf)
780 {
781     if (!p)
782         return 0;
783     p->query_buf = p->query_ptr = qbuf;
784     p->lex_buf = 0;
785     return p_query_rpn_mk(o, p);
786 }
787
788 Z_AttributesPlusTerm *yaz_pqf_scan(YAZ_PQF_Parser p, ODR o,
789                                    Odr_oid **attributeSetP,
790                                    const char *qbuf)
791 {
792     if (!p)
793         return 0;
794     p->query_buf = p->query_ptr = qbuf;
795     p->lex_buf = 0;
796     return p_query_scan_mk(p, o, attributeSetP);
797 }
798
799 int yaz_pqf_error(YAZ_PQF_Parser p, const char **msg, size_t *off)
800 {
801     switch (p->error)
802     {
803     case YAZ_PQF_ERROR_NONE:
804         *msg = "no error"; break;
805     case YAZ_PQF_ERROR_EXTRA:
806         *msg = "extra token"; break;
807     case YAZ_PQF_ERROR_MISSING:
808         *msg = "missing token"; break;
809     case YAZ_PQF_ERROR_ATTSET:
810         *msg = "unknown attribute set"; break;
811     case YAZ_PQF_ERROR_TOOMANY:
812         *msg = "too many attributes"; break;
813     case YAZ_PQF_ERROR_BADATTR:
814         *msg = "bad attribute specification"; break;
815     case YAZ_PQF_ERROR_INTERNAL:
816         *msg = "internal error"; break;
817     case YAZ_PQF_ERROR_PROXIMITY:
818         *msg = "proximity error"; break;
819     case YAZ_PQF_ERROR_BAD_INTEGER:
820         *msg = "bad integer"; break;
821     default:
822         *msg = "unknown error"; break;
823     }
824     *off = p->query_ptr - p->query_buf;
825     return p->error;
826 }
827 /*
828  * Local variables:
829  * c-basic-offset: 4
830  * c-file-style: "Stroustrup"
831  * indent-tabs-mode: nil
832  * End:
833  * vim: shiftwidth=4 tabstop=8 expandtab
834  */
835