preprocessor fixes

This commit is contained in:
pommicket 2022-01-09 19:53:18 -05:00
parent a2e594c9be
commit 6ce6f76cc1
2 changed files with 28 additions and 18 deletions

View file

@ -4,17 +4,17 @@
#define JOIN(x,y) JOIN2(x, y) #define JOIN(x,y) JOIN2(x, y)
#define X 22 #define X 22
JOIN2(X, X) JOIN(X, X)
STRINGIFY(X) STRINGIFY(X)
#define E 5 #define E 5
#define D E #define D E
#define C D #define C D
#define B C #define B C
#define A B #define A B
int x = E; int x = E;
main(void) { main(void) {
} }

View file

@ -1,7 +1,7 @@
; returns a string of null character-separated preprocessing tokens and space characters ; returns a string of null character-separated preprocessing tokens and space characters
; this corresponds to translation phases 1-3 in the C89 standard ; this corresponds to translation phases 1-3 in the C89 standard
; each sequence of two or more spaces is replaced with a single space ; each sequence of two or more spaces is replaced with a single space
; spaces following # and around ## are removed ; spaces around # and ## are removed
function split_into_preprocessing_tokens function split_into_preprocessing_tokens
argument filename argument filename
local fd local fd
@ -338,31 +338,30 @@ function split_into_preprocessing_tokens
:join_spaces_loop_end :join_spaces_loop_end
*1out = 0 *1out = 0
; delete space surrounding ## and following # ; delete space surrounding ## and #
; we want to delete spaces before # so that all preprocessor directives are at the start of the line
; (this makes recognizing them slightly easier)
in = pptokens2 in = pptokens2
out = pptokens out = pptokens
:delete_hash_spaces_loop :delete_hash_spaces_loop
c = *1in c = *1in
if c == 0 goto delete_hash_spaces_loop_end if c == 0 goto delete_hash_spaces_loop_end
pptoken_copy_and_advance(&in, &out)
if c == '# goto delete_hash_spaces_hash if c == '# goto delete_hash_spaces_hash
pptoken_copy_and_advance(&in, &out)
goto delete_hash_spaces_loop
:delete_hash_spaces_hash :delete_hash_spaces_hash
p = in + 1 if out == pptokens goto copy_and_delete_spaces_after_hash ; little edge case
if *1p == '# goto delete_surrounding_space p = out - 2
:delete_hash_spaces_skip_spaces if *1p != 32 goto copy_and_delete_spaces_after_hash ; no space before ##
pptoken_skip_spaces(&in) ; space before #/##
goto delete_hash_spaces_loop
:delete_surrounding_space
p = out - 2 ; ## can't appear at start of file
if *1p != 32 goto delete_hash_spaces_skip_spaces ; no space before ##
; space before ##
; remove it ; remove it
out -= 2 out -= 2
*1out = 0 *1out = 0
goto delete_hash_spaces_skip_spaces :copy_and_delete_spaces_after_hash
pptoken_copy_and_advance(&in, &out)
pptoken_skip_spaces(&in)
goto delete_hash_spaces_loop
:delete_hash_spaces_loop_end :delete_hash_spaces_loop_end
*1out = 0 *1out = 0
@ -829,6 +828,10 @@ function macro_replacement
goto done_replacement goto done_replacement
:fmacro_argument :fmacro_argument
q = p + 3 ; skip these characters: arg idx, null separator, first '#'
if *1q == '# goto fmacro_argument_no_rescan ; this argument is immediately followed by ## so it shouldn't be scanned for replacements
q = p - 2 ; skip these characters: null separator, second '#'
if *1q == '# goto fmacro_argument_no_rescan ; this argument is immediately preceded by ##
; write argument to *fmacro_out, performing any necessary macro substitutions ; write argument to *fmacro_out, performing any necessary macro substitutions
q = fmacro_get_arg(filename, line_number, arguments, *1p) q = fmacro_get_arg(filename, line_number, arguments, *1p)
:fmacro_arg_replace_loop :fmacro_arg_replace_loop
@ -837,6 +840,13 @@ function macro_replacement
p += 2 ; skip arg idx & null separator p += 2 ; skip arg idx & null separator
goto freplace_loop goto freplace_loop
:fmacro_argument_no_rescan
q = fmacro_get_arg(filename, line_number, arguments, *1p)
fmacro_out = memccpy(fmacro_out, q, 255)
*1fmacro_out = 0
p += 2 ; skip arg idx & null separator
goto freplace_loop
:no_replacement :no_replacement
pptoken_copy_and_advance(&in, &out) pptoken_copy_and_advance(&in, &out)
; (fallthrough) ; (fallthrough)