diff options
author | pommicket <pommicket@gmail.com> | 2022-01-09 18:39:16 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-09 18:39:16 -0500 |
commit | a2e594c9befaacf521935d39bb9914cce2de43f3 (patch) | |
tree | c0d0309d017dc3ed0cd1def9d1374a3bbd41bb02 | |
parent | 141bc9e49a9b0f2798e6c2feaf7a9d893d8764d8 (diff) |
almost done # and ##
-rw-r--r-- | 05/main.c | 8 | ||||
-rw-r--r-- | 05/preprocess.b | 58 |
2 files changed, 61 insertions, 5 deletions
@@ -1,8 +1,12 @@ -#define STRINGIFY2(x) #x +#define STRINGIFY2(x) # x #define STRINGIFY(x) STRINGIFY2(x) +#define JOIN2(x,y) x ## y +#define JOIN(x,y) JOIN2(x, y) #define X 22 -STRINGIFY(X) +JOIN2(X, X) + +STRINGIFY(X) #define E 5 #define D E diff --git a/05/preprocess.b b/05/preprocess.b index d932161..6103454 100644 --- a/05/preprocess.b +++ b/05/preprocess.b @@ -1,10 +1,13 @@ -; returns a string of null character-separated preprocessing tokens +; returns a string of null character-separated preprocessing tokens and space characters ; this corresponds to translation phases 1-3 in the C89 standard +; each sequence of two or more spaces is replaced with a single space +; spaces following # and around ## are removed function split_into_preprocessing_tokens argument filename local fd local file_contents local pptokens + local pptokens2 local p local b local c @@ -316,7 +319,54 @@ function split_into_preprocessing_tokens goto pptokens_loop :pptokens_loop_end - free(file_contents) + pptokens2 = file_contents ; repurpose file contents + + ; replace each sequence of two or more spaces with a single space + ; "Whether each nonempty sequence of other white-space characters is + ; retained or replaced by one space character is implementation-defined." (C89 ยง 2.1.1.2) + in = pptokens + out = pptokens2 + :join_spaces_loop + if *1in == 0 goto join_spaces_loop_end + c = *1in + pptoken_copy_and_advance(&in, &out) + if c == 32 goto join_spaces + goto join_spaces_loop + :join_spaces + pptoken_skip_spaces(&in) + goto join_spaces_loop + :join_spaces_loop_end + *1out = 0 + + ; delete space surrounding ## and following # + in = pptokens2 + out = pptokens + :delete_hash_spaces_loop + c = *1in + if c == 0 goto delete_hash_spaces_loop_end + pptoken_copy_and_advance(&in, &out) + if c == '# goto delete_hash_spaces_hash + + :delete_hash_spaces_hash + p = in + 1 + if *1p == '# goto delete_surrounding_space + :delete_hash_spaces_skip_spaces + pptoken_skip_spaces(&in) + 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 + out -= 2 + *1out = 0 + goto delete_hash_spaces_skip_spaces + + :delete_hash_spaces_loop_end + *1out = 0 + + free(pptokens2) close(fd) return pptokens @@ -444,7 +494,7 @@ function translation_phase_4 goto phase4_line :phase4_try_replacements macro_replacement(filename, line_number, &in, &out) - goto phase4_line + goto process_pptoken :pp_directive pptoken_skip(&in) ; skip # pptoken_skip_spaces(&in) @@ -454,6 +504,8 @@ function translation_phase_4 if b != 0 goto pp_directive_error b = str_equals(in, .str_define) if b != 0 goto pp_directive_define + puts(in) + putc(10) goto unrecognized_directive :pp_directive_error fputs(2, filename) |