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