diff options
author | pommicket <pommicket@gmail.com> | 2022-01-09 00:08:29 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-09 00:08:29 -0500 |
commit | 807a6aacf9d05f194944f32386b2e8cd71c1dd5a (patch) | |
tree | 3bf752f86af763d5d049d20cf9df4cf4a7dfb5c6 | |
parent | 4d5a5d9d972758d67db930c2d421d4067304d2ee (diff) |
object-like macro replacement working?
-rw-r--r-- | 05/main.b | 4 | ||||
-rw-r--r-- | 05/main.c | 30 | ||||
-rw-r--r-- | 05/preprocess.b | 69 |
3 files changed, 76 insertions, 27 deletions
@@ -45,6 +45,8 @@ function main local output_filename local pptokens + dat_banned_macros = 255 + object_macros = malloc(4000000) function_macros = malloc(4000000) @@ -59,7 +61,7 @@ function main print_pptokens(pptokens) print_separator() pptokens = translation_phase_4(input_filename, pptokens) - ;print_pptokens(pptokens) + print_pptokens(pptokens) print_object_macros() print_function_macros() exit(0) @@ -1,22 +1,10 @@ --#include <stdio.h> +#define B A C A B A +#define A helo what +#define C how is it going -int test(int, double, ...);\ -/* here is a nice -comment it is -here -*/ -# -#define A(_Hello, there, everyone ) 33 + _Hello - everyone * there -#define B(x, y, z) 58 -#define C(hello) hello * hello + hello / hello -#define A 22 -#define C 33 -#define _Hello_there5 -76 + sqrt(A) -int main(void) { - printf("\"Hello, world!%c\n\"", '\''); - _X55 = Y4_C_; - a.b = c; - 5 + (.3e+5+6) & 0xff | 93 -~5; - return 0; -} -#define _Hello_there 18 +#define D E +#define E D +B ! + +D +E diff --git a/05/preprocess.b b/05/preprocess.b index ba4fdbf..2b5ca93 100644 --- a/05/preprocess.b +++ b/05/preprocess.b @@ -431,13 +431,18 @@ function translation_phase_4 if c == 10 goto phase4_next_line b = isdigit(c) if b != 0 goto phase4_next_pptoken - + b = isalnum_or_underscore(c) + if b != 0 goto phase4_try_replacements + ; (fallthrough) :phase4_next_pptoken pptoken_copy_and_advance(&in, &out) goto process_pptoken :phase4_next_line pptoken_copy_and_advance(&in, &out) goto phase4_line + :phase4_try_replacements + macro_replacement(&in, &out) + goto phase4_line :pp_directive pptoken_skip(&in) ; skip # pptoken_skip_spaces(&in) @@ -477,8 +482,7 @@ function translation_phase_4 *1p = 255 ; replace newline with special "macro end" character p += 1 object_macros_size = p - object_macros - in += 2 ; skip newline and following null character - goto phase4_line + goto phase4_next_line :function_macro_definition ; a function-like macro, e.g. #define JOIN(a,b) a##b local param_names @@ -546,8 +550,7 @@ function translation_phase_4 p += 1 function_macros_size = p - function_macros free(param_names) - in += 2 ; skip newline and following null character - goto phase4_line + goto phase4_next_line :str_directive_error string : #error byte 10 @@ -605,6 +608,62 @@ function look_up_function_macro argument name return look_up_macro(function_macros, name) +function macro_replacement + argument p_in + argument p_out + global 2000 dat_banned_macros ; 255-terminated array of strings (initialized in main) + local old_banned_macros_end + local banned_macros + local b + local p + local replacement + local in + local out + + in = *8p_in + out = *8p_out + + ; "banned" macros prevent #define x x from being a problem + ; C89 ยง 3.8.3.4 + ; "If the name of the macro being replaced is found during this scan + ; of the replacement list, it is not replaced. Further, if any nested + ; replacements encounter the name of the macro being replaced, it is not replaced." + + banned_macros = &dat_banned_macros + p = banned_macros + + old_banned_macros_end = memchr(banned_macros, 255) + + :check_banned_macros_loop + if *1p == 255 goto check_banned_macros_loop_end + b = str_equals(in, p) + if b != 0 goto no_replacement + p = memchr(p, 0) + p += 1 + goto check_banned_macros_loop + :check_banned_macros_loop_end + + p = strcpy(old_banned_macros_end, in) + p += 1 + *1p = 255 + replacement = look_up_object_macro(in) + if replacement == 0 goto no_replacement + p = replacement + pptoken_skip(&in) + :objreplace_loop + if *1p == 255 goto objreplace_loop_end + macro_replacement(&p, &out) + goto objreplace_loop + :no_replacement + pptoken_copy_and_advance(&in, &out) + ; (fallthrough) + :objreplace_loop_end + *8p_in = in + *8p_out = out + ; unban this macro + *1old_banned_macros_end = 255 + return + function print_object_macros print_macros(object_macros) return |