diff --git a/cc_macro.c b/cc_macro.c index 01240f8..1d7dfb4 100644 --- a/cc_macro.c +++ b/cc_macro.c @@ -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; + } } } } diff --git a/test/test.answers b/test/test.answers index 5de1a78..228be68 100644 --- a/test/test.answers +++ b/test/test.answers @@ -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 diff --git a/test/test1000/proof.answer b/test/test1000/proof.answer index c138c20..7d87551 100644 --- a/test/test1000/proof.answer +++ b/test/test1000/proof.answer @@ -1 +1 @@ -21f64ec000afd8b05c10532c51806c04eee2120ece05141fa7c0c6fab5e56869 test/test1000/proof +cb2ed985d814d493cd376d89ef5471d66cfd76d78a7bb22fffbb076df44e0aa9 test/test1000/proof