Remove the extensive logging
[yaz-moved-to-github.git] / src / ccltoken.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 ccltoken.c
7  * \brief Implements CCL lexical analyzer (scanner)
8  */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13
14 #include "cclp.h"
15
16 /*
17  * token_cmp: Compare token with keyword(s)
18  * kw:     Keyword list. Each keyword is separated by space.
19  * token:  CCL token.
20  * return: 1 if token string matches one of the keywords in list;
21  *         0 otherwise.
22  */
23 static int token_cmp(CCL_parser cclp, const char **kw, struct ccl_token *token)
24 {
25     const char **aliases;
26     int case_sensitive = cclp->ccl_case_sensitive;
27     int i;
28
29     aliases = ccl_qual_search_special(cclp->bibset, "case");
30     if (aliases)
31         case_sensitive = atoi(aliases[0]);
32
33     for (i = 0; kw[i]; i++)
34     {
35         if (token->len == strlen(kw[i]))
36         {
37             if (case_sensitive)
38             {
39                 if (!memcmp(kw[i], token->name, token->len))
40                     return 1;
41             }
42             else
43             {
44                 if (!ccl_memicmp(kw[i], token->name, token->len))
45                     return 1;
46             }
47         }
48     }
49     return 0;
50 }
51
52 /*
53  * ccl_tokenize: tokenize CCL command string.
54  * return: CCL token list.
55  */
56 struct ccl_token *ccl_parser_tokenize(CCL_parser cclp, const char *command)
57 {
58     const char **aliases;
59     const unsigned char *cp = (const unsigned char *) command;
60     struct ccl_token *first = NULL;
61     struct ccl_token *last = NULL;
62     cclp->start_pos = command;
63
64     while (1)
65     {
66         const unsigned char *cp0 = cp;
67         while (*cp && strchr(" \t\r\n", *cp))
68             cp++;
69         if (!first)
70         {
71             first = last = (struct ccl_token *)xmalloc(sizeof(*first));
72             ccl_assert(first);
73             last->prev = NULL;
74         }
75         else
76         {
77             last->next = (struct ccl_token *)xmalloc(sizeof(*first));
78             ccl_assert(last->next);
79             last->next->prev = last;
80             last = last->next;
81         }
82         last->left_trunc = last->right_trunc = 0;
83         last->ws_prefix_buf = (const char *) cp0;
84         last->ws_prefix_len = cp - cp0;
85         last->next = NULL;
86         last->name = (const char *) cp;
87         last->len = 1;
88         switch (*cp++)
89         {
90         case '\0':
91             last->kind = CCL_TOK_EOL;
92             return first;
93         case '(':
94             last->kind = CCL_TOK_LP;
95             break;
96         case ')':
97             last->kind = CCL_TOK_RP;
98             break;
99         case ',':
100             last->kind = CCL_TOK_COMMA;
101             break;
102         case '%':
103         case '!':
104             last->kind = CCL_TOK_PROX;
105             while (isdigit(*cp))
106             {
107                 ++ last->len;
108                 cp++;
109             }
110             break;
111         case '>':
112         case '<':
113         case '=':
114             if (*cp == '=' || *cp == '<' || *cp == '>')
115             {
116                 cp++;
117                 last->kind = CCL_TOK_REL;
118                 ++ last->len;
119             }
120             else if (cp[-1] == '=')
121                 last->kind = CCL_TOK_EQ;
122             else
123                 last->kind = CCL_TOK_REL;
124             break;
125         default:
126             --cp;
127             --last->len;
128             if (*cp == '?')
129             {
130                 last->left_trunc = 1;
131                 cp++;
132             }
133             if (*cp == '"')
134             {
135                 cp++;
136                 last->kind = CCL_TOK_TERM;
137                 last->name = (const char *) cp;
138                 while (*cp && *cp != '"')
139                 {
140                     cp++;
141                     ++ last->len;
142                 }
143                 if (*cp)
144                     cp++;
145             }
146             else
147             {
148                 last->kind = CCL_TOK_TERM;
149                 last->name = (const char *) cp;
150                 while (*cp && !strchr("(),%!><=? \t\n\r", *cp))
151                 {
152                     ++ last->len;
153                     cp++;
154                 }
155                 aliases = ccl_qual_search_special(cclp->bibset, "and");
156                 if (!aliases)
157                     aliases = cclp->ccl_token_and;
158                 if (token_cmp(cclp, aliases, last))
159                     last->kind = CCL_TOK_AND;
160                 
161                 aliases = ccl_qual_search_special(cclp->bibset, "or");
162                 if (!aliases)
163                     aliases = cclp->ccl_token_or;
164                 if (token_cmp(cclp, aliases, last))
165                     last->kind = CCL_TOK_OR;
166                 
167                 aliases = ccl_qual_search_special(cclp->bibset, "not");
168                 if (!aliases)
169                     aliases = cclp->ccl_token_not;
170                 if (token_cmp(cclp, aliases, last))
171                     last->kind = CCL_TOK_NOT;
172                 
173                 aliases = ccl_qual_search_special(cclp->bibset, "set");
174                 if (!aliases)
175                     aliases = cclp->ccl_token_set;
176                 
177                 if (token_cmp(cclp, aliases, last))
178                     last->kind = CCL_TOK_SET;
179             }
180             if (*cp == '?')
181             {
182                 last->right_trunc = 1;
183                 cp++;
184             }
185         }
186     }
187     return first;
188 }
189
190 struct ccl_token *ccl_token_add(struct ccl_token *at)
191 {
192     struct ccl_token *n = (struct ccl_token *)xmalloc(sizeof(*n));
193     ccl_assert(n);
194     n->next = at->next;
195     n->prev = at;
196     at->next = n;
197     if (n->next)
198         n->next->prev = n;
199
200     n->kind = CCL_TOK_TERM;
201     n->left_trunc = n->right_trunc = 0;
202     n->name = 0;
203     n->len = 0;
204     n->ws_prefix_buf = 0;
205     n->ws_prefix_len = 0;
206     return n;
207 }
208     
209 /*
210  * ccl_token_del: delete CCL tokens
211  */
212 void ccl_token_del(struct ccl_token *list)
213 {
214     struct ccl_token *list1;
215
216     while (list) 
217     {
218         list1 = list->next;
219         xfree(list);
220         list = list1;
221     }
222 }
223
224 static const char **create_ar(const char *v1, const char *v2)
225 {
226     const char **a = (const char **) xmalloc(3 * sizeof(*a));
227     a[0] = xstrdup(v1);
228     if (v2)
229     {
230         a[1] = xstrdup(v2);
231         a[2] = 0;
232     }
233     else
234         a[1] = 0;
235     return a;
236 }
237
238 static void destroy_ar(const char **a)
239 {
240     if (a)
241     {
242         int i;
243         for (i = 0; a[i]; i++)
244             xfree((char *) a[i]);
245         xfree((char **)a);
246     }
247 }
248
249 CCL_parser ccl_parser_create(CCL_bibset bibset)
250 {
251     CCL_parser p = (CCL_parser)xmalloc(sizeof(*p));
252     if (!p)
253         return p;
254     p->look_token = NULL;
255     p->error_code = 0;
256     p->error_pos = NULL;
257     p->bibset = bibset;
258
259     p->ccl_token_and = create_ar("and", 0);
260     p->ccl_token_or = create_ar("or", 0);
261     p->ccl_token_not = create_ar("not", "andnot");
262     p->ccl_token_set = create_ar("set", 0);
263     p->ccl_case_sensitive = 1;
264
265     return p;
266 }
267
268 void ccl_parser_destroy(CCL_parser p)
269 {
270     if (!p)
271         return;
272     destroy_ar(p->ccl_token_and);
273     destroy_ar(p->ccl_token_or);
274     destroy_ar(p->ccl_token_not);
275     destroy_ar(p->ccl_token_set);
276     xfree(p);
277 }
278
279 void ccl_parser_set_case(CCL_parser p, int case_sensitivity_flag)
280 {
281     if (p)
282         p->ccl_case_sensitive = case_sensitivity_flag;
283 }
284
285 int ccl_parser_get_error(CCL_parser cclp, int *pos)
286 {
287     if (pos && cclp->error_code)
288         *pos = cclp->error_pos - cclp->start_pos;
289     return cclp->error_code;
290 }
291
292 /*
293  * Local variables:
294  * c-basic-offset: 4
295  * c-file-style: "Stroustrup"
296  * indent-tabs-mode: nil
297  * End:
298  * vim: shiftwidth=4 tabstop=8 expandtab
299  */
300