aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/preprocess.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/preprocess.c')
-rw-r--r--src/preprocess.c118
1 files changed, 65 insertions, 53 deletions
diff --git a/src/preprocess.c b/src/preprocess.c
index 2a53059..8890800 100644
--- a/src/preprocess.c
+++ b/src/preprocess.c
@@ -575,6 +575,39 @@ static Token* next_pp_token(Preprocessor* pp) {
return pp_token_at(pp, pp->pos++);
}
+static void skip_pp_token(Preprocessor* pp, TokenKind expected) {
+ Token* tok = next_pp_token(pp);
+ // TODO: currently function-like macro expansion supports only one token.
+ // assert(tok->kind == expected);
+ BOOL ok = tok->kind == expected;
+ assert(ok);
+}
+
+static Token* consume_pp_token_if(Preprocessor* pp, TokenKind expected) {
+ if (peek_pp_token(pp)->kind == expected) {
+ return next_pp_token(pp);
+ } else {
+ return NULL;
+ }
+}
+
+static Token* consume_pp_token_if_not(Preprocessor* pp, TokenKind non_expected) {
+ if (peek_pp_token(pp)->kind == non_expected) {
+ return NULL;
+ } else {
+ return next_pp_token(pp);
+ }
+}
+
+static Token* expect_pp_token(Preprocessor* pp, TokenKind expected) {
+ Token* tok = next_pp_token(pp);
+ if (tok->kind == expected) {
+ return tok;
+ }
+ fatal_error("%s:%d: expected '%s', but got '%s'", tok->loc.filename, tok->loc.line, token_kind_stringify(expected),
+ token_stringify(tok));
+}
+
static BOOL pp_eof(Preprocessor* pp) {
return peek_pp_token(pp)->kind == TokenKind_eof;
}
@@ -606,19 +639,14 @@ static BOOL skip_pp_tokens(Preprocessor* pp) {
}
static void skip_whitespaces(Preprocessor* pp) {
- while (!pp_eof(pp) && peek_pp_token(pp)->kind == TokenKind_whitespace) {
- next_pp_token(pp);
- }
+ while (!pp_eof(pp) && consume_pp_token_if(pp, TokenKind_whitespace))
+ ;
}
+// It will not consume a new-line token.
static void seek_to_next_newline(Preprocessor* pp) {
- while (!pp_eof(pp)) {
- Token* tok = peek_pp_token(pp);
- if (tok->kind == TokenKind_newline) {
- break;
- }
- next_pp_token(pp);
- }
+ while (!pp_eof(pp) && consume_pp_token_if_not(pp, TokenKind_newline))
+ ;
}
static void make_token_whitespace(Token* tok) {
@@ -633,13 +661,13 @@ static void remove_directive_tokens(Preprocessor* pp, int start, int end) {
}
static void process_endif_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_endif);
pp->skip_pp_tokens = FALSE;
remove_directive_tokens(pp, directive_token_pos, pp->pos);
}
static void process_else_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_else);
pp->skip_pp_tokens = !pp->skip_pp_tokens;
remove_directive_tokens(pp, directive_token_pos, pp->pos);
}
@@ -652,7 +680,7 @@ static int replace_pp_tokens(Preprocessor*, int, int, TokenArray*);
static BOOL expand_macro(Preprocessor*);
static void process_if_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_if);
int condition_expression_start_pos = pp->pos;
while (!pp_eof(pp)) {
@@ -664,11 +692,10 @@ static void process_if_directive(Preprocessor* pp, int directive_token_pos) {
int defined_pos = pp->pos;
// 'defined' <ws>* '(' <ws>* <ident> <ws>* ')'
// 'defined' <ws>* <ident>
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_ident);
skip_whitespaces(pp);
Token* macro_name;
- if (peek_pp_token(pp)->kind == TokenKind_paren_l) {
- next_pp_token(pp);
+ if (consume_pp_token_if(pp, TokenKind_paren_l)) {
skip_whitespaces(pp);
macro_name = next_pp_token(pp);
if (macro_name->kind != TokenKind_ident) {
@@ -735,22 +762,20 @@ static void process_if_directive(Preprocessor* pp, int directive_token_pos) {
}
static void process_ifdef_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_ifdef);
skip_whitespaces(pp);
- Token* macro_name = peek_pp_token(pp);
- if (macro_name->kind == TokenKind_ident) {
- next_pp_token(pp);
+ Token* macro_name = consume_pp_token_if(pp, TokenKind_ident);
+ if (macro_name) {
pp->skip_pp_tokens = find_macro(pp, macro_name->value.string) == -1;
}
remove_directive_tokens(pp, directive_token_pos, pp->pos);
}
static void process_ifndef_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_ifndef);
skip_whitespaces(pp);
- Token* macro_name = peek_pp_token(pp);
- if (macro_name->kind == TokenKind_ident) {
- next_pp_token(pp);
+ Token* macro_name = consume_pp_token_if(pp, TokenKind_ident);
+ if (macro_name) {
pp->skip_pp_tokens = find_macro(pp, macro_name->value.string) != -1;
}
remove_directive_tokens(pp, directive_token_pos, pp->pos);
@@ -829,7 +854,7 @@ static void expand_include_directive(Preprocessor* pp, int directive_token_pos,
}
static void process_include_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_include);
skip_whitespaces(pp);
Token* include_name = read_include_header_name(pp);
const char* include_name_resolved = resolve_include_name(pp, include_name);
@@ -847,12 +872,11 @@ static TokenArray* pp_parse_macro_parameters(Preprocessor* pp) {
// '(' is consumed by caller.
skip_whitespaces(pp);
- Token* tok = next_pp_token(pp);
- if (tok->kind == TokenKind_ident) {
+ Token* tok = consume_pp_token_if(pp, TokenKind_ident);
+ if (tok) {
*tokens_push_new(parameters) = *tok;
skip_whitespaces(pp);
- while (peek_pp_token(pp)->kind == TokenKind_comma) {
- next_pp_token(pp);
+ while (consume_pp_token_if(pp, TokenKind_comma)) {
skip_whitespaces(pp);
tok = next_pp_token(pp);
if (tok->kind != TokenKind_ident) {
@@ -860,17 +884,14 @@ static TokenArray* pp_parse_macro_parameters(Preprocessor* pp) {
}
*tokens_push_new(parameters) = *tok;
}
- tok = next_pp_token(pp);
- }
- if (tok->kind != TokenKind_paren_r) {
- fatal_error("%s:%d: invalid macro syntax", tok->loc.filename, tok->loc.line);
}
+ expect_pp_token(pp, TokenKind_paren_r);
return parameters;
}
static void process_define_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_define);
skip_whitespaces(pp);
Token* macro_name = next_pp_token(pp);
@@ -878,8 +899,7 @@ static void process_define_directive(Preprocessor* pp, int directive_token_pos)
fatal_error("%s:%d: invalid #define syntax", macro_name->loc.filename, macro_name->loc.line);
}
- if (peek_pp_token(pp)->kind == TokenKind_paren_l) {
- next_pp_token(pp);
+ if (consume_pp_token_if(pp, TokenKind_paren_l)) {
TokenArray* parameters = pp_parse_macro_parameters(pp);
int replacements_start_pos = pp->pos;
seek_to_next_newline(pp);
@@ -914,11 +934,10 @@ static void process_define_directive(Preprocessor* pp, int directive_token_pos)
}
static void process_undef_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_undef);
skip_whitespaces(pp);
- Token* macro_name = peek_pp_token(pp);
- if (macro_name->kind == TokenKind_ident) {
- next_pp_token(pp);
+ Token* macro_name = consume_pp_token_if(pp, TokenKind_ident);
+ if (macro_name) {
int macro_idx = find_macro(pp, macro_name->value.string);
if (macro_idx != -1) {
undef_macro(pp, macro_idx);
@@ -940,7 +959,7 @@ static void process_pragma_directive(Preprocessor* pp, int directive_token_pos)
}
static void process_nop_directive(Preprocessor* pp, int directive_token_pos) {
- next_pp_token(pp);
+ skip_pp_token(pp, TokenKind_pp_directive_nop);
remove_directive_tokens(pp, directive_token_pos, pp->pos);
}
@@ -949,30 +968,23 @@ static void process_nop_directive(Preprocessor* pp, int directive_token_pos) {
static MacroArgArray* pp_parse_macro_arguments(Preprocessor* pp) {
MacroArgArray* args = macroargs_new();
- Token* tok = next_pp_token(pp);
- if (tok->kind != TokenKind_paren_l) {
- fatal_error("%s:%d: invalid macro syntax", tok->loc.filename, tok->loc.line);
- }
+ expect_pp_token(pp, TokenKind_paren_l);
skip_whitespaces(pp);
- tok = next_pp_token(pp);
- if (tok->kind != TokenKind_paren_r) {
+ Token* tok = consume_pp_token_if_not(pp, TokenKind_paren_r);
+ if (tok) {
MacroArg* arg = macroargs_push_new(args);
tokens_init(&arg->tokens, 1);
*tokens_push_new(&arg->tokens) = *tok;
skip_whitespaces(pp);
- while (peek_pp_token(pp)->kind == TokenKind_comma) {
- next_pp_token(pp);
+ while (consume_pp_token_if(pp, TokenKind_comma)) {
skip_whitespaces(pp);
tok = next_pp_token(pp);
arg = macroargs_push_new(args);
tokens_init(&arg->tokens, 1);
*tokens_push_new(&arg->tokens) = *tok;
}
- tok = next_pp_token(pp);
- }
- if (tok->kind != TokenKind_paren_r) {
- fatal_error("%s:%d: invalid macro syntax", tok->loc.filename, tok->loc.line);
}
+ expect_pp_token(pp, TokenKind_paren_r);
return args;
}