Make the README's references clickable, and check that they land

The two manuals and the CosmOS README were named in prose and nothing else,
so reading about them and getting to them were separate acts. They are links
now, along with every directory in the repository map, which is the other
place somebody reading that page wants to click.

THE MANUALS HAVE SPACES IN THEIR NAMES, so the links carry %20. That detail
is why this is checked rather than eyeballed: a link with a raw space in it
points at a file that exists, so nothing about the filesystem is wrong -
the renderer just stops at the space and the link goes nowhere useful.

Tests/docs.sh now walks every relative link in every tracked markdown file
and complains about both failures: a target that is not there, and a target
with a space that should have been encoded.

Both verified by breaking them. The first attempt at that verification was
itself wrong - I removed the %20 and the check passed, because the file
really does exist under that name. That is what showed the two failures are
different things and both need catching.

13 links, all landing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-21 16:29:21 -04:00
co-authored by Claude Opus 5
parent 3f95056eec
commit 4e5710a1e6
2 changed files with 43 additions and 13 deletions
+13 -13
View File
@@ -2,7 +2,7 @@
SplitBit is an 8 bit computer that does not exist: a CPU with its own instruction set, split Program and Data memories, an interrupt and vector system, a bus that programs can enumerate, a memory controller that can write code into memory, and a disk. This repository is a C implementation of the machine, an assembler for it, a tool for its disks, and the software that runs on it, which now includes an operating system and an assembler written in SplitBit's own assembly language. SplitBit is an 8 bit computer that does not exist: a CPU with its own instruction set, split Program and Data memories, an interrupt and vector system, a bus that programs can enumerate, a memory controller that can write code into memory, and a disk. This repository is a C implementation of the machine, an assembler for it, a tool for its disks, and the software that runs on it, which now includes an operating system and an assembler written in SplitBit's own assembly language.
**SplitBit assembles SplitBit.** `Programs/CosmOS/Assembler/` runs on the machine, reads source off a SplitBit disk, and writes a boot image or a loadable program back to it with no host involved. It builds the operating system it is running under, and it builds itself, both byte for byte identical to what the C assembler produces from the same source. The test suite then boots the CosmOS that CosmOS built and has *that* one assemble CosmOS again, and the second generation is identical to the first, so the machinery has been through itself. After that the host is a convenience rather than a necessity. **SplitBit assembles SplitBit.** [`Programs/CosmOS/Assembler/`](Programs/CosmOS/Assembler) runs on the machine, reads source off a SplitBit disk, and writes a boot image or a loadable program back to it with no host involved. It builds the operating system it is running under, and it builds itself, both byte for byte identical to what the C assembler produces from the same source. The test suite then boots the CosmOS that CosmOS built and has *that* one assemble CosmOS again, and the second generation is identical to the first, so the machinery has been through itself. After that the host is a convenience rather than a necessity.
``` ```
> load Asm.sbx > load Asm.sbx
@@ -16,15 +16,15 @@ wrote Asm.sbx: program 7533, data 4099, labels 555
| Directory | What it holds | | Directory | What it holds |
| --- | --- | | --- | --- |
| `Source/Emulator` | The machine: CPU, memory controller, devices, console, disk | | [`Source/Emulator`](Source/Emulator) | The machine: CPU, memory controller, devices, console, disk |
| `Source/Assembler` | The assembler that runs on a host | | [`Source/Assembler`](Source/Assembler) | The assembler that runs on a host |
| `Source/DiskTool` | SplitDisk, which reads and writes SplitBit's filesystem | | [`Source/DiskTool`](Source/DiskTool) | SplitDisk, which reads and writes SplitBit's filesystem |
| `Programs/Examples` | Programs to read: hello, a calculator, Fibonacci, a prime sieve, Life | | [`Programs/Examples`](Programs/Examples) | Programs to read: hello, a calculator, Fibonacci, a prime sieve, Life |
| `Programs/Libraries` | Code included by name rather than linked, since there is no linker | | [`Programs/Libraries`](Programs/Libraries) | Code included by name rather than linked, since there is no linker |
| `Programs/Loader` | The standalone loader CosmOS grew out of | | [`Programs/Loader`](Programs/Loader) | The standalone loader CosmOS grew out of |
| `Programs/CosmOS` | The operating system, its applications, and the native assembler | | [`Programs/CosmOS`](Programs/CosmOS) | The operating system, its applications, and the native assembler |
| `Programs/testPrograms` | What the test suite drives | | [`Programs/testPrograms`](Programs/testPrograms) | What the test suite drives |
| `Tests` | The suite: the manifest, the recorded output, and the scripts that check it | | [`Tests`](Tests) | The suite: the manifest, the recorded output, and the scripts that check it |
## The Machine: ## The Machine:
@@ -186,11 +186,11 @@ This catches reads and writes past the end of an array, use after free, leaks, a
Three documents, divided by what they are about rather than by who reads them. Three documents, divided by what they are about rather than by who reads them.
The **SplitBit Programming Manual** describes **the machine**: the instruction set, the registers, the vector table, interrupts, devices, the memory controller, the console, storage, and faults. Everything here is true of any SplitBit, whatever is running on it. **[SplitBit Programming Manual](SplitBit%20Programming%20Manual.md)** describes **the machine**: the instruction set, the registers, the vector table, interrupts, devices, the memory controller, the console, storage, and faults. Everything here is true of any SplitBit, whatever is running on it.
The **SplitBit Assembler Manual** describes **the language and the file formats**: literal values, labels, segments, the directives, the loadable program header, and the assembler that runs on SplitBit itself. **[SplitBit Assembler Manual](SplitBit%20Assembler%20Manual.md)** describes **the language and the file formats**: literal values, labels, segments, the directives, the loadable program header, and the assembler that runs on SplitBit itself.
`Programs/CosmOS/README.md` describes **the operating system**: its shell, its applications, what a program may ask it for, and the libraries it owns. A different system on the same machine would answer all of that differently, which is why it is documented with the system rather than with the CPU. [Programs/CosmOS/README.md](Programs/CosmOS/README.md) describes **the operating system**: its shell, its applications, what a program may ask it for, and the libraries it owns. A different system on the same machine would answer all of that differently, which is why it is documented with the system rather than with the CPU.
## License: ## License:
+30
View File
@@ -59,6 +59,36 @@ for name in tracked.split(b"\0"):
% (path, number, ", ".join("%r (U+%04X)" % (c, ord(c)) for c in odd))) % (path, number, ", ".join("%r (U+%04X)" % (c, ord(c)) for c in odd)))
break break
# ---- Every link in the documents goes somewhere ----
#
# A link that does not resolve is the same kind of wrong as a stale claim: it looks like
# information and is not, and nobody notices until a stranger clicks it. The manuals have
# SPACES IN THEIR NAMES, so a link to one carries %20 and has to be unquoted before it can
# be looked for - which is the sort of thing that would otherwise be got wrong once and
# then reported as fine.
import os
import urllib.parse
for name in tracked.split(b"\0"):
if not name or not name.endswith(b".md"):
continue
path = name.decode()
here = os.path.dirname(path)
for match in re.finditer(r"\[[^\]]*\]\(([^)]+)\)", read(path)):
target = match.group(1)
if target.startswith(("http://", "https://", "#", "mailto:")):
continue
# A raw space ends the link early in most renderers, so the file existing is not
# enough - the manuals have spaces in their names and must carry %20.
if " " in target:
problems.append("%s links to \"%s\", which has a space in it: most renderers"
" stop at the space. Write it as %%20."
% (path, target))
continue
wanted = urllib.parse.unquote(target.split("#")[0])
if not os.path.exists(os.path.normpath(os.path.join(here, wanted))):
problems.append("%s links to %s, and there is nothing there" % (path, target))
# ---- Every instruction has a row, and every row is an instruction ---- # ---- Every instruction has a row, and every row is an instruction ----
# #
# A mnemonic begins with a letter, which is what keeps the offset and size columns of the # A mnemonic begins with a letter, which is what keeps the offset and size columns of the