+ fprintf(f, "string '%s'", token->v.string.begin); /* TODO suboptimal */
+ break;
+ default:
+ print_token_type(f, (token_type_t)token->type);
+ break;
+ }
+}
+
+void print_pp_token_type(FILE *f, preprocessor_token_type_t token_type)
+{
+ if(token_type == TP_EOF) {
+ fputs("end of file", f);
+ return;
+ }
+ if(token_type == TP_ERROR) {
+ fputs("error", f);
+ return;
+ }
+
+ int token_symbols_len = TP_LAST_TOKEN;
+ if(token_type < 0 || token_type >= token_symbols_len) {
+ fputs("invalid token", f);
+ return;
+ }
+
+ const symbol_t *symbol = pp_token_symbols[token_type];
+ if(symbol != NULL) {
+ fprintf(f, "'%s'", symbol->string);
+ } else {
+ if(token_type >= 0 && token_type < 256) {
+ fprintf(f, "'%c'", token_type);
+ return;
+ }
+ fputs("unknown token", f);
+ }
+}
+
+void print_pp_token(FILE *f, const token_t *token)
+{
+ switch((preprocessor_token_type_t) token->type) {
+ case TP_IDENTIFIER:
+ fprintf(f, "symbol '%s'", token->v.symbol->string);
+ break;
+ case TP_NUMBER:
+ fprintf(f, "number %s", token->v.string.begin);
+ break;
+ case TP_STRING_LITERAL:
+ fprintf(f, "string '%s'", token->v.string.begin);