From 553882d28d4885d852f478f1965456c034562eb6 Mon Sep 17 00:00:00 2001 From: Anachronaut Date: Sun, 30 Aug 2026 16:59:23 -0400 Subject: [PATCH] Start CosmOS with a script, and let a script hold its tongue Three things scripts wanted, and they are one thing: a machine that can have a face. /System/Boot/startup.sh runs before anybody can type. Every way of reaching the prompt for the first time goes through it, including the one where there is no disk - in which case there is nothing to find and nothing is said. A MISSING one is ordinary and silent, because a clean install has none and a machine that complained every boot about a file nobody wrote would be teaching its owner to ignore it. One that is THERE and does not begin with #! is the other case entirely: somebody meant that to run. #quiet stops each line being echoed, #loud puts it back. The prompt and the echo go together, because together they are what makes a script look like typing, so a quiet script gets neither and what it prints is all that appears. A nested script inherits quiet - a build that asked for it meant its helpers too - and gets its own setting back when the helper returns. Anything else beginning with # is handed to the shell, which does not know it and stops the script, because a script that asked for something this shell cannot do should not carry on as though it had been given it. clear empties the screen, which the console has been able to do since before there was a screen to do it on. THE PROMPT IS NOW SAID BY WHOEVER SUPPLIES THE LINE. It used to be said at the top of the loop, which is a decision made before the line is read and an answer not known until after - and it was wrong at both ends. #quiet is itself a line, so its prompt went out before anything knew to stay silent; and the line after a quiet script's last one comes from the console, having already been denied one. Off by exactly one line in opposite directions. A first attempt at this remembered whether the prompt had been skipped, which worked and was a flag standing in for a structure. The monitor's assembler prints a prompt of its own, so it reads through shellReadRaw, which is the same source without one. One admission. Handing the console its prompt back when a quiet script ended was a real fix when I wrote it and stopped being one an hour later, because the restructure above means the console's own path prompts whatever the flag holds. The comment claimed it fixed something. Breaking it on purpose changed nothing, which is how that was found, and it is now a comment saying so instead of a line pretending to work. The startup fixture ends QUIET on purpose: nothing puts the flag back when the outermost script finishes, so a script ending #loud would have tested the easy half. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW --- Programs/CosmOS/README.md | 43 ++++++++ Programs/CosmOS/Source/cosmos.asm | 154 ++++++++++++++++++++++------ Programs/CosmOS/Source/script.asm | 83 +++++++++++++-- SplitBit Test Manual.md | 2 +- Tests/expected/cosmos.out | 1 + Tests/expected/cosmosDeep.out | 1 + Tests/expected/cosmosInvoke.out | 1 + Tests/expected/cosmosStartup.out | 10 ++ Tests/expected/cosmosStartupBad.out | 6 ++ Tests/expected/cosmosTyped.out | 1 + Tests/input/cosmosStartup.in | 3 + Tests/makedisks.sh | 22 ++++ Tests/manifest | 10 ++ 13 files changed, 297 insertions(+), 40 deletions(-) create mode 100644 Tests/expected/cosmosStartup.out create mode 100644 Tests/expected/cosmosStartupBad.out create mode 100644 Tests/input/cosmosStartup.in diff --git a/Programs/CosmOS/README.md b/Programs/CosmOS/README.md index 08e3d1f..1b7332a 100644 --- a/Programs/CosmOS/README.md +++ b/Programs/CosmOS/README.md @@ -156,6 +156,48 @@ comment that only the kernel looks at, while here the shell requires it. **Each line is echoed as it runs**, after the prompt, so that a script reads exactly like somebody typing it and a script that stops says where. +**`#quiet` turns that off and `#loud` turns it back on.** The prompt and the echo go together, +because together they are what makes a script look like typing - so a quiet script gets +neither, and what it prints is all that appears. That is for the scripts whose own output is +the point, where prompts interleaved with the message are just in the way: + +``` +#! script +#quiet +clear +echo Segan Voyager +echo CosmOS ready. +``` + +A nested script inherits quiet from the one that started it, on the grounds that a build which +asked for quiet meant its helpers too, and gets its own setting back when the helper returns. +A script started from the prompt always begins loud. + +**Anything else beginning with `#` is handed to the shell**, which does not know it, says so, +and stops the script. A script that asked for something this shell cannot do should not carry +on as though it had been given it. + +## Starting Itself: + +If `/System/Boot/startup.sh` is there, it runs before anybody can type - every way of reaching +the prompt for the first time goes through it, including the one where there is no disk, in +which case there is simply nothing to find. + +**A missing one says nothing**, because a clean install has none and a machine that complained +every boot about a file nobody wrote would be teaching its owner to ignore it. A file that *is* +there and does not begin with `#!` is the other case entirely - somebody meant that to run - so +it says so and carries on to the prompt. + +Between them, `startup.sh` and `#quiet` are how a machine gets a face: + +``` +#! script +#quiet +clear +echo Segan Voyager +echo CosmOS ready. +``` + **A script stops at the first line that does not work.** A build whose first step failed and whose second step ran anyway produces something wrong and reports success, which is the whole reason the shell now remembers whether a line worked. What counts as not working is a command @@ -191,6 +233,7 @@ CosmOS currently provides these built-in commands: | `run [words]` | Start the loaded application and make the rest of the line available to it as an argument. | | `do