For OIDs use Odr_oid type everywhere, i.e. do not assume Odr_oid=int.
[yaz-moved-to-github.git] / src / pquery.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: pquery.c,v 1.12 2007-05-08 08:22:36 adam Exp $
6  */
7 /**
8  * \file pquery.c
9  * \brief Implements PQF parsing
10  */
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15
16 #include <yaz/proto.h>
17 #include <yaz/oid_db.h>
18 #include <yaz/pquery.h>
19
20 struct yaz_pqf_parser {
21     const char *query_buf;
22     const char *query_ptr;
23     const char *lex_buf;
24     size_t lex_len;
25     int query_look;
26     char *left_sep;
27     char *right_sep;
28     int escape_char;
29     int term_type;
30     int external_type;
31     int error;
32 };
33
34 static Z_RPNStructure *rpn_structure(struct yaz_pqf_parser *li, ODR o,
35                                      int num_attr, int max_attr, 
36                                      int *attr_list, char **attr_clist,
37                                      Odr_oid **attr_set);
38
39 static Odr_oid *query_oid_getvalbyname(struct yaz_pqf_parser *li, ODR o)
40 {
41     char buf[32];
42
43     if (li->lex_len >= sizeof(buf)-1)
44         return 0;
45     memcpy (buf, li->lex_buf, li->lex_len);
46     buf[li->lex_len] = '\0';
47     return yaz_string_to_oid_odr(yaz_oid_std(), CLASS_ATTSET, buf, o);
48 }
49
50 static int compare_term(struct yaz_pqf_parser *li, const char *src,
51                         size_t off)
52 {
53     size_t len=strlen(src);
54     
55     if (li->lex_len == len+off && !memcmp (li->lex_buf+off, src, len-off))
56         return 1;
57     return 0;
58 }
59
60 static int query_token(struct yaz_pqf_parser *li)
61 {
62     int sep_char = ' ';
63     const char *sep_match;
64     const char **qptr = &li->query_ptr;
65
66     while (**qptr == ' ')
67         (*qptr)++;
68     if (**qptr == '\0')
69         return 0;
70     li->lex_len = 0;
71     if ((sep_match = strchr (li->left_sep, **qptr)))
72     {
73         sep_char = li->right_sep[sep_match - li->left_sep];
74         ++(*qptr);
75     }
76     li->lex_buf = *qptr;
77    
78     if (**qptr == li->escape_char && isdigit (((const unsigned char *) *qptr)[1]))
79     {
80         ++(li->lex_len);
81         ++(*qptr);
82         return 'l';
83     }
84     while (**qptr && **qptr != sep_char)
85     {
86         if (**qptr == '\\')
87         {
88             ++(li->lex_len);
89             ++(*qptr);
90         }
91         ++(li->lex_len);
92         ++(*qptr);
93     }
94     if (**qptr)
95         ++(*qptr);
96     if (sep_char == ' ' &&
97         li->lex_len >= 1 && li->lex_buf[0] == li->escape_char)
98     {
99         if (compare_term (li, "and", 1))
100             return 'a';
101         if (compare_term (li, "or", 1))
102             return 'o';
103         if (compare_term (li, "not", 1))
104             return 'n';
105         if (compare_term (li, "attr", 1))
106             return 'l';
107         if (compare_term (li, "set", 1))
108             return 's';
109         if (compare_term (li, "attrset", 1))
110             return 'r';
111         if (compare_term (li, "prox", 1))
112             return 'p';
113         if (compare_term (li, "term", 1))
114             return 'y';
115     }
116     return 't';
117 }
118
119 static int lex(struct yaz_pqf_parser *li)
120 {
121     return li->query_look = query_token(li);
122 }
123
124 static int escape_string(char *out_buf, const char *in, int len)
125 {
126
127     char *out = out_buf;
128     while (--len >= 0)
129         if (*in == '\\' && len > 0)
130         {
131             --len;
132             switch (*++in)
133             {
134             case 't':
135                 *out++ = '\t';
136                 break;
137             case 'n':
138                 *out++ = '\n';
139                 break;
140             case 'r':
141                 *out++ = '\r';
142                 break;
143             case 'f':
144                 *out++ = '\f';
145                 break;
146             case 'x':
147                 if (len > 1)
148                 {
149                     char s[4];
150                     int n = 0;
151                     s[0] = *++in;
152                     s[1] = *++in;
153                     s[2] = '\0';
154                     len = len - 2;
155                     sscanf (s, "%x", &n);
156                     *out++ = n;
157                 }
158                 break;
159             case '0':
160             case '1':
161             case '2':
162             case '3':
163                 if (len > 1)
164                 {
165                     char s[4];
166                     int n = 0;
167                     s[0] = *in;
168                     s[1] = *++in;                   
169                     s[2] = *++in;
170                     s[3] = '\0';
171                     len = len - 2;
172                     sscanf (s, "%o", &n);
173                     *out++ = n;
174                 }
175                 break;
176             default:
177                 *out++ = *in;
178                 break;
179             }
180             in++;
181         }
182         else
183             *out++ = *in++;
184     return out - out_buf;
185 }
186
187 static int p_query_parse_attr(struct yaz_pqf_parser *li, ODR o,
188                               int num_attr, int *attr_list,
189                               char **attr_clist, Odr_oid **attr_set)
190 {
191     const char *cp;
192
193     if (!(cp = strchr (li->lex_buf, '=')) ||
194         (size_t) (cp-li->lex_buf) > li->lex_len)
195     {
196         attr_set[num_attr] = query_oid_getvalbyname (li, o);
197         if (attr_set[num_attr] == 0)
198         {
199             li->error = YAZ_PQF_ERROR_ATTSET;
200             return 0;
201         }
202         if (!lex (li))
203         {
204             li->error = YAZ_PQF_ERROR_MISSING;
205             return 0;
206         }
207         if (!(cp = strchr (li->lex_buf, '=')))
208         {
209             li->error = YAZ_PQF_ERROR_BADATTR;
210             return 0;
211         }
212     }
213     else 
214     {
215         if (num_attr > 0)
216             attr_set[num_attr] = attr_set[num_attr-1];
217         else
218             attr_set[num_attr] = 0;
219     }
220     if (*li->lex_buf < '0' || *li->lex_buf > '9')
221     {
222         li->error = YAZ_PQF_ERROR_BAD_INTEGER;
223         return 0;
224     }
225     attr_list[2*num_attr] = atoi(li->lex_buf);
226     cp++;
227     if (*cp >= '0' && *cp <= '9')
228     {
229         attr_list[2*num_attr+1] = atoi (cp);
230         attr_clist[num_attr] = 0;
231     }
232     else
233     {
234         int len = li->lex_len - (cp - li->lex_buf);
235         attr_list[2*num_attr+1] = 0;
236         attr_clist[num_attr] = (char *) odr_malloc (o, len+1);
237         len = escape_string(attr_clist[num_attr], cp, len);
238         attr_clist[num_attr][len] = '\0';
239     }
240     return 1;
241 }
242
243 static Z_AttributesPlusTerm *rpn_term(struct yaz_pqf_parser *li, ODR o,
244                                       int num_attr, 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         int *attr_tmp;
262
263         elements = (Z_AttributeElement**)
264             odr_malloc (o, num_attr * sizeof(*elements));
265
266         attr_tmp = (int *)odr_malloc (o, num_attr * 2 * sizeof(int));
267         memcpy (attr_tmp, attr_list, num_attr * 2 * sizeof(int));
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 = (int **)
298                     odr_nullval();
299                 elements[k]->value.complex->num_semanticAction = 0;
300             }
301             else
302             {
303                 elements[k]->which = Z_AttributeValue_numeric;
304                 elements[k]->value.numeric = &attr_tmp[2*i+1];
305             }
306             k++;
307         }
308         num_attr = k;
309     }
310     zapt->attributes = (Z_AttributeList *)
311         odr_malloc (o, sizeof(*zapt->attributes));
312     zapt->attributes->num_attributes = num_attr;
313     zapt->attributes->attributes = elements;
314
315     zapt->term = term;
316
317     term_octet->buf = (unsigned char *)odr_malloc (o, 1 + li->lex_len);
318     term_octet->size = term_octet->len =
319         escape_string ((char *) (term_octet->buf), li->lex_buf, li->lex_len);
320     term_octet->buf[term_octet->size] = 0;  /* null terminate */
321     
322     switch (li->term_type)
323     {
324     case Z_Term_general:
325         term->which = Z_Term_general;
326         term->u.general = term_octet;
327         break;
328     case Z_Term_characterString:
329         term->which = Z_Term_characterString;
330         term->u.characterString = (char*) term_octet->buf; 
331                                     /* null terminated above */
332         break;
333     case Z_Term_numeric:
334         term->which = Z_Term_numeric;
335         term->u.numeric = odr_intdup (o, atoi((char*) (term_octet->buf)));
336         break;
337     case Z_Term_null:
338         term->which = Z_Term_null;
339         term->u.null = odr_nullval();
340         break;
341     case Z_Term_external:
342         term->which = Z_Term_external;
343         term->u.external = 0;
344         break;
345     default:
346         term->which = Z_Term_null;
347         term->u.null = odr_nullval();
348         break;
349     }
350     return zapt;
351 }
352
353 static Z_Operand *rpn_simple(struct yaz_pqf_parser *li, ODR o,
354                              int num_attr, int *attr_list, 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_intdup (o, 1);
402     else if (*li->lex_buf == '0')
403         p->exclusion = odr_intdup (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, 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_intdup (o, 1);
432     else if (*li->lex_buf == '0')
433         p->ordered = odr_intdup (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, 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, 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                               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, ODR o)
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                                      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, o);
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 Z_RPNQuery *p_query_rpn_mk(ODR o, struct yaz_pqf_parser *li, const char *qbuf)
626 {
627     Z_RPNQuery *zq;
628     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, qbuf);
682 }
683
684
685 Z_AttributesPlusTerm *p_query_scan_mk(struct yaz_pqf_parser *li,
686                                       ODR o, oid_proto proto,
687                                       Odr_oid **attributeSetP,
688                                       const char *qbuf)
689 {
690     int attr_list[1024];
691     char *attr_clist[512];
692     Odr_oid *attr_set[512];
693     int num_attr = 0;
694     int max_attr = 512;
695     Odr_oid *top_set = 0;
696     Z_AttributesPlusTerm *apt;
697
698     lex (li);
699     if (li->query_look == 'r')
700     {
701         lex (li);
702         top_set = query_oid_getvalbyname(li, o);
703         if (!top_set)
704         {
705             li->error = YAZ_PQF_ERROR_ATTSET;
706             return NULL;
707         }
708         lex (li);
709     }
710     if (!top_set)
711     {
712         top_set = odr_oiddup(o, yaz_oid_attset_bib_1);
713     }
714     *attributeSetP = top_set;
715
716     while (1)
717     {
718         if (li->query_look == 'l')
719         {
720             lex (li);
721             if (!li->query_look)
722             {
723                 li->error = YAZ_PQF_ERROR_MISSING;
724                 return 0;
725             }
726             if (num_attr >= max_attr)
727             {
728                 li->error = YAZ_PQF_ERROR_TOOMANY;
729                 return 0;
730             }
731             if (!p_query_parse_attr(li, o, num_attr, attr_list,
732                                     attr_clist, attr_set))
733                 return 0;
734             num_attr++;
735             lex (li);
736         }
737         else if (li->query_look == 'y')
738         {
739             lex (li);
740             rpn_term_type (li, o);
741         }
742         else
743             break;
744     }
745     if (!li->query_look)
746     {
747         li->error = YAZ_PQF_ERROR_MISSING;
748         return 0;
749     }
750     apt = rpn_term(li, o, num_attr, attr_list, attr_clist, attr_set);
751
752     lex (li);
753
754     if (li->query_look != 0)
755     {
756         li->error = YAZ_PQF_ERROR_EXTRA;
757         return 0;
758     }
759     return apt;
760 }
761
762 Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
763                                     Odr_oid **attributeSetP,
764                                     const char *qbuf)
765 {
766     struct yaz_pqf_parser li;
767
768     li.error = 0;
769     li.left_sep = "{\"";
770     li.right_sep = "}\"";
771     li.escape_char = '@';
772     li.term_type = Z_Term_general;
773     li.query_buf = li.query_ptr = qbuf;
774     li.lex_buf = 0;
775
776     return p_query_scan_mk (&li, o, proto, attributeSetP, qbuf);
777 }
778
779 YAZ_PQF_Parser yaz_pqf_create (void)
780 {
781     YAZ_PQF_Parser p = (YAZ_PQF_Parser) xmalloc (sizeof(*p));
782
783     p->error = 0;
784     p->left_sep = "{\"";
785     p->right_sep = "}\"";
786     p->escape_char = '@';
787     p->term_type = Z_Term_general;
788
789     return p;
790 }
791
792 void yaz_pqf_destroy(YAZ_PQF_Parser p)
793 {
794     xfree (p);
795 }
796
797 Z_RPNQuery *yaz_pqf_parse(YAZ_PQF_Parser p, ODR o, const char *qbuf)
798 {
799     if (!p)
800         return 0;
801     p->query_buf = p->query_ptr = qbuf;
802     p->lex_buf = 0;
803     return p_query_rpn_mk (o, p, qbuf);
804 }
805
806 Z_AttributesPlusTerm *yaz_pqf_scan(YAZ_PQF_Parser p, ODR o,
807                                    Odr_oid **attributeSetP,
808                                    const char *qbuf)
809 {
810     if (!p)
811         return 0;
812     p->query_buf = p->query_ptr = qbuf;
813     p->lex_buf = 0;
814     return p_query_scan_mk (p, o, PROTO_Z3950, attributeSetP, qbuf);
815 }
816
817 int yaz_pqf_error (YAZ_PQF_Parser p, const char **msg, size_t *off)
818 {
819     switch (p->error)
820     {
821     case YAZ_PQF_ERROR_NONE:
822         *msg = "no error"; break;
823     case YAZ_PQF_ERROR_EXTRA:
824         *msg = "extra token"; break;
825     case YAZ_PQF_ERROR_MISSING:
826         *msg = "missing token"; break;
827     case YAZ_PQF_ERROR_ATTSET:
828         *msg = "unknown attribute set"; break;
829     case YAZ_PQF_ERROR_TOOMANY:
830         *msg = "too many attributes"; break;
831     case YAZ_PQF_ERROR_BADATTR:
832         *msg = "bad attribute specification"; break;
833     case YAZ_PQF_ERROR_INTERNAL:
834         *msg = "internal error"; break;
835     case YAZ_PQF_ERROR_PROXIMITY:
836         *msg = "proximity error"; break;
837     case YAZ_PQF_ERROR_BAD_INTEGER:
838         *msg = "bad integer"; break;
839     default:
840         *msg = "unknown error"; break;
841     }
842     *off = p->query_ptr - p->query_buf;
843     return p->error;
844 }
845 /*
846  * Local variables:
847  * c-basic-offset: 4
848  * indent-tabs-mode: nil
849  * End:
850  * vim: shiftwidth=4 tabstop=8 expandtab
851  */
852