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