Handle string literals with embedded \0 correctly.
[cparser] / token.c
1 #include <config.h>
2
3 #include "token_t.h"
4
5 #include <assert.h>
6 #include <stdio.h>
7
8 #include "symbol.h"
9 #include "lang_features.h"
10 #include "adt/array.h"
11
12 static symbol_t *token_symbols[T_LAST_TOKEN];
13
14 source_position_t builtin_source_position = { "<built-in>", 0 };
15
16 void init_tokens(void)
17 {
18         symbol_t *symbol;
19         int       last_id = -2;
20
21         memset(token_symbols, 0, T_LAST_TOKEN * sizeof(token_symbols[0]));
22
23 #define T(mode,x,str,val)                                          \
24         if (T_##x > 255) {                                             \
25                 assert(T_##x >= last_id);                                  \
26                 last_id = T_##x;                                           \
27         }                                                              \
28         if (c_mode & (mode)) {                                         \
29                 assert(T_##x >= 0 && T_##x < T_LAST_TOKEN);                \
30                 symbol               = symbol_table_insert(str);           \
31                 symbol->ID           = T_##x;                              \
32                 token_symbols[T_##x] = symbol;                             \
33         }
34
35 #define TS(x,str,val)                                              \
36         assert(T_##x >= 0 && T_##x < T_LAST_TOKEN);                    \
37         symbol               = symbol_table_insert(str);               \
38         token_symbols[T_##x] = symbol;
39
40 #include "tokens.inc"
41
42 #undef TS
43 #undef T
44
45 #define T(mode,x,str,val)                                          \
46         assert(TP_##x >= 0 && TP_##x < TP_LAST_TOKEN);                 \
47         symbol               = symbol_table_insert(str);               \
48         symbol->pp_ID        = TP_##x;
49
50 #include "tokens_preprocessor.inc"
51
52 #undef T
53 }
54
55 void exit_tokens(void)
56 {
57 }
58
59 void print_token_type(FILE *f, token_type_t token_type)
60 {
61         if(token_type == T_EOF) {
62                 fputs("end of file", f);
63                 return;
64         }
65         if(token_type == T_ERROR) {
66                 fputs("error", f);
67                 return;
68         }
69
70         int token_symbols_len = T_LAST_TOKEN;
71         if(token_type < 0 || token_type >= token_symbols_len) {
72                 fputs("invalid token", f);
73                 return;
74         }
75
76         const symbol_t *symbol = token_symbols[token_type];
77         if(symbol != NULL) {
78                 fprintf(f, "'%s'", symbol->string);
79         } else {
80                 if(token_type >= 0 && token_type < 256) {
81                         fprintf(f, "'%c'", token_type);
82                         return;
83                 }
84                 fputs("unknown token", f);
85         }
86 }
87
88 void print_token(FILE *f, const token_t *token)
89 {
90         switch(token->type) {
91         case T_IDENTIFIER:
92                 fprintf(f, "symbol '%s'", token->v.symbol->string);
93                 break;
94         case T_INTEGER:
95                 fprintf(f, "integer number %lld", token->v.intvalue);
96                 break;
97         case T_FLOATINGPOINT:
98                 fprintf(f, "floatingpointer number %LF", token->v.floatvalue);
99                 break;
100         case T_STRING_LITERAL:
101                 fprintf(f, "string '%s'", token->v.string.begin); /* TODO suboptimal */
102                 break;
103         default:
104                 print_token_type(f, (token_type_t)token->type);
105                 break;
106         }
107 }