more asserts
[cparser] / lexer.c
1 #include <config.h>
2
3 #include "lexer.h"
4 #include "token_t.h"
5 #include "symbol_table_t.h"
6 #include "adt/error.h"
7 #include "adt/strset.h"
8 #include "adt/util.h"
9 #include "type_t.h"
10
11 #include <assert.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <stdbool.h>
15 #include <ctype.h>
16
17 //#define DEBUG_CHARS
18 #define MAX_PUTBACK 3
19
20 #ifdef _WIN32
21 /* No strtold on windows and no replacement yet */
22 #define strtold(s, e) strtod(s, e)
23 #endif
24
25 #define HAS_SIGNED_CHAR
26 //#define HAS_UNSIGNED_CHAR
27
28 #if defined HAS_SIGNED_CHAR
29 typedef signed char char_type;
30 #elif defined HAS_UNSIGNED_CHAR
31 typedef unsigned char char_type;
32 #else
33 #       error signedness of char not determined
34 #endif
35
36 static int         c;
37 token_t            lexer_token;
38 symbol_t          *symbol_L;
39 static FILE       *input;
40 static char        buf[1024 + MAX_PUTBACK];
41 static const char *bufend;
42 static const char *bufpos;
43 static strset_t    stringset;
44
45 static type_t     *type_int        = NULL;
46 static type_t     *type_uint       = NULL;
47 static type_t     *type_long       = NULL;
48 static type_t     *type_ulong      = NULL;
49 static type_t     *type_longlong   = NULL;
50 static type_t     *type_ulonglong  = NULL;
51 static type_t     *type_float      = NULL;
52 static type_t     *type_double     = NULL;
53 static type_t     *type_longdouble = NULL;
54
55 static void error_prefix_at(const char *input_name, unsigned linenr)
56 {
57         fprintf(stderr, "%s:%u: Error: ", input_name, linenr);
58 }
59
60 static void error_prefix(void)
61 {
62         error_prefix_at(lexer_token.source_position.input_name,
63                         lexer_token.source_position.linenr);
64 }
65
66 static void parse_error(const char *msg)
67 {
68         error_prefix();
69         fprintf(stderr, "%s\n", msg);
70 }
71
72 static inline void next_real_char(void)
73 {
74         bufpos++;
75         if(bufpos >= bufend) {
76                 size_t s = fread(buf + MAX_PUTBACK, 1, sizeof(buf) - MAX_PUTBACK,
77                                  input);
78                 if(s == 0) {
79                         c = EOF;
80                         return;
81                 }
82                 bufpos = buf + MAX_PUTBACK;
83                 bufend = buf + MAX_PUTBACK + s;
84         }
85         c = *(bufpos);
86 }
87
88 static inline void put_back(int pc)
89 {
90         assert(bufpos >= buf);
91         //assert(bufpos < buf+MAX_PUTBACK || *bufpos == pc);
92
93         char *p = buf + (bufpos - buf);
94         *p = pc;
95
96         /* going backwards in the buffer is legal as long as it's not more often
97          * than MAX_PUTBACK */
98         bufpos--;
99
100 #ifdef DEBUG_CHARS
101         printf("putback '%c'\n", pc);
102 #endif
103 }
104
105 static inline void next_char(void);
106
107 #define MATCH_NEWLINE(code)                   \
108         case '\r':                                \
109                 next_char();                          \
110                 if(c == '\n') {                       \
111                         next_char();                      \
112                 }                                     \
113                 lexer_token.source_position.linenr++; \
114                 code;                                 \
115         case '\n':                                \
116                 next_char();                          \
117                 lexer_token.source_position.linenr++; \
118                 code;
119
120 #define eat(c_type)  do { assert(c == c_type); next_char(); } while(0)
121
122 static void maybe_concat_lines(void)
123 {
124         eat('\\');
125
126         switch(c) {
127         MATCH_NEWLINE(return;)
128
129         default:
130                 break;
131         }
132
133         put_back(c);
134         c = '\\';
135 }
136
137 static inline void next_char(void)
138 {
139         next_real_char();
140
141         /* filter trigraphs */
142         if(UNLIKELY(c == '\\')) {
143                 maybe_concat_lines();
144                 goto end_of_next_char;
145         }
146
147         if(LIKELY(c != '?'))
148                 goto end_of_next_char;
149
150         next_real_char();
151         if(LIKELY(c != '?')) {
152                 put_back(c);
153                 c = '?';
154                 goto end_of_next_char;
155         }
156
157         next_real_char();
158         switch(c) {
159         case '=': c = '#'; break;
160         case '(': c = '['; break;
161         case '/': c = '\\'; maybe_concat_lines(); break;
162         case ')': c = ']'; break;
163         case '\'': c = '^'; break;
164         case '<': c = '{'; break;
165         case '!': c = '|'; break;
166         case '>': c = '}'; break;
167         case '-': c = '~'; break;
168         default:
169                 put_back('?');
170                 put_back(c);
171                 c = '?';
172                 break;
173         }
174
175 end_of_next_char:;
176 #ifdef DEBUG_CHARS
177         printf("nchar '%c'\n", c);
178 #endif
179 }
180
181 #define SYMBOL_CHARS  \
182         case 'a':         \
183         case 'b':         \
184         case 'c':         \
185         case 'd':         \
186         case 'e':         \
187         case 'f':         \
188         case 'g':         \
189         case 'h':         \
190         case 'i':         \
191         case 'j':         \
192         case 'k':         \
193         case 'l':         \
194         case 'm':         \
195         case 'n':         \
196         case 'o':         \
197         case 'p':         \
198         case 'q':         \
199         case 'r':         \
200         case 's':         \
201         case 't':         \
202         case 'u':         \
203         case 'v':         \
204         case 'w':         \
205         case 'x':         \
206         case 'y':         \
207         case 'z':         \
208         case 'A':         \
209         case 'B':         \
210         case 'C':         \
211         case 'D':         \
212         case 'E':         \
213         case 'F':         \
214         case 'G':         \
215         case 'H':         \
216         case 'I':         \
217         case 'J':         \
218         case 'K':         \
219         case 'L':         \
220         case 'M':         \
221         case 'N':         \
222         case 'O':         \
223         case 'P':         \
224         case 'Q':         \
225         case 'R':         \
226         case 'S':         \
227         case 'T':         \
228         case 'U':         \
229         case 'V':         \
230         case 'W':         \
231         case 'X':         \
232         case 'Y':         \
233         case 'Z':         \
234         case '_':
235
236 #define DIGITS        \
237         case '0':         \
238         case '1':         \
239         case '2':         \
240         case '3':         \
241         case '4':         \
242         case '5':         \
243         case '6':         \
244         case '7':         \
245         case '8':         \
246         case '9':
247
248 static void parse_symbol(void)
249 {
250         symbol_t *symbol;
251         char     *string;
252
253         obstack_1grow(&symbol_obstack, c);
254         next_char();
255
256         while(1) {
257                 switch(c) {
258                 DIGITS
259                 SYMBOL_CHARS
260                         obstack_1grow(&symbol_obstack, c);
261                         next_char();
262                         break;
263
264                 default:
265                         goto end_symbol;
266                 }
267         }
268
269 end_symbol:
270         obstack_1grow(&symbol_obstack, '\0');
271
272         string = obstack_finish(&symbol_obstack);
273         symbol = symbol_table_insert(string);
274
275         lexer_token.type     = symbol->ID;
276         lexer_token.v.symbol = symbol;
277
278         if(symbol->string != string) {
279                 obstack_free(&symbol_obstack, string);
280         }
281 }
282
283 static void parse_integer_suffix(void)
284 {
285         if(c == 'U' || c == 'u') {
286                 next_char();
287                 if(c == 'L' || c == 'l') {
288                         next_char();
289                         if(c == 'L' || c == 'l') {
290                                 next_char();
291                                 lexer_token.datatype = type_ulonglong;
292                         } else {
293                                 lexer_token.datatype = type_ulong;
294                         }
295                 } else {
296                         lexer_token.datatype = type_uint;
297                 }
298         } else if(c == 'l' || c == 'L') {
299                 next_char();
300                 if(c == 'l' || c == 'L') {
301                         next_char();
302                         if(c == 'u' || c == 'U') {
303                                 next_char();
304                                 lexer_token.datatype = type_ulonglong;
305                         } else {
306                                 lexer_token.datatype = type_longlong;
307                         }
308                 } else if(c == 'u' || c == 'U') {
309                         next_char();
310                         lexer_token.datatype = type_ulong;
311                 } else {
312                         lexer_token.datatype = type_int;
313                 }
314         } else {
315                 lexer_token.datatype = type_int;
316         }
317 }
318
319 static void parse_floating_suffix(void)
320 {
321         switch(c) {
322         /* TODO: do something usefull with the suffixes... */
323         case 'f':
324         case 'F':
325                 next_char();
326                 lexer_token.datatype = type_float;
327                 break;
328         case 'l':
329         case 'L':
330                 next_char();
331                 lexer_token.datatype = type_longdouble;
332                 break;
333         default:
334                 lexer_token.datatype = type_double;
335                 break;
336         }
337 }
338
339 /**
340  * A replacement for strtoull. Only those parts needed for
341  * our parser are implemented.
342  */
343 static unsigned long long parse_int_string(const char *s, const char **endptr, int base) {
344         unsigned long long v = 0;
345
346         switch (base) {
347         case 16:
348                 for (;; ++s) {
349                         /* check for overrun */
350                         if (v >= 0x1000000000000000ULL)
351                                 break;
352                         switch (tolower(*s)) {
353                         case '0': v <<= 4; break;
354                         case '1': v <<= 4; v |= 0x1; break;
355                         case '2': v <<= 4; v |= 0x2; break;
356                         case '3': v <<= 4; v |= 0x3; break;
357                         case '4': v <<= 4; v |= 0x4; break;
358                         case '5': v <<= 4; v |= 0x5; break;
359                         case '6': v <<= 4; v |= 0x6; break;
360                         case '7': v <<= 4; v |= 0x7; break;
361                         case '8': v <<= 4; v |= 0x8; break;
362                         case '9': v <<= 4; v |= 0x9; break;
363                         case 'a': v <<= 4; v |= 0xa; break;
364                         case 'b': v <<= 4; v |= 0xb; break;
365                         case 'c': v <<= 4; v |= 0xc; break;
366                         case 'd': v <<= 4; v |= 0xd; break;
367                         case 'e': v <<= 4; v |= 0xe; break;
368                         case 'f': v <<= 4; v |= 0xf; break;
369                         default:
370                                 goto end;
371                         }
372                 }
373                 break;
374         case 8:
375                 for (;; ++s) {
376                         /* check for overrun */
377                         if (v >= 0x2000000000000000ULL)
378                                 break;
379                         switch (tolower(*s)) {
380                         case '0': v <<= 3; break;
381                         case '1': v <<= 3; v |= 1; break;
382                         case '2': v <<= 3; v |= 2; break;
383                         case '3': v <<= 3; v |= 3; break;
384                         case '4': v <<= 3; v |= 4; break;
385                         case '5': v <<= 3; v |= 5; break;
386                         case '6': v <<= 3; v |= 6; break;
387                         case '7': v <<= 3; v |= 7; break;
388                         default:
389                                 goto end;
390                         }
391                 }
392                 break;
393         case 10:
394                 for (;; ++s) {
395                         /* check for overrun */
396                         if (v > 0x1999999999999999ULL)
397                                 break;
398                         switch (tolower(*s)) {
399                         case '0': v *= 10; break;
400                         case '1': v *= 10; v += 1; break;
401                         case '2': v *= 10; v += 2; break;
402                         case '3': v *= 10; v += 3; break;
403                         case '4': v *= 10; v += 4; break;
404                         case '5': v *= 10; v += 5; break;
405                         case '6': v *= 10; v += 6; break;
406                         case '7': v *= 10; v += 7; break;
407                         case '8': v *= 10; v += 8; break;
408                         case '9': v *= 10; v += 9; break;
409                         default:
410                                 goto end;
411                         }
412                 }
413                 break;
414         default:
415                 assert(0);
416                 break;
417         }
418 end:
419         *endptr = s;
420         return v;
421 }
422
423 static void parse_number_hex(void)
424 {
425         assert(c == 'x' || c == 'X');
426         next_char();
427
428         while(isxdigit(c)) {
429                 obstack_1grow(&symbol_obstack, c);
430                 next_char();
431         }
432         obstack_1grow(&symbol_obstack, '\0');
433         char *string = obstack_finish(&symbol_obstack);
434
435         if(c == '.' || c == 'p' || c == 'P') {
436                 next_char();
437                 panic("Hex floating point numbers not implemented yet");
438         }
439         if(*string == '\0') {
440                 parse_error("invalid hex number");
441                 lexer_token.type = T_ERROR;
442         }
443
444         const char *endptr;
445         lexer_token.type       = T_INTEGER;
446         lexer_token.v.intvalue = parse_int_string(string, &endptr, 16);
447         if(*endptr != '\0') {
448                 parse_error("hex number literal too long");
449         }
450
451         obstack_free(&symbol_obstack, string);
452         parse_integer_suffix();
453 }
454
455 static inline bool is_octal_digit(int chr)
456 {
457         return '0' <= chr && chr <= '7';
458 }
459
460 static void parse_number_oct(void)
461 {
462         while(is_octal_digit(c)) {
463                 obstack_1grow(&symbol_obstack, c);
464                 next_char();
465         }
466         obstack_1grow(&symbol_obstack, '\0');
467         char *string = obstack_finish(&symbol_obstack);
468
469         const char *endptr;
470         lexer_token.type       = T_INTEGER;
471         lexer_token.v.intvalue = parse_int_string(string, &endptr, 8);
472         if(*endptr != '\0') {
473                 parse_error("octal number literal too long");
474         }
475
476         obstack_free(&symbol_obstack, string);
477         parse_integer_suffix();
478 }
479
480 static void parse_number_dec(void)
481 {
482         bool is_float = false;
483         while(isdigit(c)) {
484                 obstack_1grow(&symbol_obstack, c);
485                 next_char();
486         }
487
488         if(c == '.') {
489                 obstack_1grow(&symbol_obstack, '.');
490                 next_char();
491
492                 while(isdigit(c)) {
493                         obstack_1grow(&symbol_obstack, c);
494                         next_char();
495                 }
496                 is_float = true;
497         }
498         if(c == 'e' || c == 'E') {
499                 obstack_1grow(&symbol_obstack, 'e');
500                 next_char();
501
502                 if(c == '-' || c == '+') {
503                         obstack_1grow(&symbol_obstack, c);
504                         next_char();
505                 }
506
507                 while(isdigit(c)) {
508                         obstack_1grow(&symbol_obstack, c);
509                         next_char();
510                 }
511                 is_float = true;
512         }
513
514         obstack_1grow(&symbol_obstack, '\0');
515         char *string = obstack_finish(&symbol_obstack);
516
517         if(is_float) {
518                 char *endptr;
519                 lexer_token.type         = T_FLOATINGPOINT;
520                 lexer_token.v.floatvalue = strtold(string, &endptr);
521
522                 if(*endptr != '\0') {
523                         parse_error("invalid number literal");
524                 }
525
526                 parse_floating_suffix();
527         } else {
528                 const char *endptr;
529                 lexer_token.type       = T_INTEGER;
530                 lexer_token.v.intvalue = parse_int_string(string, &endptr, 10);
531
532                 if(*endptr != '\0') {
533                         parse_error("invalid number literal");
534                 }
535
536                 parse_integer_suffix();
537         }
538         obstack_free(&symbol_obstack, string);
539 }
540
541 static void parse_number(void)
542 {
543         if (c == '0') {
544                 next_char();
545                 switch (c) {
546                         case 'X':
547                         case 'x':
548                                 parse_number_hex();
549                                 break;
550                         case '0':
551                         case '1':
552                         case '2':
553                         case '3':
554                         case '4':
555                         case '5':
556                         case '6':
557                         case '7':
558                                 parse_number_oct();
559                                 break;
560                         case '8':
561                         case '9':
562                                 next_char();
563                                 parse_error("invalid octal number");
564                                 lexer_token.type = T_ERROR;
565                                 return;
566                         case '.':
567                         case 'e':
568                         case 'E':
569                         default:
570                                 obstack_1grow(&symbol_obstack, '0');
571                                 parse_number_dec();
572                                 return;
573                 }
574         } else {
575                 parse_number_dec();
576         }
577 }
578
579 static int parse_octal_sequence(const int first_digit)
580 {
581         assert(is_octal_digit(first_digit));
582         int value = first_digit - '0';
583         if (!is_octal_digit(c)) return value;
584         value = 8 * value + c - '0';
585         next_char();
586         if (!is_octal_digit(c)) return value;
587         value = 8 * value + c - '0';
588         next_char();
589         return (char_type)value;
590 }
591
592 static int parse_hex_sequence(void)
593 {
594         int value = 0;
595         while(1) {
596                 if (c >= '0' && c <= '9') {
597                         value = 16 * value + c - '0';
598                 } else if ('A' <= c && c <= 'F') {
599                         value = 16 * value + c - 'A' + 10;
600                 } else if ('a' <= c && c <= 'f') {
601                         value = 16 * value + c - 'a' + 10;
602                 } else {
603                         break;
604                 }
605                 next_char();
606         }
607
608         return (char_type)value;
609 }
610
611 static int parse_escape_sequence(void)
612 {
613         eat('\\');
614
615         int ec = c;
616         next_char();
617
618         switch(ec) {
619         case '"':  return '"';
620         case '\'': return '\'';
621         case '\\': return '\\';
622         case '?': return '\?';
623         case 'a': return '\a';
624         case 'b': return '\b';
625         case 'f': return '\f';
626         case 'n': return '\n';
627         case 'r': return '\r';
628         case 't': return '\t';
629         case 'v': return '\v';
630         case 'x':
631                 return parse_hex_sequence();
632         case '0':
633         case '1':
634         case '2':
635         case '3':
636         case '4':
637         case '5':
638         case '6':
639         case '7':
640                 return parse_octal_sequence(ec);
641         case EOF:
642                 parse_error("reached end of file while parsing escape sequence");
643                 return EOF;
644         default:
645                 parse_error("unknown escape sequence");
646                 return EOF;
647         }
648 }
649
650 const char *concat_strings(const char *s1, const char *s2)
651 {
652         size_t  len1   = strlen(s1);
653         size_t  len2   = strlen(s2);
654
655         char   *concat = obstack_alloc(&symbol_obstack, len1 + len2 + 1);
656         memcpy(concat, s1, len1);
657         memcpy(concat + len1, s2, len2 + 1);
658
659         const char *result = strset_insert(&stringset, concat);
660         if(result != concat) {
661                 obstack_free(&symbol_obstack, concat);
662         }
663
664         return result;
665 }
666
667 static void parse_string_literal(void)
668 {
669         unsigned    start_linenr = lexer_token.source_position.linenr;
670         char       *string;
671         const char *result;
672
673         assert(c == '"');
674         next_char();
675
676         int tc;
677         while(1) {
678                 switch(c) {
679                 case '\\':
680                         tc = parse_escape_sequence();
681                         obstack_1grow(&symbol_obstack, tc);
682                         break;
683
684                 case EOF:
685                         error_prefix_at(lexer_token.source_position.input_name,
686                                         start_linenr);
687                         fprintf(stderr, "string has no end\n");
688                         lexer_token.type = T_ERROR;
689                         return;
690
691                 case '"':
692                         next_char();
693                         goto end_of_string;
694
695                 default:
696                         obstack_1grow(&symbol_obstack, c);
697                         next_char();
698                         break;
699                 }
700         }
701
702 end_of_string:
703
704         /* TODO: concatenate multiple strings separated by whitespace... */
705
706         /* add finishing 0 to the string */
707         obstack_1grow(&symbol_obstack, '\0');
708         string = obstack_finish(&symbol_obstack);
709
710         /* check if there is already a copy of the string */
711         result = strset_insert(&stringset, string);
712         if(result != string) {
713                 obstack_free(&symbol_obstack, string);
714         }
715
716         lexer_token.type     = T_STRING_LITERAL;
717         lexer_token.v.string = result;
718 }
719
720 static void parse_character_constant(void)
721 {
722         eat('\'');
723
724         int found_char = 0;
725         while(1) {
726                 switch(c) {
727                 case '\\':
728                         found_char = parse_escape_sequence();
729                         break;
730
731                 MATCH_NEWLINE(
732                         parse_error("newline while parsing character constant");
733                         break;
734                 )
735
736                 case '\'':
737                         next_char();
738                         goto end_of_char_constant;
739
740                 case EOF:
741                         parse_error("EOF while parsing character constant");
742                         lexer_token.type = T_ERROR;
743                         return;
744
745                 default:
746                         if(found_char != 0) {
747                                 parse_error("more than 1 characters in character "
748                                             "constant");
749                                 goto end_of_char_constant;
750                         } else {
751                                 found_char = c;
752                                 next_char();
753                         }
754                         break;
755                 }
756         }
757
758 end_of_char_constant:
759         lexer_token.type       = T_INTEGER;
760         lexer_token.v.intvalue = found_char;
761 }
762
763 static void skip_multiline_comment(void)
764 {
765         unsigned start_linenr = lexer_token.source_position.linenr;
766
767         while(1) {
768                 switch(c) {
769                 case '*':
770                         next_char();
771                         if(c == '/') {
772                                 next_char();
773                                 return;
774                         }
775                         break;
776
777                 MATCH_NEWLINE(break;)
778
779                 case EOF:
780                         error_prefix_at(lexer_token.source_position.input_name,
781                                         start_linenr);
782                         fprintf(stderr, "at end of file while looking for comment end\n");
783                         return;
784
785                 default:
786                         next_char();
787                         break;
788                 }
789         }
790 }
791
792 static void skip_line_comment(void)
793 {
794         while(1) {
795                 switch(c) {
796                 case EOF:
797                         return;
798
799                 case '\n':
800                 case '\r':
801                         return;
802
803                 default:
804                         next_char();
805                         break;
806                 }
807         }
808 }
809
810 static token_t pp_token;
811
812 static inline void next_pp_token(void)
813 {
814         lexer_next_preprocessing_token();
815         pp_token = lexer_token;
816 }
817
818 static void eat_until_newline(void)
819 {
820         while(pp_token.type != '\n' && pp_token.type != T_EOF) {
821                 next_pp_token();
822         }
823 }
824
825 static void error_directive(void)
826 {
827         error_prefix();
828         fprintf(stderr, "#error directive: \n");
829
830         /* parse pp-tokens until new-line */
831 }
832
833 static void define_directive(void)
834 {
835         lexer_next_preprocessing_token();
836         if(lexer_token.type != T_IDENTIFIER) {
837                 parse_error("expected identifier after #define\n");
838                 eat_until_newline();
839         }
840 }
841
842 static void ifdef_directive(int is_ifndef)
843 {
844         (void) is_ifndef;
845         lexer_next_preprocessing_token();
846         //expect_identifier();
847         //extect_newline();
848 }
849
850 static void endif_directive(void)
851 {
852         //expect_newline();
853 }
854
855 static void parse_line_directive(void)
856 {
857         if(pp_token.type != T_INTEGER) {
858                 parse_error("expected integer");
859         } else {
860                 lexer_token.source_position.linenr = (unsigned int)(pp_token.v.intvalue - 1);
861                 next_pp_token();
862         }
863         if(pp_token.type == T_STRING_LITERAL) {
864                 lexer_token.source_position.input_name = pp_token.v.string;
865                 next_pp_token();
866         }
867
868         eat_until_newline();
869 }
870
871 static void parse_preprocessor_identifier(void)
872 {
873         assert(pp_token.type == T_IDENTIFIER);
874         symbol_t *symbol = pp_token.v.symbol;
875
876         switch(symbol->pp_ID) {
877         case TP_include:
878                 printf("include - enable header name parsing!\n");
879                 break;
880         case TP_define:
881                 define_directive();
882                 break;
883         case TP_ifdef:
884                 ifdef_directive(0);
885                 break;
886         case TP_ifndef:
887                 ifdef_directive(1);
888                 break;
889         case TP_endif:
890                 endif_directive();
891                 break;
892         case TP_line:
893                 next_pp_token();
894                 parse_line_directive();
895                 break;
896         case TP_if:
897         case TP_else:
898         case TP_elif:
899         case TP_undef:
900         case TP_error:
901                 error_directive();
902                 break;
903         case TP_pragma:
904                 break;
905         }
906 }
907
908 static void parse_preprocessor_directive(void)
909 {
910         next_pp_token();
911
912         switch(pp_token.type) {
913         case T_IDENTIFIER:
914                 parse_preprocessor_identifier();
915                 break;
916         case T_INTEGER:
917                 parse_line_directive();
918                 break;
919         default:
920                 parse_error("invalid preprocessor directive");
921                 eat_until_newline();
922                 break;
923         }
924 }
925
926 #define MAYBE_PROLOG                                       \
927                         next_char();                                   \
928                         while(1) {                                     \
929                                 switch(c) {
930
931 #define MAYBE(ch, set_type)                                \
932                                 case ch:                                   \
933                                         next_char();                           \
934                                         lexer_token.type = set_type;           \
935                                         return;
936
937 #define ELSE_CODE(code)                                    \
938                                 default:                                   \
939                                         code;                                  \
940                                 }                                          \
941                         } /* end of while(1) */                        \
942                         break;
943
944 #define ELSE(set_type)                                     \
945                 ELSE_CODE(                                         \
946                         lexer_token.type = set_type;                   \
947                         return;                                        \
948                 )
949
950 void lexer_next_preprocessing_token(void)
951 {
952         while(1) {
953                 switch(c) {
954                 case ' ':
955                 case '\t':
956                         next_char();
957                         break;
958
959                 MATCH_NEWLINE(
960                         lexer_token.type = '\n';
961                         return;
962                 )
963
964                 SYMBOL_CHARS
965                         parse_symbol();
966                         /* might be a wide string ( L"string" ) */
967                         if(c == '"' && (lexer_token.type == T_IDENTIFIER &&
968                            lexer_token.v.symbol == symbol_L)) {
969                                 parse_string_literal();
970                                 return;
971                         }
972                         return;
973
974                 DIGITS
975                         parse_number();
976                         return;
977
978                 case '"':
979                         parse_string_literal();
980                         return;
981
982                 case '\'':
983                         parse_character_constant();
984                         return;
985
986                 case '.':
987                         MAYBE_PROLOG
988                                 case '.':
989                                         MAYBE_PROLOG
990                                         MAYBE('.', T_DOTDOTDOT)
991                                         ELSE_CODE(
992                                                 put_back(c);
993                                                 c = '.';
994                                                 lexer_token.type = '.';
995                                                 return;
996                                         )
997                         ELSE('.')
998                 case '&':
999                         MAYBE_PROLOG
1000                         MAYBE('&', T_ANDAND)
1001                         MAYBE('=', T_ANDEQUAL)
1002                         ELSE('&')
1003                 case '*':
1004                         MAYBE_PROLOG
1005                         MAYBE('=', T_ASTERISKEQUAL)
1006                         ELSE('*')
1007                 case '+':
1008                         MAYBE_PROLOG
1009                         MAYBE('+', T_PLUSPLUS)
1010                         MAYBE('=', T_PLUSEQUAL)
1011                         ELSE('+')
1012                 case '-':
1013                         MAYBE_PROLOG
1014                         MAYBE('>', T_MINUSGREATER)
1015                         MAYBE('-', T_MINUSMINUS)
1016                         MAYBE('=', T_MINUSEQUAL)
1017                         ELSE('-')
1018                 case '!':
1019                         MAYBE_PROLOG
1020                         MAYBE('=', T_EXCLAMATIONMARKEQUAL)
1021                         ELSE('!')
1022                 case '/':
1023                         MAYBE_PROLOG
1024                         MAYBE('=', T_SLASHEQUAL)
1025                                 case '*':
1026                                         next_char();
1027                                         skip_multiline_comment();
1028                                         lexer_next_preprocessing_token();
1029                                         return;
1030                                 case '/':
1031                                         next_char();
1032                                         skip_line_comment();
1033                                         lexer_next_preprocessing_token();
1034                                         return;
1035                         ELSE('/')
1036                 case '%':
1037                         MAYBE_PROLOG
1038                         MAYBE('>', T_PERCENTGREATER)
1039                         MAYBE('=', T_PERCENTEQUAL)
1040                                 case ':':
1041                                         MAYBE_PROLOG
1042                                                 case '%':
1043                                                         MAYBE_PROLOG
1044                                                         MAYBE(':', T_PERCENTCOLONPERCENTCOLON)
1045                                                         ELSE_CODE(
1046                                                                 put_back(c);
1047                                                                 c = '%';
1048                                                                 lexer_token.type = T_PERCENTCOLON;
1049                                                                 return;
1050                                                         )
1051                                         ELSE(T_PERCENTCOLON)
1052                         ELSE('%')
1053                 case '<':
1054                         MAYBE_PROLOG
1055                         MAYBE(':', T_LESSCOLON)
1056                         MAYBE('%', T_LESSPERCENT)
1057                         MAYBE('=', T_LESSEQUAL)
1058                                 case '<':
1059                                         MAYBE_PROLOG
1060                                         MAYBE('=', T_LESSLESSEQUAL)
1061                                         ELSE(T_LESSLESS)
1062                         ELSE('<')
1063                 case '>':
1064                         MAYBE_PROLOG
1065                         MAYBE('=', T_GREATEREQUAL)
1066                                 case '>':
1067                                         MAYBE_PROLOG
1068                                         MAYBE('=', T_GREATERGREATEREQUAL)
1069                                         ELSE(T_GREATERGREATER)
1070                         ELSE('>')
1071                 case '^':
1072                         MAYBE_PROLOG
1073                         MAYBE('=', T_CARETEQUAL)
1074                         ELSE('^')
1075                 case '|':
1076                         MAYBE_PROLOG
1077                         MAYBE('=', T_PIPEEQUAL)
1078                         MAYBE('|', T_PIPEPIPE)
1079                         ELSE('|')
1080                 case ':':
1081                         MAYBE_PROLOG
1082                         MAYBE('>', T_COLONGREATER)
1083                         ELSE(':')
1084                 case '=':
1085                         MAYBE_PROLOG
1086                         MAYBE('=', T_EQUALEQUAL)
1087                         ELSE('=')
1088                 case '#':
1089                         MAYBE_PROLOG
1090                         MAYBE('#', T_HASHHASH)
1091                         ELSE('#')
1092
1093                 case '?':
1094                 case '[':
1095                 case ']':
1096                 case '(':
1097                 case ')':
1098                 case '{':
1099                 case '}':
1100                 case '~':
1101                 case ';':
1102                 case ',':
1103                 case '\\':
1104                         lexer_token.type = c;
1105                         next_char();
1106                         return;
1107
1108                 case EOF:
1109                         lexer_token.type = T_EOF;
1110                         return;
1111
1112                 default:
1113                         next_char();
1114                         error_prefix();
1115                         fprintf(stderr, "unknown character '%c' found\n", c);
1116                         lexer_token.type = T_ERROR;
1117                         return;
1118                 }
1119         }
1120 }
1121
1122 void lexer_next_token(void)
1123 {
1124         lexer_next_preprocessing_token();
1125         if(lexer_token.type != '\n')
1126                 return;
1127
1128 newline_found:
1129         do {
1130                 lexer_next_preprocessing_token();
1131         } while(lexer_token.type == '\n');
1132
1133         if(lexer_token.type == '#') {
1134                 parse_preprocessor_directive();
1135                 goto newline_found;
1136         }
1137 }
1138
1139 void init_lexer(void)
1140 {
1141         strset_init(&stringset);
1142
1143         type_int       = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_CONST);
1144         type_uint      = make_atomic_type(ATOMIC_TYPE_UINT, TYPE_QUALIFIER_CONST);
1145         type_long      = make_atomic_type(ATOMIC_TYPE_LONG, TYPE_QUALIFIER_CONST);
1146         type_ulong     = make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_CONST);
1147         type_longlong  = make_atomic_type(ATOMIC_TYPE_LONGLONG,
1148                                           TYPE_QUALIFIER_CONST);
1149         type_ulonglong = make_atomic_type(ATOMIC_TYPE_ULONGLONG,
1150                                           TYPE_QUALIFIER_CONST);
1151
1152         type_float      = make_atomic_type(ATOMIC_TYPE_FLOAT, TYPE_QUALIFIER_CONST);
1153         type_double     = make_atomic_type(ATOMIC_TYPE_DOUBLE,
1154                                            TYPE_QUALIFIER_CONST);
1155         type_longdouble = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE,
1156                                            TYPE_QUALIFIER_CONST);
1157 }
1158
1159 void lexer_open_stream(FILE *stream, const char *input_name)
1160 {
1161         input                                  = stream;
1162         lexer_token.source_position.linenr     = 0;
1163         lexer_token.source_position.input_name = input_name;
1164
1165         symbol_L = symbol_table_insert("L");
1166
1167         /* place a virtual \n at the beginning so the lexer knows that we're
1168          * at the beginning of a line */
1169         c = '\n';
1170 }
1171
1172 void exit_lexer(void)
1173 {
1174         strset_destroy(&stringset);
1175 }
1176
1177 static __attribute__((unused))
1178 void dbg_pos(const source_position_t source_position)
1179 {
1180         fprintf(stdout, "%s:%d\n", source_position.input_name,
1181                 source_position.linenr);
1182         fflush(stdout);
1183 }