summaryrefslogtreecommitdiff
path: root/05/preprocess.b
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-01-07 23:32:27 -0500
committerpommicket <pommicket@gmail.com>2022-01-07 23:32:27 -0500
commit5d6b490cce1a99a2541d1fcee101df4331d4d86a (patch)
tree902295cbd43a7a32e179412d98f75dd2705fd6db /05/preprocess.b
parent262824b21491446bb20acba8be1054207b5f50f0 (diff)
start C compiler
Diffstat (limited to '05/preprocess.b')
-rw-r--r--05/preprocess.b75
1 files changed, 75 insertions, 0 deletions
diff --git a/05/preprocess.b b/05/preprocess.b
new file mode 100644
index 0000000..36fcbd2
--- /dev/null
+++ b/05/preprocess.b
@@ -0,0 +1,75 @@
+; returns a string of null character-separated preprocessing tokens
+; this corresponds to translation phases 1-3 in the C89 standard
+function split_into_preprocessing_tokens
+ argument filename
+ local fd
+ local file_contents
+ local pptokens
+ local p
+ local c
+ local in
+ local out
+ local n
+
+ fd = open_r(filename)
+ file_contents = malloc(2000000)
+ pptokens = malloc(2000000)
+ p = file_contents
+ :pptokens_read_loop
+ n = syscall(0, fd, p, 4096)
+ if n == 0 goto pptokens_read_loop_end
+ p += n
+ :pptokens_read_loop_end
+
+ ; okay we read the file. first, delete every backslash-newline sequence (phase 2)
+ local newlines ; we add more newlines to keep line numbers right
+ newlines = 1
+ in = file_contents
+ out = file_contents
+ :backslashnewline_loop
+ c = *1in
+ if c == 0 goto backslashnewline_loop_end
+ if c == 10 goto proper_newline_loop
+ if c != '\ goto not_backslashnewline
+ p = in + 1
+ c = *1p
+ if c != 10 goto not_backslashnewline
+ in += 2 ; skip backlash and newline
+ newlines += 1 ; add one additional newline the next time around to compensate
+ goto backslashnewline_loop
+ :not_backslashnewline
+ *1out = *1in
+ out += 1
+ in += 1
+ goto backslashnewline_loop
+ :proper_newline_loop
+ if newlines == 0 goto proper_newline_loop_end
+ ; output a newline
+ *1out = 10
+ out += 1
+ newlines -= 1
+ goto proper_newline_loop
+ :proper_newline_loop_end
+ newlines = 1
+ in += 1
+ goto backslashnewline_loop
+ :backslashnewline_loop_end
+ *1out = 0
+
+ in = file_contents
+
+ fputs(1, file_contents)
+
+ free(file_contents)
+ close(fd)
+ return
+
+ :unterminated_comment
+ fputs(2, .str_unterminated_comment)
+ fputs(2, filename)
+ fputc(2, 10)
+ exit(1)
+ :str_unterminated_comment
+ string Unterminated comment in file
+ byte 32
+ byte 0