A script is given words, and keeps them

"do build.sh cosmos.asm" looked for a file called "build.sh cosmos.asm",
because scriptOpen copied the whole rest of the line into the name. So a
script could be told nothing, and a launcher - a script whose entire job
is to hand on what it was told - could not exist.

Now the name is cut off the front and what follows is kept whole. $1 to
$9 are the words of it, walked out on demand, and $args is all of them.
Nothing is stored per parameter, so there is no limit on how many a
script may be handed and no second number to keep in step. Both ways of
starting a script pass them on: "do" and typing the name.

A word that was not given is an error that stops the script, like every
other name this shell does not know. Expanding it to nothing would let a
command run with an argument missing and then report success, which is
what stop-on-failure exists to prevent. $args is always set inside a
script, empty if it was given nothing, so "if same $args" can be asked.

---- And the count that describes the block was already wrong ----

Found while adding a field to it. The state one script keeps for another
is saved by a single copy of a fixed number of bytes, and that number was
71 against a block of 77: six bytes of line position had been added in
the middle of it years after the count was written. So the tail of every
saved script was never saved, and #quiet in a helper stayed behind in the
script that called it - the opposite of what this file's own comment
promises and the README documents.

The unsaved line position turned out not to matter, because a loop keeps
its own copy in the block record. Nothing said so. Three numbers describe
this block and all three now say so in a comment, and cosmosScriptNest
ends on a helper that goes quiet and a caller that must not stay that
way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-09-06 15:06:32 -04:00
co-authored by Claude Opus 5
parent 06af7e7fbb
commit d9ebc76cf5
25 changed files with 441 additions and 25 deletions
+1
View File
@@ -46,3 +46,4 @@ Source/Emulator/rom.c
# The personal disk 'make run-voyager' puts in drive 1. Made on demand, never rebuilt, and # The personal disk 'make run-voyager' puts in drive 1. Made on demand, never rebuilt, and
# not cleaned - it is the one place in here where something made ON the machine can live. # not cleaned - it is the one place in here where something made ON the machine can live.
/Disks/ /Disks/
*.sym
+47 -1
View File
@@ -216,6 +216,52 @@ line comes from - the shell splits it, matches it and runs it without knowing th
a file is reached by its whole name, the way `load` is for a program. See Starting An a file is reached by its whole name, the way `load` is for a program. See Starting An
Application By Name. Application By Name.
### What A Script Is Given:
Whatever followed the name reaches the script, whichever way it was started - `do build.sh
cosmos.asm` and `build.sh cosmos.asm` hand it the same thing.
| Name | What it stands for |
| -- | -- |
| `$1` to `$9` | The words it was given, counted from one. |
| `$args` | All of them, exactly as they were typed. |
```
#! script
; build.sh <source>
echo building $1
cd /Source
Asm $1
```
**Nothing is stored per parameter.** The line is kept whole and the word wanted is walked out
of it, so there is no limit on how many words a script may be handed and nothing to keep in
step. `$args` is that line; `$1` is a word copied out of it.
**A word that was not given is an error**, exactly like any other name the shell does not
know: `$2` in a script given one word says `nothing is set called 2` and stops the script.
Expanding it to nothing would let a command run with an argument missing and report success,
which is the failure the whole stop-on-error rule exists to prevent. A script that genuinely
wants to work with or without something can ask `if same $args` - and `$args` is always set
inside a script, empty if it was given nothing, so that question can always be asked.
**At the prompt they mean nothing**, and say so. There is no script there to have been given
anything, so `$1` is a name nobody set.
**A script's own words win over anything `set`.** They are looked at before the eight named
slots, so a parameter cannot be shadowed by something left lying about at the prompt.
**Each script has its own**, saved and restored with the rest of where it had got to. A script
that hands different words to a helper still has its own when the helper returns. That is also
what makes a **launcher** possible: a script whose whole body is one line handing on what it
was told, without knowing what any of it means.
```
#! script
; /Apps/Lander - the launcher
Packages/app.Lander/Lander $args
```
``` ```
#! script #! script
; Build the system and put it where the machine will find it. ; Build the system and put it where the machine will find it.
@@ -325,7 +371,7 @@ CosmOS currently provides these built-in commands:
| `dir` | List the files on the mounted disk and their sizes. | | `dir` | List the files on the mounted disk and their sizes. |
| `load <path>` | Read and validate an SBEX application, then place its code and data where its header requests. | | `load <path>` | Read and validate an SBEX application, then place its code and data where its header requests. |
| `run [words]` | Start the loaded application and make the rest of the line available to it as an argument. | | `run [words]` | Start the loaded application and make the rest of the line available to it as an argument. |
| `do <script>` | Run the lines in a file as though they had been typed. See Scripts. | | `do <script> [words]` | Run the lines in a file as though they had been typed, and hand it those words. See Scripts. |
| `echo [words]` | Say the rest of the line, or a blank line with nothing after it. | | `echo [words]` | Say the rest of the line, or a blank line with nothing after it. |
| `clear` | Empty the screen. | | `clear` | Empty the screen. |
| `drive [n]` | Say which disk the shell is on, or go to another. See Several Disks. | | `drive [n]` | Say which disk the shell is on, or go to another. See Several Disks. |
+177 -1
View File
@@ -133,6 +133,11 @@ bootNoDisk:
; to ignore it. A file that is THERE and is not a script is the other case entirely: somebody ; to ignore it. A file that is THERE and is not a script is the other case entirely: somebody
; meant it to run. ; meant it to run.
bootStartup: bootStartup:
; Nobody typed this one, so there is nothing to give it.
SETD.2 NoText
SETD.1 ScriptArgsFrom
STD.2.1
SETD.0 StartupName SETD.0 StartupName
CALL scriptOpen CALL scriptOpen
BRQ bootReady BRQ bootReady
@@ -2647,10 +2652,18 @@ varExpandNamed:
varExpandLookUp: varExpandLookUp:
SETD.1 VarKeepLine SETD.1 VarKeepLine
STD.0.1 ; Where the line has got to, across the search. STD.0.1 ; Where the line has got to, across the search.
; A script's own names are asked about first, so that a parameter cannot be shadowed by
; something set at the prompt. Only inside a script: at the prompt "$1" is a name nobody
; set, and gets told so like any other.
CALL varScriptName
BRQ varExpandFound
SETD.0 VarName SETD.0 VarName
CALL varFind CALL varFind
BNQ varExpandNoSuch BNQ varExpandNoSuch
CALL varValueOf CALL varValueOf
varExpandFound:
SETD.1 VarKeepLine SETD.1 VarKeepLine
LDD.0.1 LDD.0.1
@@ -2733,6 +2746,139 @@ varExpandLong:
CALL newLine CALL newLine
BRI commandFailed BRI commandFailed
; ---- The names a script gets for nothing ----
;
; "$args" is everything it was given, and "$1" to "$9" are the words of that, counted from
; one. Nothing is stored per parameter: the line it was given is kept whole and the word
; wanted is walked out of it, so there is no limit on how many a script may be handed and
; nothing to keep in step.
;
; A NAME ONE OF THESE MISSES IS AN ERROR, like every other name this shell does not know.
; "$2" in a script given one word says so and stops it, rather than quietly becoming nothing
; and letting a command run with an argument missing - which is the rule set.asm's own comment
; argues for at length, applied to the names a script did not have to set.
;
; Q is zero if VarName is one of them, and DP3 is left on the value. DP3 because a RET puts
; the others back, which is the same reason varValueOf answers there.
varScriptName:
SETD.1 ScriptDepth
LDA.1
BRA varScriptNo ; Not in a script, so these names mean nothing here.
SETD.0 VarName
SETD.1 ArgsWord
CALL textSame
BRQ varScriptAll
; One character, and that character a digit from one to nine. Testing the length first is
; what keeps "1st" from being read as "1".
SETD.0 VarName
INCD.0
LDA.0
BNA varScriptNo
SETD.0 VarName
LDA.0
INIB 0x31
CCF
SUB
BRC varScriptNo ; Below '1'. There is no word nought.
LDA.0
INIB 0x3A
CCF
SUB
BNC varScriptNo ; Above '9'.
LDA.0
INIB 0x30
CCF
SUB
MVQA ; Which word is wanted, one to nine.
CALL varScriptWord
RET
varScriptAll:
SETD.3 ScriptArgs
RSTA
RSTB
CCF
ADD ; Q is zero: it is one of them.
RET
varScriptNo:
INIA 0x01
RSTB
CCF
ADD
RET
; A is which word is wanted. Copies it out into VarWord and leaves DP3 on it, because the
; words are separated by spaces rather than ended by zeroes and everything downstream of here
; walks a string until it ends.
;
; Q is one if the script was not given that many, which reads as a name that is not set.
varScriptWord:
SETD.1 VarWordWanted
STA.1
SETD.0 ScriptArgs
varScriptSkip:
LDA.0
BRA varScriptShort ; The end, and the word wanted is past it.
INIB 0x20
CCF
SUB
BNQ varScriptWordAt ; Not a space, so a word begins here.
INCD.0
BRI varScriptSkip
varScriptWordAt:
SETD.1 VarWordWanted
LDA.1
DECA
STA.1
BRA varScriptTake ; Counted down to nought, so this is the one.
varScriptPast:
LDA.0
BRA varScriptShort
INIB 0x20
CCF
SUB
BRQ varScriptSkip ; The end of this word, so the next one is looked for.
INCD.0
BRI varScriptPast
varScriptTake:
SETD.1 VarWord
varScriptTakeChar:
LDA.0
BRA varScriptTaken
INIB 0x20
CCF
SUB
BRQ varScriptTaken
LDA.0
STA.1
INCD.0
INCD.1
BRI varScriptTakeChar
varScriptTaken:
RSTA
STA.1 ; The zero that makes it a string.
SETD.3 VarWord
RSTB
CCF
ADD ; Q is zero, A having been reset above.
RET
varScriptShort:
INIA 0x01
RSTB
CCF
ADD
RET
varExpandNoSuch: varExpandNoSuch:
SETD.0 VarNoSuch SETD.0 VarNoSuch
CALL printString CALL printString
@@ -3521,6 +3667,13 @@ promptAsScript:
LDA.0 LDA.0
CALL sbfsUse CALL sbfsUse
; Whatever followed the word, which reaches a script the same way it reaches a program.
; The line was split before the dispatch chain ran, so this is already the rest of it.
SETD.1 TextRest
LDD.2.1
SETD.1 ScriptArgsFrom
STD.2.1
SETD.0 ProgramName SETD.0 ProgramName
CALL scriptOpen CALL scriptOpen
BRQ prompt ; It is open, and the next line read will come from it. BRQ prompt ; It is open, and the next line read will come from it.
@@ -4898,6 +5051,17 @@ doScript:
LDA.0 LDA.0
BRA scriptNoName BRA scriptNoName
; The file, and then whatever else was on the line. textSplit cuts the first word off in
; place and leaves TextRest on what follows, and a RET puts DP0 back - so afterwards DP0
; names just the file and TextRest names what the script is being given.
;
; Through DP2, because DP0 is the file and must still be it when scriptOpen is called.
CALL textSplit
SETD.1 TextRest
LDD.2.1
SETD.1 ScriptArgsFrom
STD.2.1
CALL scriptOpen CALL scriptOpen
BRQ prompt ; It is open, and the next line read will come from it. BRQ prompt ; It is open, and the next line read will come from it.
@@ -7598,7 +7762,7 @@ HelpCdText:
mkdir <path> make a directory mkdir <path> make a directory
rmdir <path> remove an empty one" rmdir <path> remove an empty one"
HelpScriptText: HelpScriptText:
"do <file> run the lines in a file, which must start with #! "do <file> [words] run the lines in a file, which must start with #!
echo [words] say them echo [words] say them
clear empty the screen" clear empty the screen"
HelpMoreText: HelpMoreText:
@@ -7809,6 +7973,12 @@ ShellNameCount:
AppsPath: AppsPath:
"/Apps" "/Apps"
ArgsWord:
"args"
; An empty string, for a script the machine started rather than somebody typing, which was
; therefore given nothing.
NoText:
0x00
VarNoSuch: VarNoSuch:
"nothing is set called " "nothing is set called "
VarTooLong: VarTooLong:
@@ -8249,6 +8419,12 @@ VarSlots:
#Reserve 0d512 #Reserve 0d512
VarSlot: VarSlot:
0x00 0x00
; One word of what a script was given, copied out so that it ends in a zero like every other
; value. A whole line of room, because one word can be the whole line.
VarWord:
#Reserve 0d128
VarWordWanted:
0x00
VarWanted: VarWanted:
0x00 0x00 0x00 0x00
VarKeepValue: VarKeepValue:
+50 -8
View File
@@ -72,7 +72,7 @@ scriptSlotAt:
DECA DECA
BRA scriptSlotDone BRA scriptSlotDone
scriptSlotStep: scriptSlotStep:
DPUP.3 0d71 DPUP.3 0d205
DECA DECA
BNA scriptSlotStep BNA scriptSlotStep
scriptSlotDone: scriptSlotDone:
@@ -80,7 +80,7 @@ scriptSlotDone:
; Seventy bytes, DP0 to DP1. ; Seventy bytes, DP0 to DP1.
scriptCopyState: scriptCopyState:
INIB 0d71 INIB 0d205
scriptCopyByte: scriptCopyByte:
LDA.0 LDA.0
STA.1 STA.1
@@ -154,6 +154,17 @@ scriptOpenFirst:
INIB 0d63 INIB 0d63
CALL copyText CALL copyText
; ---- And what it was given ----
;
; After the push, so that what the script one level up was given is already somewhere safe.
; A script started with nothing gets an EMPTY one rather than none at all, which is what
; makes "$args" always mean something inside a script while "$1" can be missing.
SETD.1 ScriptArgsFrom
LDD.0.1
SETD.1 ScriptArgs
INIB 0d128
CALL copyText
CALL scriptKeepDrive CALL scriptKeepDrive
SETD.0 ScriptName SETD.0 ScriptName
SWI osFileInfo SWI osFileInfo
@@ -584,11 +595,30 @@ ScriptDepth:
ScriptDrive: ScriptDrive:
0x00 0x00
; ---- Seventy bytes, and they are next to each other on purpose ---- ; Where the arguments are, for the length of one call to scriptOpen. A pointer rather than the
; text, because the text is still sitting in the line that named the script and copying it
; twice would buy nothing.
ScriptArgsFrom:
0x00 0x00
; ---- Two hundred and five 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 ; Name, blocks left, next block, where in the block, what it was given, and whether it is
; where a script has got to. Saving it is one copy because of this order, and nothing else ; echoing: the whole of a running script. Saving it is one copy because of this order, and
; may be put between them. ; nothing else may be put between them.
;
; ---- THREE NUMBERS DESCRIBE THIS BLOCK AND ALL THREE MUST AGREE ----
;
; scriptCopyState how many bytes one of them is
; scriptSlotAt how far apart two saved ones are
; ScriptSaved four of them
;
; They did not agree, and that is what this warning is for. Six bytes of line position were
; added in the middle of the block and the count stayed at 71, so the last six bytes of every
; saved script were never saved: a nested script's #quiet leaked back out to the script that
; called it, which is the opposite of what this file's own comment promises. The line position
; that went unsaved with it turned out not to matter - a loop keeps its own copy in the block
; record - but nothing said so, and the next field added would have been chosen at random.
ScriptName: ScriptName:
#Reserve 0d64 #Reserve 0d64
ScriptBlocks: ScriptBlocks:
@@ -617,10 +647,22 @@ ScriptLineBlocks:
ScriptQuiet: ScriptQuiet:
0x00 0x00
; ---- What the script was given ----
;
; The rest of the line that started it, kept whole rather than picked apart, because picking
; it apart costs a place to put every piece and a limit on how many there may be. "$1" walks
; this and copies out the word it wants; "$args" is this.
;
; A WHOLE LINE OF ROOM, so that nothing a person can type can be cut short. The line is 127
; and the script's own name has already come off the front of it, so this can never be filled
; - which is worth 128 bytes a level to never have to explain.
ScriptArgs:
#Reserve 0d128
; Three would do - a save happens on the second script and not the first - but four costs ; Three would do - a save happens on the second script and not the first - but four costs
; seventy bytes and removes an off-by-one from the only place it could hide. ; one more and removes an off-by-one from the only place it could hide.
ScriptSaved: ScriptSaved:
#Reserve 0d284 #Reserve 0d820
ScriptInto: ScriptInto:
0x00 0x00 0x00 0x00
ScriptRoom: ScriptRoom:
+1 -1
View File
@@ -125,7 +125,7 @@ from `make`, not from here.
### 1. Recorded output ### 1. Recorded output
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares `Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
everything it printed against a file in `Tests/expected`. 213 tests, of which 151 run, 35 everything it printed against a file in `Tests/expected`. 214 tests, of which 152 run, 35
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
given at all. given at all.
+1 -1
View File
@@ -7,7 +7,7 @@ run [words] start what was loaded, and tell it those words
cd [path] go to a directory, or to the root with nothing after it cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory mkdir <path> make a directory
rmdir <path> remove an empty one rmdir <path> remove an empty one
do <file> run the lines in a file, which must start with #! do <file> [words] run the lines in a file, which must start with #!
echo [words] say them echo [words] say them
clear empty the screen clear empty the screen
delete <file> take it off the disk delete <file> take it off the disk
+6 -1
View File
@@ -44,8 +44,13 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
crossed.txt 560 crossed.txt 560
32 files, 1 directory 37 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+1 -1
View File
@@ -15,7 +15,7 @@ run [words] start what was loaded, and tell it those words
cd [path] go to a directory, or to the root with nothing after it cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory mkdir <path> make a directory
rmdir <path> remove an empty one rmdir <path> remove an empty one
do <file> run the lines in a file, which must start with #! do <file> [words] run the lines in a file, which must start with #!
echo [words] say them echo [words] say them
clear empty the screen clear empty the screen
delete <file> take it off the disk delete <file> take it off the disk
+6 -1
View File
@@ -34,7 +34,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> drive 1 > drive 1
> dir > dir
other.txt 28 other.txt 28
+6 -1
View File
@@ -51,7 +51,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+6 -1
View File
@@ -41,7 +41,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+6 -1
View File
@@ -41,7 +41,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+1 -1
View File
@@ -46,7 +46,7 @@ run [words] start what was loaded, and tell it those words
cd [path] go to a directory, or to the root with nothing after it cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory mkdir <path> make a directory
rmdir <path> remove an empty one rmdir <path> remove an empty one
do <file> run the lines in a file, which must start with #! do <file> [words] run the lines in a file, which must start with #!
echo [words] say them echo [words] say them
clear empty the screen clear empty the screen
delete <file> take it off the disk delete <file> take it off the disk
+6 -1
View File
@@ -127,7 +127,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+6 -1
View File
@@ -46,7 +46,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+6 -1
View File
@@ -34,7 +34,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> load > load
load what? load what?
> load nosuch.sbx > load nosuch.sbx
+43
View File
@@ -0,0 +1,43 @@
CosmOS
> do args.script red green
> echo one is $1
one is red
> echo two is $2
two is green
> echo all of it is $args
all of it is red green
> args.script blue yellow
> echo one is $1
one is blue
> echo two is $2
two is yellow
> echo all of it is $args
all of it is blue yellow
> pass.script hello there
> Say $args
it says: hello there
finished
> do holds.script top level
> echo outer has $1
outer has top
> do args.script deep down
> echo one is $1
one is deep
> echo two is $2
two is down
> echo all of it is $args
all of it is deep down
> echo outer still has $1 and $args
outer still has top and top level
> do args.script only
> echo one is $1
one is only
> echo two is $2
nothing is set called 2
stopped: that line did not work
> $1
nothing is set called 1
> exit
halted
Execution halted.
[exit 0]
+7
View File
@@ -24,6 +24,13 @@ self
> do loop.script > do loop.script
do: scripts are only four deep do: scripts are only four deep
stopped: that line did not work stopped: that line did not work
> do aloud.script
> echo aloud first
aloud first
> do hush.script
the helper is quiet
> echo aloud again
aloud again
> exit > exit
halted halted
Execution halted. Execution halted.
+6 -1
View File
@@ -32,7 +32,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> load Say.sbx > load Say.sbx
loaded, starting at 5000 loaded, starting at 5000
> run the disk took its time > run the disk took its time
+6 -1
View File
@@ -41,7 +41,12 @@ nonl.script 38
outer.script 376 outer.script 376
inner.script 44 inner.script 44
loop.script 35 loop.script 35
31 files, 1 directory hush.script 42
aloud.script 59
args.script 64
pass.script 20
holds.script 87
36 files, 1 directory
> exit > exit
halted halted
Execution halted. Execution halted.
+1 -1
View File
@@ -7,7 +7,7 @@ run [words] start what was loaded, and tell it those words
cd [path] go to a directory, or to the root with nothing after it cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory mkdir <path> make a directory
rmdir <path> remove an empty one rmdir <path> remove an empty one
do <file> run the lines in a file, which must start with #! do <file> [words] run the lines in a file, which must start with #!
echo [words] say them echo [words] say them
clear empty the screen clear empty the screen
delete <file> take it off the disk delete <file> take it off the disk
+7
View File
@@ -0,0 +1,7 @@
do args.script red green
args.script blue yellow
pass.script hello there
do holds.script top level
do args.script only
$1
exit
+1
View File
@@ -1,3 +1,4 @@
do outer.script do outer.script
do loop.script do loop.script
do aloud.script
exit exit
+27
View File
@@ -296,6 +296,33 @@ printf '#! script\necho inner one\necho inner two\n' > inner.script
# A script that runs itself, which is what the depth limit is for. # A script that runs itself, which is what the depth limit is for.
printf '#! script\necho self\ndo loop.script\n' > loop.script printf '#! script\necho self\ndo loop.script\n' > loop.script
"$TOOL" put "$DISKS/cosmos.img" loop.script >/dev/null "$TOOL" put "$DISKS/cosmos.img" loop.script >/dev/null
# ---- And what a nested script gives back ----
#
# hush.script goes quiet and heard.script must not stay that way. The state one script keeps
# for another is saved by a single copy of a fixed number of bytes, and that number was six
# short of the block it was copying - so the last fields of it, quiet among them, were never
# saved at all. Nothing said so: the echo simply stopped, in the caller, after the helper
# returned. The check is that "echo aloud again" is ECHOED and not merely obeyed.
#
# MIND WHAT A NEW NAME HERE BEGINS WITH. Tab is checked against this disk, and a second file
# sharing a prefix with one of the words those tests type turns a unique completion into a
# list. "heard.script" was the first draft and it shadowed hello.sbx.
printf '#! script\n#quiet\necho the helper is quiet\n' > hush.script
"$TOOL" put "$DISKS/cosmos.img" hush.script >/dev/null
printf '#! script\necho aloud first\ndo hush.script\necho aloud again\n' > aloud.script
"$TOOL" put "$DISKS/cosmos.img" aloud.script >/dev/null
# ---- What a script is given ----
#
# args.script says what reached it; pass.script is the shape a launcher has, handing on what
# it was told without knowing what any of it means; holds.script gives a helper different
# words and must still have its own afterwards.
printf '#! script\necho one is $1\necho two is $2\necho all of it is $args\n' > args.script
"$TOOL" put "$DISKS/cosmos.img" args.script >/dev/null
printf '#! script\nSay $args\n' > pass.script
"$TOOL" put "$DISKS/cosmos.img" pass.script >/dev/null
printf '#! script\necho outer has $1\ndo args.script deep down\necho outer still has $1 and $args\n' > holds.script
"$TOOL" put "$DISKS/cosmos.img" holds.script >/dev/null
# ---- A disk that starts itself ---- # ---- A disk that starts itself ----
# #
+16
View File
@@ -983,7 +983,23 @@ cosmosScriptEdges | CosmOS/Source/cosmos.asm | run | cosmosScr
# into the single buffer, so coming back means reading the outer one's again and landing on # into the single buffer, so coming back means reading the outer one's again and landing on
# the byte it left. Then a script that runs itself, which stops at four deep and takes every # the byte it left. Then a script that runs itself, which stops at four deep and takes every
# level with it, because a build whose helper failed should not carry on in its caller. # level with it, because a build whose helper failed should not carry on in its caller.
# It also ends on the state a nested script gives back. The saved block is copied by a fixed
# count, that count was six bytes short of the block, and quiet was in the six - so a helper
# that went quiet left its caller quiet. "echo aloud again" being ECHOED is the check.
cosmosScriptNest | CosmOS/Source/cosmos.asm | run | cosmosScriptNest.in | 200000000 | disks/cosmos.img cosmosScriptNest | CosmOS/Source/cosmos.asm | run | cosmosScriptNest.in | 200000000 | disks/cosmos.img
# ---- What a script is given ----
#
# $1 to $9 are the words it was handed and $args is all of them. Nothing is stored per
# parameter: the line is kept whole and the word wanted is walked out of it.
#
# Five claims in one session. Both ways of starting a script pass words on - "do" and typing
# the name. A LAUNCHER can hand on what it was told without knowing what any of it means,
# which is the reason this rung is on the ladder at all. A nested script gets its own words
# and the caller still has its own afterwards. And a word that was not given is an ERROR that
# stops the script, like every other name the shell does not know - not silently nothing,
# which would let a command run with an argument missing. At the prompt they are ordinary
# unset names, because there is no script to have been given anything.
cosmosScriptArgs | CosmOS/Source/cosmos.asm | run | cosmosScriptArgs.in | 200000000 | disks/cosmos.img
# ---- Starting itself ---- # ---- Starting itself ----
# #
# /System/Boot/startup.sh runs before anybody can type. This one is also the check on #quiet # /System/Boot/startup.sh runs before anybody can type. This one is also the check on #quiet