summaryrefslogtreecommitdiff
path: root/04
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-01-07 11:29:37 -0500
committerpommicket <pommicket@gmail.com>2022-01-07 11:30:14 -0500
commit479ff20704ecfb9e78dda1d52375368fbafbabbd (patch)
tree65a0f82549baed7a63ef0712eab345dac70b5ef2 /04
parent519069a89df7f2f704b9ba7052fc80660817115f (diff)
add 04 to bootstrap, #line
Diffstat (limited to '04')
-rw-r--r--04/README.md3
-rw-r--r--04/in0381
2 files changed, 76 insertions, 8 deletions
diff --git a/04/README.md b/04/README.md
index 6f638b6..a0a7f8d 100644
--- a/04/README.md
+++ b/04/README.md
@@ -212,6 +212,9 @@ conditionally jump to the specified label. `{operator}` should be one of
- `return {rvalue}`
- `string {str}` - places a literal string in the code
- `byte {number}` - places a literal byte in the code
+- `#line {line number} {filename}` / `#line {line number}` - set line number and optionally the filename for future errors (no code is outputted from this)
+
+The `#line` directive (which also exists in C) seems a bit strange, but its use will be revealed soon.
Now let's get down into the weeds:
diff --git a/04/in03 b/04/in03
index c2f45ef..6daf3c5 100644
--- a/04/in03
+++ b/04/in03
@@ -16,6 +16,13 @@ I=8S
A=d2
?I>A:argv_file_names
; use default input/output filenames
+
+ ; set :filename appropriately
+ J=:filename
+ I=:input_filename
+ C=d0
+ call :memccpy
+
; open input file
J=:input_filename
I=d0
@@ -30,7 +37,18 @@ A=d2
J=A
?J<0:output_file_error
!:second_pass_starting_point
-:argv_file_names
+:argv_file_names
+ ; get filenames from command-line arguments
+
+ ; set :filename appropriately
+ I=S
+ ; argv[1] is at *(rsp+16)
+ I+=d16
+ I=8I
+ J=:filename
+ C=d0
+ call :memccpy
+
; open input file
J=S
; argv[1] is at *(rsp+16)
@@ -174,6 +192,13 @@ D=A
?D!0:handle_string
I=:line
+J=:"#line"
+C=x20
+call :string=
+D=A
+?D!0:handle_#line
+
+I=:line
J=:"goto"
C=x20
call :string=
@@ -275,13 +300,18 @@ align
; 5 = length of "byte "
I+=d5
call :read_number
+ ; store away number in rbp
+ R=A
+ ; make sure number is immediately followed by newline
+ C=1I
+ D=xa
+ ?C!D:bad_number
; make sure byte is 0-255
- C=A
D=xff
- ?CaD:bad_byte
+ ?RaD:bad_byte
; write byte
I=:byte
- 1I=C
+ 1I=R
J=d4
D=d1
syscall x1
@@ -289,6 +319,35 @@ align
:byte
reserve d1
+:handle_#line
+ I=:line
+ ; 6 = length of "#line "
+ I+=d6
+ call :read_number
+ ; store line number
+ D=A
+ C=:line_number
+ ; subtract one so that we specify the number of the *next* line
+ D-=d1
+ 8C=D
+ ; check character after line number
+ C=1I
+ D=xa
+ ; if it's a newline, we're done
+ ?C=D:read_line
+ ; otherwise, it'd better be a space
+ D=x20
+ ?C!D:bad_statement
+ ; set the filename
+ I+=d1
+ J=:filename
+ C=xa
+ call :memccpy
+ ; we want a null-terminated, not newline-terminated filename
+ J-=d1
+ 1J=0
+ !:read_line
+
:handle_string
I=:line
; 7 = length of "string "
@@ -2139,7 +2198,9 @@ align
:program_error
R=B
- B=:"Line"
+ B=:filename
+ call :eputs
+ B=:":"
call :eputs
D=:line_number
@@ -2155,9 +2216,8 @@ align
J=d1
syscall x3c
-:"Line"
- str Line
- x20
+:":"
+ str :
x0
:line_number_separator
@@ -2346,6 +2406,9 @@ align
:"string"
str string
x20
+:"#line"
+ str #line
+ x20
:"goto"
str goto
x20
@@ -2408,6 +2471,8 @@ align
reserve d8
:line_number
reserve d8
+:filename
+ reserve d80
:global_variables
reserve d50000
:local_variables