Reading a script must not move the person who started it
A script is fetched a block at a time while its lines run, and its name is resolved afresh for every block. A name with a drive in front of it moves the machine to that drive on the way past - sbfsWalk calls sbfsUse - so a script found in the system's place on drive 0, started by somebody standing on a disk of their own, ran its lines on the system disk. Always possible with "do 0:/Apps/setup.sh", and reachable by typing a name now that the search finds scripts the same three places it finds programs. The drive is kept across each fetch and put back after it, at both places a script's name is resolved. The test has to work for it. A script that fits in one block is read entirely while it is being opened, and the opening was never the hard part; and the keep in scriptFill cannot be broken on its own, because scriptOpen has already written the variable down. So the script on the disk crosses two block boundaries and moves itself between them: what it says about where it is standing is 1 before the move and 0 after. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
fd962f0084
commit
06af7e7fbb
@@ -154,8 +154,10 @@ scriptOpenFirst:
|
||||
INIB 0d63
|
||||
CALL copyText
|
||||
|
||||
CALL scriptKeepDrive
|
||||
SETD.0 ScriptName
|
||||
SWI osFileInfo
|
||||
CALL scriptGiveDriveBack
|
||||
BRQ scriptOpenThere
|
||||
INIA 0x01
|
||||
BRI scriptOpenFailed
|
||||
@@ -426,6 +428,7 @@ scriptFill:
|
||||
OR
|
||||
BRQ scriptFillNoMore
|
||||
|
||||
CALL scriptKeepDrive
|
||||
SETD.0 ScriptName
|
||||
SETD.1 ScriptBlock
|
||||
SETD.2 ScriptIndex
|
||||
@@ -433,6 +436,7 @@ scriptFill:
|
||||
INCD.2
|
||||
LDB.2
|
||||
SWI osFileBlock
|
||||
CALL scriptGiveDriveBack
|
||||
BNQ scriptFillNoMore
|
||||
|
||||
; DP3 is how many bytes came back. The nought goes after them.
|
||||
@@ -488,6 +492,40 @@ scriptFillNoMore:
|
||||
ADD
|
||||
RET
|
||||
|
||||
; ---- Reading a script must not move the person ----
|
||||
;
|
||||
; The name is resolved afresh for every block, and a name with a drive in front of it moves
|
||||
; the machine to that drive as a side effect of being resolved - sbfsWalk calls sbfsUse on
|
||||
; the way past. So a script found in the system's place on drive 0, started by somebody
|
||||
; standing on a disk of their own, would run its lines on the system disk instead of theirs.
|
||||
;
|
||||
; It matters more now than it used to. `do 0:/Apps/setup.sh` was always able to do this;
|
||||
; typing a name now finds scripts the same three places a program is looked for, and the
|
||||
; third of them is drive-qualified.
|
||||
;
|
||||
; The answer that survives the CALL: Q into A and the byte count onto the stack, because
|
||||
; sbfsUse writes Q and RET puts DP3 back the way it found it.
|
||||
scriptKeepDrive:
|
||||
INA 0x24
|
||||
SETD.1 ScriptDrive
|
||||
STA.1
|
||||
RET
|
||||
|
||||
scriptGiveDriveBack:
|
||||
PSHD.3
|
||||
MVQA
|
||||
PSHA
|
||||
SETD.1 ScriptDrive
|
||||
LDA.1
|
||||
CALL sbfsUse
|
||||
POPA
|
||||
POPD.3
|
||||
; A holds what Q held. Adding nought to it is how it becomes Q again.
|
||||
RSTB
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; Everything up to and including the next line feed, thrown away. Used for the shebang.
|
||||
scriptSkipLine:
|
||||
CALL scriptByte
|
||||
@@ -541,6 +579,11 @@ LoudWord:
|
||||
ScriptDepth:
|
||||
0x00
|
||||
|
||||
; The drive the person is standing on, kept across a block being fetched. Not part of the
|
||||
; saved state below: it is only ever live for the length of one read.
|
||||
ScriptDrive:
|
||||
0x00
|
||||
|
||||
; ---- Seventy bytes, and they are next to each other on purpose ----
|
||||
;
|
||||
; Name, blocks left, next block, where in the block, and whether it is echoing: the whole of
|
||||
|
||||
Reference in New Issue
Block a user