Add support for conditional inclusion

- support for #if, #elif, #else, #endif, but no macro expansion just
  yet. Any macro is treated as undefined and expands to 0.

for example:
./bin/M2-Planet -E test.c

 #if 1 == FOO
foo
 #else
bar
 #endif

results in

bar
This commit is contained in:
Sanne Wouda 2021-01-05 20:17:25 +00:00
parent cd96f65a23
commit 89c6513cd8
3 changed files with 247 additions and 14 deletions

View File

@ -18,6 +18,15 @@
#include "gcc_req.h"
void require(int bool, char* error);
int numerate_string(char *a);
struct conditional_inclusion {
struct conditional_inclusion* prev;
int include; /* 1 == include, 0 == skip */
int previous_condition_matched; /* 1 == all subsequent conditions treated as FALSE */
};
struct conditional_inclusion *conditional_inclusion_top;
/* point where we are currently modifying the global_token list */
struct token_list* macro_token;
@ -56,18 +65,230 @@ void eat_newline_tokens()
}
}
void macro_directive()
int macro_expression();
int macro_variable()
{
/* unhandled macro directive; let's eat until a newline; om nom nom */
while (TRUE)
eat_current_token();
return 0;
}
int macro_number()
{
int result = numerate_string(macro_token->s);
eat_current_token();
return result;
}
int macro_primary_expr()
{
if ('-' == macro_token->s[0])
{
eat_current_token();
return -macro_primary_expr();
}
else if ('!' == macro_token->s[0])
{
eat_current_token();
return !macro_primary_expr();
}
else if ('(' == macro_token->s[0])
{
eat_current_token();
return macro_expression();
} else if (in_set(macro_token->s[0], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"))
return macro_variable();
else if (in_set(macro_token->s[0], "0123456789"))
return macro_number();
else
return 0; /* FIXME: error handling */
}
if (NULL == macro_token)
return;
int macro_additive_expr()
{
int lhs = macro_primary_expr();
if ('\n' == macro_token->s[0])
return;
if (match("+", macro_token->s))
{
eat_current_token();
return lhs + macro_additive_expr();
}
else if (match("-", macro_token->s))
{
eat_current_token();
return lhs - macro_additive_expr();
}
else if (match("*", macro_token->s))
{
eat_current_token();
return lhs * macro_additive_expr();
}
else if (match("/", macro_token->s))
{
eat_current_token();
return lhs / macro_additive_expr();
}
else if (match("%", macro_token->s))
{
eat_current_token();
return lhs % macro_additive_expr();
}
else if (match(">>", macro_token->s))
{
eat_current_token();
return lhs >> macro_additive_expr();
}
else if (match("<<", macro_token->s))
{
eat_current_token();
return lhs << macro_additive_expr();
}
else
{
return lhs;
}
}
int macro_relational_expr()
{
int lhs = macro_additive_expr();
if (match("<", macro_token->s))
{
eat_current_token();
return lhs < macro_relational_expr();
}
else if (match("<=", macro_token->s))
{
eat_current_token();
return lhs <= macro_relational_expr();
}
else if (match(">=", macro_token->s))
{
eat_current_token();
return lhs >= macro_relational_expr();
}
else if (match(">", macro_token->s))
{
eat_current_token();
return lhs > macro_relational_expr();
}
else if (match("==", macro_token->s))
{
eat_current_token();
return lhs == macro_relational_expr();
}
else if (match("!=", macro_token->s))
{
eat_current_token();
return lhs != macro_relational_expr();
}
else
{
return lhs;
}
}
int macro_bitwise_expr()
{
int rhs;
int lhs = macro_relational_expr();
if (match("&", macro_token->s))
{
eat_current_token();
return lhs & macro_bitwise_expr();
}
else if (match("&&", macro_token->s))
{
eat_current_token();
rhs = macro_bitwise_expr();
return lhs && rhs;
}
else if (match("|", macro_token->s))
{
eat_current_token();
rhs = macro_bitwise_expr();
return lhs | rhs;
}
else if (match("||", macro_token->s))
{
eat_current_token();
rhs = macro_bitwise_expr();
return lhs || rhs;
}
else if (match("^", macro_token->s))
{
eat_current_token();
rhs = macro_bitwise_expr();
return lhs ^ rhs;
}
else
{
return lhs;
}
}
int macro_expression()
{
return macro_bitwise_expr();
}
void macro_directive()
{
struct conditional_inclusion *t;
int result;
/* FIXME: whitespace is allowed between "#"" and "if" */
if(match("#if", macro_token->s))
{
eat_current_token();
/* evaluate constant integer expression */
result = macro_expression();
/* push conditional inclusion */
t = calloc(1, sizeof(struct conditional_inclusion));
t->prev = conditional_inclusion_top;
conditional_inclusion_top = t;
t->include = TRUE;
if (FALSE == result)
{
t->include = FALSE;
}
t->previous_condition_matched = t->include;
}
else if (match("#elif", macro_token->s))
{
eat_current_token();
result = macro_expression();
conditional_inclusion_top->include = result && !conditional_inclusion_top->previous_condition_matched;
conditional_inclusion_top->previous_condition_matched =
conditional_inclusion_top->previous_condition_matched || conditional_inclusion_top->include;
}
else if (match("#else", macro_token->s))
{
eat_current_token();
conditional_inclusion_top->include = !conditional_inclusion_top->previous_condition_matched;
}
else if (match("#endif", macro_token->s))
{
eat_current_token();
/* pop conditional inclusion */
t = conditional_inclusion_top;
conditional_inclusion_top = conditional_inclusion_top->prev;
free(t);
}
else
{
/* unhandled macro directive; let's eat until a newline; om nom nom */
while (TRUE)
{
if (NULL == macro_token)
return;
if ('\n' == macro_token->s[0])
return;
eat_current_token();
}
}
}
@ -93,7 +314,19 @@ void preprocess()
else
{
start_of_line = FALSE;
macro_token = macro_token->next;
if (NULL == conditional_inclusion_top)
{
macro_token = macro_token->next;
}
else if (!conditional_inclusion_top->include)
{
/* rewrite the token stream to exclude the current token */
eat_current_token();
}
else
{
macro_token = macro_token->next;
}
}
}
}

View File

@ -169,8 +169,8 @@ a2a83f42119e646b389b98647cf6cf2aa9597185997c9453db746178c8c4c0bf test/results/t
698853b79efb30865a663c4863c050639eb21c7400008f7840830503928973d4 test/results/test0106-knight-native-binary
45c2ba61dc209d7ffa39de9ff0f0a7f8f3ea4d7e38598c72f982fcaf9a05c84a test/results/test0106-knight-posix-binary
944580ff4aae38aafac139faf6eed5bfe4ff68b01a7a3adfa346de8803101182 test/results/test0106-x86-binary
206905afbcc1ef41d5b241fb72381c0854792fedbbd467ea33c52728cc8946b6 test/results/test1000-aarch64-binary
85a238be594b0bbd3d2613872cc15315f5ad79f4491c424f006f1e98dc6234ef test/results/test1000-amd64-binary
27bf47331a04a42cae324da6862f21625c093ee27e9cf2504b1c6c80b98e814a test/results/test1000-armv7l-binary
e5102501c6939447a87084fd3853d55dcc32b80142efaa72b5f9305d80026b84 test/results/test1000-knight-posix-binary
c0c649496e3c5738667d3bef74a917253471e192b3e550152c083d1ccf579d09 test/results/test1000-x86-binary
5d0a41c3ec339d6413167ab9e87d8d3444863d1dc12883592ad23669654cb7ce test/results/test1000-aarch64-binary
37952a1f53e7859408bee89a5521cb3ef818363fa4bda682a3696c24fe7ff645 test/results/test1000-amd64-binary
8cf345632079de545b1fac3158c7a2d048fa64ec0fed927c4b1bbffabdef5b3f test/results/test1000-armv7l-binary
f761471e800c86dcbaa1be532a7a0ccd3f6100e76852891331adb171c64bc932 test/results/test1000-knight-posix-binary
f5662f155218f9e73d92cfa28bab8d12c6ed407a5662cf583299ac4f5ec71f95 test/results/test1000-x86-binary

View File

@ -1 +1 @@
21f64ec000afd8b05c10532c51806c04eee2120ece05141fa7c0c6fab5e56869 test/test1000/proof
cb2ed985d814d493cd376d89ef5471d66cfd76d78a7bb22fffbb076df44e0aa9 test/test1000/proof