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