Added yaz_encode_pqf_term to encode PQF strings.
[yaz-moved-to-github.git] / src / cclptree.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 cclptree.c
7  * \brief Implements CCL parse tree printing
8  *
9  * This source file implements functions to parse and print
10  * a CCL node tree (as a result of parsing).
11  */
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #include <yaz/querytowrbuf.h>
18 #include <yaz/ccl.h>
19
20 static void ccl_pquery_indent(WRBUF w, struct ccl_rpn_node *p, int indent);
21
22 static void ccl_pquery_complex(WRBUF w, struct ccl_rpn_node *p, int indent)
23 {
24     int sep_char = indent == -1 ? ' ' : '\n';
25     int next_indent = indent == -1 ? indent : indent+1;
26     switch (p->kind)
27     {
28     case CCL_RPN_AND:
29         wrbuf_puts(w, "@and");
30         break;
31     case CCL_RPN_OR:
32         wrbuf_puts(w, "@or");
33         break;
34     case CCL_RPN_NOT:
35         wrbuf_puts(w, "@not");
36         break;
37     case CCL_RPN_PROX:
38         if (p->u.p[2] && p->u.p[2]->kind == CCL_RPN_TERM)
39         {
40             const char *cp = p->u.p[2]->u.t.term;
41             /* exlusion distance ordered relation which-code unit-code */
42             if (*cp == '!')
43             {   
44                 /* word order specified */
45                 if (isdigit(((const unsigned char *) cp)[1]))
46                     wrbuf_printf(w, "@prox 0 %s 1 2 k 2", cp+1);
47                 else
48                     wrbuf_printf(w, "@prox 0 1 1 2 k 2");
49             } 
50             else if (*cp == '%')
51             {
52                 /* word order not specified */
53                 if (isdigit(((const unsigned char *) cp)[1]))
54                     wrbuf_printf(w, "@prox 0 %s 0 2 k 2", cp+1);
55                 else
56                     wrbuf_printf(w, "@prox 0 1 0 2 k 2");
57             }
58         }
59         else
60             wrbuf_puts(w, "@prox 0 2 0 1 k 2");
61         break;
62     default:
63         wrbuf_puts(w, "@ bad op (unknown)");
64     }
65     wrbuf_putc(w, sep_char);
66     ccl_pquery_indent(w, p->u.p[0], next_indent);
67     ccl_pquery_indent(w, p->u.p[1], next_indent);
68 }
69
70 static void ccl_prterm(WRBUF w, const char *term)
71 {
72     yaz_encode_pqf_term(w, term, strlen(term));
73 }
74
75 static void ccl_pquery_indent(WRBUF w, struct ccl_rpn_node *p, int indent)
76 {
77     struct ccl_rpn_attr *att;
78
79     if (!p)
80         return;
81     if (indent != -1)
82     {
83         int i;
84         for (i = 0; i < indent; i++)
85             wrbuf_putc(w, ' ');
86     }
87     switch (p->kind)
88     {
89     case CCL_RPN_AND:
90     case CCL_RPN_OR:
91     case CCL_RPN_NOT:
92     case CCL_RPN_PROX:
93         ccl_pquery_complex(w, p, indent);
94         break;
95     case CCL_RPN_SET:
96         wrbuf_puts(w, "@set ");
97         ccl_prterm(w, p->u.setname);
98         if (indent != -1)
99             wrbuf_putc(w, '\n');
100         break;
101     case CCL_RPN_TERM:
102         for (att = p->u.t.attr_list; att; att = att->next)
103         {
104             char tmpattr[128];
105             wrbuf_puts(w, "@attr ");
106             if (att->set)
107             {
108                 wrbuf_puts(w, att->set);
109                 wrbuf_puts(w, " ");
110             }
111             switch(att->kind)
112             {
113             case CCL_RPN_ATTR_NUMERIC:
114                 sprintf(tmpattr, "%d=%d ", att->type, att->value.numeric);
115                 wrbuf_puts(w, tmpattr);
116                 break;
117             case CCL_RPN_ATTR_STRING:
118                 sprintf(tmpattr, "%d=", att->type);
119                 wrbuf_puts(w, tmpattr);
120                 wrbuf_puts(w, att->value.str);
121                 wrbuf_puts(w, " ");
122                 break;
123             }
124         }
125         ccl_prterm(w, p->u.t.term);
126         if (indent != -1)
127             wrbuf_putc(w, '\n');
128         break;
129     }
130 }
131
132 void ccl_pquery(WRBUF w, struct ccl_rpn_node *p)
133 {
134     ccl_pquery_indent(w, p, -1);
135 }
136
137 void ccl_pr_tree(struct ccl_rpn_node *rpn, FILE *fd_out)
138 {
139     WRBUF w = wrbuf_alloc();
140
141     ccl_pquery_indent(w, rpn, 0);
142     
143     fputs(wrbuf_cstr(w), fd_out);
144     wrbuf_destroy(w);
145 }
146
147 /*
148  * Local variables:
149  * c-basic-offset: 4
150  * indent-tabs-mode: nil
151  * End:
152  * vim: shiftwidth=4 tabstop=8 expandtab
153  */
154