--input.position.colno;
}
-#define MATCH_NEWLINE(code) \
- case '\r': \
- next_char(); \
- if (input.c == '\n') { \
- case '\n': \
- next_char(); \
- } \
- info.whitespace = 0; \
- ++input.position.lineno; \
- input.position.colno = 1; \
- code
+#define NEWLINE \
+ '\r': \
+ next_char(); \
+ if (input.c == '\n') { \
+ case '\n': \
+ next_char(); \
+ } \
+ info.whitespace = 0; \
+ ++input.position.lineno; \
+ input.position.colno = 1; \
+ goto newline; \
+ newline // Let it look like an ordinary case label.
#define eat(c_type) (assert(input.c == c_type), next_char())
eat('\\');
switch (input.c) {
- MATCH_NEWLINE(
+ case NEWLINE:
return;
- )
default:
break;
return result;
}
-static string_t make_string(char *string, size_t len)
+static string_t sym_make_string(string_encoding_t const enc)
{
- const char *result = identify_string(string);
- return (string_t) {result, len};
+ obstack_1grow(&symbol_obstack, '\0');
+ size_t const len = obstack_object_size(&symbol_obstack) - 1;
+ char *const string = obstack_finish(&symbol_obstack);
+ char const *const result = identify_string(string);
+ return (string_t){ result, len, enc };
}
static void parse_string(utf32 const delimiter, preprocessor_token_kind_t const kind, string_encoding_t const enc, char const *const context)
break;
}
- MATCH_NEWLINE(
+ case NEWLINE:
errorf(&pp_token.base.source_position, "newline while parsing %s", context);
break;
- )
case EOF: {
source_position_t source_position;
}
}
-end_of_string:;
- obstack_1grow(&symbol_obstack, '\0');
- size_t const size = obstack_object_size(&symbol_obstack) - 1;
- char *const string = obstack_finish(&symbol_obstack);
-
- pp_token.kind = kind;
- pp_token.string.encoding = enc;
- pp_token.string.string = make_string(string, size);
+end_of_string:
+ pp_token.kind = kind;
+ pp_token.literal.string = sym_make_string(enc);
}
static void parse_string_literal(string_encoding_t const enc)
static void parse_character_constant(string_encoding_t const enc)
{
parse_string('\'', TP_CHARACTER_CONSTANT, enc, "character constant");
- if (pp_token.string.string.size == 0) {
+ if (pp_token.literal.string.size == 0) {
parse_error("empty character constant");
}
}
-#define SYMBOL_CHARS_WITHOUT_E_P \
- case 'a': \
+#define SYMBOL_CASES_WITHOUT_E_P \
+ 'a': \
case 'b': \
case 'c': \
case 'd': \
case 'X': \
case 'Y': \
case 'Z': \
- case '_':
+ case '_'
-#define SYMBOL_CHARS \
- SYMBOL_CHARS_WITHOUT_E_P \
+#define SYMBOL_CASES \
+ SYMBOL_CASES_WITHOUT_E_P: \
case 'e': \
case 'p': \
case 'E': \
- case 'P':
+ case 'P'
-#define DIGITS \
- case '0': \
+#define DIGIT_CASES \
+ '0': \
case '1': \
case '2': \
case '3': \
case '6': \
case '7': \
case '8': \
- case '9':
+ case '9'
/**
* returns next final token from a preprocessor macro expansion
}
break;
- MATCH_NEWLINE(
+ case NEWLINE:
break;
- )
case EOF: {
source_position_t source_position;
next_char();
continue;
- MATCH_NEWLINE(
+ case NEWLINE:
info.at_line_begin = true;
return;
- )
case '/':
next_char();
while (true) {
switch (input.c) {
- DIGITS
- SYMBOL_CHARS
+ case DIGIT_CASES:
+ case SYMBOL_CASES:
obstack_1grow(&symbol_obstack, (char) input.c);
next_char();
break;
while (true) {
switch (input.c) {
case '.':
- DIGITS
- SYMBOL_CHARS_WITHOUT_E_P
+ case DIGIT_CASES:
+ case SYMBOL_CASES_WITHOUT_E_P:
obstack_1grow(&symbol_obstack, (char) input.c);
next_char();
break;
}
end_number:
- obstack_1grow(&symbol_obstack, '\0');
- size_t size = obstack_object_size(&symbol_obstack);
- char *string = obstack_finish(&symbol_obstack);
-
- pp_token.kind = TP_NUMBER;
- pp_token.number.number = make_string(string, size);
+ pp_token.kind = TP_NUMBER;
+ pp_token.literal.string = sym_make_string(STRING_ENCODING_CHAR);
}
next_char();
goto restart;
- MATCH_NEWLINE(
+ case NEWLINE:
info.at_line_begin = true;
info.had_whitespace = true;
goto restart;
- )
- SYMBOL_CHARS
+ case SYMBOL_CASES:
parse_symbol();
return;
- DIGITS
+ case DIGIT_CASES:
parse_number();
return;
case '~':
case ';':
case ',':
- case '\\':
pp_token.kind = input.c;
next_char();
return;
fputs(pp_token.base.symbol->string, out);
break;
case TP_NUMBER:
- fputs(pp_token.number.number.begin, out);
+ fputs(pp_token.literal.string.begin, out);
break;
case TP_STRING_LITERAL:
- fputs(get_string_encoding_prefix(pp_token.string.encoding), out);
+ fputs(get_string_encoding_prefix(pp_token.literal.string.encoding), out);
fputc('"', out);
- fputs(pp_token.string.string.begin, out);
+ fputs(pp_token.literal.string.begin, out);
fputc('"', out);
break;
case TP_CHARACTER_CONSTANT:
- fputs(get_string_encoding_prefix(pp_token.string.encoding), out);
+ fputs(get_string_encoding_prefix(pp_token.literal.string.encoding), out);
fputc('\'', out);
- fputs(pp_token.string.string.begin, out);
+ fputs(pp_token.literal.string.begin, out);
fputc('\'', out);
break;
default:
case TP_NUMBER:
case TP_CHARACTER_CONSTANT:
case TP_STRING_LITERAL:
- return strings_equal(&token1->string.string, &token2->string.string);
+ return strings_equal(&token1->literal.string, &token2->literal.string);
default:
return true;
eat_pp_directive();
}
+/** behind an #include we can have the special headername lexems.
+ * They're only allowed behind an #include so they're not recognized
+ * by the normal next_preprocessing_token. We handle them as a special
+ * exception here */
static void parse_headername(void)
{
const source_position_t start_position = input.position;
- string_t string = {NULL, 0};
+ string_t string = { NULL, 0, STRING_ENCODING_CHAR };
assert(obstack_object_size(&symbol_obstack) == 0);
- /* behind an #include we can have the special headername lexems.
- * They're only allowed behind an #include so they're not recognized
- * by the normal next_preprocessing_token. We handle them as a special
- * exception here */
if (info.at_line_begin) {
parse_error("expected headername after #include");
goto finish_error;
/* check wether we have a "... or <... headername */
switch (input.c) {
- case '<':
+ {
+ utf32 delimiter;
+ case '<': delimiter = '>'; goto parse_name;
+ case '"': delimiter = '"'; goto parse_name;
+parse_name:
next_char();
while (true) {
switch (input.c) {
+ case NEWLINE:
case EOF:
- /* fallthrough */
- MATCH_NEWLINE(
- parse_error("header name without closing '>'");
+ errorf(&pp_token.base.source_position, "header name without closing '%c'", (char)delimiter);
goto finish_error;
- )
- case '>':
- next_char();
- goto finished_headername;
- }
- obstack_1grow(&symbol_obstack, (char) input.c);
- next_char();
- }
- /* we should never be here */
- case '"':
- next_char();
- while (true) {
- switch (input.c) {
- case EOF:
- /* fallthrough */
- MATCH_NEWLINE(
- parse_error("header name without closing '>'");
- goto finish_error;
- )
- case '"':
- next_char();
- goto finished_headername;
+ default:
+ if (input.c == delimiter) {
+ next_char();
+ goto finished_headername;
+ } else {
+ obstack_1grow(&symbol_obstack, (char)input.c);
+ next_char();
+ }
+ break;
}
- obstack_1grow(&symbol_obstack, (char) input.c);
- next_char();
}
/* we should never be here */
+ }
default:
/* TODO: do normal pp_token parsing and concatenate results */
}
finished_headername:
- obstack_1grow(&symbol_obstack, '\0');
- const size_t size = (size_t)obstack_object_size(&symbol_obstack);
- char *const headername = obstack_finish(&symbol_obstack);
- string = make_string(headername, size);
+ string = sym_make_string(STRING_ENCODING_CHAR);
finish_error:
pp_token.base.source_position = start_position;
pp_token.kind = TP_HEADERNAME;
- pp_token.string.string = string;
+ pp_token.literal.string = string;
}
static bool do_include(bool system_include, const char *headername)
/* skip till newline */
while (true) {
switch (input.c) {
- MATCH_NEWLINE(
- return;
- )
+ case NEWLINE:
case EOF:
return;
}
skip_whitespace();
bool system_include = input.c == '<';
parse_headername();
- string_t headername = pp_token.string.string;
+ string_t headername = pp_token.literal.string;
if (headername.begin == NULL) {
eat_pp_directive();
return false;
/* switch inputs */
emit_newlines();
push_input();
- bool res = do_include(system_include, pp_token.string.string.begin);
+ bool res = do_include(system_include, pp_token.literal.string.begin);
if (!res) {
- errorf(&pp_token.base.source_position,
- "failed including '%S': %s", pp_token.string, strerror(errno));
+ errorf(&pp_token.base.source_position, "failed including '%S': %s", &pp_token.literal, strerror(errno));
pop_restore_input();
return false;
}
condition = true;
} else {
/* evaluate wether we are in true or false case */
- condition = !pp_token.base.symbol->pp_definition == is_ifndef;
+ condition = (bool)!pp_token.base.symbol->pp_definition == is_ifndef;
next_preprocessing_token();
if (conditional->in_else) {
errorf(&pp_token.base.source_position,
"#else after #else (condition started %P)",
- conditional->source_position);
+ &conditional->source_position);
skip_mode = true;
return;
}