51cdf0e2831a4ee39b55b3f21d12f95f0b760159
[egate.git] / ccl / ccltoken.c
1 /* CCL - lexical analysis
2  * Europagate, 1995
3  *
4  * $Log: ccltoken.c,v $
5  * Revision 1.8  1995/05/11 14:03:57  adam
6  * Changes in the reading of qualifier(s). New function: ccl_qual_fitem.
7  * New variable ccl_case_sensitive, which controls whether reserved
8  * words and field names are case sensitive or not.
9  *
10  * Revision 1.7  1995/04/19  12:11:24  adam
11  * Minor change.
12  *
13  * Revision 1.6  1995/04/17  09:31:48  adam
14  * Improved handling of qualifiers. Aliases or reserved words.
15  *
16  * Revision 1.5  1995/02/23  08:32:00  adam
17  * Changed header.
18  *
19  * Revision 1.3  1995/02/15  17:42:16  adam
20  * Minor changes of the api of this module. FILE* argument added
21  * to ccl_pr_tree.
22  *
23  * Revision 1.2  1995/02/14  19:55:13  adam
24  * Header files ccl.h/cclp.h are gone! They have been merged an
25  * moved to ../include/ccl.h.
26  * Node kind(s) in ccl_rpn_node have changed names.
27  *
28  * Revision 1.1  1995/02/13  12:35:21  adam
29  * First version of CCL. Qualifiers aren't handled yet.
30  *
31  */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <assert.h>
37
38 #include <ccl.h>
39
40 const char *ccl_token_and = "and";
41 const char *ccl_token_or = "or";
42 const char *ccl_token_not = "not andnot";
43 const char *ccl_token_set = "set";
44 int ccl_case_sensitive = 1;
45
46 /*
47  * token_cmp: Compare token with keyword(s)
48  * kw:     Keyword list. Each keyword is separated by space.
49  * token:  CCL token.
50  * return: 1 if token string matches one of the keywords in list;
51  *         0 otherwise.
52  */
53 static int token_cmp (const char *kw, struct ccl_token *token)
54 {
55     const char *cp1 = kw;
56     const char *cp2;
57     if (!kw)
58         return 0;
59     while ((cp2 = strchr (cp1, ' ')))
60     {
61         if (token->len == cp2-cp1)
62             if (ccl_case_sensitive)
63             {
64                 if (!memcmp (cp1, token->name, token->len))
65                     return 1;
66             }
67             else
68             {
69                 if (!ccl_memicmp (cp1, token->name, token->len))
70                     return 1;
71             }
72         cp1 = cp2+1;
73     }
74     if (ccl_case_sensitive)
75         return token->len == strlen(cp1) 
76             && !memcmp (cp1, token->name, token->len);
77     return token->len == strlen(cp1) &&
78         !ccl_memicmp (cp1, token->name, token->len);
79 }
80
81 /*
82  * ccl_tokenize: tokenize CCL command string.
83  * return: CCL token list.
84  */
85 struct ccl_token *ccl_tokenize (const char *command)
86 {
87     const char *cp = command;
88     struct ccl_token *first = NULL;
89     struct ccl_token *last = NULL;
90
91     while (1)
92     {
93         while (*cp && strchr (" \t\r\n", *cp))
94         {
95             cp++;
96             continue;
97         }
98         if (!first)
99         {
100             first = last = malloc (sizeof (*first));
101             assert (first);
102             last->prev = NULL;
103         }
104         else
105         {
106             last->next = malloc (sizeof(*first));
107             assert (last->next);
108             last->next->prev = last;
109             last = last->next;
110         }
111         last->next = NULL;
112         last->name = cp;
113         last->len = 1;
114         switch (*cp++)
115         {
116         case '\0':
117             last->kind = CCL_TOK_EOL;
118             return first;
119         case '(':
120             last->kind = CCL_TOK_LP;
121             break;
122         case ')':
123             last->kind = CCL_TOK_RP;
124             break;
125         case ',':
126             last->kind = CCL_TOK_COMMA;
127             break;
128         case '%':
129         case '!':
130             last->kind = CCL_TOK_PROX;
131             while (*cp == '%' || *cp == '!')
132             {
133                 ++ last->len;
134                 cp++;
135             }
136             break;
137         case '>':
138         case '<':
139         case '=':
140             if (*cp == '=' || *cp == '<' || *cp == '>')
141             {
142                 cp++;
143                 last->kind = CCL_TOK_REL;
144                 ++ last->len;
145             }
146             else if (cp[-1] == '=')
147                 last->kind = CCL_TOK_EQ;
148             else
149                 last->kind = CCL_TOK_REL;
150             break;
151         case '-':
152             last->kind = CCL_TOK_MINUS;
153             break;
154         case '\"':
155             last->kind = CCL_TOK_TERM;
156             last->name = cp;
157             last->len = 0;
158             while (*cp && *cp != '\"')
159             {
160                 cp++;
161                 ++ last->len;
162             }
163             if (*cp == '\"')
164                 cp++;
165             break;
166         default:
167             while (*cp && !strchr ("(),%!><=- \t\n\r", *cp))
168             {
169                 cp++;
170                 ++ last->len;
171             }
172             if (token_cmp (ccl_token_and, last))
173                 last->kind = CCL_TOK_AND;
174             else if (token_cmp (ccl_token_or, last))
175                 last->kind = CCL_TOK_OR;
176             else if (token_cmp (ccl_token_not, last))
177                 last->kind = CCL_TOK_NOT;
178             else if (token_cmp (ccl_token_set, last))
179                 last->kind = CCL_TOK_SET;
180             else
181                 last->kind = CCL_TOK_TERM;
182         }
183     }
184     return first;
185 }