fmacro # and ##

This commit is contained in:
pommicket 2022-01-09 17:37:23 -05:00
parent 2bb803e673
commit 2214ea4017
2 changed files with 51 additions and 17 deletions

View file

@ -1,4 +1,4 @@
#define TEST(x,y,z) x hello y there z #define TEST(x,y,z) x##y#z
TEST((55,(33,3)),22,(3,49)) TEST(22,4594,hello there folks)
main(void) { main(void) {
} }

View file

@ -729,7 +729,38 @@ function macro_replacement
pptoken_copy_and_advance(&p, &fmacro_out) pptoken_copy_and_advance(&p, &fmacro_out)
goto freplace_loop goto freplace_loop
:freplace_hash_operator :freplace_hash_operator
; don't output # / ## tokens ; handle paste and stringify operators
; NOTE: we already ensured that there's no spaces following #,
; and no spaces surrounding ## in split_into_preprocessing_tokens
p += 1
if *1p == '# goto freplace_hashhash_operator
; stringify operator
p += 1 ; skip null separator following #
q = fmacro_get_arg(filename, line_number, arguments, *1p)
*1fmacro_out = '"
fmacro_out += 1
; @NONSTANDARD: this doesn't work if the argument contains " or \
:fmacro_stringify_loop
c = *1q
q += 1
if c == 255 goto fmacro_stringify_loop_end
if c == 0 goto fmacro_stringify_loop
*1fmacro_out = c
fmacro_out += 1
goto fmacro_stringify_loop
:fmacro_stringify_loop_end
*1fmacro_out = '"
fmacro_out += 1
*1fmacro_out = 0
fmacro_out += 1
p += 2 ; skip arg idx & null separator
goto freplace_loop
:freplace_hashhash_operator
; the paste operator (e.g. #define JOIN(a,b) a##b)
; wow! surprisingly simple!
fmacro_out -= 1
pptoken_skip(&p) pptoken_skip(&p)
goto freplace_loop goto freplace_loop
:freplace_loop_end :freplace_loop_end
@ -747,19 +778,7 @@ function macro_replacement
:fmacro_argument :fmacro_argument
; write argument to *fmacro_out ; write argument to *fmacro_out
local arg_idx q = fmacro_get_arg(filename, line_number, arguments, *1p)
arg_idx = *1p
q = arguments
:fmacro_argfind_loop
if *1q == 255 goto fmacro_too_few_arguments
if arg_idx == 1 goto fmacro_arg_found
q = memchr(q, 255)
q += 1
arg_idx -= 1
goto fmacro_argfind_loop
:fmacro_arg_found
; q = argument
fmacro_out = memccpy(fmacro_out, q, 255) fmacro_out = memccpy(fmacro_out, q, 255)
*1fmacro_out = 0 *1fmacro_out = 0
p += 2 ; skip arg idx & null separator p += 2 ; skip arg idx & null separator
@ -781,12 +800,27 @@ function macro_replacement
:str_empty_fmacro_invocation :str_empty_fmacro_invocation
string No arguments provided to function-like macro. string No arguments provided to function-like macro.
byte 0 byte 0
function fmacro_get_arg
argument filename
argument line_number
argument arguments
argument arg_idx
:fmacro_argfind_loop
if *1arguments == 255 goto fmacro_too_few_arguments
if arg_idx == 1 goto fmacro_arg_found
arguments = memchr(arguments, 255)
arguments += 1
arg_idx -= 1
goto fmacro_argfind_loop
:fmacro_arg_found
return arguments
:fmacro_too_few_arguments :fmacro_too_few_arguments
compile_error(filename, line_number, .str_fmacro_too_few_arguments) compile_error(filename, line_number, .str_fmacro_too_few_arguments)
:str_fmacro_too_few_arguments :str_fmacro_too_few_arguments
string Too few arguments to function-like macro. string Too few arguments to function-like macro.
byte 0 byte 0
function fmacro_arg_end function fmacro_arg_end
argument filename argument filename
argument line_number argument line_number