fixed warning for 64bit build
[cparser] / lexer.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include <config.h>
21
22 #include "diagnostic.h"
23 #include "lexer.h"
24 #include "symbol_t.h"
25 #include "token_t.h"
26 #include "symbol_table_t.h"
27 #include "adt/error.h"
28 #include "adt/strset.h"
29 #include "adt/util.h"
30 #include "types.h"
31 #include "type_t.h"
32 #include "target_architecture.h"
33 #include "parser.h"
34 #include "warning.h"
35 #include "lang_features.h"
36
37 #include <assert.h>
38 #include <errno.h>
39 #include <string.h>
40 #include <stdbool.h>
41 #include <ctype.h>
42
43 //#define DEBUG_CHARS
44 #define MAX_PUTBACK 3
45
46 #ifdef _WIN32
47 /* No strtold on windows and no replacement yet */
48 #define strtold(s, e) strtod(s, e)
49 #endif
50
51 static int         c;
52 token_t            lexer_token;
53 symbol_t          *symbol_L;
54 static FILE       *input;
55 static char        buf[1024 + MAX_PUTBACK];
56 static const char *bufend;
57 static const char *bufpos;
58 static strset_t    stringset;
59
60 /**
61  * Prints a parse error message at the current token.
62  *
63  * @param msg   the error message
64  */
65 static void parse_error(const char *msg)
66 {
67         errorf(&lexer_token.source_position,  "%s", msg);
68 }
69
70 /**
71  * Prints an internal error message at the current token.
72  *
73  * @param msg   the error message
74  */
75 static NORETURN internal_error(const char *msg)
76 {
77         internal_errorf(&lexer_token.source_position,  "%s", msg);
78 }
79
80 static inline void next_real_char(void)
81 {
82         assert(bufpos <= bufend);
83         if (bufpos >= bufend) {
84                 size_t s = fread(buf + MAX_PUTBACK, 1, sizeof(buf) - MAX_PUTBACK,
85                                  input);
86                 if(s == 0) {
87                         c = EOF;
88                         return;
89                 }
90                 bufpos = buf + MAX_PUTBACK;
91                 bufend = buf + MAX_PUTBACK + s;
92         }
93         c = *bufpos++;
94 }
95
96 /**
97  * Put a character back into the buffer.
98  *
99  * @param pc  the character to put back
100  */
101 static inline void put_back(int pc)
102 {
103         assert(bufpos > buf);
104         *(--bufpos - buf + buf) = (char) pc;
105
106 #ifdef DEBUG_CHARS
107         printf("putback '%c'\n", pc);
108 #endif
109 }
110
111 static inline void next_char(void);
112
113 #define MATCH_NEWLINE(code)                   \
114         case '\r':                                \
115                 next_char();                          \
116                 if(c == '\n') {                       \
117                         next_char();                      \
118                 }                                     \
119                 lexer_token.source_position.linenr++; \
120                 code                                  \
121         case '\n':                                \
122                 next_char();                          \
123                 lexer_token.source_position.linenr++; \
124                 code
125
126 #define eat(c_type)  do { assert(c == c_type); next_char(); } while(0)
127
128 static void maybe_concat_lines(void)
129 {
130         eat('\\');
131
132         switch(c) {
133         MATCH_NEWLINE(return;)
134
135         default:
136                 break;
137         }
138
139         put_back(c);
140         c = '\\';
141 }
142
143 /**
144  * Set c to the next input character, ie.
145  * after expanding trigraphs.
146  */
147 static inline void next_char(void)
148 {
149         next_real_char();
150
151         /* filter trigraphs */
152         if(UNLIKELY(c == '\\')) {
153                 maybe_concat_lines();
154                 goto end_of_next_char;
155         }
156
157         if(LIKELY(c != '?'))
158                 goto end_of_next_char;
159
160         next_real_char();
161         if(LIKELY(c != '?')) {
162                 put_back(c);
163                 c = '?';
164                 goto end_of_next_char;
165         }
166
167         next_real_char();
168         switch(c) {
169         case '=': c = '#'; break;
170         case '(': c = '['; break;
171         case '/': c = '\\'; maybe_concat_lines(); break;
172         case ')': c = ']'; break;
173         case '\'': c = '^'; break;
174         case '<': c = '{'; break;
175         case '!': c = '|'; break;
176         case '>': c = '}'; break;
177         case '-': c = '~'; break;
178         default:
179                 put_back(c);
180                 put_back('?');
181                 c = '?';
182                 break;
183         }
184
185 end_of_next_char:;
186 #ifdef DEBUG_CHARS
187         printf("nchar '%c'\n", c);
188 #endif
189 }
190
191 #define SYMBOL_CHARS  \
192         case 'a':         \
193         case 'b':         \
194         case 'c':         \
195         case 'd':         \
196         case 'e':         \
197         case 'f':         \
198         case 'g':         \
199         case 'h':         \
200         case 'i':         \
201         case 'j':         \
202         case 'k':         \
203         case 'l':         \
204         case 'm':         \
205         case 'n':         \
206         case 'o':         \
207         case 'p':         \
208         case 'q':         \
209         case 'r':         \
210         case 's':         \
211         case 't':         \
212         case 'u':         \
213         case 'v':         \
214         case 'w':         \
215         case 'x':         \
216         case 'y':         \
217         case 'z':         \
218         case 'A':         \
219         case 'B':         \
220         case 'C':         \
221         case 'D':         \
222         case 'E':         \
223         case 'F':         \
224         case 'G':         \
225         case 'H':         \
226         case 'I':         \
227         case 'J':         \
228         case 'K':         \
229         case 'L':         \
230         case 'M':         \
231         case 'N':         \
232         case 'O':         \
233         case 'P':         \
234         case 'Q':         \
235         case 'R':         \
236         case 'S':         \
237         case 'T':         \
238         case 'U':         \
239         case 'V':         \
240         case 'W':         \
241         case 'X':         \
242         case 'Y':         \
243         case 'Z':         \
244         case '_':
245
246 #define DIGITS        \
247         case '0':         \
248         case '1':         \
249         case '2':         \
250         case '3':         \
251         case '4':         \
252         case '5':         \
253         case '6':         \
254         case '7':         \
255         case '8':         \
256         case '9':
257
258 /**
259  * Read a symbol from the input and build
260  * the lexer_token.
261  */
262 static void parse_symbol(void)
263 {
264         symbol_t *symbol;
265         char     *string;
266
267         obstack_1grow(&symbol_obstack, (char) c);
268         next_char();
269
270         while(1) {
271                 switch(c) {
272                 DIGITS
273                 SYMBOL_CHARS
274                         obstack_1grow(&symbol_obstack, (char) c);
275                         next_char();
276                         break;
277
278                 default:
279                         goto end_symbol;
280                 }
281         }
282
283 end_symbol:
284         obstack_1grow(&symbol_obstack, '\0');
285
286         string = obstack_finish(&symbol_obstack);
287         symbol = symbol_table_insert(string);
288
289         lexer_token.type     = symbol->ID;
290         lexer_token.v.symbol = symbol;
291
292         if(symbol->string != string) {
293                 obstack_free(&symbol_obstack, string);
294         }
295 }
296
297 static void parse_integer_suffix(bool is_oct_hex)
298 {
299         bool is_unsigned  = false;
300         bool min_long     = false;
301         bool min_longlong = false;
302
303         if(c == 'U' || c == 'u') {
304                 is_unsigned = true;
305                 next_char();
306                 if(c == 'L' || c == 'l') {
307                         min_long = true;
308                         next_char();
309                         if(c == 'L' || c == 'l') {
310                                 min_longlong = true;
311                                 next_char();
312                         }
313                 }
314         } else if(c == 'l' || c == 'L') {
315                 min_long = true;
316                 next_char();
317                 if(c == 'l' || c == 'L') {
318                         min_longlong = true;
319                         next_char();
320                         if(c == 'u' || c == 'U') {
321                                 is_unsigned = true;
322                                 next_char();
323                         }
324                 } else if(c == 'u' || c == 'U') {
325                         is_unsigned = true;
326                         next_char();
327                         lexer_token.datatype = type_unsigned_long;
328                 }
329         }
330
331         if(!is_unsigned) {
332                 long long v = lexer_token.v.intvalue;
333                 if(!min_long) {
334                         if(v >= TARGET_INT_MIN && v <= TARGET_INT_MAX) {
335                                 lexer_token.datatype = type_int;
336                                 return;
337                         } else if(is_oct_hex && v >= 0 && v <= TARGET_UINT_MAX) {
338                                 lexer_token.datatype = type_unsigned_int;
339                                 return;
340                         }
341                 }
342                 if(!min_longlong) {
343                         if(v >= TARGET_LONG_MIN && v <= TARGET_LONG_MAX) {
344                                 lexer_token.datatype = type_long;
345                                 return;
346                         } else if(is_oct_hex && v >= 0 && (unsigned long long)v <= (unsigned long long)TARGET_ULONG_MAX) {
347                                 lexer_token.datatype = type_unsigned_long;
348                                 return;
349                         }
350                 }
351                 unsigned long long uv = (unsigned long long) v;
352                 if(is_oct_hex && uv > (unsigned long long) TARGET_LONGLONG_MAX) {
353                         lexer_token.datatype = type_unsigned_long_long;
354                         return;
355                 }
356
357                 lexer_token.datatype = type_long_long;
358         } else {
359                 unsigned long long v = (unsigned long long) lexer_token.v.intvalue;
360                 if(!min_long && v <= TARGET_UINT_MAX) {
361                         lexer_token.datatype = type_unsigned_int;
362                         return;
363                 }
364                 if(!min_longlong && v <= TARGET_ULONG_MAX) {
365                         lexer_token.datatype = type_unsigned_long;
366                         return;
367                 }
368                 lexer_token.datatype = type_unsigned_long_long;
369         }
370 }
371
372 static void parse_floating_suffix(void)
373 {
374         switch(c) {
375         /* TODO: do something useful with the suffixes... */
376         case 'f':
377         case 'F':
378                 next_char();
379                 lexer_token.datatype = type_float;
380                 break;
381         case 'l':
382         case 'L':
383                 next_char();
384                 lexer_token.datatype = type_long_double;
385                 break;
386         default:
387                 lexer_token.datatype = type_double;
388                 break;
389         }
390 }
391
392 /**
393  * A replacement for strtoull. Only those parts needed for
394  * our parser are implemented.
395  */
396 static unsigned long long parse_int_string(const char *s, const char **endptr, int base) {
397         unsigned long long v = 0;
398
399         switch (base) {
400         case 16:
401                 for (;; ++s) {
402                         /* check for overrun */
403                         if (v >= 0x1000000000000000ULL)
404                                 break;
405                         switch (tolower(*s)) {
406                         case '0': v <<= 4; break;
407                         case '1': v <<= 4; v |= 0x1; break;
408                         case '2': v <<= 4; v |= 0x2; break;
409                         case '3': v <<= 4; v |= 0x3; break;
410                         case '4': v <<= 4; v |= 0x4; break;
411                         case '5': v <<= 4; v |= 0x5; break;
412                         case '6': v <<= 4; v |= 0x6; break;
413                         case '7': v <<= 4; v |= 0x7; break;
414                         case '8': v <<= 4; v |= 0x8; break;
415                         case '9': v <<= 4; v |= 0x9; break;
416                         case 'a': v <<= 4; v |= 0xa; break;
417                         case 'b': v <<= 4; v |= 0xb; break;
418                         case 'c': v <<= 4; v |= 0xc; break;
419                         case 'd': v <<= 4; v |= 0xd; break;
420                         case 'e': v <<= 4; v |= 0xe; break;
421                         case 'f': v <<= 4; v |= 0xf; break;
422                         default:
423                                 goto end;
424                         }
425                 }
426                 break;
427         case 8:
428                 for (;; ++s) {
429                         /* check for overrun */
430                         if (v >= 0x2000000000000000ULL)
431                                 break;
432                         switch (tolower(*s)) {
433                         case '0': v <<= 3; break;
434                         case '1': v <<= 3; v |= 1; break;
435                         case '2': v <<= 3; v |= 2; break;
436                         case '3': v <<= 3; v |= 3; break;
437                         case '4': v <<= 3; v |= 4; break;
438                         case '5': v <<= 3; v |= 5; break;
439                         case '6': v <<= 3; v |= 6; break;
440                         case '7': v <<= 3; v |= 7; break;
441                         default:
442                                 goto end;
443                         }
444                 }
445                 break;
446         case 10:
447                 for (;; ++s) {
448                         /* check for overrun */
449                         if (v > 0x1999999999999999ULL)
450                                 break;
451                         switch (tolower(*s)) {
452                         case '0': v *= 10; break;
453                         case '1': v *= 10; v += 1; break;
454                         case '2': v *= 10; v += 2; break;
455                         case '3': v *= 10; v += 3; break;
456                         case '4': v *= 10; v += 4; break;
457                         case '5': v *= 10; v += 5; break;
458                         case '6': v *= 10; v += 6; break;
459                         case '7': v *= 10; v += 7; break;
460                         case '8': v *= 10; v += 8; break;
461                         case '9': v *= 10; v += 9; break;
462                         default:
463                                 goto end;
464                         }
465                 }
466                 break;
467         default:
468                 assert(0);
469                 break;
470         }
471 end:
472         *endptr = s;
473         return v;
474 }
475
476 /**
477  * Parses a hex number including hex floats and set the
478  * lexer_token.
479  */
480 static void parse_number_hex(void)
481 {
482         assert(c == 'x' || c == 'X');
483         next_char();
484
485         while(isxdigit(c)) {
486                 obstack_1grow(&symbol_obstack, (char) c);
487                 next_char();
488         }
489         obstack_1grow(&symbol_obstack, '\0');
490         char *string = obstack_finish(&symbol_obstack);
491
492         if(c == '.' || c == 'p' || c == 'P') {
493                 next_char();
494                 internal_error("Hex floating point numbers not implemented yet");
495         }
496         if(*string == '\0') {
497                 parse_error("invalid hex number");
498                 lexer_token.type = T_ERROR;
499         }
500
501         const char *endptr;
502         lexer_token.type       = T_INTEGER;
503         lexer_token.v.intvalue = parse_int_string(string, &endptr, 16);
504         if(*endptr != '\0') {
505                 parse_error("hex number literal too long");
506         }
507
508         obstack_free(&symbol_obstack, string);
509         parse_integer_suffix(true);
510 }
511
512 /**
513  * Returns true if the given char is a octal digit.
514  *
515  * @param char  the character to check
516  */
517 static inline bool is_octal_digit(int chr)
518 {
519         switch(chr) {
520         case '0':
521         case '1':
522         case '2':
523         case '3':
524         case '4':
525         case '5':
526         case '6':
527         case '7':
528                 return true;
529         default:
530                 return false;
531         }
532 }
533
534 /**
535  * Parses a octal number and set the lexer_token.
536  */
537 static void parse_number_oct(void)
538 {
539         while(is_octal_digit(c)) {
540                 obstack_1grow(&symbol_obstack, (char) c);
541                 next_char();
542         }
543         obstack_1grow(&symbol_obstack, '\0');
544         char *string = obstack_finish(&symbol_obstack);
545
546         const char *endptr;
547         lexer_token.type       = T_INTEGER;
548         lexer_token.v.intvalue = parse_int_string(string, &endptr, 8);
549         if(*endptr != '\0') {
550                 parse_error("octal number literal too long");
551         }
552
553         obstack_free(&symbol_obstack, string);
554         parse_integer_suffix(true);
555 }
556
557 /**
558  * Parses a decimal including float number and set the
559  * lexer_token.
560  */
561 static void parse_number_dec(void)
562 {
563         bool is_float = false;
564         while(isdigit(c)) {
565                 obstack_1grow(&symbol_obstack, (char) c);
566                 next_char();
567         }
568
569         if(c == '.') {
570                 obstack_1grow(&symbol_obstack, '.');
571                 next_char();
572
573                 while(isdigit(c)) {
574                         obstack_1grow(&symbol_obstack, (char) c);
575                         next_char();
576                 }
577                 is_float = true;
578         }
579         if(c == 'e' || c == 'E') {
580                 obstack_1grow(&symbol_obstack, 'e');
581                 next_char();
582
583                 if(c == '-' || c == '+') {
584                         obstack_1grow(&symbol_obstack, (char) c);
585                         next_char();
586                 }
587
588                 while(isdigit(c)) {
589                         obstack_1grow(&symbol_obstack, (char) c);
590                         next_char();
591                 }
592                 is_float = true;
593         }
594
595         obstack_1grow(&symbol_obstack, '\0');
596         char *string = obstack_finish(&symbol_obstack);
597
598         if(is_float) {
599                 char *endptr;
600                 lexer_token.type         = T_FLOATINGPOINT;
601                 lexer_token.v.floatvalue = strtold(string, &endptr);
602
603                 if(*endptr != '\0') {
604                         parse_error("invalid number literal");
605                 }
606
607                 parse_floating_suffix();
608         } else {
609                 const char *endptr;
610                 lexer_token.type       = T_INTEGER;
611                 lexer_token.v.intvalue = parse_int_string(string, &endptr, 10);
612
613                 if(*endptr != '\0') {
614                         parse_error("invalid number literal");
615                 }
616
617                 parse_integer_suffix(false);
618         }
619         obstack_free(&symbol_obstack, string);
620 }
621
622 /**
623  * Parses a number and sets the lexer_token.
624  */
625 static void parse_number(void)
626 {
627         if (c == '0') {
628                 next_char();
629                 switch (c) {
630                         case 'X':
631                         case 'x':
632                                 parse_number_hex();
633                                 break;
634                         case '0':
635                         case '1':
636                         case '2':
637                         case '3':
638                         case '4':
639                         case '5':
640                         case '6':
641                         case '7':
642                                 parse_number_oct();
643                                 break;
644                         case '8':
645                         case '9':
646                                 next_char();
647                                 parse_error("invalid octal number");
648                                 lexer_token.type = T_ERROR;
649                                 return;
650                         case '.':
651                         case 'e':
652                         case 'E':
653                         default:
654                                 obstack_1grow(&symbol_obstack, '0');
655                                 parse_number_dec();
656                                 return;
657                 }
658         } else {
659                 parse_number_dec();
660         }
661 }
662
663 /**
664  * Returns the value of a digit.
665  * The only portable way to do it ...
666  */
667 static int digit_value(int digit) {
668         switch (digit) {
669         case '0': return 0;
670         case '1': return 1;
671         case '2': return 2;
672         case '3': return 3;
673         case '4': return 4;
674         case '5': return 5;
675         case '6': return 6;
676         case '7': return 7;
677         case '8': return 8;
678         case '9': return 9;
679         case 'a':
680         case 'A': return 10;
681         case 'b':
682         case 'B': return 11;
683         case 'c':
684         case 'C': return 12;
685         case 'd':
686         case 'D': return 13;
687         case 'e':
688         case 'E': return 14;
689         case 'f':
690         case 'F': return 15;
691         default:
692                 internal_error("wrong character given");
693         }
694 }
695
696 /**
697  * Parses an octal character sequence.
698  *
699  * @param first_digit  the already read first digit
700  */
701 static int parse_octal_sequence(const int first_digit)
702 {
703         assert(is_octal_digit(first_digit));
704         int value = digit_value(first_digit);
705         if (!is_octal_digit(c)) return value;
706         value = 8 * value + digit_value(c);
707         next_char();
708         if (!is_octal_digit(c)) return value;
709         value = 8 * value + digit_value(c);
710         next_char();
711
712         if(char_is_signed) {
713                 return (signed char) value;
714         } else {
715                 return (unsigned char) value;
716         }
717 }
718
719 /**
720  * Parses a hex character sequence.
721  */
722 static int parse_hex_sequence(void)
723 {
724         int value = 0;
725         while(isxdigit(c)) {
726                 value = 16 * value + digit_value(c);
727                 next_char();
728         }
729
730         if(char_is_signed) {
731                 return (signed char) value;
732         } else {
733                 return (unsigned char) value;
734         }
735 }
736
737 /**
738  * Parse an escape sequence.
739  */
740 static int parse_escape_sequence(void)
741 {
742         eat('\\');
743
744         int ec = c;
745         next_char();
746
747         switch(ec) {
748         case '"':  return '"';
749         case '\'': return '\'';
750         case '\\': return '\\';
751         case '?': return '\?';
752         case 'a': return '\a';
753         case 'b': return '\b';
754         case 'f': return '\f';
755         case 'n': return '\n';
756         case 'r': return '\r';
757         case 't': return '\t';
758         case 'v': return '\v';
759         case 'x':
760                 return parse_hex_sequence();
761         case '0':
762         case '1':
763         case '2':
764         case '3':
765         case '4':
766         case '5':
767         case '6':
768         case '7':
769                 return parse_octal_sequence(ec);
770         case EOF:
771                 parse_error("reached end of file while parsing escape sequence");
772                 return EOF;
773         default:
774                 parse_error("unknown escape sequence");
775                 return EOF;
776         }
777 }
778
779 /**
780  * Concatenate two strings.
781  */
782 string_t concat_strings(const string_t *const s1, const string_t *const s2)
783 {
784         const size_t len1 = s1->size - 1;
785         const size_t len2 = s2->size - 1;
786
787         char *const concat = obstack_alloc(&symbol_obstack, len1 + len2 + 1);
788         memcpy(concat, s1->begin, len1);
789         memcpy(concat + len1, s2->begin, len2 + 1);
790
791 #if 0 /* TODO hash */
792         const char *result = strset_insert(&stringset, concat);
793         if(result != concat) {
794                 obstack_free(&symbol_obstack, concat);
795         }
796
797         return result;
798 #else
799         return (string_t){ concat, len1 + len2 + 1 };
800 #endif
801 }
802
803 /**
804  * Concatenate a string and a wide string.
805  */
806 wide_string_t concat_string_wide_string(const string_t *const s1, const wide_string_t *const s2)
807 {
808         const size_t len1 = s1->size - 1;
809         const size_t len2 = s2->size - 1;
810
811         wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
812         const char *const src = s1->begin;
813         for (size_t i = 0; i != len1; ++i) {
814                 concat[i] = src[i];
815         }
816         memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
817
818         return (wide_string_t){ concat, len1 + len2 + 1 };
819 }
820
821 /**
822  * Concatenate two wide strings.
823  */
824 wide_string_t concat_wide_strings(const wide_string_t *const s1, const wide_string_t *const s2)
825 {
826         const size_t len1 = s1->size - 1;
827         const size_t len2 = s2->size - 1;
828
829         wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
830         memcpy(concat,        s1->begin, len1       * sizeof(*concat));
831         memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
832
833         return (wide_string_t){ concat, len1 + len2 + 1 };
834 }
835
836 /**
837  * Concatenate a wide string and a string.
838  */
839 wide_string_t concat_wide_string_string(const wide_string_t *const s1, const string_t *const s2)
840 {
841         const size_t len1 = s1->size - 1;
842         const size_t len2 = s2->size - 1;
843
844         wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
845         memcpy(concat, s1->begin, len1 * sizeof(*concat));
846         const char *const src = s2->begin;
847         for (size_t i = 0; i != len2 + 1; ++i) {
848                 concat[i] = src[i];
849         }
850
851         return (wide_string_t){ concat, len1 + len2 + 1 };
852 }
853
854 /**
855  * Parse a string literal and set lexer_token.
856  */
857 static void parse_string_literal(void)
858 {
859         const unsigned start_linenr = lexer_token.source_position.linenr;
860
861         eat('"');
862
863         int tc;
864         while(1) {
865                 switch(c) {
866                 case '\\':
867                         tc = parse_escape_sequence();
868                         obstack_1grow(&symbol_obstack, (char) tc);
869                         break;
870
871                 case EOF: {
872                         source_position_t source_position;
873                         source_position.input_name = lexer_token.source_position.input_name;
874                         source_position.linenr     = start_linenr;
875                         errorf(&source_position, "string has no end");
876                         lexer_token.type = T_ERROR;
877                         return;
878                 }
879
880                 case '"':
881                         next_char();
882                         goto end_of_string;
883
884                 default:
885                         obstack_1grow(&symbol_obstack, (char) c);
886                         next_char();
887                         break;
888                 }
889         }
890
891 end_of_string:
892
893         /* TODO: concatenate multiple strings separated by whitespace... */
894
895         /* add finishing 0 to the string */
896         obstack_1grow(&symbol_obstack, '\0');
897         const size_t      size   = (size_t)obstack_object_size(&symbol_obstack);
898         const char *const string = obstack_finish(&symbol_obstack);
899
900 #if 0 /* TODO hash */
901         /* check if there is already a copy of the string */
902         result = strset_insert(&stringset, string);
903         if(result != string) {
904                 obstack_free(&symbol_obstack, string);
905         }
906 #else
907         const char *const result = string;
908 #endif
909
910         lexer_token.type           = T_STRING_LITERAL;
911         lexer_token.v.string.begin = result;
912         lexer_token.v.string.size  = size;
913 }
914
915 /**
916  * Parse a wide character constant and set lexer_token.
917  */
918 static void parse_wide_character_constant(void)
919 {
920         const unsigned start_linenr = lexer_token.source_position.linenr;
921
922         eat('\'');
923
924         while(1) {
925                 switch(c) {
926                 case '\\': {
927                         wchar_rep_t tc = parse_escape_sequence();
928                         obstack_grow(&symbol_obstack, &tc, sizeof(tc));
929                         break;
930                 }
931
932                 MATCH_NEWLINE(
933                         parse_error("newline while parsing character constant");
934                         break;
935                 )
936
937                 case '\'':
938                         next_char();
939                         goto end_of_wide_char_constant;
940
941                 case EOF: {
942                         source_position_t source_position = lexer_token.source_position;
943                         source_position.linenr = start_linenr;
944                         errorf(&source_position, "EOF while parsing character constant");
945                         lexer_token.type = T_ERROR;
946                         return;
947                 }
948
949                 default: {
950                         wchar_rep_t tc = (wchar_rep_t) c;
951                         obstack_grow(&symbol_obstack, &tc, sizeof(tc));
952                         next_char();
953                         break;
954                 }
955                 }
956         }
957
958 end_of_wide_char_constant:;
959         size_t             size   = (size_t) obstack_object_size(&symbol_obstack);
960         assert(size % sizeof(wchar_rep_t) == 0);
961         size /= sizeof(wchar_rep_t);
962
963         const wchar_rep_t *string = obstack_finish(&symbol_obstack);
964
965         lexer_token.type                = T_WIDE_CHARACTER_CONSTANT;
966         lexer_token.v.wide_string.begin = string;
967         lexer_token.v.wide_string.size  = size;
968         lexer_token.datatype            = type_wchar_t;
969 }
970
971 /**
972  * Parse a wide string literal and set lexer_token.
973  */
974 static void parse_wide_string_literal(void)
975 {
976         const unsigned start_linenr = lexer_token.source_position.linenr;
977
978         assert(c == '"');
979         next_char();
980
981         while(1) {
982                 switch(c) {
983                 case '\\': {
984                         wchar_rep_t tc = parse_escape_sequence();
985                         obstack_grow(&symbol_obstack, &tc, sizeof(tc));
986                         break;
987                 }
988
989                 case EOF: {
990                         source_position_t source_position;
991                         source_position.input_name = lexer_token.source_position.input_name;
992                         source_position.linenr     = start_linenr;
993                         errorf(&source_position, "string has no end");
994                         lexer_token.type = T_ERROR;
995                         return;
996                 }
997
998                 case '"':
999                         next_char();
1000                         goto end_of_string;
1001
1002                 default: {
1003                         wchar_rep_t tc = c;
1004                         obstack_grow(&symbol_obstack, &tc, sizeof(tc));
1005                         next_char();
1006                         break;
1007                 }
1008                 }
1009         }
1010
1011 end_of_string:;
1012
1013         /* TODO: concatenate multiple strings separated by whitespace... */
1014
1015         /* add finishing 0 to the string */
1016         wchar_rep_t nul = L'\0';
1017         obstack_grow(&symbol_obstack, &nul, sizeof(nul));
1018         const size_t             size   = (size_t)obstack_object_size(&symbol_obstack) / sizeof(wchar_rep_t);
1019         const wchar_rep_t *const string = obstack_finish(&symbol_obstack);
1020
1021 #if 0 /* TODO hash */
1022         /* check if there is already a copy of the string */
1023         const wchar_rep_t *const result = strset_insert(&stringset, string);
1024         if(result != string) {
1025                 obstack_free(&symbol_obstack, string);
1026         }
1027 #else
1028         const wchar_rep_t *const result = string;
1029 #endif
1030
1031         lexer_token.type                = T_WIDE_STRING_LITERAL;
1032         lexer_token.v.wide_string.begin = result;
1033         lexer_token.v.wide_string.size  = size;
1034 }
1035
1036 /**
1037  * Parse a character constant and set lexer_token.
1038  */
1039 static void parse_character_constant(void)
1040 {
1041         const unsigned start_linenr = lexer_token.source_position.linenr;
1042
1043         eat('\'');
1044
1045         while(1) {
1046                 switch(c) {
1047                 case '\\': {
1048                         int tc = parse_escape_sequence();
1049                         obstack_1grow(&symbol_obstack, (char) tc);
1050                         break;
1051                 }
1052
1053                 MATCH_NEWLINE(
1054                         parse_error("newline while parsing character constant");
1055                         break;
1056                 )
1057
1058                 case '\'':
1059                         next_char();
1060                         goto end_of_char_constant;
1061
1062                 case EOF: {
1063                         source_position_t source_position;
1064                         source_position.input_name = lexer_token.source_position.input_name;
1065                         source_position.linenr     = start_linenr;
1066                         errorf(&source_position, "EOF while parsing character constant");
1067                         lexer_token.type = T_ERROR;
1068                         return;
1069                 }
1070
1071                 default:
1072                         obstack_1grow(&symbol_obstack, (char) c);
1073                         next_char();
1074                         break;
1075
1076                 }
1077         }
1078
1079 end_of_char_constant:;
1080         const size_t      size   = (size_t)obstack_object_size(&symbol_obstack);
1081         const char *const string = obstack_finish(&symbol_obstack);
1082
1083         lexer_token.type           = T_CHARACTER_CONSTANT;
1084         lexer_token.v.string.begin = string;
1085         lexer_token.v.string.size  = size;
1086         lexer_token.datatype       = type_int;
1087 }
1088
1089 /**
1090  * Skip a multiline comment.
1091  */
1092 static void skip_multiline_comment(void)
1093 {
1094         unsigned start_linenr = lexer_token.source_position.linenr;
1095
1096         while(1) {
1097                 switch(c) {
1098                 case '/':
1099                         next_char();
1100                         if (c == '*') {
1101                                 /* TODO: nested comment, warn here */
1102                         }
1103                         break;
1104                 case '*':
1105                         next_char();
1106                         if(c == '/') {
1107                                 next_char();
1108                                 return;
1109                         }
1110                         break;
1111
1112                 MATCH_NEWLINE(break;)
1113
1114                 case EOF: {
1115                         source_position_t source_position;
1116                         source_position.input_name = lexer_token.source_position.input_name;
1117                         source_position.linenr     = start_linenr;
1118                         errorf(&source_position, "at end of file while looking for comment end");
1119                         return;
1120                 }
1121
1122                 default:
1123                         next_char();
1124                         break;
1125                 }
1126         }
1127 }
1128
1129 /**
1130  * Skip a single line comment.
1131  */
1132 static void skip_line_comment(void)
1133 {
1134         while(1) {
1135                 switch(c) {
1136                 case EOF:
1137                         return;
1138
1139                 case '\n':
1140                 case '\r':
1141                         return;
1142
1143                 default:
1144                         next_char();
1145                         break;
1146                 }
1147         }
1148 }
1149
1150 /** The current preprocessor token. */
1151 static token_t pp_token;
1152
1153 /**
1154  * Read the next preprocessor token.
1155  */
1156 static inline void next_pp_token(void)
1157 {
1158         lexer_next_preprocessing_token();
1159         pp_token = lexer_token;
1160 }
1161
1162 /**
1163  * Eat all preprocessor tokens until newline.
1164  */
1165 static void eat_until_newline(void)
1166 {
1167         while(pp_token.type != '\n' && pp_token.type != T_EOF) {
1168                 next_pp_token();
1169         }
1170 }
1171
1172 /**
1173  * Handle the define directive.
1174  */
1175 static void define_directive(void)
1176 {
1177         lexer_next_preprocessing_token();
1178         if(lexer_token.type != T_IDENTIFIER) {
1179                 parse_error("expected identifier after #define\n");
1180                 eat_until_newline();
1181         }
1182 }
1183
1184 /**
1185  * Handle the ifdef directive.
1186  */
1187 static void ifdef_directive(int is_ifndef)
1188 {
1189         (void) is_ifndef;
1190         lexer_next_preprocessing_token();
1191         //expect_identifier();
1192         //extect_newline();
1193 }
1194
1195 /**
1196  * Handle the endif directive.
1197  */
1198 static void endif_directive(void)
1199 {
1200         //expect_newline();
1201 }
1202
1203 /**
1204  * Parse the line directive.
1205  */
1206 static void parse_line_directive(void)
1207 {
1208         if(pp_token.type != T_INTEGER) {
1209                 parse_error("expected integer");
1210         } else {
1211                 lexer_token.source_position.linenr = (unsigned int)(pp_token.v.intvalue - 1);
1212                 next_pp_token();
1213         }
1214         if(pp_token.type == T_STRING_LITERAL) {
1215                 lexer_token.source_position.input_name = pp_token.v.string.begin;
1216                 next_pp_token();
1217         }
1218
1219         eat_until_newline();
1220 }
1221
1222 /**
1223  * STDC pragmas.
1224  */
1225 typedef enum {
1226         STDC_UNKNOWN,
1227         STDC_FP_CONTRACT,
1228         STDC_FENV_ACCESS,
1229         STDC_CX_LIMITED_RANGE
1230 } stdc_pragma_kind_t;
1231
1232 /**
1233  * STDC pragma values.
1234  */
1235 typedef enum {
1236         STDC_VALUE_UNKNOWN,
1237         STDC_VALUE_ON,
1238         STDC_VALUE_OFF,
1239         STDC_VALUE_DEFAULT
1240 } stdc_pragma_value_kind_t;
1241
1242 /**
1243  * Parse a pragma directive.
1244  */
1245 static void parse_pragma(void) {
1246         bool unknown_pragma = true;
1247
1248         next_pp_token();
1249         if (pp_token.v.symbol->pp_ID == TP_STDC) {
1250                 stdc_pragma_kind_t kind = STDC_UNKNOWN;
1251                 /* a STDC pragma */
1252                 if (c_mode & _C99) {
1253                         next_pp_token();
1254
1255                         switch (pp_token.v.symbol->pp_ID) {
1256                         case TP_FP_CONTRACT:
1257                                 kind = STDC_FP_CONTRACT;
1258                                 break;
1259                         case TP_FENV_ACCESS:
1260                                 kind = STDC_FENV_ACCESS;
1261                                 break;
1262                         case TP_CX_LIMITED_RANGE:
1263                                 kind = STDC_CX_LIMITED_RANGE;
1264                                 break;
1265                         default:
1266                                 break;
1267                         }
1268                         if (kind != STDC_UNKNOWN) {
1269                                 stdc_pragma_value_kind_t value = STDC_VALUE_UNKNOWN;
1270                                 next_pp_token();
1271                                 switch (pp_token.v.symbol->pp_ID) {
1272                                 case TP_ON:
1273                                         value = STDC_VALUE_ON;
1274                                         break;
1275                                 case TP_OFF:
1276                                         value = STDC_VALUE_OFF;
1277                                         break;
1278                                 case TP_DEFAULT:
1279                                         value = STDC_VALUE_DEFAULT;
1280                                         break;
1281                                 default:
1282                                         break;
1283                                 }
1284                                 if (value != STDC_VALUE_UNKNOWN) {
1285                                         unknown_pragma = false;
1286                                 } else {
1287                                         errorf(&pp_token.source_position, "bad STDC pragma argument");
1288                                 }
1289                         }
1290                 }
1291         } else {
1292                 unknown_pragma = true;
1293         }
1294         eat_until_newline();
1295         if (unknown_pragma && warning.unknown_pragmas) {
1296                 warningf(&pp_token.source_position, "encountered unknown #pragma");
1297         }
1298 }
1299
1300 /**
1301  * Parse a preprocessor non-null directive.
1302  */
1303 static void parse_preprocessor_identifier(void)
1304 {
1305         assert(pp_token.type == T_IDENTIFIER);
1306         symbol_t *symbol = pp_token.v.symbol;
1307
1308         switch(symbol->pp_ID) {
1309         case TP_include:
1310                 printf("include - enable header name parsing!\n");
1311                 break;
1312         case TP_define:
1313                 define_directive();
1314                 break;
1315         case TP_ifdef:
1316                 ifdef_directive(0);
1317                 break;
1318         case TP_ifndef:
1319                 ifdef_directive(1);
1320                 break;
1321         case TP_endif:
1322                 endif_directive();
1323                 break;
1324         case TP_line:
1325                 next_pp_token();
1326                 parse_line_directive();
1327                 break;
1328         case TP_if:
1329         case TP_else:
1330         case TP_elif:
1331         case TP_undef:
1332         case TP_error:
1333                 /* TODO; output the rest of the line */
1334                 parse_error("#error directive: ");
1335                 break;
1336         case TP_pragma:
1337                 parse_pragma();
1338                 break;
1339         }
1340 }
1341
1342 /**
1343  * Parse a preprocessor directive.
1344  */
1345 static void parse_preprocessor_directive(void)
1346 {
1347         next_pp_token();
1348
1349         switch(pp_token.type) {
1350         case T_IDENTIFIER:
1351                 parse_preprocessor_identifier();
1352                 break;
1353         case T_INTEGER:
1354                 parse_line_directive();
1355                 break;
1356         case '\n':
1357                 /* NULL directive, see Â§ 6.10.7 */
1358                 break;
1359         default:
1360                 parse_error("invalid preprocessor directive");
1361                 eat_until_newline();
1362                 break;
1363         }
1364 }
1365
1366 #define MAYBE_PROLOG                                       \
1367                         next_char();                                   \
1368                         while(1) {                                     \
1369                                 switch(c) {
1370
1371 #define MAYBE(ch, set_type)                                \
1372                                 case ch:                                   \
1373                                         next_char();                           \
1374                                         lexer_token.type = set_type;           \
1375                                         return;
1376
1377 #define ELSE_CODE(code)                                    \
1378                                 default:                                   \
1379                                         code                                   \
1380                                 }                                          \
1381                         } /* end of while(1) */                        \
1382                         break;
1383
1384 #define ELSE(set_type)                                     \
1385                 ELSE_CODE(                                         \
1386                         lexer_token.type = set_type;                   \
1387                         return;                                        \
1388                 )
1389
1390 void lexer_next_preprocessing_token(void)
1391 {
1392         while(1) {
1393                 switch(c) {
1394                 case ' ':
1395                 case '\t':
1396                         next_char();
1397                         break;
1398
1399                 MATCH_NEWLINE(
1400                         lexer_token.type = '\n';
1401                         return;
1402                 )
1403
1404                 SYMBOL_CHARS
1405                         parse_symbol();
1406                         /* might be a wide string ( L"string" ) */
1407                         if(lexer_token.type == T_IDENTIFIER &&
1408                             lexer_token.v.symbol == symbol_L) {
1409                             if(c == '"') {
1410                                         parse_wide_string_literal();
1411                                 } else if(c == '\'') {
1412                                         parse_wide_character_constant();
1413                                 }
1414                         }
1415                         return;
1416
1417                 DIGITS
1418                         parse_number();
1419                         return;
1420
1421                 case '"':
1422                         parse_string_literal();
1423                         return;
1424
1425                 case '\'':
1426                         parse_character_constant();
1427                         return;
1428
1429                 case '.':
1430                         MAYBE_PROLOG
1431                                 case '0':
1432                                 case '1':
1433                                 case '2':
1434                                 case '3':
1435                                 case '4':
1436                                 case '5':
1437                                 case '6':
1438                                 case '7':
1439                                 case '8':
1440                                 case '9':
1441                                         put_back(c);
1442                                         c = '.';
1443                                         parse_number_dec();
1444                                         return;
1445
1446                                 case '.':
1447                                         MAYBE_PROLOG
1448                                         MAYBE('.', T_DOTDOTDOT)
1449                                         ELSE_CODE(
1450                                                 put_back(c);
1451                                                 c = '.';
1452                                                 lexer_token.type = '.';
1453                                                 return;
1454                                         )
1455                         ELSE('.')
1456                 case '&':
1457                         MAYBE_PROLOG
1458                         MAYBE('&', T_ANDAND)
1459                         MAYBE('=', T_ANDEQUAL)
1460                         ELSE('&')
1461                 case '*':
1462                         MAYBE_PROLOG
1463                         MAYBE('=', T_ASTERISKEQUAL)
1464                         ELSE('*')
1465                 case '+':
1466                         MAYBE_PROLOG
1467                         MAYBE('+', T_PLUSPLUS)
1468                         MAYBE('=', T_PLUSEQUAL)
1469                         ELSE('+')
1470                 case '-':
1471                         MAYBE_PROLOG
1472                         MAYBE('>', T_MINUSGREATER)
1473                         MAYBE('-', T_MINUSMINUS)
1474                         MAYBE('=', T_MINUSEQUAL)
1475                         ELSE('-')
1476                 case '!':
1477                         MAYBE_PROLOG
1478                         MAYBE('=', T_EXCLAMATIONMARKEQUAL)
1479                         ELSE('!')
1480                 case '/':
1481                         MAYBE_PROLOG
1482                         MAYBE('=', T_SLASHEQUAL)
1483                                 case '*':
1484                                         next_char();
1485                                         skip_multiline_comment();
1486                                         lexer_next_preprocessing_token();
1487                                         return;
1488                                 case '/':
1489                                         next_char();
1490                                         skip_line_comment();
1491                                         lexer_next_preprocessing_token();
1492                                         return;
1493                         ELSE('/')
1494                 case '%':
1495                         MAYBE_PROLOG
1496                         MAYBE('>', '}')
1497                         MAYBE('=', T_PERCENTEQUAL)
1498                                 case ':':
1499                                         MAYBE_PROLOG
1500                                                 case '%':
1501                                                         MAYBE_PROLOG
1502                                                         MAYBE(':', T_HASHHASH)
1503                                                         ELSE_CODE(
1504                                                                 put_back(c);
1505                                                                 c = '%';
1506                                                                 lexer_token.type = '#';
1507                                                                 return;
1508                                                         )
1509                                         ELSE('#')
1510                         ELSE('%')
1511                 case '<':
1512                         MAYBE_PROLOG
1513                         MAYBE(':', '[')
1514                         MAYBE('%', '{')
1515                         MAYBE('=', T_LESSEQUAL)
1516                                 case '<':
1517                                         MAYBE_PROLOG
1518                                         MAYBE('=', T_LESSLESSEQUAL)
1519                                         ELSE(T_LESSLESS)
1520                         ELSE('<')
1521                 case '>':
1522                         MAYBE_PROLOG
1523                         MAYBE('=', T_GREATEREQUAL)
1524                                 case '>':
1525                                         MAYBE_PROLOG
1526                                         MAYBE('=', T_GREATERGREATEREQUAL)
1527                                         ELSE(T_GREATERGREATER)
1528                         ELSE('>')
1529                 case '^':
1530                         MAYBE_PROLOG
1531                         MAYBE('=', T_CARETEQUAL)
1532                         ELSE('^')
1533                 case '|':
1534                         MAYBE_PROLOG
1535                         MAYBE('=', T_PIPEEQUAL)
1536                         MAYBE('|', T_PIPEPIPE)
1537                         ELSE('|')
1538                 case ':':
1539                         MAYBE_PROLOG
1540                         MAYBE('>', ']')
1541                         ELSE(':')
1542                 case '=':
1543                         MAYBE_PROLOG
1544                         MAYBE('=', T_EQUALEQUAL)
1545                         ELSE('=')
1546                 case '#':
1547                         MAYBE_PROLOG
1548                         MAYBE('#', T_HASHHASH)
1549                         ELSE('#')
1550
1551                 case '?':
1552                 case '[':
1553                 case ']':
1554                 case '(':
1555                 case ')':
1556                 case '{':
1557                 case '}':
1558                 case '~':
1559                 case ';':
1560                 case ',':
1561                 case '\\':
1562                         lexer_token.type = c;
1563                         next_char();
1564                         return;
1565
1566                 case EOF:
1567                         lexer_token.type = T_EOF;
1568                         return;
1569
1570                 default:
1571                         next_char();
1572                         errorf(&lexer_token.source_position, "unknown character '%c' found\n", c);
1573                         lexer_token.type = T_ERROR;
1574                         return;
1575                 }
1576         }
1577 }
1578
1579 void lexer_next_token(void)
1580 {
1581         lexer_next_preprocessing_token();
1582         if(lexer_token.type != '\n')
1583                 return;
1584
1585 newline_found:
1586         do {
1587                 lexer_next_preprocessing_token();
1588         } while(lexer_token.type == '\n');
1589
1590         if(lexer_token.type == '#') {
1591                 parse_preprocessor_directive();
1592                 goto newline_found;
1593         }
1594 }
1595
1596 void init_lexer(void)
1597 {
1598         strset_init(&stringset);
1599 }
1600
1601 void lexer_open_stream(FILE *stream, const char *input_name)
1602 {
1603         input                                  = stream;
1604         lexer_token.source_position.linenr     = 0;
1605         lexer_token.source_position.input_name = input_name;
1606
1607         symbol_L = symbol_table_insert("L");
1608         bufpos = NULL;
1609         bufend = NULL;
1610
1611         /* place a virtual \n at the beginning so the lexer knows that we're
1612          * at the beginning of a line */
1613         c = '\n';
1614 }
1615
1616 void exit_lexer(void)
1617 {
1618         strset_destroy(&stringset);
1619 }
1620
1621 static __attribute__((unused))
1622 void dbg_pos(const source_position_t source_position)
1623 {
1624         fprintf(stdout, "%s:%u\n", source_position.input_name,
1625                 source_position.linenr);
1626         fflush(stdout);
1627 }