Add defined() macro operator

This commit is contained in:
Rui Ueyama 2020-08-31 16:50:58 +09:00
parent 769b5a0941
commit 5cb2f89e6a
2 changed files with 70 additions and 1 deletions

View File

@ -66,6 +66,7 @@ static Macro *macros;
static CondIncl *cond_incl;
static Token *preprocess2(Token *tok);
static Macro *find_macro(Token *tok);
static bool is_hash(Token *tok) {
return tok->at_bol && equal(tok, "#");
@ -232,10 +233,48 @@ static Token *copy_line(Token **rest, Token *tok) {
return head.next;
}
static Token *new_num_token(int val, Token *tmpl) {
char *buf = format("%d\n", val);
return tokenize(new_file(tmpl->file->name, tmpl->file->file_no, buf));
}
static Token *read_const_expr(Token **rest, Token *tok) {
tok = copy_line(rest, tok);
Token head = {};
Token *cur = &head;
while (tok->kind != TK_EOF) {
// "defined(foo)" or "defined foo" becomes "1" if macro "foo"
// is defined. Otherwise "0".
if (equal(tok, "defined")) {
Token *start = tok;
bool has_paren = consume(&tok, tok->next, "(");
if (tok->kind != TK_IDENT)
error_tok(start, "macro name must be an identifier");
Macro *m = find_macro(tok);
tok = tok->next;
if (has_paren)
tok = skip(tok, ")");
cur = cur->next = new_num_token(m ? 1 : 0, start);
continue;
}
cur = cur->next = tok;
tok = tok->next;
}
cur->next = tok;
return head.next;
}
// Read and evaluate a constant expression.
static long eval_const_expr(Token **rest, Token *tok) {
Token *start = tok;
Token *expr = copy_line(rest, tok->next);
Token *expr = read_const_expr(rest, tok->next);
expr = preprocess2(expr);
if (expr->kind == TK_EOF)

View File

@ -253,6 +253,36 @@ int main() {
#define paste4(x, y, z) x##y##z
ASSERT(123, paste4(1,2,3));
#define M12
#if defined(M12)
m = 3;
#else
m = 4;
#endif
ASSERT(3, m);
#define M12
#if defined M12
m = 3;
#else
m = 4;
#endif
ASSERT(3, m);
#if defined(M12) - 1
m = 3;
#else
m = 4;
#endif
ASSERT(4, m);
#if defined(NO_SUCH_MACRO)
m = 3;
#else
m = 4;
#endif
ASSERT(4, m);
printf("OK\n");
return 0;
}