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