cd moves it, dir lists the directory it is in, and the prompt says which one - but only when that is not the root, so a machine nobody has moved about on looks exactly as it always did and every recorded test that never says "cd" keeps its recorded prompt. A path beginning with a separator is measured from the root and anything else from where the machine is, so a bare name means a file in the current directory. NO PROGRAM HAD TO BE TOLD: the working directory lives in sbfs.asm beside the thing that resolves paths, because it is what a relative path MEANS. Keeping it in the shell would have meant either handing it down on every call or pasting it onto the front of every name, and the second of those is how a name that is already absolute gets ruined. Nothing stores the path. The working directory is an entry index and two bytes, and the text on the prompt is built each time by walking the chain of parents upward, writing names from the end of a buffer towards the front - which is the order they arrive in, and saves reversing them afterwards. sbfsFind splits into a walk and a check. "cd /" and "cd .." both end at the root quite legitimately, and had no way to say so through a routine whose only word for the root was "missing". Typing a program's name now tries two places in order: where you are, then /Apps. The first makes a program you are working on the one that runs; the second lets Snake work from anywhere. A word already beginning with a separator has said where to look, so only that place is tried. osChangeDir exists so that "a program may move about, and the shell puts the working directory back" is a thing that can happen rather than a promise about nothing. Both halves of that were unfalsifiable without it: with no way for a program to move, removing the restore changed no test. Wander is the program that moves - it goes where it is told and reads a file there by a bare name - and with it on the disk, removing the restore fails. The remembered file is dropped whenever what a relative path means changes: a cd, a program calling osChangeDir, a program exiting. Removing all of them fails the test and removing any one of them does not, because today every path into that cache belongs to a program that exits. It is kept in all three because the cost is a call and the failure is a file's blocks being handed out under another file's name. The cwd fixture holds two files called notes.txt saying different things, and a Say.sbx in /A that is really hello. Two copies of one program, or two copies of one file, would have passed with the whole of this deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
106 lines
1.7 KiB
NASM
106 lines
1.7 KiB
NASM
; Goes somewhere else and reads a file by a bare name once it is there.
|
|
;
|
|
; This exists to prove two things the shell promises and nothing else could test. First
|
|
; that osChangeDir works: the file it prints is named with no path at all, so the only way
|
|
; to reach it is to be standing in the right place. Second that the shell puts the working
|
|
; directory back afterwards: the prompt after this returns says where the shell was, not
|
|
; where this went.
|
|
;
|
|
; Written by Anachronaut
|
|
|
|
#Include services.asm
|
|
#Program
|
|
#Base 0x4000
|
|
|
|
start:
|
|
; Where to go is the argument. Nothing else about this program says a directory name, so
|
|
; running it anywhere else moves it anywhere else.
|
|
SETD.0 Where
|
|
INIB 0d40
|
|
SWI osArgument
|
|
SETD.0 Where
|
|
LDA.0
|
|
BRA noWhere
|
|
|
|
SETD.0 Where
|
|
SWI osChangeDir
|
|
BNQ noSuchPlace
|
|
|
|
SETD.0 Went
|
|
SWI osPrintString
|
|
|
|
; And now a bare name, which means nothing until you are somewhere.
|
|
SETD.0 Bare
|
|
CALL fileStreamOpen
|
|
BNQ noFile
|
|
|
|
wanderBlock:
|
|
CALL fileStreamNext
|
|
BNQ noFile
|
|
PSHD.3
|
|
POPB
|
|
POPA
|
|
SETD.2 Left
|
|
STA.2
|
|
INCD.2
|
|
STB.2
|
|
|
|
SETD.2 Left
|
|
LDA.2
|
|
INCD.2
|
|
LDB.2
|
|
OR
|
|
BRQ wanderDone
|
|
|
|
SETD.0 FileStreamBlock
|
|
SETD.2 Left
|
|
INCD.2
|
|
LDB.2
|
|
wanderByte:
|
|
LDA.0
|
|
OUTA 0x00
|
|
INCD.0
|
|
DECB
|
|
BNB wanderByte
|
|
BRI wanderBlock
|
|
|
|
wanderDone:
|
|
SWI osExit
|
|
|
|
noWhere:
|
|
SETD.0 NoWhereText
|
|
SWI osPrintString
|
|
SWI osExit
|
|
noSuchPlace:
|
|
SETD.0 NoPlaceText
|
|
SWI osPrintString
|
|
SWI osExit
|
|
noFile:
|
|
SETD.0 NoFileText
|
|
SWI osPrintString
|
|
SWI osExit
|
|
|
|
#Data
|
|
#Base 0x2000
|
|
|
|
Where:
|
|
#Reserve 0d40
|
|
Left:
|
|
0x00 0x00
|
|
Went:
|
|
"moved, and reading a bare name from there:
|
|
"
|
|
NoWhereText:
|
|
"wander where?
|
|
"
|
|
NoPlaceText:
|
|
"cannot go there
|
|
"
|
|
NoFileText:
|
|
"nothing of that name here
|
|
"
|
|
Bare:
|
|
"notes.txt"
|
|
|
|
#Include fileStream.asm
|