summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-01-09 00:08:29 -0500
committerpommicket <pommicket@gmail.com>2022-01-09 00:08:29 -0500
commit807a6aacf9d05f194944f32386b2e8cd71c1dd5a (patch)
tree3bf752f86af763d5d049d20cf9df4cf4a7dfb5c6
parent4d5a5d9d972758d67db930c2d421d4067304d2ee (diff)
object-like macro replacement working?
-rw-r--r--05/main.b4
-rw-r--r--05/main.c30
-rw-r--r--05/preprocess.b69
3 files changed, 76 insertions, 27 deletions
diff --git a/05/main.b b/05/main.b
index 4d83223..041979e 100644
--- a/05/main.b
+++ b/05/main.b
@@ -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)
diff --git a/05/main.c b/05/main.c
index 4d48c66..3186a09 100644
--- a/05/main.c
+++ b/05/main.c
@@ -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