object-like macro replacement working?

This commit is contained in:
pommicket 2022-01-09 00:08:29 -05:00
parent 4d5a5d9d97
commit 807a6aacf9
3 changed files with 76 additions and 27 deletions

View file

@ -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)

View file

@ -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

View file

@ -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