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