]> mj.ucw.cz Git - umpf.git/blob - lex.c
fix if-else bug
[umpf.git] / lex.c
1 #include <stdio.h>
2 #include <ctype.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6
7 #include "cond.tab.h"
8 #include "umpf.h"
9 #define KLEN 10 
10
11 struct keys {
12         char* keywords;
13         enum yytokentype keytoks;
14 };
15
16 static struct keys kwds[] = 
17         {       {"copy", KW_COPY},
18                 {"else", KW_ELSE},
19                 {"if", KW_IF}, 
20                 {"mail", KW_MAIL}, 
21                 {"pipe", KW_PIPE},
22                 {"discard", KW_DISCARD},
23                 {"filter", KW_FILTER}
24         };
25
26 void
27 read_conf(char* filename)
28 {
29         conf = fopen(filename, "r");
30
31         if (! conf) {
32                 fprintf(stderr, "Error reading config file: %m\nSaving to default mailbox %s\n", default_mailbox);
33                 longjmp(env, 1); 
34         }
35 }
36
37 void __attribute__ ((noreturn)) 
38 die(char* msg, ...)
39 {
40         va_list args;
41
42         va_start(args, msg);
43         vfprintf(stderr, msg, args);
44         fputc('\n', stderr);
45         va_end(args);
46         exit(1);
47 }
48
49 void*
50 xmalloc(size_t size)
51 {
52         void* ret;
53
54         if (!(ret = malloc(size)))
55                 die("Low memory");
56
57         return ret;
58 }
59
60 void*
61 xrealloc(void* buf, size_t size)
62 {
63         buf = realloc(buf, size);
64         
65         if (!buf)
66                 die("Low memory");
67
68         return buf;
69 }
70
71 static void __attribute__ ((noreturn)) 
72 parse_err(char* msg, ...)
73 {
74         va_list args;
75
76         va_start(args, msg);
77         fprintf(stderr, "Line %d: ", line);
78         vfprintf(stderr, msg, args);
79         fputc('\n', stderr);
80         va_end(args);
81         exit(1);
82 }
83
84 char*
85 xstrdup(const char* s)
86 {
87         void* ret;
88
89         if (!(ret = strdup(s)))
90                 die("Low memory");
91
92         return ret;
93 }
94
95 static char*
96 get_string_out(int delim)
97 {
98         int last = delim; 
99         int i = 0;
100         int c;
101         char buf[BUFSIZE];
102
103         while ((c = getc(conf)) != delim || last == '\\'){
104                 if (last=='\\' && c != delim)
105                         buf[i-1] = c;
106                 else {          
107                         buf[i] = c;
108                         i++;
109                 }
110                 last = c;
111                 if (i >= BUFSIZE-1)
112                         parse_err("Too long string, max allowed length is %d",BUFSIZE-1);       
113         }       
114         buf[i] = '\0';
115
116         return xstrdup(buf);
117 }
118
119 static int
120 is_var_id(int c)
121 {
122         return  (c >= '0' && c <= '9' ) ||
123                 (c >= 'a' && c <= 'z') ||
124                 (c >= 'A' && c <= 'Z') ||
125                 c == '_' ||
126                 c == '-'; 
127 }
128
129 static int
130 is_alpha(int c)
131 {
132         return (c >= 'a' && c <= 'z') ||
133                 (c >= 'A' && c <= 'Z');
134 }
135
136 int
137 yylex(void)
138 {
139         int c;
140         
141         while ((c = getc(conf)) == ' ' || c == '\t' || c =='\n'){
142                 if (c == '\n')
143                         line++;
144         }
145         
146         if (c == EOF)
147                 return 0;
148         
149         int d = getc(conf);
150         if (d >= 0) {
151                 switch (CC(c,d)) {
152                 case CC('!','='): yylval.n = CC('!','='); return NEQ;
153                 case CC('!','~'): yylval.n = CC('!','='); return NRE;
154                 case CC('<','='): yylval.n = CC('<','='); return LE;
155                 case CC('>','='): yylval.n = CC('>','='); return GE;
156                 case CC('=','='): yylval.n = CC('=','='); return EQ;
157                 case CC('~','~'): yylval.n = CC('~','~'); return RE;
158                 case CC('-','>'): yylval.n = CC('-','>'); return ARROW;
159                 }
160                 ungetc(d,conf);
161         }
162
163         switch (c) {
164                 case '!':
165                 case '(':
166                 case ')':
167                 case '-':
168                 case '+':
169                 case '*':
170                 case '/':
171                 case '{':
172                 case '}':
173                 case '<':
174                 case '>':
175                 case '=':
176                 case ';':
177                 case '.':
178                 case '|':
179                 case '&':
180                 case '^':
181                         yylval.n = c;
182                         return c;
183                 
184                 case '"':
185                 case '\'':
186                         yylval.str = get_string_out(c);
187                         return CONST;   
188         }
189
190         if (c >= '0' && c <= '9'){
191                 ungetc(c,conf);
192                 int i = 0;
193                 char buf[BUFSIZE];
194         
195                 while ((c = getc(conf))>= '0' && c<= '9'){
196                         buf[i] = c;
197                         i++;
198                         if (i >= BUFSIZE-1)
199                                 parse_err("Too long number");   
200                 }
201                 ungetc(c,conf);
202                 buf[i] = 0;
203                 yylval.str = xstrdup(buf);
204
205                 return CONST;
206         }
207
208         if (c == '$'){
209                 int i = 0;
210                 char buf[BUFSIZE];
211         
212                 while (is_var_id(c = getc(conf))){
213                         buf[i]=c;
214                         i++;
215                         if (i >= BUFSIZE-1)
216                                 parse_err("Too long identifier, max allowed length is %d",BUFSIZE-1);   
217                 }
218                 ungetc(c,conf);
219                 buf[i] = 0;
220                 yylval.str = xstrdup(buf);
221
222                 return VAR;
223         }
224
225         if (is_alpha(c)){
226                 char buf[KLEN]; 
227                 int n, i = 0;
228
229                 ungetc(c,conf);
230                 while (is_alpha(c = getc(conf))){
231                         buf[i++] = c;
232                         if (i >= KLEN)
233                                 parse_err("Keyword too long");
234                 }
235                 buf[i] = 0;
236                 ungetc(c,conf);
237
238                 n = (sizeof(kwds)/sizeof(struct keys));
239                 for (i = 0; i < n; i++){
240                         if (!strcmp(buf,kwds[i].keywords))
241                                 return kwds[i].keytoks;
242                 }
243
244                 parse_err("Unknown keyword %s", buf);
245         }
246
247         parse_err("Unknown character %c", c);
248 }