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