From e3100b4718ad57bc526d97e13dc5dfbe80864455 Mon Sep 17 00:00:00 2001 From: Anachronaut Date: Mon, 17 Aug 2026 23:26:21 -0400 Subject: [PATCH] Fixed assembler bug that caused crash on IR array resize. Added line editor app. --- Programs/CosmOS/Apps/Edit.asm | 829 +++++++++++++++++++ Programs/CosmOS/Apps/Say.asm | 57 ++ Programs/CosmOS/Source/cosmos.asm | 170 +++- Programs/CosmOS/Source/sbfs.asm | 226 +++++ Programs/CosmOS/Source/services.asm | 1 + Programs/CosmOS/Source/text.asm | 76 ++ Programs/makefile | 2 +- Programs/testPrograms/sbfsEditTest.asm | 233 ++++++ README.md | 4 + Source/Assembler/firstPass.c | 18 +- SplitBit Programming Manual.md | 72 +- Tests/docs.sh | 19 +- Tests/expected/16bitFibonacci.out | 2 +- Tests/expected/16bitSegmentedSieve.out | 2 +- Tests/expected/16bitSegmentedSieveModern.out | 2 +- Tests/expected/16x16Life.out | 2 +- Tests/expected/16x16LifeModern.out | 2 +- Tests/expected/32bitFibonacci.out | 2 +- Tests/expected/8bitFibonacci.out | 2 +- Tests/expected/8bitSieve.out | 2 +- Tests/expected/bankBoundsTest.out | 2 +- Tests/expected/blitTest.out | 2 +- Tests/expected/branchTest.out | 2 +- Tests/expected/consoleInterruptTest.out | 2 +- Tests/expected/consoleModeTest.out | 2 +- Tests/expected/consoleTest.out | 2 +- Tests/expected/controllerReadTest.out | 2 +- Tests/expected/controllerWriteTest.out | 2 +- Tests/expected/cosmos.out | 6 +- Tests/expected/cosmosDump.out | 2 +- Tests/expected/cosmosEdit.out | 21 + Tests/expected/cosmosFiles.out | 17 + Tests/expected/cosmosHello.out | 2 +- Tests/expected/cosmosKeys.out | 2 +- Tests/expected/cosmosLife.out | 2 +- Tests/expected/cosmosLifeKey.out | 2 +- Tests/expected/cosmosNoDisk.out | 2 +- Tests/expected/cosmosRun.out | 5 +- Tests/expected/cosmosSay.out | 11 + Tests/expected/cosmosSnake.out | 2 +- Tests/expected/dataPointerTest.out | 2 +- Tests/expected/deviceTest.out | 2 +- Tests/expected/diskProtectTest.out | 2 +- Tests/expected/diskTest.out | 2 +- Tests/expected/dispatchTest.out | 2 +- Tests/expected/faultResumeTest.out | 2 +- Tests/expected/faultTest.out | 2 +- Tests/expected/fenceTest.out | 2 +- Tests/expected/hello.out | 2 +- Tests/expected/inputTest.out | 2 +- Tests/expected/inputTestOld.out | 2 +- Tests/expected/int16print.out | 2 +- Tests/expected/interruptExample.out | 2 +- Tests/expected/interruptFlagTest.out | 2 +- Tests/expected/loader.out | 2 +- Tests/expected/loaderTest.out | 2 +- Tests/expected/maskTest.out | 2 +- Tests/expected/mathTest.out | 2 +- Tests/expected/moveQTest.out | 2 +- Tests/expected/paddingTest.out | 2 +- Tests/expected/pinnedVectorTest.out | 2 +- Tests/expected/pointerTableTest.out | 2 +- Tests/expected/printHello.out | 2 +- Tests/expected/printTest.out | 2 +- Tests/expected/refusalFaultTest.out | 2 +- Tests/expected/refusalTest.out | 2 +- Tests/expected/registerBankTest.out | 2 +- Tests/expected/registryTest.out | 2 +- Tests/expected/sbfsEditTest.out | 8 + Tests/expected/sbfsReadTest.out | 2 +- Tests/expected/sbfsWalkTest.out | 2 +- Tests/expected/sbfsWriteTest.out | 2 +- Tests/expected/stackPointerTest.out | 2 +- Tests/expected/stackReclaimTest.out | 2 +- Tests/expected/staticTableTest.out | 2 +- Tests/expected/swiFaultTest.out | 2 +- Tests/expected/textTest.out | 2 +- Tests/expected/twoPointerCopy.out | 2 +- Tests/expected/vectorTest.out | 2 +- Tests/input/cosmosEdit.in | 22 + Tests/input/cosmosFiles.in | 9 + Tests/input/cosmosSay.in | 5 + Tests/makedisks.sh | 33 +- Tests/manifest | 27 + Tests/run.sh | 19 + Tests/terminal.sh | 259 ++++++ makefile | 4 + 87 files changed, 2201 insertions(+), 74 deletions(-) create mode 100644 Programs/CosmOS/Apps/Edit.asm create mode 100644 Programs/CosmOS/Apps/Say.asm create mode 100644 Programs/testPrograms/sbfsEditTest.asm create mode 100644 Tests/expected/cosmosEdit.out create mode 100644 Tests/expected/cosmosFiles.out create mode 100644 Tests/expected/cosmosSay.out create mode 100644 Tests/expected/sbfsEditTest.out create mode 100644 Tests/input/cosmosEdit.in create mode 100644 Tests/input/cosmosFiles.in create mode 100644 Tests/input/cosmosSay.in create mode 100755 Tests/terminal.sh diff --git a/Programs/CosmOS/Apps/Edit.asm b/Programs/CosmOS/Apps/Edit.asm new file mode 100644 index 0000000..2042f73 --- /dev/null +++ b/Programs/CosmOS/Apps/Edit.asm @@ -0,0 +1,829 @@ +; Edit, a line editor for CosmOS. +; +; The first program on this machine that makes a file a person typed. Everything on every +; disk before this one was put there by the host tool. +; +; It is line oriented, in the manner of ed, and that is a deliberate choice rather than a +; limitation of the machine - Snake already draws a whole screen and steers with single +; keys. A full screen editor wants scrolling, a redraw model and cursor arithmetic, none of +; which teaches anything about files, and files are what this exists to exercise. So it +; stays in line mode and reads whole lines, which is what the console does without being +; asked for anything. +; +; l list the whole thing, numbered +; a add lines at the end, until a line that is just a dot +; i put lines in before line n, the same way +; c change line n +; d delete line n +; w write it back +; q stop without writing +; +; ---- How the text is kept ---- +; +; A LINKED LIST OF LINES, not one buffer with newlines in it. Each line is a node holding +; where the next one is, how long it is, and its bytes: +; +; 0 2 where the next line is, or zero +; 2 1 how many bytes this line has +; 3 the bytes +; +; Inserting is then two pointers changed and nothing moved, and so is deleting. With one +; flat buffer both of them would mean shifting everything after the edit, which on a +; machine with no memcpy is a loop over every byte of the rest of the document, run for +; every keystroke's worth of editing. +; +; The price is that DELETED LINES ARE NOT REUSED. A new line always goes at the end of the +; arena, and an unlinked one just sits there. A session that edits heavily uses more room +; than the document needs, and writing the file out and reading it back is what tidies it +; up. That is an honest trade for a program this size, and it is written down here rather +; than left as a surprise. +; +; Two regions are used by arrangement rather than reserved, because reserving them would +; put tens of kilobytes of zeroes into the file for no reason: +; +; 0x4000 the file, on its way in or out +; 0x8000 the arena the lines live in +; +; Nothing is running but this, so both are ours. It is the same arrangement CosmOS makes +; with 0x8000 while it is loading something, for the same reason. + +#Include services.asm + +#Program + + #Base 0x2000 + +start: + SETD.0 FileName + INIB 0d23 + SWI osArgument + SETD.0 FileName + LDA.0 + BRA noName + + ; Everything is set here rather than trusted to be zero, since running a program a second + ; time does not load it again. + RSTA + SETD.0 TextHead + STA.0 + INCD.0 + STA.0 + SETD.0 ArenaFree + INIA 0x80 + STA.0 + INCD.0 + RSTA + STA.0 + + CALL sbfsMount + BNQ noDisk + + CALL loadFile + + SETD.0 FileName + CALL printString + SETD.0 CommaText + CALL printString + CALL countLines + MVQA + CALL printByteDecimal + SETD.0 LinesText + CALL printString + CALL newLine + +commandLoop: + SETD.0 PromptText + CALL printString + SETD.0 Command + INIB 0d40 + CALL readLine + + ; Running out of typing ends it, the same way it ends the shell. + SETD.0 ConsoleEndOfInput + LDA.0 + BNA quit + + SETD.0 Command + LDA.0 + BRA commandLoop ; An empty line asks for nothing. + + ; Whatever number follows the letter, if there is one. The spaces between the two are + ; stepped over first: a number is what somebody typed after "d ", not after "d". + SETD.0 Command + INCD.0 +commandSpaces: + LDA.0 + INIB 0x20 + XOR + BNQ commandArgument + INCD.0 + BRI commandSpaces +commandArgument: + CALL textNumber + MVQA + SETD.0 Wanted + STA.0 + + SETD.0 Command + LDA.0 + + INIB 0d108 ; l + XOR + BRQ doList + INIB 0d97 ; a + XOR + BRQ doAppend + INIB 0d105 ; i + XOR + BRQ doInsert + INIB 0d99 ; c + XOR + BRQ doChange + INIB 0d100 ; d + XOR + BRQ doDelete + INIB 0d119 ; w + XOR + BRQ doWrite + INIB 0d113 ; q + XOR + BRQ quit + + SETD.0 WhatText + CALL printString + CALL newLine + BRI commandLoop + +quit: + SWI osExit + +noName: + SETD.0 NoNameText + CALL printString + CALL newLine + SWI osExit + +noDisk: + SETD.0 NoDiskText + CALL printString + CALL newLine + SWI osExit + +; ---- The commands ---- + +doList: + CALL listLines + BRI commandLoop + +doAppend: + CALL countLines + MVQA + INCA + SETD.0 Wanted + STA.0 ; Adding at the end is inserting before the line after it. + BRI insertLoop + +doInsert: + SETD.0 Wanted + LDA.0 + BRA insertNeedsLine +insertLoop: + SETD.0 EnteringText + CALL printString + SETD.0 Entry + INIB 0d80 + CALL readLine + SETD.0 ConsoleEndOfInput + LDA.0 + BNA commandLoop + + ; A line that is just a dot ends it, which is the oldest convention there is for this. + SETD.0 Entry + SETD.1 DotText + CALL textSame + BRQ commandLoop + + SETD.0 Entry + CALL makeNode + SETD.0 Wanted + LDA.0 + CALL linkBefore + SETD.0 Wanted + LDA.0 + INCA + STA.0 ; The next one goes after the one just put in. + BRI insertLoop + +insertNeedsLine: + SETD.0 NeedsLineText + CALL printString + CALL newLine + BRI commandLoop + +doChange: + SETD.0 Wanted + LDA.0 + BRA insertNeedsLine + CALL findLine + BNQ noSuchLine + + SETD.0 EnteringText + CALL printString + SETD.0 Entry + INIB 0d80 + CALL readLine + SETD.0 ConsoleEndOfInput + LDA.0 + BNA commandLoop + + SETD.0 Entry + CALL makeNode + SETD.0 Wanted + LDA.0 + CALL linkBefore ; The new one goes in front of the old one, + SETD.0 Wanted + LDA.0 + INCA + CALL unlinkLine ; and the old one, now one further along, comes out. + BRI commandLoop + +doDelete: + SETD.0 Wanted + LDA.0 + BRA insertNeedsLine + CALL unlinkLine + BNQ noSuchLine + BRI commandLoop + +noSuchLine: + SETD.0 NoLineText + CALL printString + CALL newLine + BRI commandLoop + +doWrite: + CALL writeFile + BNQ writeFailed + SETD.0 WrittenText + CALL printString + SETD.0 WroteSize + CALL printWordDecimal + SETD.0 BytesText + CALL printString + CALL newLine + BRI commandLoop + +writeFailed: + SETD.0 NoWriteText + CALL printString + CALL newLine + BRI commandLoop + +; ---- The list of lines ---- + +; DP0 is a string. Puts a node holding it at the end of the arena, and leaves DP3 on it. +makeNode: + SETD.1 ArenaFree + LDD.3.1 + + PSHD.3 + POPD.1 + RSTA + STA.1 ; Nothing follows it yet. + INCD.1 + STA.1 + INCD.1 + PSHD.1 ; Where the length goes, once it is known. + INCD.1 + RSTB + +makeNodeLoop: + LDA.0 + BRA makeNodeEnd + STA.1 + INCD.0 + INCD.1 + INCB + BRI makeNodeLoop + +makeNodeEnd: + POPD.0 + PSHB + POPA + STA.0 ; How long it turned out to be. + INIB 0d3 + CCF + ADD + MVQA + SETD.0 ArenaFree + CALL addByteToWord + RET + +; A is a line number. Leaves DP3 on that line and PrevLine on the one before it, which is +; zero when it is the first. Q is zero if there is such a line. +findLine: + SETD.1 Wanted2 + STA.1 + INIA 0d1 + SETD.1 Counted + STA.1 + RSTA + SETD.1 PrevLine + STA.1 + INCD.1 + STA.1 + SETD.1 TextHead + LDD.3.1 + +findLineStep: + PSHD.3 + POPA + POPB + OR + BRQ findLineMissing + + SETD.1 Counted + LDA.1 + SETD.1 Wanted2 + LDB.1 + XOR + BRQ findLineFound + + PSHD.3 + SETD.1 PrevLine + POPD.0 + STD.0.1 + PSHD.3 + POPD.0 + LDD.3.0 ; On to whatever follows it. + SETD.1 Counted + LDA.1 + INCA + STA.1 + BRI findLineStep + +findLineFound: + RSTA + RSTB + CCF + ADD + RET + +findLineMissing: + RSTA + INIB 0d1 + CCF + ADD + RET + +; DP3 is a new node and A is the line number it should become. Puts it there. +linkBefore: + PSHD.3 + SETD.1 NewLine + POPD.0 + STD.0.1 ; The new node, while the old ones are looked through. + + CALL findLine ; Which may miss, and missing means putting it at the end. + + ; What the new node should point at is whatever was there, or nothing. + SETD.1 NewLine + LDD.0.1 + BNQ linkBeforeAtEnd + PSHD.3 + POPD.1 + STD.1.0 ; new.next = the line that was there + BRI linkBeforeAttach + +linkBeforeAtEnd: + ; Nothing was there, so the new one ends the list and goes after whatever was last. + RSTA + STA.0 + INCD.0 + STA.0 + SETD.1 NewLine + LDD.0.1 + +linkBeforeAttach: + ; And whatever came before now points at the new one. Before the first line, that is + ; the head of the list rather than a node. + SETD.1 PrevLine + LDD.2.1 + PSHD.2 + POPA + POPB + OR + BRQ linkBeforeHead + + SETD.1 NewLine + LDD.0.1 + SETD.1 PrevLine + LDD.1.1 + STD.0.1 + RET + +linkBeforeHead: + SETD.1 NewLine + LDD.0.1 + SETD.1 TextHead + STD.0.1 + RET + +; A is a line number. Takes it out of the list. Q is zero if there was such a line. +unlinkLine: + CALL findLine + BNQ unlinkMissing + + ; What follows the one being taken out. + PSHD.3 + POPD.0 + LDD.0.0 + + SETD.1 PrevLine + LDD.2.1 + PSHD.2 + POPA + POPB + OR + BRQ unlinkHead + + SETD.1 PrevLine + LDD.1.1 + STD.0.1 + BRI unlinkDone + +unlinkHead: + SETD.1 TextHead + STD.0.1 + +unlinkDone: + RSTA + RSTB + CCF + ADD + RET + +unlinkMissing: + RSTA + INIB 0d1 + CCF + ADD + RET + +; Q is how many lines there are. +countLines: + RSTA + SETD.1 Counted + STA.1 + SETD.1 TextHead + LDD.3.1 +countStep: + PSHD.3 + POPA + POPB + OR + BRQ countDone + SETD.1 Counted + LDA.1 + INCA + STA.1 + PSHD.3 + POPD.0 + LDD.3.0 + BRI countStep +countDone: + SETD.1 Counted + LDA.1 + RSTB + CCF + ADD + RET + +listLines: + INIA 0d1 + SETD.1 Counted + STA.1 + SETD.1 TextHead + LDD.3.1 +listStep: + PSHD.3 + POPA + POPB + OR + BRQ listDone + + SETD.0 Counted + LDA.0 + CALL printByteDecimal + SETD.0 ColonText + CALL printString + + PSHD.3 + POPD.1 + DPUP.1 0d02 + LDA.1 + SETD.1 Leftover + STA.1 + PSHD.3 + POPD.0 + DPUP.0 0d03 + SETD.1 Leftover + LDA.1 + BRA listEmpty +listChars: + LDA.0 + OUTA 0x00 + INCD.0 + SETD.1 Leftover + LDA.1 + DECA + STA.1 + BNA listChars +listEmpty: + CALL newLine + + SETD.1 Counted + LDA.1 + INCA + STA.1 + PSHD.3 + POPD.0 + LDD.3.0 + BRI listStep +listDone: + RET + +; ---- The file ---- + +; Reads the file into lines, if there is one. A name that is not on the disk is a new +; document rather than a mistake, which is what makes this the way to start one. +loadFile: + SETD.0 FileName + CALL sbfsFind + BNQ loadNothing + + SETD.1 0x40 0x00 + CALL sbfsRead + BNQ loadNothing + + ; How many bytes came back: the block count is the high byte of the length and the tail + ; is the low one, which is how a size is put together everywhere on this disk. + SETD.0 SbfsFileBlocks + DPUP.0 0d01 + LDA.0 + SETD.1 ReadLeft + STA.1 + SETD.0 SbfsFileTail + LDA.0 + SETD.1 ReadLeft + INCD.1 + STA.1 + + SETD.0 0x40 0x00 + SETD.1 Entry + RSTA + SETD.2 EntryLength + STA.2 + +splitStep: + ; Anything left? + SETD.2 ReadLeft + LDA.2 + INCD.2 + LDB.2 + OR + BRQ splitLast + + ; How long the line is so far is kept in memory rather than in B, because comparing + ; against a newline needs B and would quietly count the comparison instead of the line. + LDA.0 + INIB 0d10 + XOR + BRQ splitLine + + STA.1 ; A is still the character; an ALU operation does not touch it. + INCD.1 + SETD.2 EntryLength + LDA.2 + INCA + STA.2 + BRI splitOn + +splitLine: + RSTA + STA.1 ; The line ends here, so it becomes a string. + PSHD.0 ; How far through the file we are. + SETD.0 Entry + CALL makeNode + CALL appendNode + POPD.0 + SETD.1 Entry + RSTA + SETD.2 EntryLength + STA.2 + +splitOn: + INCD.0 + SETD.2 ReadLeft + CALL takeOneOff + BRI splitStep + +splitLast: + ; A file that does not end in a newline still has a last line in it. + SETD.2 EntryLength + LDA.2 + BRA loadNothing + RSTA + STA.1 + SETD.0 Entry + CALL makeNode + CALL appendNode +loadNothing: + RET + +; DP3 is a node. Puts it on the end of the list. +appendNode: + ; The node has to be put somewhere safe first: counting the lines walks the list in DP3, + ; which is where the node being added is being held. + PSHD.3 + CALL countLines + MVQA + INCA + POPD.3 + CALL linkBefore + RET + +; DP2 is a two byte count. Takes one off it. +takeOneOff: + DPUP.2 0d01 + LDA.2 + DECA + STA.2 + BNC takeOneDone ; No borrow, so the high half is untouched. + DPDN.2 0d01 + LDA.2 + DECA + STA.2 + RET +takeOneDone: + RET + +; Builds the whole document at 0x4000 and saves it. Q is zero if it worked. +writeFile: + SETD.1 0x40 0x00 + SETD.2 TextHead + LDD.3.2 + +writeStep: + PSHD.3 + POPA + POPB + OR + BRQ writeOut + + PSHD.3 + POPD.0 + DPUP.0 0d02 + LDA.0 + SETD.2 Leftover + STA.2 + INCD.0 + LDA.2 + BRA writeBreak +writeChars: + LDA.0 + STA.1 + INCD.0 + INCD.1 + SETD.2 Leftover + LDA.2 + DECA + STA.2 + BNA writeChars +writeBreak: + INIA 0d10 + STA.1 + INCD.1 + + PSHD.3 + POPD.0 + LDD.3.0 + BRI writeStep + +writeOut: + ; Where the building stopped says how big it is, with no arithmetic worth the name: the + ; buffer starts on a page boundary at 0x4000, so the high byte less 0x40 is the number of + ; whole blocks and the low byte is the tail. + SETD.2 WroteSize + STD.1.2 + SETD.0 WroteSize + LDA.0 + INIB 0x40 + CCF + SUB + MVQA + SETD.0 SbfsFileBlocks + RSTB + STB.0 + INCD.0 + STA.0 + SETD.0 WroteSize + INCD.0 + LDA.0 + SETD.0 SbfsFileTail + STA.0 + + ; The size the file is about to be, said in bytes, before saving changes what these mean. + SETD.0 WroteSize + LDA.0 + INIB 0x40 + CCF + SUB + MVQA + SETD.0 WroteSize + STA.0 + + SETD.0 FileName + SETD.1 0x40 0x00 + CALL sbfsSaveFile + RET + +; DP0 is a two byte number, A is a byte. Adds the one to the other. +addByteToWord: + DPUP.0 0d01 + LDB.0 + CCF + ADD + STQ.0 + DPDN.0 0d01 + LDA.0 + RSTB + ADD + STQ.0 + RET + +#Data + + #Base 0x1000 + +PromptText: +"> " +EnteringText: +": " +ColonText: +": " +CommaText: +", " +LinesText: +" lines" +WrittenText: +"written, " +BytesText: +" bytes" +DotText: +"." +WhatText: +"l list, a add, i insert, c change, d delete, w write, q quit" +NoNameText: +"edit what? try: run edit " +NoDiskText: +"there is no disk" +NoLineText: +"there is no such line" +NeedsLineText: +"which line?" +NoWriteText: +"it would not write" + +FileName: + #Reserve 0d24 +Command: + #Reserve 0d41 +Entry: + #Reserve 0d81 + +TextHead: + 0x00 0x00 +ArenaFree: + 0x00 0x00 +PrevLine: + 0x00 0x00 +NewLine: + 0x00 0x00 +Wanted: + 0x00 +Wanted2: + 0x00 +Counted: + 0x00 +Leftover: + 0x00 +EntryLength: + 0x00 +ReadLeft: + 0x00 0x00 +WroteSize: + 0x00 0x00 + +#Include sbfs.asm +#Include text.asm +#Include console.asm diff --git a/Programs/CosmOS/Apps/Say.asm b/Programs/CosmOS/Apps/Say.asm new file mode 100644 index 0000000..c80cf38 --- /dev/null +++ b/Programs/CosmOS/Apps/Say.asm @@ -0,0 +1,57 @@ +; A program that is told what to work on. +; +; Everything loaded before this one did the same thing however it was started, because +; there was no way to tell one anything. A tool that edits a document needs to know which +; document, and that is the same need a dozen other things will have, so it is a service +; rather than something an editor arranges for itself. +; +; run says it was given nothing +; run whatever else says "whatever else" +; +; The whole rest of the line arrives, spaces and all, rather than a list of words. What +; counts as an argument is the program's business; the system's business is handing over +; what was typed. + +#Include services.asm + +#Program + + #Base 0x2000 + +start: + SETD.0 Given + INIB 0d64 + SWI osArgument + + SETD.0 Given + LDA.0 + BRA sayNothing + + SETD.0 SaidText + SWI osPrintString + SETD.0 Given + SWI osPrintString + BRI sayEnd + +sayNothing: + SETD.0 NothingText + SWI osPrintString + +sayEnd: + SETD.0 NewLine + SWI osPrintString + SWI osExit + +#Data + + #Base 0x1000 + +SaidText: +"it says: " +NothingText: +"nothing was said" +NewLine: + 0x0A 0x00 + +Given: + #Reserve 0d64 diff --git a/Programs/CosmOS/Source/cosmos.asm b/Programs/CosmOS/Source/cosmos.asm index 3f6e4da..ba6609a 100644 --- a/Programs/CosmOS/Source/cosmos.asm +++ b/Programs/CosmOS/Source/cosmos.asm @@ -109,6 +109,16 @@ prompt: CALL textSame BRQ doDump + SETD.0 CommandLine + SETD.1 DeleteName + CALL textSame + BRQ doDelete + + SETD.0 CommandLine + SETD.1 RenameName + CALL textSame + BRQ doRename + SETD.0 CommandLine SETD.1 HelpName CALL textSame @@ -195,7 +205,16 @@ dirDone: SETD.0 DirSeen LDA.0 CALL printByteDecimal + ; One file is not one files. Cheap to get right and it reads as carelessness otherwise. + SETD.0 DirSeen + LDA.0 + DECA + BRA dirOne SETD.0 FilesText + BRI dirCount +dirOne: + SETD.0 FileText +dirCount: CALL printString CALL newLine BRI prompt @@ -470,6 +489,84 @@ loadComplain: CALL newLine BRI prompt +; ---- delete and rename ---- +; +; The two things a disk needs that reading and writing do not provide, and the two that +; anything editing a document will want from the shell as well as from a program. Deleting +; frees an entry and its blocks; renaming changes twenty two bytes and moves nothing. + +doDelete: + SETD.0 DiskReady + LDA.0 + BRA fileNoDisk + + SETD.1 TextRest + LDD.0.1 + LDA.0 + BRA deleteWhat + + CALL sbfsDelete + BNQ deleteFailed + SETD.0 Deleted + CALL printString + CALL newLine + BRI prompt + +deleteWhat: + SETD.0 DeleteWhat + BRI fileComplain +deleteFailed: + SETD.0 NoSuchFile + BRI fileComplain + +doRename: + SETD.0 DiskReady + LDA.0 + BRA fileNoDisk + + SETD.1 TextRest + LDD.0.1 + LDA.0 + BRA renameWhat + + ; Two names, so the rest of the line is split again. textSplit writes a zero over the + ; space it cuts at, so what was one string becomes two without anything being copied. + SETD.1 TextRest + LDD.0.1 + SETD.1 RenameFrom + STD.0.1 + CALL textSplit + + SETD.1 TextRest + LDD.1.1 + LDA.1 + BRA renameWhat ; Only one name was given, and this needs both. + + SETD.2 RenameFrom + LDD.0.2 + CALL sbfsRename + BNQ renameFailed + SETD.0 Renamed + CALL printString + CALL newLine + BRI prompt + +renameWhat: + SETD.0 RenameWhat + BRI fileComplain +renameFailed: + ; Either there is no such file or the new name is already taken. Which of the two is not + ; worth another message: both mean the disk does not have room for that name to move. + SETD.0 RenameNo + BRI fileComplain + +fileNoDisk: + SETD.0 NoDisk +fileComplain: + CALL printString + CALL newLine + BRI prompt + ; ---- run ---- ; ; Hands the machine to whatever was loaded. Where the Stack is now is written down first, @@ -485,6 +582,15 @@ doRun: SETD.1 SystemStack STD.0.1 + ; Whatever followed the word "run" is kept where the program can ask for it. Copied + ; rather than pointed at, because what it is pointing at is the line the shell typed + ; into, and a program is entitled to outlive the shell's opinion of that. + SETD.1 TextRest + LDD.0.1 + SETD.1 RunArgument + INIB 0d64 + CALL copyText + CALL installVectors ; The entry address is a number until BRD makes it a place. DP3 is the one to build it @@ -499,6 +605,26 @@ runNothing: CALL newLine BRI prompt +; DP0 is a string, DP1 is where it should go, and B is how much room there is counting +; the zero on the end. What does not fit is left behind, and what is written is a string +; either way. +copyText: + BRB copyTextDone ; No room at all, so nothing is written, not even the zero. +copyTextLoop: + DECB + BRB copyTextEnd ; Only room for the terminator now. + LDA.0 + STA.1 + BRA copyTextDone + INCD.0 + INCD.1 + BRI copyTextLoop +copyTextEnd: + RSTA + STA.1 +copyTextDone: + RET + ; ---- Putting a program's vectors in, and taking them out again ---- ; ; The vector table lives in Program Memory, which no instruction can write, so both of @@ -635,6 +761,20 @@ handleReadLine: CALL readLine RETI +; What the program was asked to work on. DP0 says where to put it and B how much room +; there is, counting the zero on the end, which is the same bargain readLine offers. +; +; Being asked for rather than left at an agreed address is deliberate. The two sides of +; this already have to agree on a vector number and nothing else, and that number is +; written down once in services.asm; an address would be a second thing to agree about, in +; a memory map that is a convention rather than anything enforced. +handleArgument: + PSHD.0 + POPD.1 + SETD.0 RunArgument + CALL copyText + RETI + ; Giving the machine back. This is the one place MVDS earns its keep. The program's Stack, ; and the frame this very interrupt arrived on, are both abandoned where they lie, because ; nothing is going to return through either of them. @@ -893,13 +1033,17 @@ Farewell: "halted" FilesText: " files" +FileText: +" file" ; Two strings rather than one, because a string literal stops at 255 characters and each ; one carries its own zero byte, so they are printed in turn rather than joined. HelpText: "dir list what is on the disk load read a program off the disk -run start what was loaded" +run [words] start what was loaded, and tell it those words +delete take it off the disk +rename call it something else" HelpMoreText: "dump sixty four bytes of memory, and again for more dump
@@ -923,6 +1067,16 @@ LoadWhat: "load what?" NoSuchFile: "no such file" +Deleted: +"gone" +Renamed: +"renamed" +DeleteWhat: +"delete what?" +RenameWhat: +"rename what to what?" +RenameNo: +"there is no such file, or that name is taken" TooManyVectors: "that program wants more vectors than there is room for" Unreadable: @@ -944,6 +1098,10 @@ LoadName: "load" RunName: "run" +DeleteName: +"delete" +RenameName: +"rename" HelpName: "help" ExitName: @@ -960,6 +1118,15 @@ LoadCount: LoadVersion: 0x00 +; Where the first of rename's two names is, kept while the second is picked out of the +; line, since finding that needs the pointers for itself. +RenameFrom: + 0x00 0x00 + +; What followed "run", kept for the program to ask for. +RunArgument: + #Reserve 0d64 + ; ---- The vectors a loaded program brought with it ---- ; ; Six bytes each: where it goes, what goes there, and what was there before. The last two @@ -1013,4 +1180,5 @@ CommandLine: osPrintString handlePrintString osReadLine handleReadLine osExit handleExit + osArgument handleArgument Device 0x20 diskDone diff --git a/Programs/CosmOS/Source/sbfs.asm b/Programs/CosmOS/Source/sbfs.asm index 44e8999..a81aaf3 100644 --- a/Programs/CosmOS/Source/sbfs.asm +++ b/Programs/CosmOS/Source/sbfs.asm @@ -991,6 +991,208 @@ sbfsSameByte: XOR RET +; ---- Deleting ---- +; +; Frees a file. DP0 names it, and Q is zero if it went. +; +; A deleted entry and one that was never used are the same thing, which is the whole of +; what deleting is here: the entry is zeroed and its blocks stop being spoken for. THE +; BLOCKS THEMSELVES ARE LEFT EXACTLY AS THEY WERE, so what was in a file is still on the +; disk until something is put over the top of it. Worth knowing if anything is ever meant +; to be private. The host tool does the same, so the two agree about what a deleted disk +; looks like. +; +; Nothing is compacted. Deleting leaves a hole, and because files are contiguous a hole is +; only usable by something that fits inside it. That is the price of the directory being +; the whole allocation map, and tidying it up is an ordinary program somebody can write +; rather than anything the format has to say. +sbfsDelete: + CALL sbfsFind + BNQ sbfsDeleteFailed + + ; How much room it was taking, worked out before the entry that says so is thrown away. + CALL sbfsFileExtent + + ; sbfsFind leaves DP3 on the entry and SbfsBlock on the directory block it came out of, + ; which is everything needed to change it and put it back. + PSHD.3 + POPD.0 + INIB 0d32 +sbfsDeleteWipe: + RSTA + STA.0 + INCD.0 + DECB + BNB sbfsDeleteWipe + + SETD.1 SbfsBuffer + CALL sbfsBufferIn + CALL sbfsWriteBlock + BNQ sbfsDeleteFailed + + ; And the free count goes back up. It is a note rather than the truth, but a note worth + ; keeping right. + RSTA + SETD.0 SbfsBlock + STA.0 + INCD.0 + STA.0 + CALL sbfsReadBlock + BNQ sbfsDeleteFailed + SETD.1 SbfsBuffer + CALL sbfsBufferOut + SETD.0 SbfsBuffer + DPUP.0 0d12 + SETD.2 SbfsWantBlocks + CALL sbfsAddWord + SETD.1 SbfsBuffer + CALL sbfsBufferIn + CALL sbfsWriteBlock + RET + +sbfsDeleteFailed: + RSTA + INIB 0d1 + CCF + ADD + RET + +; ---- Renaming ---- +; +; DP0 is the name a file has, DP1 is the name it should have. Q is zero if it was renamed. +; +; Only the twenty two bytes of the name change, so no data moves and no block is touched +; but the one holding the entry. THAT IS WHAT MAKES A SAFE SAVE POSSIBLE. Writing a file +; that has grown means putting it somewhere else, and the obvious order - throw the old one +; away, then write the new one - loses the lot if there turns out to be nowhere to put it. +; Renaming is the cheapest thing this filesystem can do and the only one that can be left +; until last, so it is what the order is built around. +sbfsRename: + ; Where the old name is, kept somewhere that finding things will not tread on. + SETD.2 SbfsSavedName + STD.0.2 + + PSHD.1 + POPD.0 + SETD.1 SbfsNewName + CALL sbfsKeepName ; Twenty two bytes, padded, the way an entry holds one. + + ; Refused if something already answers to the new name. Two entries with one name is a + ; disk that cannot be searched sensibly: a search answers with whichever it meets first, + ; so the other becomes unreachable without ever having been deleted. + SETD.0 SbfsNewName + CALL sbfsFind + BRQ sbfsRenameFailed + + SETD.2 SbfsSavedName + LDD.0.2 + CALL sbfsFind + BNQ sbfsRenameFailed + + PSHD.3 + POPD.1 + DPUP.1 0d06 ; Past the flags, the start, the block count and the tail. + SETD.0 SbfsNewName + INIA 0d22 + SETD.2 SbfsCount + STA.2 +sbfsRenameName: + LDA.0 + STA.1 + INCD.0 + INCD.1 + LDA.2 + DECA + STA.2 + BNA sbfsRenameName + + SETD.1 SbfsBuffer + CALL sbfsBufferIn + CALL sbfsWriteBlock + RET + +sbfsRenameFailed: + RSTA + INIB 0d1 + CCF + ADD + RET + +; ---- Saving over something that is already there ---- +; +; DP0 names the file, DP1 is the data, and SbfsFileBlocks with SbfsFileTail say how big it +; now is. Q is zero if it was saved. +; +; This is the routine every tool that edits a document wants, and the reason it is here +; rather than in each of them is that the careful order is not obvious and getting it wrong +; destroys somebody's work: +; +; make a temporary nothing is lost if there is nowhere to put it +; write it +; delete the original only once the new one is safely down +; rename the temporary +; +; The obvious order - delete, create, write - looks fine and is a trap. Files here are +; contiguous, so a file that has grown may not fit where it was, and a create can be +; refused for want of a run long enough even on a disk with plenty of free blocks. Do it +; that way round and the original is already gone when that happens. +sbfsSaveFile: + SETD.2 SbfsSaveName + STD.0.2 + SETD.2 SbfsSaveData + STD.1.2 + + ; How big it is, kept aside: finding and deleting things both overwrite the place the + ; size is normally said, because both of them describe whatever they last looked at. + SETD.0 SbfsSaveBlocks + SETD.2 SbfsFileBlocks + CALL sbfsSetWord + SETD.0 SbfsFileTail + LDA.0 + SETD.1 SbfsSaveTail + STA.1 + + ; A temporary left behind by a save that did not finish would be in the way. Whether + ; there was one is not worth asking about, since either answer leads here. + SETD.0 SbfsTempName + CALL sbfsDelete + + SETD.0 SbfsFileBlocks + SETD.2 SbfsSaveBlocks + CALL sbfsSetWord + SETD.0 SbfsSaveTail + LDA.0 + SETD.1 SbfsFileTail + STA.1 + + SETD.0 SbfsTempName + CALL sbfsCreate + BNQ sbfsSaveFailed + + SETD.2 SbfsSaveData + LDD.1.2 + CALL sbfsWriteFile + BNQ sbfsSaveFailed + + ; Now, and not before, the old one goes. It may not exist, which is what saving something + ; for the first time looks like from here. + SETD.2 SbfsSaveName + LDD.0.2 + CALL sbfsDelete + + SETD.0 SbfsTempName + SETD.2 SbfsSaveName + LDD.1.2 + CALL sbfsRename + RET + +sbfsSaveFailed: + RSTA + INIB 0d1 + CCF + ADD + RET + #Data SbfsMagic: @@ -1050,5 +1252,29 @@ SbfsName: SbfsWanted: #Reserve 0d22 +; ---- What renaming and saving keep ---- + +; A name on its way into an entry, padded to the twenty two bytes an entry holds. +SbfsNewName: + #Reserve 0d22 + +; Where a name lives, kept across a search, which needs the pointers for itself. +SbfsSavedName: + 0x00 0x00 + +SbfsSaveName: + 0x00 0x00 +SbfsSaveData: + 0x00 0x00 +SbfsSaveBlocks: + 0x00 0x00 +SbfsSaveTail: + 0x00 + +; What a document is called while it is being written and is not yet the real thing. A +; name nothing else is likely to want, and short enough to leave room for a long one. +SbfsTempName: +"sbfs.part" + SbfsBuffer: #Reserve 0d256 diff --git a/Programs/CosmOS/Source/services.asm b/Programs/CosmOS/Source/services.asm index 99ea515..dd11f44 100644 --- a/Programs/CosmOS/Source/services.asm +++ b/Programs/CosmOS/Source/services.asm @@ -24,3 +24,4 @@ osPrintString 0d16 ; DP0 names a string. Prints it. osReadLine 0d17 ; DP0 names somewhere to put a line read from the console. osExit 0d18 ; Give the machine back to the system. + osArgument 0d19 ; DP0 names somewhere to put the rest of the run command. diff --git a/Programs/CosmOS/Source/text.asm b/Programs/CosmOS/Source/text.asm index db1478f..5c77767 100644 --- a/Programs/CosmOS/Source/text.asm +++ b/Programs/CosmOS/Source/text.asm @@ -215,6 +215,82 @@ textHexNo: ADD RET +; ---- A number written in decimal ---- +; +; DP0 names it. Q is the value, and TextDigits says how many digits were read, which is +; zero when there was no number there at all. Stops at the first thing that is not a digit. +; +; Decimal rather than hex, and one byte rather than two, because this is for the numbers a +; person types at a program: a line number, a count, a how many. Nobody counts lines in +; hex, and nobody types a line number above 255 on a machine this size. textHexWord is +; still the one for an address, where hex is what everybody means. +; +; Ten times the running total is worked out as eight of it plus two of it, because nothing +; on this machine multiplies. Anything past 255 wraps, which is what the same sum does +; everywhere else here. +textNumber: + RSTA + SETD.1 TextValue + STA.1 + SETD.1 TextDigits + STA.1 + +textNumberLoop: + LDA.0 + BRA textNumberDone + + ; Below '0' or above '9' ends it. + INIB 0d48 + CCF + SUB + BRC textNumberDone ; It borrowed, so the character was below '0'. + MVQA + INIB 0d10 + CCF + SUB + BNC textNumberDone ; It did not borrow, so it was ten or more past '0'. + + PSHA ; The digit, while the total is multiplied. + SETD.1 TextValue + LDA.1 + LDB.1 + CCF + ADD ; Twice. + MVQA + MVQB + PSHA ; Twice, kept: ten is eight and two. + CCF + ADD ; Four times. + MVQA + MVQB + CCF + ADD ; Eight times. + MVQA + POPB + CCF + ADD ; Ten times. + MVQA + POPB + CCF + ADD ; And the digit. + SETD.1 TextValue + STQ.1 + + SETD.1 TextDigits + LDA.1 + INCA + STA.1 + INCD.0 + BRI textNumberLoop + +textNumberDone: + SETD.1 TextValue + LDA.1 + RSTB + CCF + ADD ; Q is the value, the way a routine hands a byte back. + RET + #Data ; Where the rest of the line begins, after textSplit has taken a word off the front. diff --git a/Programs/makefile b/Programs/makefile index 6ed6c83..b7933ae 100644 --- a/Programs/makefile +++ b/Programs/makefile @@ -76,7 +76,7 @@ cosmos: $(COSMOS) $(APPS) $(COSMOS_DISK): $(APPS) @mkdir -p $(@D) rm -f $@ - $(DISKTOOL) format $@ 64 2 + $(DISKTOOL) format $@ 256 2 @for app in $(APPS); do $(DISKTOOL) put $@ $$app; done cosmos-disk: $(COSMOS_DISK) diff --git a/Programs/testPrograms/sbfsEditTest.asm b/Programs/testPrograms/sbfsEditTest.asm new file mode 100644 index 0000000..e1252fa --- /dev/null +++ b/Programs/testPrograms/sbfsEditTest.asm @@ -0,0 +1,233 @@ +; Deleting, renaming, and saving over something that is already there. +; +; Reading and writing were built first because a program had to be got onto a disk and off +; it again. What a document needs is different and it is all about the second time: a file +; that is written once is easy, and a file that is written again having grown is where this +; format's bargain shows. Files are contiguous and do not grow, so saving a longer version +; means putting it somewhere else and letting go of where it was. +; +; THE ORDER MATTERS AND THE OBVIOUS ONE IS WRONG. Delete the old, create the new, write it: +; that loses the lot when the create is refused for want of a run long enough, which is a +; thing that happens on a disk with plenty of free blocks once it is in pieces. sbfsSaveFile +; does it the other way round, and the rename at the end of that is why renaming exists. +; +; Correct output is: +; here.txt 0002 already here +; doc.txt 0003 first draft +; doc.txt 0004 a second draft, which is longer than the first +; notes.txt 0004 a second draft, which is longer than the first +; doc.txt gone +; notes.txt gone +; +; The start block moving from 0003 to 0004 is the file being put somewhere else, which is +; what saving a longer one has to do. The last two lines are a rename and a delete having +; actually happened rather than having been reported. + +#Include print.asm +#Include sbfs.asm + +#Program + +start: + CALL sbfsMount + BNQ failed + + SETD.0 Existing + CALL report + BNQ failed + + ; Written once, the ordinary way. + SETD.0 DocName + SETD.1 ShortText + INIA 0d11 + CALL makeAndWrite + BNQ failed + SETD.0 DocName + CALL report + BNQ failed + + ; And again, longer. Nothing here says where it goes; that is sbfsSaveFile's business. + SETD.0 SbfsFileBlocks + RSTA + STA.0 + INCD.0 + STA.0 + SETD.0 SbfsFileTail + INIA 0d46 + STA.0 + SETD.0 DocName + SETD.1 LongText + CALL sbfsSaveFile + BNQ failed + SETD.0 DocName + CALL report + BNQ failed + + ; Renaming moves nothing: the same blocks answer to a different name. + SETD.0 DocName + SETD.1 NewName + CALL sbfsRename + BNQ failed + SETD.0 NewName + CALL report + BNQ failed + + ; And the old name is not there any more, which is the half of renaming that could have + ; quietly not happened. + SETD.0 DocName + CALL expectGone + + SETD.0 NewName + CALL sbfsDelete + BNQ failed + SETD.0 NewName + CALL expectGone + HALT + +failed: + SETD.0 Failed + CALL printString + CALL lineFeed + HALT + +; DP0 names the file, DP1 is its text, A is how long it is. Everything here fits in a +; block, so the whole length is the tail. +makeAndWrite: + PSHD.1 + SETD.1 SbfsFileTail + STA.1 + RSTA + SETD.1 SbfsFileBlocks + STA.1 + INCD.1 + STA.1 + CALL sbfsCreate + POPD.1 + BNQ makeFailed + CALL sbfsWriteFile + RET +makeFailed: + RET + +; DP0 names a file that should not be there. Says so either way. +expectGone: + PSHD.0 + POPD.3 + CALL printString + CALL padName + PSHD.3 + POPD.0 + CALL sbfsFind + BRQ goneStillThere + SETD.0 GoneText + CALL printString + CALL lineFeed + RET +goneStillThere: + SETD.0 StillText + CALL printString + CALL lineFeed + RET + +; Prints a file's name, where it begins, and what is in it. +report: + PSHD.0 + POPD.3 + CALL printString + CALL padName + PSHD.3 + POPD.0 + CALL sbfsFind + BNQ reportFailed + + SETD.0 SbfsFileStart + LDA.0 + CALL printByteHex + INCD.0 + LDA.0 + CALL printByteHex + CALL blankSpace + + SETD.1 Landing + CALL sbfsRead + BNQ reportFailed + + SETD.0 Landing + SETD.1 SbfsFileTail + LDA.1 + SETD.1 LeftOver + STA.1 + BRA reportEnd +reportLoop: + LDA.0 + OUTA 0x00 + INCD.0 + SETD.1 LeftOver + LDA.1 + DECA + STA.1 + BNA reportLoop +reportEnd: + CALL lineFeed + RSTA + RSTB + CCF + ADD + RET + +reportFailed: + RSTA + INIB 0d1 + CCF + ADD + RET + +; Names are different lengths and the columns should not be, so this pads out to eleven. +; DP3 holds the name, which is where the caller left it. +padName: + PSHD.3 + POPD.0 + INIB 0d11 +padCount: + LDA.0 + BRA padOut + INCD.0 + DECB + BNB padCount +padOut: + RSTA +padLoop: + BRB padDone + INIA 0x20 + OUTA 0x00 + DECB + BRI padLoop +padDone: + RET + +#Data + +Existing: +"here.txt" +DocName: +"doc.txt" +NewName: +"notes.txt" + +ShortText: +"first draft" +LongText: +"a second draft, which is longer than the first" + +GoneText: +"gone" +StillText: +"STILL THERE" +Failed: +"failed" + +LeftOver: + 0x00 + +Landing: + #Reserve 0d256 diff --git a/README.md b/README.md index 0a5c806..8d02ee9 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,10 @@ Disk images that tests read from are built by Tests/makedisks.sh before the run, The disk tool is checked separately by Tests/disk.sh, which make test runs afterwards: it puts files of every awkward size onto an image and takes them off again, and checks that the things the format says cannot happen are refused. +Tests/terminal.sh checks the things a recorded output cannot see. Every other test pipes input in and output to a file, which answers what a program prints and is blind to two whole classes of behaviour: **when** something is printed, since piped output is buffered and flushed at exit, so a prompt shown before its answer is asked for and one shown an hour late produce identical files; and **what happens to the terminal**, since key mode only touches one when there is one. Both have gone wrong here, and both were found by a person whose terminal stopped working rather than by anything in this suite. So it runs the emulator under a pseudo-terminal and asks the questions directly: that a prompt arrives before input is read, that a keystroke arrives without Return, that the terminal is handed back however the machine dies, and that suspending and resuming leave it as they found it. + +A cycle count is deliberately **not** part of a recorded result. The last line of the emulator's output has the number taken out of it before anything is compared, keeping only whether the program stopped on its own or ran into its limit, which is behaviour. Two instructions added to CosmOS used to move that number in six unrelated files at once, so a real difference would arrive in a crowd of meaningless ones. Anything that wants to measure cycles should say so in a test of its own. + Tests/docs.sh then checks the manuals against the code: that every instruction has a row and every row is an instruction, that the counts in the headings are right, that every directive is written down, that every routine the manuals promise exists, and that the worked examples still assemble to the bytes printed beside them. Documentation goes stale quietly, and this is what stops it. Tests are defined in Tests/manifest, one line per program. To record the current output as the expected result, after you have checked that it is correct: diff --git a/Source/Assembler/firstPass.c b/Source/Assembler/firstPass.c index 3623214..9d2f699 100644 --- a/Source/Assembler/firstPass.c +++ b/Source/Assembler/firstPass.c @@ -166,8 +166,18 @@ int loadFile(intermediateElement **intermediateArray, char *fileName, int *inter exit(1); } // Read off tokens. - while (readToken(&(*intermediateArray)[*intermediateIndex], file, &lineNumber)) { - if ((size_t)*intermediateIndex >= *arraySize - 1) { + // + // ROOM IS MADE BEFORE THE TOKEN IS READ, not after. readToken writes into the element + // at the current index, so a check that came afterwards was checking whether the write + // that had already happened was allowed to. It survived for a long time because the + // margin usually covered it, and stopped surviving when a file grew past a doubling: + // several paths below take a SECOND element for one token - an #Include takes one for + // the file name, #Align and #Reserve take one for the count - so the index can move by + // two in an iteration and step straight over a margin of one. + // + // The margin is two for that reason, which is the most any one iteration uses. + while (1) { + if ((size_t)*intermediateIndex + 2 >= *arraySize) { size_t grownSize = *arraySize * 2; // Double the size of the array. // Into a temporary, so that the old allocation is still ours to free if // this fails, rather than being lost the moment realloc returns NULL. @@ -184,7 +194,9 @@ int loadFile(intermediateElement **intermediateArray, char *fileName, int *inter *intermediateArray = grown; *arraySize = grownSize; } - //printf("Token number %d\n", intermediateIndex); + if (!readToken(&(*intermediateArray)[*intermediateIndex], file, &lineNumber)) { + break; + } // Go ahead and mark what we already know about this token. (*intermediateArray)[*intermediateIndex].fileName = fileName; (*intermediateArray)[*intermediateIndex].lineNumber = lineNumber; diff --git a/SplitBit Programming Manual.md b/SplitBit Programming Manual.md index 2f2f65e..b816c6a 100644 --- a/SplitBit Programming Manual.md +++ b/SplitBit Programming Manual.md @@ -454,9 +454,9 @@ Status bit 1 says the last operation failed: there is no disk, or the block aske A disk error is not a fault. Faults on this machine mean it cannot continue, and a read that fails is an ordinary thing that happens to working programs on failing media. It is reported so that a program can cope with it, rather than stopping the machine and taking the choice away. -## Reading The Filesystem: +## Reading And Writing The Filesystem: -The disk knows blocks and nothing else, so a filesystem is software. Programs/CosmOS/Source/sbfs.asm reads one. +The disk knows blocks and nothing else, so a filesystem is software. Programs/CosmOS/Source/sbfs.asm is one. | Routine | Does | | --- | --- | @@ -467,11 +467,35 @@ The disk knows blocks and nothing else, so a filesystem is software. Programs/Co | sbfsNext | Steps the walk to the next entry in use. Q is zero if there was one. | | sbfsCreate | Makes a file. DP0 names it, and SbfsFileBlocks with SbfsFileTail say how big it is. Q is zero if it was made, and then SbfsFileStart says where it went. | | sbfsWriteFile | Writes the file that was made, from Data Memory at DP1. | +| sbfsDelete | DP0 names a file. Frees its entry and its blocks. Q is zero if it went. | +| sbfsRename | DP0 is the name a file has, DP1 the name it should have. Q is zero if it was renamed. Refused if something already answers to the new name. | +| sbfsSaveFile | DP0 names the file, DP1 is the data, and SbfsFileBlocks with SbfsFileTail say how big it now is. Writes it whether or not it was there before, and whatever size it used to be. | Finding a file and listing what is there are different jobs. sbfsFind searches for one name; sbfsFirst and sbfsNext walk the whole directory, stopping on each entry that is in use and stepping over the free ones. A walk keeps a directory block in SbfsBuffer between calls, so anything else that goes to the disk in the middle of one ends it: take what is wanted out of an entry before asking the disk for anything else. A file's size is settled when it is made, because nothing can grow one afterwards. Files are laid down contiguously, so the block after a file usually belongs to somebody else. A program that does not know how much it will write has to guess high and accept the slack, or build its output elsewhere and make the file once the size is known. +### Saving Something Twice: + +Which is why saving a document is not the same as writing a file, and why sbfsSaveFile exists rather than each tool doing it. A file that has grown will usually not fit where it was, so saving it means putting it somewhere else and letting go of where it was — and **the obvious order is a trap**: + +``` + delete the old one + make a new one <- refused, and the old one is already gone + write it +``` + +A create can be refused for want of a run long enough even on a disk with plenty of free blocks, because free blocks are only useful to a contiguous file when they are next to each other. Done in that order, the first fragmented disk somebody meets eats their work. sbfsSaveFile does it the other way round: + +``` + make a temporary nothing is lost if there is nowhere to put it + write it + delete the original only now, once the new one is safely down + rename the temporary +``` + +**That is what renaming is for.** It looks like a convenience and it is the safety mechanism: it is the only one of the three operations that moves no data — a name lives in the directory entry, so renaming writes twenty two bytes into one block — which makes it the only one that can be left until last and relied on not to fail. + Finding room is a walk through the directory rather than a lookup, because there is no allocation table. With files laid down contiguously the directory already says which blocks are spoken for, and a second copy of that would be a second thing to keep right. The free count in the superblock is kept up to date but it is a note rather than the truth: it can be worked out again from the directory, and the directory is the one to believe. A file's length is its block count times 256 plus its tail, which is the same as putting the block count in the high byte and the tail in the low one. Nothing pads a file out, so the bytes after the end of one are whatever else happened to be in that block, and it is the reading program's business to stop where the tail says. @@ -519,6 +543,30 @@ Every routine names the Data Pointer it works through rather than assuming there readLine cuts a line short if it is longer than the buffer, and then reads the rest of it and throws it away, so that what is left over does not turn up as the next line. ConsoleEndOfInput is set if the console ran out instead of ending a line, and it is cleared at the start of every call, so it always describes the last line read. That is a different thing from an empty line, and a program reading until there is no more has to be able to tell the two apart. +## What A Program May Ask The System For: + +A loaded program is on its own hardware and can do anything the machine can do — it is a fence, not a wall. But the things it usually wants are things the system is already doing, and asking is both shorter and the only way to reach code that was assembled separately. `CALL` needs a label, and a label has to be in the same assembly; `SWI` needs only a number both sides agree on. + +Those numbers are written down once, in `Programs/CosmOS/Source/services.asm`, which both the system and the program include. Neither side ever types a number. + +| Service | Does | +| --- | --- | +| osPrintString | DP0 names a string ending in a zero byte. Prints it. | +| osReadLine | DP0 names somewhere to put a line, B says how much room there is. Reads one from the console. | +| osExit | Gives the machine back. Does not return. | +| osArgument | DP0 names somewhere to put whatever followed the run command, B says how much room there is. | + +``` +#Include services.asm + ... + SETD.0 Message + SWI osPrintString +``` + +`osArgument` is how a program is told what it is for. Everything written before it did the same thing however it was started, which is fine for a program that greets you and no use to one that edits a named document. What arrives is the whole rest of the line, spaces and all, rather than a list of words: what counts as an argument is the program's business, and handing over what was typed is the system's. + +A handler is entered with the caller's registers exactly as they were, because an interrupt frame is pushed rather than cleared. That is why a service can be given a pointer in DP0 and a count in B without any of it being copied anywhere first. + ## Loading A Program From A Disk: A program that was not the one the machine booted from carries sixteen bytes in front of it saying where it belongs. @@ -571,6 +619,26 @@ That is not general placement: a base applies to a whole segment, and only the f Whoever does the loading keeps its own code and data below the addresses the loaded program claims. That is an arrangement between the two of them rather than anything the machine enforces. Programs/CosmOS is where that arrangement is written down as a memory map and kept to. +## Programs That Come With The System: + +`Programs/CosmOS/Apps` holds what the shell can load. Most of them are old programs that were written for the bare machine and needed five edits to become loadable ones; the last three were written for the system as it is now. + +| Program | What it is for | +| --- | --- | +| Life | Conway's Game of Life, which had to be taught to stop, since a program that never ends takes the shell with it. Polls the console between generations. | +| Snake | A game. Draws a whole screen with cursor addressing and steers with single keys, asking the console once a frame and never waiting. | +| Keys | The console interrupting rather than being asked. The only one that brings a vector of its own, which is what the version two format exists for. | +| Say | Prints whatever it was told, which is the shortest thing that shows osArgument working. | +| Edit | A line editor. | + +### The Editor: + +`Edit` is the first program on this machine that makes a file a person typed — every byte on every disk before it was put there by the host tool. It is line oriented in the manner of `ed`: `l` lists, `a` adds at the end, `i` and `c` and `d` take a line number, `w` writes and `q` stops. + +It keeps the document as a **linked list of lines** rather than one buffer with newlines in it. Each line says where the next one is, how long it is, and then its bytes. Inserting is two pointers changed and nothing moved; with a flat buffer it would mean shifting every byte after the edit, on a machine whose only block move is a device asked politely. The price is that deleted lines are not reused, so a heavy session uses more room than the document needs and writing it out is what tidies up. + +Saving goes through `sbfsSaveFile`, so a document that has grown is written somewhere else and the original is only let go of once the new one is safely down. That is the whole reason the editor was written: not because the machine needed an editor, but because every tool that produces a file needs the same four operations, and building them for one imaginary tool is how they end up wrong. + ## Refusing: A device can refuse what it was asked to do. This is not the same as interrupting. An interrupt is a device asking for attention later, answered between instructions once the CPU is ready. A refusal is a device saying no to the instruction happening now, so the machine stops where it stands rather than carrying on as though the access had worked. diff --git a/Tests/docs.sh b/Tests/docs.sh index 310bd75..b841f40 100755 --- a/Tests/docs.sh +++ b/Tests/docs.sh @@ -179,6 +179,23 @@ else: problems.append("%s is bit %d of the console status port and The Console does" " not mention it" % (name, bit)) +# ---- Every service the system offers has a row ---- +# +# services.asm is the one place the numbers are written, and both the system and every +# program include it. A service added there and not here is one nothing can find out about +# except by reading the source of the operating system. +services = read("Programs/CosmOS/Source/services.asm") +offered = re.findall(r'^\s{2}(os[A-Za-z]+)\s+0d\d+', services, re.M) +if not offered: + problems.append("no services could be found in services.asm") +elif "## What A Program May Ask The System For:" not in pm: + problems.append("the Programming Manual has lost its services section") +else: + section = pm.split("## What A Program May Ask The System For:")[1].split("\n## ")[0] + for name in offered: + if ("| %s |" % name) not in section: + problems.append("%s is a service and has no row in the services table" % name) + # ---- Every directive the assembler knows is written down ---- for directive in sorted(set(re.findall(r'"(#[A-Za-z]+)"', util))): if directive not in am: @@ -189,7 +206,7 @@ for directive in sorted(set(re.findall(r'"(#[A-Za-z]+)"', util))): # The first column of the table in each of these sections names something the library has # to define. A routine renamed in the source and not in the manual is caught here, which # is what keeps the tables a description rather than a memory. -for heading, library in [("## Reading The Filesystem:", "Programs/CosmOS/Source/sbfs.asm"), +for heading, library in [("## Reading And Writing The Filesystem:", "Programs/CosmOS/Source/sbfs.asm"), ("## The Console Library:", "Programs/CosmOS/Source/console.asm")]: if heading not in pm: problems.append("the Programming Manual has lost its \"%s\" section" diff --git a/Tests/expected/16bitFibonacci.out b/Tests/expected/16bitFibonacci.out index ea23c1b..50b9a2b 100644 --- a/Tests/expected/16bitFibonacci.out +++ b/Tests/expected/16bitFibonacci.out @@ -1,3 +1,3 @@ 0000 0001 0001 0002 0003 0005 0008 000D 0015 0022 0037 0059 0090 00E9 0179 0262 03DB 063D 0A18 1055 1A6D 2AC2 452F 6FF1 -Execution halted after 2534 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/16bitSegmentedSieve.out b/Tests/expected/16bitSegmentedSieve.out index 30a0e58..e555473 100644 --- a/Tests/expected/16bitSegmentedSieve.out +++ b/Tests/expected/16bitSegmentedSieve.out @@ -1,3 +1,3 @@ 0002 0003 0005 0007 000B 000D 0011 0013 0017 001D 001F 0025 0029 002B 002F 0035 003B 003D 0043 0047 0049 004F 0053 0059 0061 0065 0067 006B 006D 0071 007F 0083 0089 008B 0095 0097 009D 00A3 00A7 00AD 00B3 00B5 00BF 00C1 00C5 00C7 00D3 00DF 00E3 00E5 00E9 00EF 00F1 00FB 0101 0107 010D 010F 0115 0119 011B 0125 0133 0137 0139 013D 014B 0151 015B 015D 0161 0167 016F 0175 017B 017F 0185 018D 0191 0199 01A3 01A5 01AF 01B1 01B7 01BB 01C1 01C9 01CD 01CF 01D3 01DF 01E7 01EB 01F3 01F7 01FD 0209 020B 021D 0223 022D 0233 0239 023B 0241 024B 0251 0257 0259 025F 0265 0269 026B 0277 0281 0283 0287 028D 0293 0295 02A1 02A5 02AB 02B3 02BD 02C5 02CF 02D7 02DD 02E3 02E7 02EF 02F5 02F9 0301 0305 0313 031D 0329 032B 0335 0337 033B 033D 0347 0355 0359 035B 035F 036D 0371 0373 0377 038B 038F 0397 03A1 03A9 03AD 03B3 03B9 03C7 03CB 03D1 03D7 03DF 03E5 03F1 03F5 03FB 03FD 0407 0409 040F 0419 041B 0425 0427 042D 043F 0443 0445 0449 044F 0455 045D 0463 0469 047F 0481 048B 0493 049D 04A3 04A9 04B1 04BD 04C1 04C7 04CD 04CF 04D5 04E1 04EB 04FD 04FF 0503 0509 050B 0511 0515 0517 051B 0527 0529 052F 0551 0557 055D 0565 0577 0581 058F 0593 0595 0599 059F 05A7 05AB 05AD 05B3 05BF 05C9 05CB 05CF 05D1 05D5 05DB 05E7 05F3 05FB 0607 060D 0611 0617 061F 0623 062B 062F 063D 0641 0647 0649 064D 0653 0655 065B 0665 0679 067F 0683 0685 069D 06A1 06A3 06AD 06B9 06BB 06C5 06CD 06D3 06D9 06DF 06F1 06F7 06FB 06FD 0709 0713 071F 0727 0737 0745 074B 074F 0751 0755 0757 0761 076D 0773 0779 078B 078D 079D 079F 07B5 07BB 07C3 07C9 07CD 07CF 07D3 07DB 07E1 07EB 07ED 07F7 0805 080F 0815 0821 0823 0827 0829 0833 083F 0841 0851 0853 0859 085D 085F 0869 0871 0883 089B 089F 08A5 08AD 08BD 08BF 08C3 08CB 08DB 08DD 08E1 08E9 08EF 08F5 08F9 0905 0907 091D 0923 0925 092B 092F 0935 0943 0949 094D 094F 0955 0959 095F 096B 0971 0977 0985 0989 098F 099B 09A3 09A9 09AD 09C7 09D9 09E3 09EB 09EF 09F5 09F7 09FD 0A13 0A1F 0A21 0A31 0A39 0A3D 0A49 0A57 0A61 0A63 0A67 0A6F 0A75 0A7B 0A7F 0A81 0A85 0A8B 0A93 0A97 0A99 0A9F 0AA9 0AAB 0AB5 0ABD 0AC1 0ACF 0AD9 0AE5 0AE7 0AED 0AF1 0AF3 0B03 0B11 0B15 0B1B 0B23 0B29 0B2D 0B3F 0B47 0B51 0B57 0B5D 0B65 0B6F 0B7B 0B89 0B8D 0B93 0B99 0B9B 0BB7 0BB9 0BC3 0BCB 0BCF 0BDD 0BE1 0BE9 0BF5 0BFB 0C07 0C0B 0C11 0C25 0C2F 0C31 0C41 0C5B 0C5F 0C61 0C6D 0C73 0C77 0C83 0C89 0C91 0C95 0C9D 0CB3 0CB5 0CB9 0CBB 0CC7 0CE3 0CE5 0CEB 0CF1 0CF7 0CFB 0D01 0D03 0D0F 0D13 0D1F 0D21 0D2B 0D2D 0D3D 0D3F 0D4F 0D55 0D69 0D79 0D81 0D85 0D87 0D8B 0D8D 0DA3 0DAB 0DB7 0DBD 0DC7 0DC9 0DCD 0DD3 0DD5 0DDB 0DE5 0DE7 0DF3 0DFD 0DFF 0E09 0E17 0E1D 0E21 0E27 0E2F 0E35 0E3B 0E4B 0E57 0E59 0E5D 0E6B 0E71 0E75 0E7D 0E87 0E8F 0E95 0E9B 0EB1 0EB7 0EB9 0EC3 0ED1 0ED5 0EDB 0EED 0EEF 0EF9 0F07 0F0B 0F0D 0F17 0F25 0F29 0F31 0F43 0F47 0F4D 0F4F 0F53 0F59 0F5B 0F67 0F6B 0F7F 0F95 0FA1 0FA3 0FA7 0FAD 0FB3 0FB5 0FBB 0FD1 0FD3 0FD9 0FE9 0FEF 0FFB 0FFD 1003 100F 101F 1021 1025 102B 1039 103D 103F 1051 1069 1073 1079 107B 1085 1087 1091 1093 109D 10A3 10A5 10AF 10B1 10BB 10C1 10C9 10E7 10F1 10F3 10FD 1105 110B 1115 1127 112D 1139 1145 1147 1159 115F 1163 1169 116F 1181 1183 118D 119B 11A1 11A5 11A7 11AB 11C3 11C5 11D1 11D7 11E7 11EF 11F5 11FB 120D 121D 121F 1223 1229 122B 1231 1237 1241 1247 1253 125F 1271 1273 1279 127D 128F 1297 12AF 12B3 12B5 12B9 12BF 12C1 12CD 12D1 12DF 12FD 1307 130D 1319 1327 132D 1337 1343 1345 1349 134F 1357 135D 1367 1369 136D 137B 1381 1387 138B 1391 1393 139D 139F 13AF 13BB 13C3 13D5 13D9 13DF 13EB 13ED 13F3 13F9 13FF 141B 1421 142F 1433 143B 1445 144D 1459 146B 146F 1471 1475 148D 1499 149F 14A1 14B1 14B7 14BD 14CB 14D5 14E3 14E7 1505 150B 1511 1517 151F 1525 1529 152B 1537 153D 1541 1543 1549 155F 1565 1567 156B 157D 157F 1583 158F 1591 1597 159B 15B5 15BB 15C1 15C5 15CD 15D7 15F7 1607 1609 160F 1613 1615 1619 161B 1625 1633 1639 163D 1645 164F 1655 1669 166D 166F 1675 1693 1697 169F 16A9 16AF 16B5 16BD 16C3 16CF 16D3 16D9 16DB 16E1 16E5 16EB 16ED 16F7 16F9 1709 170F 1723 1727 1733 1741 175D 1763 1777 177B 178D 1795 179B 179F 17A5 17B3 17B9 17BF 17C9 17CB 17D5 17E1 17E9 17F3 17F5 17FF 1807 1813 181D 1835 1837 183B 1843 1849 184D 1855 1867 1871 1877 187D 187F 1885 188F 189B 189D 18A7 18AD 18B3 18B9 18C1 18C7 18D1 18D7 18D9 18DF 18E5 18EB 18F5 18FD 1915 191B 1931 1933 1945 1949 1951 195B 1979 1981 1993 1997 1999 19A3 19A9 19AB 19B1 19B5 19C7 19CF 19DB 19ED 19FD 1A03 1A05 1A11 1A17 1A21 1A23 1A2D 1A2F 1A35 1A3F 1A4D 1A51 1A69 1A6B 1A7B 1A7D 1A87 1A89 1A93 1AA7 1AAB 1AAD 1AB1 1AB9 1AC9 1ACF 1AD5 1AD7 1AE3 1AF3 1AFB 1AFF 1B05 1B23 1B25 1B2F 1B31 1B37 1B3B 1B41 1B47 1B4F 1B55 1B59 1B65 1B6B 1B73 1B7F 1B83 1B91 1B9D 1BA7 1BBF 1BC5 1BD1 1BD7 1BD9 1BEF 1BF7 1C09 1C13 1C19 1C27 1C2B 1C2D 1C33 1C3D 1C45 1C4B 1C4F 1C55 1C73 1C81 1C8B 1C8D 1C99 1CA3 1CA5 1CB5 1CB7 1CC9 1CE1 1CF3 1CF9 1D09 1D1B 1D21 1D23 1D35 1D39 1D3F 1D41 1D4B 1D53 1D5D 1D63 1D69 1D71 1D75 1D7B 1D7D 1D87 1D89 1D95 1D99 1D9F 1DA5 1DA7 1DB3 1DB7 1DC5 1DD7 1DDB 1DE1 1DF5 1DF9 1E01 1E07 1E0B 1E13 1E17 1E25 1E2B 1E2F 1E3D 1E49 1E4D 1E4F 1E6D 1E71 1E89 1E8F 1E95 1EA1 1EAD 1EBB 1EC1 1EC5 1EC7 1ECB 1EDD 1EE3 1EEF 1EF7 1EFD 1F01 1F0D 1F0F 1F1B 1F39 1F49 1F4B 1F51 1F67 1F75 1F7B 1F85 1F91 1F97 1F99 1F9D 1FA5 1FAF 1FB5 1FBB 1FD3 1FE1 1FE7 1FEB 1FF3 1FFF 2011 201B 201D 2027 2029 202D 2033 2047 204D 2051 205F 2063 2065 2069 2077 207D 2089 20A1 20AB 20B1 20B9 20C3 20C5 20E3 20E7 20ED 20EF 20FB 20FF 210D 2113 2135 2141 2149 214F 2159 215B 215F 2173 217D 2185 2195 2197 21A1 21AF 21B3 21B5 21C1 21C7 21D7 21DD 21E5 21E9 21F1 21F5 21FB 2203 2209 220F 221B 2221 2225 222B 2231 2239 224B 224F 2263 2267 2273 2275 227F 2285 2287 2291 229D 229F 22A3 22B7 22BD 22DB 22E1 22E5 22ED 22F7 2303 2309 230B 2327 2329 232F 2333 2335 2345 2351 2353 2359 2363 236B 2383 238F 2395 23A7 23AD 23B1 23BF 23C5 23C9 23D5 23DD 23E3 23EF 23F3 23F9 2405 240B 2417 2419 2429 243D 2441 2443 244D 245F 2467 246B 2479 247D 247F 2485 249B 24A1 24AF 24B5 24BB 24C5 24CB 24CD 24D7 24D9 24DD 24DF 24F5 24F7 24FB 2501 2507 2513 2519 2527 2531 253D 2543 254B 254F 2573 2581 258D 2593 2597 259D 259F 25AB 25B1 25BD 25CD 25CF 25D9 25E1 25F7 25F9 2605 260B 260F 2615 2627 2629 2635 263B 263F 264B 2653 2659 2665 2669 266F 267B 2681 2683 268F 269B 269F 26AD 26B3 26C3 26C9 26CB 26D5 26DD 26EF 26F5 2717 2719 2735 2737 274D 2753 2755 275F 276B 276D 2773 2777 277F 2795 279B 279D 27A7 27AF 27B3 27B9 27C1 27C5 27D1 27E3 27EF 2803 2807 280D 2813 281B 281F 2821 2831 283D 283F 2849 2851 285B 285D 2861 2867 2875 2881 2897 289F 28BB 28BD 28C1 28D5 28D9 28DB 28DF 28ED 28F7 2903 2905 2911 2921 2923 293F 2947 295D 2965 2969 296F 2975 2983 2987 298F 299B 29A1 29A7 29AB 29BF 29C3 29D5 29D7 29E3 29E9 29ED 29F3 2A01 2A13 2A1D 2A25 2A2F 2A4F 2A55 2A5F 2A65 2A6B 2A6D 2A73 2A83 2A89 2A8B 2A97 2A9D 2AB9 2ABB 2AC5 2ACD 2ADD 2AE3 2AEB 2AF1 2AFB 2B13 2B27 2B31 2B33 2B3D 2B3F 2B4B 2B4F 2B55 2B69 2B6D 2B6F 2B7B 2B8D 2B97 2B99 2BA3 2BA5 2BA9 2BBD 2BCD 2BE7 2BEB 2BF3 2BF9 2BFD 2C09 2C0F 2C17 2C23 2C2F 2C35 2C39 2C41 2C57 2C59 2C69 2C77 2C81 2C87 2C93 2C9F 2CAD 2CB3 2CB7 2CCB 2CCF 2CDB 2CE1 2CE3 2CE9 2CEF 2CFF 2D07 2D1D 2D1F 2D3B 2D43 2D49 2D4D 2D61 2D65 2D71 2D89 2D9D 2DA1 2DA9 2DB3 2DB5 2DC5 2DC7 2DD3 2DDF 2E01 2E03 2E07 2E0D 2E19 2E1F 2E25 2E2D 2E33 2E37 2E39 2E3F 2E57 2E5B 2E6F 2E79 2E7F 2E85 2E93 2E97 2E9D 2EA3 2EA5 2EB1 2EB7 2EC1 2EC3 2ECD 2ED3 2EE7 2EEB 2F05 2F09 2F0B 2F11 2F27 2F29 2F41 2F45 2F4B 2F4D 2F51 2F57 2F6F 2F75 2F7D 2F81 2F83 2FA5 2FAB 2FB3 2FC3 2FCF 2FD1 2FDB 2FDD 2FE7 2FED 2FF5 2FF9 3001 300D 3023 3029 3037 303B 3055 3059 305B 3067 3071 3079 307D 3085 3091 3095 30A3 30A9 30B9 30BF 30C7 30CB 30D1 30D7 30DF 30E5 30EF 30FB 30FD 3103 3109 3119 3121 3127 312D 3139 3143 3145 314B 315D 3161 3167 316D 3173 317F 3191 3199 319F 31A9 31B1 31C3 31C7 31D5 31DB 31ED 31F7 31FF 3209 3215 3217 321D 3229 3235 3259 325D 3263 326B 326F 3275 3277 327B 328D 3299 329F 32A7 32AD 32B3 32B7 32C9 32CB 32CF 32D1 32E9 32ED 32F3 32F9 3307 3325 332B 332F 3335 3341 3347 335B 335F 3367 336B 3373 3379 337F 3383 33A1 33A3 33AD 33B9 33C1 33CB 33D3 33EB 33F1 33FD 3401 340F 3413 3419 341B 3437 3445 3455 3457 3463 3469 346D 3481 348B 3491 3497 349D 34A5 34AF 34BB 34C9 34D3 34E1 34F1 34FF 3509 3517 351D 352D 3533 353B 3541 3551 3565 356F 3571 3577 357B 357D 3581 358D 358F 3599 359B 35A1 35B7 35BD 35BF 35C3 35D5 35DD 35E7 35EF 3605 3607 3611 3623 3631 3635 3637 363B 364D 364F 3653 3659 3661 366B 366D 368B 368F 36AD 36AF 36B9 36BB 36CD 36D1 36E3 36E9 36F7 3701 3703 3707 371B 373F 3745 3749 374F 375D 3761 3775 377F 378D 37A3 37A9 37AB 37C9 37D5 37DF 37F1 37F3 37F7 3805 380B 3821 3833 3835 3841 3847 384B 3853 3857 385F 3865 386F 3871 387D 388F 3899 38A7 38B7 38C5 38C9 38CF 38D5 38D7 38DD 38E1 38E3 38FF 3901 391D 3923 3925 3929 392F 393D 3941 394D 395B 396B 3979 397D 3983 398B 3991 3995 399B 39A1 39A7 39AF 39B3 39BB 39BF 39CD 39DD 39E5 39EB 39EF 39FB 3A03 3A13 3A15 3A1F 3A27 3A2B 3A31 3A4B 3A51 3A5B 3A63 3A67 3A6D 3A79 3A87 3AA5 3AA9 3AB7 3ACD 3AD5 3AE1 3AE5 3AEB 3AF3 3AFD 3B03 3B11 3B1B 3B21 3B23 3B2D 3B39 3B45 3B53 3B59 3B5F 3B71 3B7B 3B81 3B89 3B9B 3B9F 3BA5 3BA7 3BAD 3BB7 3BB9 3BC3 3BCB 3BD1 3BD7 3BE1 3BE3 3BF5 3BFF 3C01 3C0D 3C11 3C17 3C1F 3C29 3C35 3C43 3C4F 3C53 3C5B 3C65 3C6B 3C71 3C85 3C89 3C97 3CA7 3CB5 3CBF 3CC7 3CD1 3CDD 3CDF 3CF1 3CF7 3D03 3D0D 3D19 3D1B 3D1F 3D21 3D2D 3D33 3D37 3D3F 3D43 3D6F 3D73 3D75 3D79 3D7B 3D85 3D91 3D97 3D9D 3DAB 3DAF 3DB5 3DBB 3DC1 3DC9 3DCF 3DF3 3E05 3E09 3E0F 3E11 3E1D 3E23 3E29 3E2F 3E33 3E41 3E57 3E63 3E65 3E77 3E81 3E87 3EA1 3EB9 3EBD 3EBF 3EC3 3EC5 3EC9 3ED7 3EDB 3EE1 3EE7 3EEF 3EFF 3F0B 3F0D 3F37 3F3B 3F3D 3F41 3F59 3F5F 3F65 3F67 3F79 3F7D 3F8B 3F91 3FAD 3FBF 3FCD 3FD3 3FDD 3FE9 3FEB 3FF1 3FFD 401B 4021 4025 402B 4031 403F 4043 4045 405D 4061 4067 406D 4087 4091 40A3 40A9 40B1 40B7 40BD 40DB 40DF 40EB 40F7 40F9 4109 410B 4111 4115 4121 4133 4135 413B 413F 4159 4165 416B 4177 417B 4193 41AB 41B7 41BD 41BF 41CB 41E7 41EF 41F3 41F9 4205 4207 4219 421F 4223 4229 422F 4243 4253 4255 425B 4261 4273 427D 4283 4285 4289 4291 4297 429D 42B5 42C5 42CB 42D3 42DD 42E3 42F1 4307 430F 431F 4325 4327 4333 4337 4339 434F 4357 4369 438B 438D 4393 43A5 43A9 43AF 43B5 43BD 43C7 43CF 43E1 43E7 43EB 43ED 43F1 43F9 4409 440B 4417 4423 4429 443B 443F 4445 444B 4451 4453 4459 4465 446F 4483 448F 44A1 44A5 44AB 44AD 44BD 44BF 44C9 44D7 44DB 44F9 44FB 4505 4511 4513 452B 4531 4541 4549 4553 4555 4561 4577 457D 457F 458F 45A3 45AD 45AF 45BB 45C7 45D9 45E3 45EF 45F5 45F7 4601 4603 4609 4613 4625 4627 4633 4639 463D 4643 4645 465D 4679 467B 467F 4681 468B 468D 469D 46A9 46B1 46C7 46C9 46CF 46D3 46D5 46DF 46E5 46F9 4705 470F 4717 4723 4729 472F 4735 4739 474B 474D 4751 475D 476F 4771 477D 4783 4787 4789 4799 47A5 47B1 47BF 47C3 47CB 47DD 47E1 47ED 47FB 4801 4807 480B 4813 4819 481D 4831 483D 4847 4855 4859 485B 486B 486D 4879 4897 489B 48A1 48B9 48CD 48E5 48EF 48F7 4903 490D 4919 491F 492B 4937 493D 4945 4955 4963 4969 496D 4973 4997 49AB 49B5 49D3 49DF 49E1 49E5 49E7 4A03 4A0F 4A1D 4A23 4A39 4A41 4A45 4A57 4A5D 4A6B 4A7D 4A81 4A87 4A89 4A8F 4AB1 4AC3 4AC5 4AD5 4ADB 4AED 4AEF 4B07 4B0B 4B0D 4B13 4B1F 4B25 4B31 4B3B 4B43 4B49 4B59 4B65 4B6D 4B77 4B85 4BAD 4BB3 4BB5 4BBB 4BBF 4BCB 4BD9 4BDD 4BDF 4BE3 4BE5 4BE9 4BF1 4BF7 4C01 4C07 4C0D 4C0F 4C15 4C1B 4C21 4C2D 4C33 4C4B 4C55 4C57 4C61 4C67 4C73 4C79 4C7F 4C8D 4C93 4C99 4CCD 4CE1 4CE7 4CF1 4CF3 4CFD 4D05 4D0F 4D1B 4D27 4D29 4D2F 4D33 4D41 4D51 4D59 4D65 4D6B 4D81 4D83 4D8D 4D95 4D9B 4DB1 4DB3 4DC9 4DCF 4DD7 4DE1 4DED 4DF9 4DFB 4E05 4E0B 4E17 4E19 4E1D 4E2B 4E35 4E37 4E3D 4E4F 4E53 4E5F 4E67 4E79 4E85 4E8B 4E91 4E95 4E9B 4EA1 4EAF 4EB3 4EB5 4EC1 4ECD 4ED1 4ED7 4EE9 4EFB 4F07 4F09 4F19 4F25 4F2D 4F3F 4F49 4F63 4F67 4F6D 4F75 4F7B 4F81 4F85 4F87 4F91 4FA5 4FA9 4FAF 4FB7 4FBB 4FCF 4FD9 4FDB 4FFD 4FFF 5003 501B 501D 5029 5035 503F 5045 5047 5053 5071 5077 5083 5093 509F 50A1 50B7 50C9 50D5 50E3 50ED 50EF 50FB 5107 510B 510D 5111 5117 5123 5125 5135 5147 5149 5171 5179 5189 518F 5197 51A1 51A3 51A7 51B9 51C1 51CB 51D3 51DF 51E3 51F5 51F7 5209 5213 5215 5219 521B 521F 5227 5243 5245 524B 5261 526D 5273 5281 5293 5297 529D 52A5 52AB 52B1 52BB 52C3 52C7 52C9 52DB 52E5 52EB 52FF 5315 531D 5323 5341 5345 5347 534B 535D 5363 5381 5383 5387 538F 5395 5399 539F 53AB 53B9 53DB 53E9 53EF 53F3 53F5 53FB 53FF 540D 5411 5413 5419 5435 5437 543B 5441 5449 5453 5455 545F 5461 546B 546D 5471 548F 5491 549D 54A9 54B3 54C5 54D1 54DF 54E9 54EB 54F7 54FD 5507 550D 551B 5527 552B 5539 553D 554F 5551 555B 5563 5567 556F 5579 5585 5597 55A9 55B1 55B7 55C9 55D9 55E7 55ED 55F3 55FD 560B 560F 5615 5617 5623 562F 5633 5639 563F 564B 564D 565D 565F 566B 5671 5675 5683 5689 568D 568F 569B 56AD 56B1 56D5 56E7 56F3 56FF 5701 5705 5707 570B 5713 571F 5723 5747 574D 575F 5761 576D 5777 577D 5789 57A1 57A9 57AF 57B5 57C5 57D1 57D3 57E5 57EF 5803 580D 580F 5815 5827 582B 582D 5855 585B 585D 586D 586F 5873 587B 588D 5897 58A3 58A9 58AB 58B5 58BD 58C1 58C7 58D3 58D5 58DF 58F1 58F9 58FF 5903 5917 591B 5921 5945 594B 594D 5957 595D 5975 597B 5989 5999 599F 59B1 59B3 59BD 59D1 59DB 59E3 59E9 59ED 59F3 59F5 59FF 5A01 5A0D 5A11 5A13 5A17 5A1F 5A29 5A2F 5A3B 5A4D 5A5B 5A67 5A77 5A7F 5A85 5A95 5A9D 5AA1 5AA3 5AA9 5ABB 5AD3 5AE5 5AEF 5AFB 5AFD 5B01 5B0F 5B19 5B1F 5B25 5B2B 5B3D 5B49 5B4B 5B67 5B79 5B87 5B97 5BA3 5BB1 5BC9 5BD5 5BEB 5BF1 5BF3 5BFD 5C05 5C09 5C0B 5C0F 5C1D 5C29 5C2F 5C33 5C39 5C47 5C4B 5C4D 5C51 5C6F 5C75 5C77 5C7D 5C87 5C89 5CA7 5CBD 5CBF 5CC3 5CC9 5CD1 5CD7 5CDD 5CED 5CF9 5D05 5D0B 5D13 5D17 5D19 5D31 5D3D 5D41 5D47 5D4F 5D55 5D5B 5D65 5D67 5D6D 5D79 5D95 5DA3 5DA9 5DAD 5DB9 5DC1 5DC7 5DD3 5DD7 5DDD 5DEB 5DF1 5DFD 5E07 5E0D 5E13 5E1B 5E21 5E27 5E2B 5E2D 5E31 5E39 5E45 5E49 5E57 5E69 5E73 5E75 5E85 5E8B 5E9F 5EA5 5EAF 5EB7 5EBB 5ED9 5EFD 5F09 5F11 5F27 5F33 5F35 5F3B 5F47 5F57 5F5D 5F63 5F65 5F77 5F7B 5F95 5F99 5FA1 5FB3 5FBD 5FC5 5FCF 5FD5 5FE3 5FE7 5FFB 6011 6023 602F 6037 6053 605F 6065 606B 6073 6079 6085 609D 60AD 60BB 60BF 60CD 60D9 60DF 60E9 60F5 6109 610F 6113 611B 612D 6139 614B 6155 6157 615B 616F 6179 6187 618B 6191 6193 619D 61B5 61C7 61C9 61CD 61E1 61F1 61FF 6209 6217 621D 6221 6227 623B 6241 624B 6251 6253 625F 6265 6283 628D 6295 629B 629F 62A5 62AD 62D5 62D7 62DB 62DD 62E9 62FB 62FF 6305 630D 6317 631D 632F 6341 6343 634F 635F 6367 636D 6371 6377 637D 637F 63B3 63C1 63C5 63D9 63E9 63EB 63EF 63F5 6401 6403 6409 6415 6421 6427 642B 6439 6443 6449 644F 645D 6467 6475 6485 648D 6493 649F 64A3 64AB 64C1 64C7 64C9 64DB 64F1 64F7 64F9 650B 6511 6521 652F 6539 653F 654B 654D 6553 6557 655F 6571 657D 658D 658F 6593 65A1 65A5 65AD 65B9 65C5 65E3 65F3 65FB 65FF 6601 6607 661D 6629 6631 663B 6641 6647 664D 665B 6661 6673 667D 6689 668B 6695 6697 669B 66B5 66B9 66C5 66CD 66D1 66E3 66EB 66F5 6703 6713 6719 671F 6727 6731 6737 673F 6745 6751 675B 676F 6779 6781 6785 6791 67AB 67BD 67C1 67CD 67DF 67E5 6803 6809 6811 6817 682D 6839 683B 683F 6845 684B 684D 6857 6859 685D 6863 6869 686B 6871 6887 6899 689F 68B1 68BD 68C5 68D1 68D7 68E1 68ED 68EF 68FF 6901 690B 690D 6917 6929 692F 6943 6947 6949 694F 6965 696B 6971 6983 6989 6997 69A3 69B3 69B5 69BB 69C1 69C5 69D3 69DF 69E3 69E5 69F7 6A07 6A2B 6A37 6A3D 6A4B 6A67 6A69 6A75 6A7B 6A87 6A8D 6A91 6A93 6AA3 6AC1 6AC9 6AE1 6AE7 6B05 6B0F 6B11 6B23 6B27 6B2D 6B39 6B41 6B57 6B59 6B5F 6B75 6B87 6B89 6B93 6B95 6B9F 6BBD 6BBF 6BDB 6BE1 6BEF 6BFF 6C05 6C19 6C29 6C2B 6C31 6C35 6C55 6C59 6C5B 6C5F 6C65 6C67 6C73 6C77 6C7D 6C83 6C8F 6C91 6C97 6C9B 6CA1 6CA9 6CAF 6CB3 6CC7 6CCB 6CEB 6CF5 6CFD 6D0D 6D0F 6D25 6D27 6D2B 6D31 6D39 6D3F 6D4F 6D5D 6D61 6D73 6D7B 6D7F 6D93 6D99 6DA5 6DB1 6DB7 6DC1 6DC3 6DCD 6DCF 6DDB 6DF7 6E03 6E15 6E17 6E29 6E33 6E3B 6E45 6E75 6E77 6E7B 6E81 6E89 6E93 6E95 6E9F 6EBD 6EBF 6EE3 6EE9 6EF3 6EF9 6EFB 6F0D 6F11 6F17 6F1F 6F2F 6F3D 6F4D 6F53 6F61 6F65 6F79 6F7D 6F83 6F85 6F8F 6F9B 6F9D 6FA3 6FAF 6FB5 6FBB 6FBF 6FCB 6FCD 6FD3 6FD7 6FE3 6FE9 6FF1 6FF5 6FF7 6FFD 700F 7019 701F 7027 7033 7039 704F 7051 7057 7063 7075 7079 7087 708D 7091 70A5 70AB 70BB 70C3 70C7 70CF 70E5 70ED 70F9 70FF 7105 7115 7121 7133 7151 7159 715D 715F 7163 7169 7183 7187 7195 71AD 71C3 71C9 71CB 71D1 71DB 71E1 71EF 71F5 71FB 7207 7211 7217 7219 7225 722F 723B 7243 7255 7267 7271 7277 727F 728F 7295 729B 72A3 72B3 72C7 72CB 72CD 72D7 72D9 72E3 72EF 72F5 72FD 7303 730D 7321 732B 733D 7357 735B 7361 737F 7381 7385 738D 7393 739F 73AB 73BD 73C1 73C9 73DF 73E5 73E7 73F3 7415 741B 742D 7439 743F 7441 745D 746B 747B 7489 748D 749B 74A7 74AB 74B1 74B7 74B9 74DD 74E1 74E7 74FB 7507 751F 7525 753B 753D 754D 755F 756B 7577 7589 758B 7591 7597 759D 75A1 75A7 75B5 75B9 75BB 75D1 75D9 75E5 75EB 75F5 75FB 7603 760F 7621 762D 7633 763D 763F 7655 7663 7669 766F 7673 7685 768B 769F 76B5 76B7 76C3 76DB 76DF 76F1 7703 7705 771B 771D 7721 772D 7735 7741 774B 7759 775D 775F 7771 7781 77A7 77AD 77B3 77B9 77C5 77CF 77D5 77E1 77E9 77EF 77F3 77F9 7807 7825 782B 7835 783D 7853 7859 7861 786D 7877 7879 7883 7885 788B 7895 7897 78A1 78AD 78BF 78D3 78D9 78DD 78E5 78FB 7901 7907 7925 792B 7939 793F 794B 7957 795D 7967 7969 7973 7991 7993 79A3 79AB 79AF 79B1 79B7 79C9 79CD 79CF 79D5 79D9 79F3 79F7 79FF 7A05 7A0F 7A11 7A15 7A1B 7A23 7A27 7A2D 7A4B 7A57 7A59 7A5F 7A65 7A69 7A7D 7A93 7A9B 7A9F 7AA1 7AA5 7AED 7AF5 7AF9 7B01 7B17 7B19 7B1D 7B2B 7B35 7B37 7B3B 7B4F 7B55 7B5F 7B71 7B77 7B8B 7B9B 7BA1 7BA9 7BAF 7BB3 7BC7 7BD3 7BE9 7BEB 7BEF 7BF1 7BFD 7C07 7C19 7C1B 7C31 7C37 7C49 7C67 7C69 7C73 7C81 7C8B 7C93 7CA3 7CD5 7CDB 7CE5 7CED 7CF7 7D03 7D09 7D1B 7D1D 7D33 7D39 7D3B 7D3F 7D45 7D4D 7D53 7D59 7D63 7D75 7D77 7D8D 7D8F 7D9F 7DAD 7DB7 7DBD 7DBF 7DCB 7DD5 7DE9 7DED 7DFB 7E01 7E05 7E29 7E2B 7E2F 7E35 7E41 7E43 7E47 7E55 7E61 7E67 7E6B 7E71 7E73 7E79 7E7D 7E91 7E9B 7E9D 7EA7 7EAD 7EB9 7EBB 7ED3 7EDF 7EEB 7EF1 7EF7 7EFB 7F13 7F15 7F19 7F31 7F33 7F39 7F3D 7F43 7F4B 7F5B 7F61 7F63 7F6D 7F79 7F87 7F8D 7FAF 7FB5 7FC3 7FC9 7FCD 7FCF 7FED 8003 800B 800F 8015 801D 8021 8023 803F 8041 8047 804B 8065 8077 808D 808F 8095 80A5 80AB 80AD 80BD 80C9 80CB 80D7 80DB 80E1 80E7 80F5 80FF 8105 810D 8119 811D 812F 8131 813B 8143 8153 8159 815F 817D 817F 8189 819B 819D 81A7 81AF 81B3 81BB 81C7 81DF 8207 8209 8215 821F 8225 8231 8233 823F 8243 8245 8249 824F 8261 826F 827B 8281 8285 8293 82B1 82B5 82BD 82C7 82CF 82D5 82DF 82F1 82F9 82FD 830B 831B 8321 8329 832D 8333 8335 833F 8341 834D 8351 8353 8357 835D 8365 8369 836F 838F 83A7 83B1 83B9 83CB 83D5 83D7 83DD 83E7 83E9 83ED 83FF 8405 8411 8413 8423 8425 843B 8441 8447 844F 8461 8465 8477 8483 848B 8491 8495 84A9 84AF 84CD 84E3 84EF 84F1 84F7 8509 850D 854B 854F 8551 855D 8563 856D 856F 857B 8587 85A3 85A5 85A9 85B7 85CD 85D3 85D5 85DB 85E1 85EB 85F9 85FD 85FF 8609 860F 8617 8621 862F 8639 863F 8641 864D 8663 8675 867D 8687 8699 86A5 86A7 86B3 86B7 86C3 86C5 86CF 86D1 86D7 86E9 86EF 86F5 8717 871D 871F 872B 872F 8735 8747 8759 875B 876B 8771 8777 877F 8785 878F 87A1 87A9 87B3 87BB 87C5 87C7 87CB 87DD 87F7 8803 8819 881B 881F 8821 8837 883D 8843 8851 8861 8867 887B 8885 8891 8893 88A5 88CF 88D3 88EB 88ED 88F3 88FD 8909 890B 8911 891B 8923 8927 892D 8939 8945 894D 8951 8957 8963 8981 8995 899B 89B3 89B9 89C3 89CF 89D1 89DB 89EF 89F5 89FB 89FF 8A0B 8A19 8A23 8A35 8A41 8A49 8A4F 8A5B 8A5F 8A6D 8A77 8A79 8A85 8AA3 8AB3 8AB5 8AC1 8AC7 8ACB 8ACD 8AD1 8AD7 8AF1 8AF5 8B07 8B09 8B0D 8B13 8B21 8B57 8B5D 8B91 8B93 8BA3 8BA9 8BAF 8BBB 8BD5 8BD9 8BDB 8BE1 8BF7 8BFD 8BFF 8C0B 8C17 8C1D 8C27 8C39 8C3B 8C47 8C53 8C5D 8C6F 8C7B 8C81 8C89 8C8F 8C99 8C9F 8CA7 8CAB 8CAD 8CB1 8CC5 8CDD 8CE3 8CE9 8CF3 8D01 8D0B 8D0D 8D23 8D29 8D37 8D41 8D5B 8D5F 8D71 8D79 8D85 8D91 8D9B 8DA7 8DAD 8DB5 8DC5 8DCB 8DD3 8DD9 8DDF 8DF5 8DF7 8E01 8E15 8E1F 8E25 8E51 8E63 8E69 8E73 8E75 8E79 8E7F 8E8D 8E91 8EAB 8EAF 8EB1 8EBD 8EC7 8ECF 8ED3 8EDB 8EE7 8EEB 8EF7 8EFF 8F15 8F1D 8F23 8F2D 8F3F 8F45 8F4B 8F53 8F59 8F65 8F69 8F71 8F83 8F8D 8F99 8F9F 8FAB 8FAD 8FB3 8FB7 8FB9 8FC9 8FD5 8FE1 8FEF 8FF9 9007 900D 9017 9023 9025 9031 9037 903B 9041 9043 904F 9053 906D 9073 9085 908B 9095 909B 909D 90AF 90B9 90C1 90C5 90DF 90E9 90FD 9103 9113 9127 9133 913D 9145 914F 9151 9161 9167 917B 9185 9199 919D 91BB 91BD 91C1 91C9 91D9 91DB 91ED 91F1 91F3 91F9 9203 9215 9221 922F 9241 9247 9257 926B 9271 9275 927D 9283 9287 928D 9299 92A1 92AB 92AD 92B9 92BF 92C3 92C5 92CB 92D5 92D7 92E7 92F3 9301 930B 9311 9319 931F 933B 933D 9343 9355 9373 9395 9397 93A7 93B3 93B5 93C7 93D7 93DD 93E5 93EF 93F7 9401 9409 9413 943F 9445 944B 944F 9463 9467 9469 946D 947B 9497 949F 94A5 94B5 94C3 94E1 94E7 9505 9509 9517 9521 9527 952D 9535 9539 954B 9557 955D 955F 9575 9581 9589 958F 959B 959F 95AD 95B1 95B7 95B9 95BD 95CF 95E3 95E9 95F9 961F 962F 9631 9635 963B 963D 9665 968F 969D 96A1 96A7 96A9 96C1 96CB 96D1 96D3 96E5 96EF 96FB 96FD 970D 970F 9715 9725 972B 9733 9737 9739 9743 9749 9751 975B 975D 976F 977F 9787 9793 97A5 97B1 97B7 97C3 97CD 97D3 97D9 97EB 97F7 9805 9809 980B 9815 9829 982F 983B 9841 9851 986B 986F 9881 9883 9887 98A7 98B1 98B9 98BF 98C3 98C9 98CF 98DD 98E3 98F5 98F9 98FB 990D 9917 991F 9929 9931 993B 993D 9941 9947 9949 9953 997D 9985 9991 9995 999B 99AD 99AF 99BF 99C7 99CB 99CD 99D7 99E5 99F1 99FB 9A0F 9A13 9A1B 9A25 9A4B 9A4F 9A55 9A57 9A61 9A75 9A7F 9A8B 9A91 9A9D 9AB7 9AC3 9AC7 9ACF 9AEB 9AF3 9AF7 9AFF 9B17 9B1D 9B27 9B2F 9B35 9B45 9B51 9B59 9B63 9B6F 9B77 9B8D 9B93 9B95 9B9F 9BA1 9BA7 9BB1 9BB7 9BBD 9BC5 9BCB 9BCF 9BDD 9BF9 9C01 9C11 9C23 9C2B 9C2F 9C35 9C49 9C4D 9C5F 9C65 9C67 9C7F 9C97 9C9D 9CA3 9CAF 9CBB 9CBF 9CC1 9CD7 9CD9 9CE3 9CE9 9CF1 9CFD 9D01 9D15 9D27 9D2D 9D31 9D3D 9D55 9D5B 9D61 9D97 9D9F 9DA5 9DA9 9DC3 9DE7 9DEB 9DED 9DF1 9E0B 9E17 9E23 9E27 9E2D 9E33 9E3B 9E47 9E51 9E53 9E5F 9E6F 9E81 9E87 9E8F 9E95 9EA1 9EB3 9EBD 9EBF 9EF5 9EF9 9EFB 9F05 9F23 9F2F 9F37 9F3B 9F43 9F53 9F61 9F6D 9F73 9F77 9F7D 9F89 9F8F 9F91 9F95 9FA3 9FAF 9FB3 9FC1 9FC7 9FDF 9FE5 9FEB 9FF5 A001 A00D A021 A033 A039 A03F A04F A057 A05B A061 A075 A079 A099 A09D A0AB A0B5 A0B7 A0BD A0C9 A0D9 A0DB A0DF A0E5 A0F1 A0F3 A0FD A105 A10B A10F A111 A11B A129 A12F A135 A141 A153 A175 A17D A187 A18D A1A5 A1AB A1AD A1B7 A1C3 A1C5 A1E3 A1ED A1FB A207 A213 A223 A229 A22F A231 A243 A247 A24D A26B A279 A27D A283 A289 A28B A291 A295 A29B A2A9 A2AF A2B3 A2BB A2C5 A2D1 A2D7 A2F7 A301 A309 A31F A321 A32B A331 A349 A351 A355 A373 A379 A37B A387 A397 A39F A3A5 A3A9 A3AF A3B7 A3C7 A3D5 A3DB A3E1 A3E5 A3E7 A3F1 A3FD A3FF A40F A41D A421 A423 A427 A43B A44D A457 A459 A463 A469 A475 A493 A49B A4AD A4B9 A4C3 A4C5 A4CB A4D1 A4D5 A4E1 A4ED A4EF A4F3 A4FF A511 A529 A52B A535 A53B A543 A553 A55B A561 A56D A577 A585 A58B A597 A59D A5A3 A5A7 A5A9 A5C1 A5C5 A5CB A5D3 A5D9 A5DD A5DF A5E3 A5E9 A5F7 A5FB A603 A60D A625 A63D A649 A64B A651 A65D A673 A691 A693 A699 A6AB A6B5 A6BB A6C1 A6C9 A6CD A6CF A6D5 A6DF A6E7 A6F1 A6F7 A6FF A70F A715 A723 A729 A72D A745 A74D A757 A759 A765 A76B A76F A793 A795 A7AB A7B1 A7B9 A7BF A7C9 A7D1 A7D7 A7E3 A7ED A7FB A805 A80B A81D A829 A82B A837 A83B A855 A85F A86D A87D A88F A897 A8A9 A8B5 A8C1 A8C7 A8D7 A8E5 A8FD A907 A913 A91B A931 A937 A939 A943 A97F A985 A987 A98B A993 A9A3 A9B1 A9BB A9C1 A9D9 A9DF A9EB A9FD AA15 AA17 AA35 AA39 AA3B AA47 AA4D AA57 AA59 AA5D AA6B AA71 AA81 AA83 AA8D AA95 AAAB AABF AAC5 AAC9 AAE9 AAEF AB01 AB05 AB07 AB0B AB0D AB11 AB19 AB4D AB5B AB71 AB73 AB89 AB9D ABA7 ABAF ABB9 ABBB ABC1 ABC5 ABD3 ABD7 ABDD ABF1 ABF5 ABFB ABFD AC09 AC15 AC1B AC27 AC37 AC39 AC45 AC4F AC57 AC5B AC61 AC63 AC7F AC8B AC93 AC9D ACA9 ACAB ACAF ACBD ACD9 ACE1 ACE7 ACEB ACED ACF1 ACF7 ACF9 AD05 AD3F AD45 AD53 AD5D AD5F AD65 AD81 ADA1 ADA5 ADC3 ADCB ADD1 ADD5 ADDB ADE7 ADF3 ADF5 ADF9 ADFF AE05 AE13 AE23 AE2B AE49 AE4D AE4F AE59 AE61 AE67 AE6B AE71 AE8B AE8F AE9B AE9D AEA7 AEB9 AEC5 AED1 AEE3 AEE5 AEE9 AEF5 AEFD AF09 AF13 AF27 AF2B AF33 AF43 AF4F AF57 AF5D AF6D AF75 AF7F AF8B AF99 AF9F AFA3 AFAB AFB7 AFBB AFCF AFD5 AFFD B005 B015 B01B B03F B041 B047 B04B B051 B053 B069 B07B B07D B087 B08D B0B1 B0BF B0CB B0CF B0E1 B0E9 B0ED B0FB B105 B107 B111 B119 B11D B11F B131 B141 B14D B15B B165 B173 B179 B17F B1A9 B1B3 B1B9 B1BF B1D3 B1DD B1E5 B1F1 B1F5 B201 B213 B215 B21F B22D B23F B249 B25B B263 B269 B26D B27B B281 B28B B2A9 B2B7 B2BD B2C3 B2C7 B2D3 B2F9 B2FD B2FF B303 B309 B311 B31D B327 B32D B33F B345 B377 B37D B381 B387 B393 B39B B3A5 B3C5 B3CB B3E1 B3E3 B3ED B3F9 B40B B40D B413 B417 B435 B43D B443 B449 B45B B465 B467 B46B B477 B48B B495 B49D B4B5 B4BF B4C1 B4C7 B4DD B4E3 B4E5 B4F7 B501 B50D B50F B52D B53F B54B B567 B569 B56F B573 B579 B587 B58D B599 B5A3 B5AB B5AF B5BB B5D5 B5DF B5E7 B5ED B5FD B5FF B609 B61B B629 B62F B633 B639 B647 B657 B659 B65F B663 B66F B683 B687 B69B B69F B6A5 B6B1 B6B3 B6D7 B6DB B6E1 B6E3 B6ED B6EF B705 B70D B713 B71D B729 B735 B747 B755 B76D B791 B795 B7A9 B7C1 B7CB B7D1 B7D3 B7EF B7F5 B807 B80F B813 B819 B821 B827 B82B B82D B839 B855 B867 B875 B885 B893 B8A5 B8AF B8B7 B8BD B8C1 B8C7 B8CD B8D5 B8EB B8F7 B8F9 B903 B915 B91B B91D B92F B939 B93B B947 B951 B963 B983 B989 B98D B993 B999 B9A1 B9A7 B9AD B9B7 B9CB B9D1 B9DD B9E7 B9EF B9F9 BA07 BA0D BA17 BA25 BA29 BA2B BA41 BA53 BA55 BA5F BA61 BA65 BA79 BA7D BA7F BAA1 BAA3 BAAF BAB5 BABF BAC1 BACB BADD BAE3 BAF1 BAFD BB09 BB1F BB27 BB2D BB3D BB43 BB4B BB4F BB5B BB61 BB69 BB6D BB91 BB97 BB9D BBB1 BBC9 BBCF BBDB BBED BBF7 BBF9 BC03 BC1D BC23 BC33 BC3B BC41 BC45 BC5D BC6F BC77 BC83 BC8F BC99 BCAB BCB7 BCB9 BCD1 BCD5 BCE1 BCF3 BCFF BD0D BD17 BD19 BD1D BD35 BD41 BD4F BD59 BD5F BD61 BD67 BD6B BD71 BD8B BD8F BD95 BD9B BD9D BDB3 BDBB BDCD BDD1 BDE3 BDEB BDEF BE07 BE09 BE15 BE21 BE25 BE27 BE5B BE5D BE6F BE75 BE79 BE7F BE8B BE8D BE93 BE9F BEA9 BEB1 BEB5 BEB7 BECF BED9 BEDB BEE5 BEE7 BEF3 BEF9 BF0B BF33 BF39 BF4D BF5D BF5F BF6B BF71 BF7B BF87 BF89 BF8D BF93 BFA1 BFAD BFB9 BFCF BFD5 BFDD BFE1 BFE3 BFF3 C005 C011 C013 C019 C029 C02F C031 C037 C03B C047 C065 C06D C07D C07F C091 C09B C0B3 C0B5 C0BB C0D3 C0D7 C0D9 C0EF C0F1 C101 C103 C109 C115 C119 C12B C133 C137 C145 C149 C15B C173 C179 C17B C181 C18B C18D C197 C1BD C1C3 C1CD C1DB C1E1 C1E7 C1FF C203 C205 C211 C221 C22F C23F C24B C24D C253 C25D C277 C27B C27D C289 C28F C293 C29F C2A7 C2B3 C2BD C2CF C2D5 C2E3 C2FF C301 C307 C311 C313 C317 C325 C347 C349 C34F C365 C367 C371 C37F C383 C385 C395 C39D C3A7 C3AD C3B5 C3BF C3C7 C3CB C3D1 C3D3 C3E3 C3E9 C3EF C401 C41F C42D C433 C437 C455 C457 C461 C46F C473 C487 C491 C499 C49D C4A5 C4B7 C4BB C4C9 C4CF C4D3 C4EB C4F1 C4F7 C509 C51B C51D C541 C547 C551 C55F C56B C56F C575 C577 C595 C59B C59F C5A1 C5A7 C5C3 C5D7 C5DB C5EF C5FB C613 C623 C635 C641 C64F C655 C659 C665 C685 C691 C697 C6A1 C6A9 C6B3 C6B9 C6CB C6CD C6DD C6EB C6F1 C707 C70D C719 C71B C72D C731 C739 C757 C763 C767 C773 C775 C77F C7A5 C7BB C7BD C7C1 C7CF C7D5 C7E1 C7F9 C7FD C7FF C803 C811 C81D C827 C829 C839 C83F C853 C857 C86B C881 C88D C88F C893 C895 C8A1 C8B7 C8CF C8D5 C8DB C8DD C8E3 C8E7 C8ED C8EF C8F9 C905 C911 C917 C919 C91F C92F C937 C93D C941 C953 C95F C96B C979 C97D C989 C98F C997 C99D C9AF C9B5 C9BF C9CB C9D9 C9DF C9E3 C9EB CA01 CA07 CA09 CA25 CA37 CA39 CA4B CA55 CA5B CA69 CA73 CA75 CA7F CA8D CA93 CA9D CA9F CAB5 CABB CAC3 CAC9 CAD9 CAE5 CAED CB03 CB05 CB09 CB17 CB29 CB35 CB3B CB53 CB59 CB63 CB65 CB71 CB87 CB99 CB9F CBB3 CBB9 CBC3 CBD1 CBD5 CBD7 CBDD CBE9 CBFF CC0D CC19 CC1D CC23 CC2B CC41 CC43 CC4D CC59 CC61 CC89 CC8B CC91 CC9B CCA3 CCA7 CCD1 CCE5 CCE9 CD09 CD15 CD1F CD25 CD31 CD3D CD3F CD49 CD51 CD57 CD5B CD63 CD67 CD81 CD93 CD97 CD9F CDBB CDC1 CDD3 CDD9 CDE5 CDE7 CDF1 CDF7 CDFD CE0B CE15 CE21 CE2F CE47 CE4D CE51 CE65 CE7B CE7D CE8F CE93 CE99 CEA5 CEA7 CEB7 CEC9 CED7 CEDD CEE3 CEE7 CEED CEF5 CF07 CF0B CF19 CF37 CF3B CF4D CF55 CF5F CF61 CF65 CF6D CF79 CF7D CF89 CF9B CF9D CFA9 CFB3 CFB5 CFC5 CFCD CFD1 CFEF CFF1 CFF7 D013 D015 D01F D021 D033 D03D D04B D04F D069 D06F D081 D085 D099 D09F D0A3 D0AB D0BD D0C1 D0CD D0E7 D0FF D103 D117 D12D D12F D141 D157 D159 D15D D169 D16B D171 D177 D17D D181 D187 D195 D199 D1B1 D1BD D1C3 D1D5 D1D7 D1E3 D1FF D20D D211 D217 D21F D235 D23B D247 D259 D261 D265 D279 D27F D283 D289 D28B D29D D2A3 D2A7 D2B3 D2BF D2C7 D2E3 D2E9 D2F1 D2FB D2FD D315 D321 D32B D343 D34B D355 D369 D375 D37B D387 D393 D397 D3A5 D3B1 D3C9 D3EB D3FD D405 D40F D415 D427 D42F D433 D43B D44B D459 D45F D463 D469 D481 D483 D489 D48D D493 D495 D4A5 D4AB D4B1 D4C5 D4DD D4E1 D4E3 D4E7 D4F5 D4F9 D50B D50D D513 D51F D523 D531 D535 D537 D549 D559 D55F D565 D567 D577 D58B D591 D597 D5B5 D5B9 D5C1 D5C7 D5DF D5EF D5F5 D5FB D603 D60F D62D D631 D643 D655 D65D D661 D67B D685 D687 D69D D6A5 D6AF D6BD D6C3 D6C7 D6D9 D6E1 D6ED D709 D70B D711 D715 D721 D727 D73F D745 D74D D757 D76B D77B D783 D7A1 D7A7 D7AD D7B1 D7B3 D7BD D7CB D7D1 D7DB D7FB D811 D823 D825 D829 D82B D82F D837 D84D D855 D867 D873 D88F D891 D8A1 D8AD D8BF D8CD D8D7 D8E9 D8F5 D8FB D91B D925 D933 D939 D943 D945 D94F D951 D957 D96D D96F D973 D979 D981 D98B D991 D99F D9A5 D9A9 D9B5 D9D3 D9EB D9F1 D9F7 D9FF DA05 DA09 DA0B DA0F DA15 DA1D DA23 DA29 DA3F DA51 DA59 DA5D DA5F DA71 DA77 DA7B DA7D DA8D DA9F DAB3 DABD DAC3 DAC9 DAE7 DAE9 DAF5 DB11 DB17 DB1D DB23 DB25 DB31 DB3B DB43 DB55 DB67 DB6B DB73 DB85 DB8F DB91 DBAD DBAF DBB9 DBC7 DBCB DBCD DBEB DBF7 DC0D DC27 DC31 DC39 DC3F DC49 DC51 DC61 DC6F DC75 DC7B DC85 DC93 DC99 DC9D DC9F DCA9 DCB5 DCB7 DCBD DCC7 DCCF DCD3 DCD5 DCDF DCF9 DD0F DD15 DD17 DD23 DD35 DD39 DD53 DD57 DD5F DD69 DD6F DD7D DD87 DD89 DD9B DDA1 DDAB DDBF DDC5 DDCB DDCF DDE7 DDE9 DDED DDF5 DDFB DE0B DE19 DE29 DE3B DE3D DE41 DE4D DE4F DE59 DE5B DE61 DE6D DE77 DE7D DE83 DE97 DE9D DEA1 DEA7 DECD DED1 DED7 DEE3 DEF1 DEF5 DF01 DF09 DF13 DF1F DF2B DF33 DF37 DF3D DF4B DF55 DF5B DF67 DF69 DF73 DF85 DF87 DF99 DFA3 DFAB DFB5 DFB7 DFC3 DFC7 DFD5 DFF1 DFF3 E003 E005 E017 E01D E027 E02D E035 E045 E053 E071 E07B E08F E095 E09F E0B7 E0B9 E0D5 E0D7 E0E3 E0F3 E0F9 E101 E125 E129 E131 E135 E143 E14F E159 E161 E16D E171 E177 E17F E183 E189 E197 E1AD E1B5 E1BB E1BF E1C1 E1CB E1D1 E1E5 E1EF E1F7 E1FD E203 E219 E22B E22D E23D E243 E257 E25B E275 E279 E287 E29D E2AB E2AF E2BB E2C1 E2C9 E2CD E2D3 E2D9 E2F3 E2FD E2FF E311 E323 E327 E329 E339 E33B E34D E351 E357 E35F E363 E369 E375 E377 E37D E383 E39F E3C5 E3C9 E3D1 E3E1 E3FB E3FF E401 E40B E417 E419 E423 E42B E431 E43B E447 E449 E453 E455 E46D E471 E48F E4A9 E4AF E4B5 E4C7 E4CD E4D3 E4E9 E4EB E4F5 E507 E521 E525 E537 E53F E545 E54B E557 E567 E56D E575 E585 E58B E593 E5A3 E5A5 E5CF E609 E611 E615 E61B E61D E621 E629 E639 E63F E653 E657 E663 E66F E675 E681 E683 E68D E68F E695 E6AB E6AD E6B7 E6BD E6C5 E6CB E6D5 E6E3 E6E9 E6EF E6F3 E705 E70D E717 E71F E72F E73D E747 E749 E753 E755 E761 E767 E76B E77F E789 E791 E7C5 E7CD E7D7 E7DD E7DF E7E9 E7F1 E7FB E801 E807 E80F E819 E81B E831 E833 E837 E83D E84B E84F E851 E869 E875 E879 E893 E8A5 E8A9 E8AF E8BD E8DB E8E1 E8E5 E8EB E8ED E903 E90B E90F E915 E917 E92D E933 E93B E94B E951 E95F E963 E969 E97B E983 E98F E995 E9A1 E9B9 E9D7 E9E7 E9EF EA11 EA19 EA2F EA35 EA43 EA4D EA5F EA6D EA71 EA7D EA85 EA89 EAAD EAB3 EAB9 EABB EAC5 EAC7 EACB EADF EAE5 EAEB EAF5 EB01 EB07 EB09 EB31 EB39 EB3F EB5B EB61 EB63 EB6F EB81 EB85 EB9D EBAB EBB1 EBB7 EBC1 EBD5 EBDF EBED EBFD EC0B EC1B EC21 EC29 EC4D EC51 EC5D EC69 EC6F EC7B ECAD ECB9 ECBF ECC3 ECC9 ECCF ECD7 ECDD ECE7 ECE9 ECF3 ECF5 ED07 ED11 ED1F ED2F ED37 ED3D ED41 ED55 ED59 ED5B ED65 ED6B ED79 ED8B ED95 EDBB EDC5 EDD7 EDD9 EDE3 EDE5 EDF1 EDF5 EDF7 EDFB EE09 EE0F EE19 EE21 EE49 EE4F EE63 EE67 EE73 EE7B EE81 EEA3 EEAB EEC1 EEC9 EED5 EEDF EEE1 EEF1 EF1B EF27 EF2F EF45 EF4D EF63 EF6B EF71 EF93 EF95 EF9B EF9F EFAD EFB3 EFC3 EFC5 EFDB EFE1 EFE9 F001 F017 F01D F01F F02B F02F F035 F043 F047 F04F F067 F06B F071 F077 F079 F08F F0A3 F0A9 F0AD F0BB F0BF F0C5 F0CB F0D3 F0D9 F0E3 F0E9 F0F1 F0F7 F107 F115 F11B F121 F137 F13D F155 F175 F17B F18D F193 F1A5 F1AF F1B7 F1D5 F1E7 F1ED F1FD F209 F20F F21B F21D F223 F227 F233 F23B F241 F257 F25F F265 F269 F277 F281 F293 F2A7 F2B1 F2B3 F2B9 F2BD F2BF F2DB F2ED F2EF F2F9 F2FF F305 F30B F319 F341 F359 F35B F35F F367 F373 F377 F38B F38F F3AF F3C1 F3D1 F3D7 F3FB F403 F409 F40D F413 F421 F425 F42B F445 F44B F455 F463 F475 F47F F485 F48B F499 F4A3 F4A9 F4AF F4BD F4C3 F4DB F4DF F4ED F503 F50B F517 F521 F529 F535 F547 F551 F563 F56B F583 F58D F595 F599 F5B1 F5B7 F5C9 F5CF F5D1 F5DB F5F9 F5FB F605 F607 F60B F60D F635 F637 F653 F65B F661 F667 F679 F67F F689 F697 F69B F6AD F6CB F6DD F6DF F6EB F709 F70F F72D F731 F743 F74F F751 F755 F763 F769 F773 F779 F781 F787 F791 F79D F79F F7A5 F7B1 F7BB F7BD F7CF F7D3 F7E7 F7EB F7F1 F7FF F805 F80B F821 F827 F82D F835 F847 F859 F863 F865 F86F F871 F877 F87B F881 F88D F89F F8A1 F8AB F8B3 F8B7 F8C9 F8CB F8D1 F8D7 F8DD F8E7 F8EF F8F9 F8FF F911 F91D F925 F931 F937 F93B F941 F94F F95F F961 F96D F971 F977 F99D F9A3 F9A9 F9B9 F9CD F9E9 F9FD FA07 FA0D FA13 FA21 FA25 FA3F FA43 FA51 FA5B FA6D FA7B FA97 FA99 FA9D FAAB FABB FABD FAD9 FADF FAE7 FAED FB0F FB17 FB1B FB2D FB2F FB3F FB47 FB4D FB75 FB7D FB8F FB93 FBB1 FBB7 FBC3 FBC5 FBE3 FBE9 FBF3 FC01 FC29 FC37 FC41 FC43 FC4F FC59 FC61 FC65 FC6D FC73 FC79 FC95 FC97 FC9B FCA7 FCB5 FCC5 FCCD FCEB FCFB FD0D FD0F FD19 FD2B FD31 FD51 FD55 FD67 FD6D FD6F FD7B FD85 FD97 FD99 FD9F FDA9 FDB7 FDC9 FDE5 FDEB FDF3 FE03 FE05 FE09 FE1D FE27 FE2F FE41 FE4B FE4D FE57 FE5F FE63 FE69 FE75 FE7B FE8F FE93 FE95 FE9B FE9F FEB3 FEBD FED7 FEE9 FEF3 FEF5 FF07 FF0D FF1D FF2B FF2F FF49 FF4D FF5B FF65 FF71 FF7F FF85 FF8B FF8F FF9D FFA7 FFA9 FFC7 FFD9 FFEF FFF1 -Execution halted after 2821638 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/16bitSegmentedSieveModern.out b/Tests/expected/16bitSegmentedSieveModern.out index 6fabc45..e555473 100644 --- a/Tests/expected/16bitSegmentedSieveModern.out +++ b/Tests/expected/16bitSegmentedSieveModern.out @@ -1,3 +1,3 @@ 0002 0003 0005 0007 000B 000D 0011 0013 0017 001D 001F 0025 0029 002B 002F 0035 003B 003D 0043 0047 0049 004F 0053 0059 0061 0065 0067 006B 006D 0071 007F 0083 0089 008B 0095 0097 009D 00A3 00A7 00AD 00B3 00B5 00BF 00C1 00C5 00C7 00D3 00DF 00E3 00E5 00E9 00EF 00F1 00FB 0101 0107 010D 010F 0115 0119 011B 0125 0133 0137 0139 013D 014B 0151 015B 015D 0161 0167 016F 0175 017B 017F 0185 018D 0191 0199 01A3 01A5 01AF 01B1 01B7 01BB 01C1 01C9 01CD 01CF 01D3 01DF 01E7 01EB 01F3 01F7 01FD 0209 020B 021D 0223 022D 0233 0239 023B 0241 024B 0251 0257 0259 025F 0265 0269 026B 0277 0281 0283 0287 028D 0293 0295 02A1 02A5 02AB 02B3 02BD 02C5 02CF 02D7 02DD 02E3 02E7 02EF 02F5 02F9 0301 0305 0313 031D 0329 032B 0335 0337 033B 033D 0347 0355 0359 035B 035F 036D 0371 0373 0377 038B 038F 0397 03A1 03A9 03AD 03B3 03B9 03C7 03CB 03D1 03D7 03DF 03E5 03F1 03F5 03FB 03FD 0407 0409 040F 0419 041B 0425 0427 042D 043F 0443 0445 0449 044F 0455 045D 0463 0469 047F 0481 048B 0493 049D 04A3 04A9 04B1 04BD 04C1 04C7 04CD 04CF 04D5 04E1 04EB 04FD 04FF 0503 0509 050B 0511 0515 0517 051B 0527 0529 052F 0551 0557 055D 0565 0577 0581 058F 0593 0595 0599 059F 05A7 05AB 05AD 05B3 05BF 05C9 05CB 05CF 05D1 05D5 05DB 05E7 05F3 05FB 0607 060D 0611 0617 061F 0623 062B 062F 063D 0641 0647 0649 064D 0653 0655 065B 0665 0679 067F 0683 0685 069D 06A1 06A3 06AD 06B9 06BB 06C5 06CD 06D3 06D9 06DF 06F1 06F7 06FB 06FD 0709 0713 071F 0727 0737 0745 074B 074F 0751 0755 0757 0761 076D 0773 0779 078B 078D 079D 079F 07B5 07BB 07C3 07C9 07CD 07CF 07D3 07DB 07E1 07EB 07ED 07F7 0805 080F 0815 0821 0823 0827 0829 0833 083F 0841 0851 0853 0859 085D 085F 0869 0871 0883 089B 089F 08A5 08AD 08BD 08BF 08C3 08CB 08DB 08DD 08E1 08E9 08EF 08F5 08F9 0905 0907 091D 0923 0925 092B 092F 0935 0943 0949 094D 094F 0955 0959 095F 096B 0971 0977 0985 0989 098F 099B 09A3 09A9 09AD 09C7 09D9 09E3 09EB 09EF 09F5 09F7 09FD 0A13 0A1F 0A21 0A31 0A39 0A3D 0A49 0A57 0A61 0A63 0A67 0A6F 0A75 0A7B 0A7F 0A81 0A85 0A8B 0A93 0A97 0A99 0A9F 0AA9 0AAB 0AB5 0ABD 0AC1 0ACF 0AD9 0AE5 0AE7 0AED 0AF1 0AF3 0B03 0B11 0B15 0B1B 0B23 0B29 0B2D 0B3F 0B47 0B51 0B57 0B5D 0B65 0B6F 0B7B 0B89 0B8D 0B93 0B99 0B9B 0BB7 0BB9 0BC3 0BCB 0BCF 0BDD 0BE1 0BE9 0BF5 0BFB 0C07 0C0B 0C11 0C25 0C2F 0C31 0C41 0C5B 0C5F 0C61 0C6D 0C73 0C77 0C83 0C89 0C91 0C95 0C9D 0CB3 0CB5 0CB9 0CBB 0CC7 0CE3 0CE5 0CEB 0CF1 0CF7 0CFB 0D01 0D03 0D0F 0D13 0D1F 0D21 0D2B 0D2D 0D3D 0D3F 0D4F 0D55 0D69 0D79 0D81 0D85 0D87 0D8B 0D8D 0DA3 0DAB 0DB7 0DBD 0DC7 0DC9 0DCD 0DD3 0DD5 0DDB 0DE5 0DE7 0DF3 0DFD 0DFF 0E09 0E17 0E1D 0E21 0E27 0E2F 0E35 0E3B 0E4B 0E57 0E59 0E5D 0E6B 0E71 0E75 0E7D 0E87 0E8F 0E95 0E9B 0EB1 0EB7 0EB9 0EC3 0ED1 0ED5 0EDB 0EED 0EEF 0EF9 0F07 0F0B 0F0D 0F17 0F25 0F29 0F31 0F43 0F47 0F4D 0F4F 0F53 0F59 0F5B 0F67 0F6B 0F7F 0F95 0FA1 0FA3 0FA7 0FAD 0FB3 0FB5 0FBB 0FD1 0FD3 0FD9 0FE9 0FEF 0FFB 0FFD 1003 100F 101F 1021 1025 102B 1039 103D 103F 1051 1069 1073 1079 107B 1085 1087 1091 1093 109D 10A3 10A5 10AF 10B1 10BB 10C1 10C9 10E7 10F1 10F3 10FD 1105 110B 1115 1127 112D 1139 1145 1147 1159 115F 1163 1169 116F 1181 1183 118D 119B 11A1 11A5 11A7 11AB 11C3 11C5 11D1 11D7 11E7 11EF 11F5 11FB 120D 121D 121F 1223 1229 122B 1231 1237 1241 1247 1253 125F 1271 1273 1279 127D 128F 1297 12AF 12B3 12B5 12B9 12BF 12C1 12CD 12D1 12DF 12FD 1307 130D 1319 1327 132D 1337 1343 1345 1349 134F 1357 135D 1367 1369 136D 137B 1381 1387 138B 1391 1393 139D 139F 13AF 13BB 13C3 13D5 13D9 13DF 13EB 13ED 13F3 13F9 13FF 141B 1421 142F 1433 143B 1445 144D 1459 146B 146F 1471 1475 148D 1499 149F 14A1 14B1 14B7 14BD 14CB 14D5 14E3 14E7 1505 150B 1511 1517 151F 1525 1529 152B 1537 153D 1541 1543 1549 155F 1565 1567 156B 157D 157F 1583 158F 1591 1597 159B 15B5 15BB 15C1 15C5 15CD 15D7 15F7 1607 1609 160F 1613 1615 1619 161B 1625 1633 1639 163D 1645 164F 1655 1669 166D 166F 1675 1693 1697 169F 16A9 16AF 16B5 16BD 16C3 16CF 16D3 16D9 16DB 16E1 16E5 16EB 16ED 16F7 16F9 1709 170F 1723 1727 1733 1741 175D 1763 1777 177B 178D 1795 179B 179F 17A5 17B3 17B9 17BF 17C9 17CB 17D5 17E1 17E9 17F3 17F5 17FF 1807 1813 181D 1835 1837 183B 1843 1849 184D 1855 1867 1871 1877 187D 187F 1885 188F 189B 189D 18A7 18AD 18B3 18B9 18C1 18C7 18D1 18D7 18D9 18DF 18E5 18EB 18F5 18FD 1915 191B 1931 1933 1945 1949 1951 195B 1979 1981 1993 1997 1999 19A3 19A9 19AB 19B1 19B5 19C7 19CF 19DB 19ED 19FD 1A03 1A05 1A11 1A17 1A21 1A23 1A2D 1A2F 1A35 1A3F 1A4D 1A51 1A69 1A6B 1A7B 1A7D 1A87 1A89 1A93 1AA7 1AAB 1AAD 1AB1 1AB9 1AC9 1ACF 1AD5 1AD7 1AE3 1AF3 1AFB 1AFF 1B05 1B23 1B25 1B2F 1B31 1B37 1B3B 1B41 1B47 1B4F 1B55 1B59 1B65 1B6B 1B73 1B7F 1B83 1B91 1B9D 1BA7 1BBF 1BC5 1BD1 1BD7 1BD9 1BEF 1BF7 1C09 1C13 1C19 1C27 1C2B 1C2D 1C33 1C3D 1C45 1C4B 1C4F 1C55 1C73 1C81 1C8B 1C8D 1C99 1CA3 1CA5 1CB5 1CB7 1CC9 1CE1 1CF3 1CF9 1D09 1D1B 1D21 1D23 1D35 1D39 1D3F 1D41 1D4B 1D53 1D5D 1D63 1D69 1D71 1D75 1D7B 1D7D 1D87 1D89 1D95 1D99 1D9F 1DA5 1DA7 1DB3 1DB7 1DC5 1DD7 1DDB 1DE1 1DF5 1DF9 1E01 1E07 1E0B 1E13 1E17 1E25 1E2B 1E2F 1E3D 1E49 1E4D 1E4F 1E6D 1E71 1E89 1E8F 1E95 1EA1 1EAD 1EBB 1EC1 1EC5 1EC7 1ECB 1EDD 1EE3 1EEF 1EF7 1EFD 1F01 1F0D 1F0F 1F1B 1F39 1F49 1F4B 1F51 1F67 1F75 1F7B 1F85 1F91 1F97 1F99 1F9D 1FA5 1FAF 1FB5 1FBB 1FD3 1FE1 1FE7 1FEB 1FF3 1FFF 2011 201B 201D 2027 2029 202D 2033 2047 204D 2051 205F 2063 2065 2069 2077 207D 2089 20A1 20AB 20B1 20B9 20C3 20C5 20E3 20E7 20ED 20EF 20FB 20FF 210D 2113 2135 2141 2149 214F 2159 215B 215F 2173 217D 2185 2195 2197 21A1 21AF 21B3 21B5 21C1 21C7 21D7 21DD 21E5 21E9 21F1 21F5 21FB 2203 2209 220F 221B 2221 2225 222B 2231 2239 224B 224F 2263 2267 2273 2275 227F 2285 2287 2291 229D 229F 22A3 22B7 22BD 22DB 22E1 22E5 22ED 22F7 2303 2309 230B 2327 2329 232F 2333 2335 2345 2351 2353 2359 2363 236B 2383 238F 2395 23A7 23AD 23B1 23BF 23C5 23C9 23D5 23DD 23E3 23EF 23F3 23F9 2405 240B 2417 2419 2429 243D 2441 2443 244D 245F 2467 246B 2479 247D 247F 2485 249B 24A1 24AF 24B5 24BB 24C5 24CB 24CD 24D7 24D9 24DD 24DF 24F5 24F7 24FB 2501 2507 2513 2519 2527 2531 253D 2543 254B 254F 2573 2581 258D 2593 2597 259D 259F 25AB 25B1 25BD 25CD 25CF 25D9 25E1 25F7 25F9 2605 260B 260F 2615 2627 2629 2635 263B 263F 264B 2653 2659 2665 2669 266F 267B 2681 2683 268F 269B 269F 26AD 26B3 26C3 26C9 26CB 26D5 26DD 26EF 26F5 2717 2719 2735 2737 274D 2753 2755 275F 276B 276D 2773 2777 277F 2795 279B 279D 27A7 27AF 27B3 27B9 27C1 27C5 27D1 27E3 27EF 2803 2807 280D 2813 281B 281F 2821 2831 283D 283F 2849 2851 285B 285D 2861 2867 2875 2881 2897 289F 28BB 28BD 28C1 28D5 28D9 28DB 28DF 28ED 28F7 2903 2905 2911 2921 2923 293F 2947 295D 2965 2969 296F 2975 2983 2987 298F 299B 29A1 29A7 29AB 29BF 29C3 29D5 29D7 29E3 29E9 29ED 29F3 2A01 2A13 2A1D 2A25 2A2F 2A4F 2A55 2A5F 2A65 2A6B 2A6D 2A73 2A83 2A89 2A8B 2A97 2A9D 2AB9 2ABB 2AC5 2ACD 2ADD 2AE3 2AEB 2AF1 2AFB 2B13 2B27 2B31 2B33 2B3D 2B3F 2B4B 2B4F 2B55 2B69 2B6D 2B6F 2B7B 2B8D 2B97 2B99 2BA3 2BA5 2BA9 2BBD 2BCD 2BE7 2BEB 2BF3 2BF9 2BFD 2C09 2C0F 2C17 2C23 2C2F 2C35 2C39 2C41 2C57 2C59 2C69 2C77 2C81 2C87 2C93 2C9F 2CAD 2CB3 2CB7 2CCB 2CCF 2CDB 2CE1 2CE3 2CE9 2CEF 2CFF 2D07 2D1D 2D1F 2D3B 2D43 2D49 2D4D 2D61 2D65 2D71 2D89 2D9D 2DA1 2DA9 2DB3 2DB5 2DC5 2DC7 2DD3 2DDF 2E01 2E03 2E07 2E0D 2E19 2E1F 2E25 2E2D 2E33 2E37 2E39 2E3F 2E57 2E5B 2E6F 2E79 2E7F 2E85 2E93 2E97 2E9D 2EA3 2EA5 2EB1 2EB7 2EC1 2EC3 2ECD 2ED3 2EE7 2EEB 2F05 2F09 2F0B 2F11 2F27 2F29 2F41 2F45 2F4B 2F4D 2F51 2F57 2F6F 2F75 2F7D 2F81 2F83 2FA5 2FAB 2FB3 2FC3 2FCF 2FD1 2FDB 2FDD 2FE7 2FED 2FF5 2FF9 3001 300D 3023 3029 3037 303B 3055 3059 305B 3067 3071 3079 307D 3085 3091 3095 30A3 30A9 30B9 30BF 30C7 30CB 30D1 30D7 30DF 30E5 30EF 30FB 30FD 3103 3109 3119 3121 3127 312D 3139 3143 3145 314B 315D 3161 3167 316D 3173 317F 3191 3199 319F 31A9 31B1 31C3 31C7 31D5 31DB 31ED 31F7 31FF 3209 3215 3217 321D 3229 3235 3259 325D 3263 326B 326F 3275 3277 327B 328D 3299 329F 32A7 32AD 32B3 32B7 32C9 32CB 32CF 32D1 32E9 32ED 32F3 32F9 3307 3325 332B 332F 3335 3341 3347 335B 335F 3367 336B 3373 3379 337F 3383 33A1 33A3 33AD 33B9 33C1 33CB 33D3 33EB 33F1 33FD 3401 340F 3413 3419 341B 3437 3445 3455 3457 3463 3469 346D 3481 348B 3491 3497 349D 34A5 34AF 34BB 34C9 34D3 34E1 34F1 34FF 3509 3517 351D 352D 3533 353B 3541 3551 3565 356F 3571 3577 357B 357D 3581 358D 358F 3599 359B 35A1 35B7 35BD 35BF 35C3 35D5 35DD 35E7 35EF 3605 3607 3611 3623 3631 3635 3637 363B 364D 364F 3653 3659 3661 366B 366D 368B 368F 36AD 36AF 36B9 36BB 36CD 36D1 36E3 36E9 36F7 3701 3703 3707 371B 373F 3745 3749 374F 375D 3761 3775 377F 378D 37A3 37A9 37AB 37C9 37D5 37DF 37F1 37F3 37F7 3805 380B 3821 3833 3835 3841 3847 384B 3853 3857 385F 3865 386F 3871 387D 388F 3899 38A7 38B7 38C5 38C9 38CF 38D5 38D7 38DD 38E1 38E3 38FF 3901 391D 3923 3925 3929 392F 393D 3941 394D 395B 396B 3979 397D 3983 398B 3991 3995 399B 39A1 39A7 39AF 39B3 39BB 39BF 39CD 39DD 39E5 39EB 39EF 39FB 3A03 3A13 3A15 3A1F 3A27 3A2B 3A31 3A4B 3A51 3A5B 3A63 3A67 3A6D 3A79 3A87 3AA5 3AA9 3AB7 3ACD 3AD5 3AE1 3AE5 3AEB 3AF3 3AFD 3B03 3B11 3B1B 3B21 3B23 3B2D 3B39 3B45 3B53 3B59 3B5F 3B71 3B7B 3B81 3B89 3B9B 3B9F 3BA5 3BA7 3BAD 3BB7 3BB9 3BC3 3BCB 3BD1 3BD7 3BE1 3BE3 3BF5 3BFF 3C01 3C0D 3C11 3C17 3C1F 3C29 3C35 3C43 3C4F 3C53 3C5B 3C65 3C6B 3C71 3C85 3C89 3C97 3CA7 3CB5 3CBF 3CC7 3CD1 3CDD 3CDF 3CF1 3CF7 3D03 3D0D 3D19 3D1B 3D1F 3D21 3D2D 3D33 3D37 3D3F 3D43 3D6F 3D73 3D75 3D79 3D7B 3D85 3D91 3D97 3D9D 3DAB 3DAF 3DB5 3DBB 3DC1 3DC9 3DCF 3DF3 3E05 3E09 3E0F 3E11 3E1D 3E23 3E29 3E2F 3E33 3E41 3E57 3E63 3E65 3E77 3E81 3E87 3EA1 3EB9 3EBD 3EBF 3EC3 3EC5 3EC9 3ED7 3EDB 3EE1 3EE7 3EEF 3EFF 3F0B 3F0D 3F37 3F3B 3F3D 3F41 3F59 3F5F 3F65 3F67 3F79 3F7D 3F8B 3F91 3FAD 3FBF 3FCD 3FD3 3FDD 3FE9 3FEB 3FF1 3FFD 401B 4021 4025 402B 4031 403F 4043 4045 405D 4061 4067 406D 4087 4091 40A3 40A9 40B1 40B7 40BD 40DB 40DF 40EB 40F7 40F9 4109 410B 4111 4115 4121 4133 4135 413B 413F 4159 4165 416B 4177 417B 4193 41AB 41B7 41BD 41BF 41CB 41E7 41EF 41F3 41F9 4205 4207 4219 421F 4223 4229 422F 4243 4253 4255 425B 4261 4273 427D 4283 4285 4289 4291 4297 429D 42B5 42C5 42CB 42D3 42DD 42E3 42F1 4307 430F 431F 4325 4327 4333 4337 4339 434F 4357 4369 438B 438D 4393 43A5 43A9 43AF 43B5 43BD 43C7 43CF 43E1 43E7 43EB 43ED 43F1 43F9 4409 440B 4417 4423 4429 443B 443F 4445 444B 4451 4453 4459 4465 446F 4483 448F 44A1 44A5 44AB 44AD 44BD 44BF 44C9 44D7 44DB 44F9 44FB 4505 4511 4513 452B 4531 4541 4549 4553 4555 4561 4577 457D 457F 458F 45A3 45AD 45AF 45BB 45C7 45D9 45E3 45EF 45F5 45F7 4601 4603 4609 4613 4625 4627 4633 4639 463D 4643 4645 465D 4679 467B 467F 4681 468B 468D 469D 46A9 46B1 46C7 46C9 46CF 46D3 46D5 46DF 46E5 46F9 4705 470F 4717 4723 4729 472F 4735 4739 474B 474D 4751 475D 476F 4771 477D 4783 4787 4789 4799 47A5 47B1 47BF 47C3 47CB 47DD 47E1 47ED 47FB 4801 4807 480B 4813 4819 481D 4831 483D 4847 4855 4859 485B 486B 486D 4879 4897 489B 48A1 48B9 48CD 48E5 48EF 48F7 4903 490D 4919 491F 492B 4937 493D 4945 4955 4963 4969 496D 4973 4997 49AB 49B5 49D3 49DF 49E1 49E5 49E7 4A03 4A0F 4A1D 4A23 4A39 4A41 4A45 4A57 4A5D 4A6B 4A7D 4A81 4A87 4A89 4A8F 4AB1 4AC3 4AC5 4AD5 4ADB 4AED 4AEF 4B07 4B0B 4B0D 4B13 4B1F 4B25 4B31 4B3B 4B43 4B49 4B59 4B65 4B6D 4B77 4B85 4BAD 4BB3 4BB5 4BBB 4BBF 4BCB 4BD9 4BDD 4BDF 4BE3 4BE5 4BE9 4BF1 4BF7 4C01 4C07 4C0D 4C0F 4C15 4C1B 4C21 4C2D 4C33 4C4B 4C55 4C57 4C61 4C67 4C73 4C79 4C7F 4C8D 4C93 4C99 4CCD 4CE1 4CE7 4CF1 4CF3 4CFD 4D05 4D0F 4D1B 4D27 4D29 4D2F 4D33 4D41 4D51 4D59 4D65 4D6B 4D81 4D83 4D8D 4D95 4D9B 4DB1 4DB3 4DC9 4DCF 4DD7 4DE1 4DED 4DF9 4DFB 4E05 4E0B 4E17 4E19 4E1D 4E2B 4E35 4E37 4E3D 4E4F 4E53 4E5F 4E67 4E79 4E85 4E8B 4E91 4E95 4E9B 4EA1 4EAF 4EB3 4EB5 4EC1 4ECD 4ED1 4ED7 4EE9 4EFB 4F07 4F09 4F19 4F25 4F2D 4F3F 4F49 4F63 4F67 4F6D 4F75 4F7B 4F81 4F85 4F87 4F91 4FA5 4FA9 4FAF 4FB7 4FBB 4FCF 4FD9 4FDB 4FFD 4FFF 5003 501B 501D 5029 5035 503F 5045 5047 5053 5071 5077 5083 5093 509F 50A1 50B7 50C9 50D5 50E3 50ED 50EF 50FB 5107 510B 510D 5111 5117 5123 5125 5135 5147 5149 5171 5179 5189 518F 5197 51A1 51A3 51A7 51B9 51C1 51CB 51D3 51DF 51E3 51F5 51F7 5209 5213 5215 5219 521B 521F 5227 5243 5245 524B 5261 526D 5273 5281 5293 5297 529D 52A5 52AB 52B1 52BB 52C3 52C7 52C9 52DB 52E5 52EB 52FF 5315 531D 5323 5341 5345 5347 534B 535D 5363 5381 5383 5387 538F 5395 5399 539F 53AB 53B9 53DB 53E9 53EF 53F3 53F5 53FB 53FF 540D 5411 5413 5419 5435 5437 543B 5441 5449 5453 5455 545F 5461 546B 546D 5471 548F 5491 549D 54A9 54B3 54C5 54D1 54DF 54E9 54EB 54F7 54FD 5507 550D 551B 5527 552B 5539 553D 554F 5551 555B 5563 5567 556F 5579 5585 5597 55A9 55B1 55B7 55C9 55D9 55E7 55ED 55F3 55FD 560B 560F 5615 5617 5623 562F 5633 5639 563F 564B 564D 565D 565F 566B 5671 5675 5683 5689 568D 568F 569B 56AD 56B1 56D5 56E7 56F3 56FF 5701 5705 5707 570B 5713 571F 5723 5747 574D 575F 5761 576D 5777 577D 5789 57A1 57A9 57AF 57B5 57C5 57D1 57D3 57E5 57EF 5803 580D 580F 5815 5827 582B 582D 5855 585B 585D 586D 586F 5873 587B 588D 5897 58A3 58A9 58AB 58B5 58BD 58C1 58C7 58D3 58D5 58DF 58F1 58F9 58FF 5903 5917 591B 5921 5945 594B 594D 5957 595D 5975 597B 5989 5999 599F 59B1 59B3 59BD 59D1 59DB 59E3 59E9 59ED 59F3 59F5 59FF 5A01 5A0D 5A11 5A13 5A17 5A1F 5A29 5A2F 5A3B 5A4D 5A5B 5A67 5A77 5A7F 5A85 5A95 5A9D 5AA1 5AA3 5AA9 5ABB 5AD3 5AE5 5AEF 5AFB 5AFD 5B01 5B0F 5B19 5B1F 5B25 5B2B 5B3D 5B49 5B4B 5B67 5B79 5B87 5B97 5BA3 5BB1 5BC9 5BD5 5BEB 5BF1 5BF3 5BFD 5C05 5C09 5C0B 5C0F 5C1D 5C29 5C2F 5C33 5C39 5C47 5C4B 5C4D 5C51 5C6F 5C75 5C77 5C7D 5C87 5C89 5CA7 5CBD 5CBF 5CC3 5CC9 5CD1 5CD7 5CDD 5CED 5CF9 5D05 5D0B 5D13 5D17 5D19 5D31 5D3D 5D41 5D47 5D4F 5D55 5D5B 5D65 5D67 5D6D 5D79 5D95 5DA3 5DA9 5DAD 5DB9 5DC1 5DC7 5DD3 5DD7 5DDD 5DEB 5DF1 5DFD 5E07 5E0D 5E13 5E1B 5E21 5E27 5E2B 5E2D 5E31 5E39 5E45 5E49 5E57 5E69 5E73 5E75 5E85 5E8B 5E9F 5EA5 5EAF 5EB7 5EBB 5ED9 5EFD 5F09 5F11 5F27 5F33 5F35 5F3B 5F47 5F57 5F5D 5F63 5F65 5F77 5F7B 5F95 5F99 5FA1 5FB3 5FBD 5FC5 5FCF 5FD5 5FE3 5FE7 5FFB 6011 6023 602F 6037 6053 605F 6065 606B 6073 6079 6085 609D 60AD 60BB 60BF 60CD 60D9 60DF 60E9 60F5 6109 610F 6113 611B 612D 6139 614B 6155 6157 615B 616F 6179 6187 618B 6191 6193 619D 61B5 61C7 61C9 61CD 61E1 61F1 61FF 6209 6217 621D 6221 6227 623B 6241 624B 6251 6253 625F 6265 6283 628D 6295 629B 629F 62A5 62AD 62D5 62D7 62DB 62DD 62E9 62FB 62FF 6305 630D 6317 631D 632F 6341 6343 634F 635F 6367 636D 6371 6377 637D 637F 63B3 63C1 63C5 63D9 63E9 63EB 63EF 63F5 6401 6403 6409 6415 6421 6427 642B 6439 6443 6449 644F 645D 6467 6475 6485 648D 6493 649F 64A3 64AB 64C1 64C7 64C9 64DB 64F1 64F7 64F9 650B 6511 6521 652F 6539 653F 654B 654D 6553 6557 655F 6571 657D 658D 658F 6593 65A1 65A5 65AD 65B9 65C5 65E3 65F3 65FB 65FF 6601 6607 661D 6629 6631 663B 6641 6647 664D 665B 6661 6673 667D 6689 668B 6695 6697 669B 66B5 66B9 66C5 66CD 66D1 66E3 66EB 66F5 6703 6713 6719 671F 6727 6731 6737 673F 6745 6751 675B 676F 6779 6781 6785 6791 67AB 67BD 67C1 67CD 67DF 67E5 6803 6809 6811 6817 682D 6839 683B 683F 6845 684B 684D 6857 6859 685D 6863 6869 686B 6871 6887 6899 689F 68B1 68BD 68C5 68D1 68D7 68E1 68ED 68EF 68FF 6901 690B 690D 6917 6929 692F 6943 6947 6949 694F 6965 696B 6971 6983 6989 6997 69A3 69B3 69B5 69BB 69C1 69C5 69D3 69DF 69E3 69E5 69F7 6A07 6A2B 6A37 6A3D 6A4B 6A67 6A69 6A75 6A7B 6A87 6A8D 6A91 6A93 6AA3 6AC1 6AC9 6AE1 6AE7 6B05 6B0F 6B11 6B23 6B27 6B2D 6B39 6B41 6B57 6B59 6B5F 6B75 6B87 6B89 6B93 6B95 6B9F 6BBD 6BBF 6BDB 6BE1 6BEF 6BFF 6C05 6C19 6C29 6C2B 6C31 6C35 6C55 6C59 6C5B 6C5F 6C65 6C67 6C73 6C77 6C7D 6C83 6C8F 6C91 6C97 6C9B 6CA1 6CA9 6CAF 6CB3 6CC7 6CCB 6CEB 6CF5 6CFD 6D0D 6D0F 6D25 6D27 6D2B 6D31 6D39 6D3F 6D4F 6D5D 6D61 6D73 6D7B 6D7F 6D93 6D99 6DA5 6DB1 6DB7 6DC1 6DC3 6DCD 6DCF 6DDB 6DF7 6E03 6E15 6E17 6E29 6E33 6E3B 6E45 6E75 6E77 6E7B 6E81 6E89 6E93 6E95 6E9F 6EBD 6EBF 6EE3 6EE9 6EF3 6EF9 6EFB 6F0D 6F11 6F17 6F1F 6F2F 6F3D 6F4D 6F53 6F61 6F65 6F79 6F7D 6F83 6F85 6F8F 6F9B 6F9D 6FA3 6FAF 6FB5 6FBB 6FBF 6FCB 6FCD 6FD3 6FD7 6FE3 6FE9 6FF1 6FF5 6FF7 6FFD 700F 7019 701F 7027 7033 7039 704F 7051 7057 7063 7075 7079 7087 708D 7091 70A5 70AB 70BB 70C3 70C7 70CF 70E5 70ED 70F9 70FF 7105 7115 7121 7133 7151 7159 715D 715F 7163 7169 7183 7187 7195 71AD 71C3 71C9 71CB 71D1 71DB 71E1 71EF 71F5 71FB 7207 7211 7217 7219 7225 722F 723B 7243 7255 7267 7271 7277 727F 728F 7295 729B 72A3 72B3 72C7 72CB 72CD 72D7 72D9 72E3 72EF 72F5 72FD 7303 730D 7321 732B 733D 7357 735B 7361 737F 7381 7385 738D 7393 739F 73AB 73BD 73C1 73C9 73DF 73E5 73E7 73F3 7415 741B 742D 7439 743F 7441 745D 746B 747B 7489 748D 749B 74A7 74AB 74B1 74B7 74B9 74DD 74E1 74E7 74FB 7507 751F 7525 753B 753D 754D 755F 756B 7577 7589 758B 7591 7597 759D 75A1 75A7 75B5 75B9 75BB 75D1 75D9 75E5 75EB 75F5 75FB 7603 760F 7621 762D 7633 763D 763F 7655 7663 7669 766F 7673 7685 768B 769F 76B5 76B7 76C3 76DB 76DF 76F1 7703 7705 771B 771D 7721 772D 7735 7741 774B 7759 775D 775F 7771 7781 77A7 77AD 77B3 77B9 77C5 77CF 77D5 77E1 77E9 77EF 77F3 77F9 7807 7825 782B 7835 783D 7853 7859 7861 786D 7877 7879 7883 7885 788B 7895 7897 78A1 78AD 78BF 78D3 78D9 78DD 78E5 78FB 7901 7907 7925 792B 7939 793F 794B 7957 795D 7967 7969 7973 7991 7993 79A3 79AB 79AF 79B1 79B7 79C9 79CD 79CF 79D5 79D9 79F3 79F7 79FF 7A05 7A0F 7A11 7A15 7A1B 7A23 7A27 7A2D 7A4B 7A57 7A59 7A5F 7A65 7A69 7A7D 7A93 7A9B 7A9F 7AA1 7AA5 7AED 7AF5 7AF9 7B01 7B17 7B19 7B1D 7B2B 7B35 7B37 7B3B 7B4F 7B55 7B5F 7B71 7B77 7B8B 7B9B 7BA1 7BA9 7BAF 7BB3 7BC7 7BD3 7BE9 7BEB 7BEF 7BF1 7BFD 7C07 7C19 7C1B 7C31 7C37 7C49 7C67 7C69 7C73 7C81 7C8B 7C93 7CA3 7CD5 7CDB 7CE5 7CED 7CF7 7D03 7D09 7D1B 7D1D 7D33 7D39 7D3B 7D3F 7D45 7D4D 7D53 7D59 7D63 7D75 7D77 7D8D 7D8F 7D9F 7DAD 7DB7 7DBD 7DBF 7DCB 7DD5 7DE9 7DED 7DFB 7E01 7E05 7E29 7E2B 7E2F 7E35 7E41 7E43 7E47 7E55 7E61 7E67 7E6B 7E71 7E73 7E79 7E7D 7E91 7E9B 7E9D 7EA7 7EAD 7EB9 7EBB 7ED3 7EDF 7EEB 7EF1 7EF7 7EFB 7F13 7F15 7F19 7F31 7F33 7F39 7F3D 7F43 7F4B 7F5B 7F61 7F63 7F6D 7F79 7F87 7F8D 7FAF 7FB5 7FC3 7FC9 7FCD 7FCF 7FED 8003 800B 800F 8015 801D 8021 8023 803F 8041 8047 804B 8065 8077 808D 808F 8095 80A5 80AB 80AD 80BD 80C9 80CB 80D7 80DB 80E1 80E7 80F5 80FF 8105 810D 8119 811D 812F 8131 813B 8143 8153 8159 815F 817D 817F 8189 819B 819D 81A7 81AF 81B3 81BB 81C7 81DF 8207 8209 8215 821F 8225 8231 8233 823F 8243 8245 8249 824F 8261 826F 827B 8281 8285 8293 82B1 82B5 82BD 82C7 82CF 82D5 82DF 82F1 82F9 82FD 830B 831B 8321 8329 832D 8333 8335 833F 8341 834D 8351 8353 8357 835D 8365 8369 836F 838F 83A7 83B1 83B9 83CB 83D5 83D7 83DD 83E7 83E9 83ED 83FF 8405 8411 8413 8423 8425 843B 8441 8447 844F 8461 8465 8477 8483 848B 8491 8495 84A9 84AF 84CD 84E3 84EF 84F1 84F7 8509 850D 854B 854F 8551 855D 8563 856D 856F 857B 8587 85A3 85A5 85A9 85B7 85CD 85D3 85D5 85DB 85E1 85EB 85F9 85FD 85FF 8609 860F 8617 8621 862F 8639 863F 8641 864D 8663 8675 867D 8687 8699 86A5 86A7 86B3 86B7 86C3 86C5 86CF 86D1 86D7 86E9 86EF 86F5 8717 871D 871F 872B 872F 8735 8747 8759 875B 876B 8771 8777 877F 8785 878F 87A1 87A9 87B3 87BB 87C5 87C7 87CB 87DD 87F7 8803 8819 881B 881F 8821 8837 883D 8843 8851 8861 8867 887B 8885 8891 8893 88A5 88CF 88D3 88EB 88ED 88F3 88FD 8909 890B 8911 891B 8923 8927 892D 8939 8945 894D 8951 8957 8963 8981 8995 899B 89B3 89B9 89C3 89CF 89D1 89DB 89EF 89F5 89FB 89FF 8A0B 8A19 8A23 8A35 8A41 8A49 8A4F 8A5B 8A5F 8A6D 8A77 8A79 8A85 8AA3 8AB3 8AB5 8AC1 8AC7 8ACB 8ACD 8AD1 8AD7 8AF1 8AF5 8B07 8B09 8B0D 8B13 8B21 8B57 8B5D 8B91 8B93 8BA3 8BA9 8BAF 8BBB 8BD5 8BD9 8BDB 8BE1 8BF7 8BFD 8BFF 8C0B 8C17 8C1D 8C27 8C39 8C3B 8C47 8C53 8C5D 8C6F 8C7B 8C81 8C89 8C8F 8C99 8C9F 8CA7 8CAB 8CAD 8CB1 8CC5 8CDD 8CE3 8CE9 8CF3 8D01 8D0B 8D0D 8D23 8D29 8D37 8D41 8D5B 8D5F 8D71 8D79 8D85 8D91 8D9B 8DA7 8DAD 8DB5 8DC5 8DCB 8DD3 8DD9 8DDF 8DF5 8DF7 8E01 8E15 8E1F 8E25 8E51 8E63 8E69 8E73 8E75 8E79 8E7F 8E8D 8E91 8EAB 8EAF 8EB1 8EBD 8EC7 8ECF 8ED3 8EDB 8EE7 8EEB 8EF7 8EFF 8F15 8F1D 8F23 8F2D 8F3F 8F45 8F4B 8F53 8F59 8F65 8F69 8F71 8F83 8F8D 8F99 8F9F 8FAB 8FAD 8FB3 8FB7 8FB9 8FC9 8FD5 8FE1 8FEF 8FF9 9007 900D 9017 9023 9025 9031 9037 903B 9041 9043 904F 9053 906D 9073 9085 908B 9095 909B 909D 90AF 90B9 90C1 90C5 90DF 90E9 90FD 9103 9113 9127 9133 913D 9145 914F 9151 9161 9167 917B 9185 9199 919D 91BB 91BD 91C1 91C9 91D9 91DB 91ED 91F1 91F3 91F9 9203 9215 9221 922F 9241 9247 9257 926B 9271 9275 927D 9283 9287 928D 9299 92A1 92AB 92AD 92B9 92BF 92C3 92C5 92CB 92D5 92D7 92E7 92F3 9301 930B 9311 9319 931F 933B 933D 9343 9355 9373 9395 9397 93A7 93B3 93B5 93C7 93D7 93DD 93E5 93EF 93F7 9401 9409 9413 943F 9445 944B 944F 9463 9467 9469 946D 947B 9497 949F 94A5 94B5 94C3 94E1 94E7 9505 9509 9517 9521 9527 952D 9535 9539 954B 9557 955D 955F 9575 9581 9589 958F 959B 959F 95AD 95B1 95B7 95B9 95BD 95CF 95E3 95E9 95F9 961F 962F 9631 9635 963B 963D 9665 968F 969D 96A1 96A7 96A9 96C1 96CB 96D1 96D3 96E5 96EF 96FB 96FD 970D 970F 9715 9725 972B 9733 9737 9739 9743 9749 9751 975B 975D 976F 977F 9787 9793 97A5 97B1 97B7 97C3 97CD 97D3 97D9 97EB 97F7 9805 9809 980B 9815 9829 982F 983B 9841 9851 986B 986F 9881 9883 9887 98A7 98B1 98B9 98BF 98C3 98C9 98CF 98DD 98E3 98F5 98F9 98FB 990D 9917 991F 9929 9931 993B 993D 9941 9947 9949 9953 997D 9985 9991 9995 999B 99AD 99AF 99BF 99C7 99CB 99CD 99D7 99E5 99F1 99FB 9A0F 9A13 9A1B 9A25 9A4B 9A4F 9A55 9A57 9A61 9A75 9A7F 9A8B 9A91 9A9D 9AB7 9AC3 9AC7 9ACF 9AEB 9AF3 9AF7 9AFF 9B17 9B1D 9B27 9B2F 9B35 9B45 9B51 9B59 9B63 9B6F 9B77 9B8D 9B93 9B95 9B9F 9BA1 9BA7 9BB1 9BB7 9BBD 9BC5 9BCB 9BCF 9BDD 9BF9 9C01 9C11 9C23 9C2B 9C2F 9C35 9C49 9C4D 9C5F 9C65 9C67 9C7F 9C97 9C9D 9CA3 9CAF 9CBB 9CBF 9CC1 9CD7 9CD9 9CE3 9CE9 9CF1 9CFD 9D01 9D15 9D27 9D2D 9D31 9D3D 9D55 9D5B 9D61 9D97 9D9F 9DA5 9DA9 9DC3 9DE7 9DEB 9DED 9DF1 9E0B 9E17 9E23 9E27 9E2D 9E33 9E3B 9E47 9E51 9E53 9E5F 9E6F 9E81 9E87 9E8F 9E95 9EA1 9EB3 9EBD 9EBF 9EF5 9EF9 9EFB 9F05 9F23 9F2F 9F37 9F3B 9F43 9F53 9F61 9F6D 9F73 9F77 9F7D 9F89 9F8F 9F91 9F95 9FA3 9FAF 9FB3 9FC1 9FC7 9FDF 9FE5 9FEB 9FF5 A001 A00D A021 A033 A039 A03F A04F A057 A05B A061 A075 A079 A099 A09D A0AB A0B5 A0B7 A0BD A0C9 A0D9 A0DB A0DF A0E5 A0F1 A0F3 A0FD A105 A10B A10F A111 A11B A129 A12F A135 A141 A153 A175 A17D A187 A18D A1A5 A1AB A1AD A1B7 A1C3 A1C5 A1E3 A1ED A1FB A207 A213 A223 A229 A22F A231 A243 A247 A24D A26B A279 A27D A283 A289 A28B A291 A295 A29B A2A9 A2AF A2B3 A2BB A2C5 A2D1 A2D7 A2F7 A301 A309 A31F A321 A32B A331 A349 A351 A355 A373 A379 A37B A387 A397 A39F A3A5 A3A9 A3AF A3B7 A3C7 A3D5 A3DB A3E1 A3E5 A3E7 A3F1 A3FD A3FF A40F A41D A421 A423 A427 A43B A44D A457 A459 A463 A469 A475 A493 A49B A4AD A4B9 A4C3 A4C5 A4CB A4D1 A4D5 A4E1 A4ED A4EF A4F3 A4FF A511 A529 A52B A535 A53B A543 A553 A55B A561 A56D A577 A585 A58B A597 A59D A5A3 A5A7 A5A9 A5C1 A5C5 A5CB A5D3 A5D9 A5DD A5DF A5E3 A5E9 A5F7 A5FB A603 A60D A625 A63D A649 A64B A651 A65D A673 A691 A693 A699 A6AB A6B5 A6BB A6C1 A6C9 A6CD A6CF A6D5 A6DF A6E7 A6F1 A6F7 A6FF A70F A715 A723 A729 A72D A745 A74D A757 A759 A765 A76B A76F A793 A795 A7AB A7B1 A7B9 A7BF A7C9 A7D1 A7D7 A7E3 A7ED A7FB A805 A80B A81D A829 A82B A837 A83B A855 A85F A86D A87D A88F A897 A8A9 A8B5 A8C1 A8C7 A8D7 A8E5 A8FD A907 A913 A91B A931 A937 A939 A943 A97F A985 A987 A98B A993 A9A3 A9B1 A9BB A9C1 A9D9 A9DF A9EB A9FD AA15 AA17 AA35 AA39 AA3B AA47 AA4D AA57 AA59 AA5D AA6B AA71 AA81 AA83 AA8D AA95 AAAB AABF AAC5 AAC9 AAE9 AAEF AB01 AB05 AB07 AB0B AB0D AB11 AB19 AB4D AB5B AB71 AB73 AB89 AB9D ABA7 ABAF ABB9 ABBB ABC1 ABC5 ABD3 ABD7 ABDD ABF1 ABF5 ABFB ABFD AC09 AC15 AC1B AC27 AC37 AC39 AC45 AC4F AC57 AC5B AC61 AC63 AC7F AC8B AC93 AC9D ACA9 ACAB ACAF ACBD ACD9 ACE1 ACE7 ACEB ACED ACF1 ACF7 ACF9 AD05 AD3F AD45 AD53 AD5D AD5F AD65 AD81 ADA1 ADA5 ADC3 ADCB ADD1 ADD5 ADDB ADE7 ADF3 ADF5 ADF9 ADFF AE05 AE13 AE23 AE2B AE49 AE4D AE4F AE59 AE61 AE67 AE6B AE71 AE8B AE8F AE9B AE9D AEA7 AEB9 AEC5 AED1 AEE3 AEE5 AEE9 AEF5 AEFD AF09 AF13 AF27 AF2B AF33 AF43 AF4F AF57 AF5D AF6D AF75 AF7F AF8B AF99 AF9F AFA3 AFAB AFB7 AFBB AFCF AFD5 AFFD B005 B015 B01B B03F B041 B047 B04B B051 B053 B069 B07B B07D B087 B08D B0B1 B0BF B0CB B0CF B0E1 B0E9 B0ED B0FB B105 B107 B111 B119 B11D B11F B131 B141 B14D B15B B165 B173 B179 B17F B1A9 B1B3 B1B9 B1BF B1D3 B1DD B1E5 B1F1 B1F5 B201 B213 B215 B21F B22D B23F B249 B25B B263 B269 B26D B27B B281 B28B B2A9 B2B7 B2BD B2C3 B2C7 B2D3 B2F9 B2FD B2FF B303 B309 B311 B31D B327 B32D B33F B345 B377 B37D B381 B387 B393 B39B B3A5 B3C5 B3CB B3E1 B3E3 B3ED B3F9 B40B B40D B413 B417 B435 B43D B443 B449 B45B B465 B467 B46B B477 B48B B495 B49D B4B5 B4BF B4C1 B4C7 B4DD B4E3 B4E5 B4F7 B501 B50D B50F B52D B53F B54B B567 B569 B56F B573 B579 B587 B58D B599 B5A3 B5AB B5AF B5BB B5D5 B5DF B5E7 B5ED B5FD B5FF B609 B61B B629 B62F B633 B639 B647 B657 B659 B65F B663 B66F B683 B687 B69B B69F B6A5 B6B1 B6B3 B6D7 B6DB B6E1 B6E3 B6ED B6EF B705 B70D B713 B71D B729 B735 B747 B755 B76D B791 B795 B7A9 B7C1 B7CB B7D1 B7D3 B7EF B7F5 B807 B80F B813 B819 B821 B827 B82B B82D B839 B855 B867 B875 B885 B893 B8A5 B8AF B8B7 B8BD B8C1 B8C7 B8CD B8D5 B8EB B8F7 B8F9 B903 B915 B91B B91D B92F B939 B93B B947 B951 B963 B983 B989 B98D B993 B999 B9A1 B9A7 B9AD B9B7 B9CB B9D1 B9DD B9E7 B9EF B9F9 BA07 BA0D BA17 BA25 BA29 BA2B BA41 BA53 BA55 BA5F BA61 BA65 BA79 BA7D BA7F BAA1 BAA3 BAAF BAB5 BABF BAC1 BACB BADD BAE3 BAF1 BAFD BB09 BB1F BB27 BB2D BB3D BB43 BB4B BB4F BB5B BB61 BB69 BB6D BB91 BB97 BB9D BBB1 BBC9 BBCF BBDB BBED BBF7 BBF9 BC03 BC1D BC23 BC33 BC3B BC41 BC45 BC5D BC6F BC77 BC83 BC8F BC99 BCAB BCB7 BCB9 BCD1 BCD5 BCE1 BCF3 BCFF BD0D BD17 BD19 BD1D BD35 BD41 BD4F BD59 BD5F BD61 BD67 BD6B BD71 BD8B BD8F BD95 BD9B BD9D BDB3 BDBB BDCD BDD1 BDE3 BDEB BDEF BE07 BE09 BE15 BE21 BE25 BE27 BE5B BE5D BE6F BE75 BE79 BE7F BE8B BE8D BE93 BE9F BEA9 BEB1 BEB5 BEB7 BECF BED9 BEDB BEE5 BEE7 BEF3 BEF9 BF0B BF33 BF39 BF4D BF5D BF5F BF6B BF71 BF7B BF87 BF89 BF8D BF93 BFA1 BFAD BFB9 BFCF BFD5 BFDD BFE1 BFE3 BFF3 C005 C011 C013 C019 C029 C02F C031 C037 C03B C047 C065 C06D C07D C07F C091 C09B C0B3 C0B5 C0BB C0D3 C0D7 C0D9 C0EF C0F1 C101 C103 C109 C115 C119 C12B C133 C137 C145 C149 C15B C173 C179 C17B C181 C18B C18D C197 C1BD C1C3 C1CD C1DB C1E1 C1E7 C1FF C203 C205 C211 C221 C22F C23F C24B C24D C253 C25D C277 C27B C27D C289 C28F C293 C29F C2A7 C2B3 C2BD C2CF C2D5 C2E3 C2FF C301 C307 C311 C313 C317 C325 C347 C349 C34F C365 C367 C371 C37F C383 C385 C395 C39D C3A7 C3AD C3B5 C3BF C3C7 C3CB C3D1 C3D3 C3E3 C3E9 C3EF C401 C41F C42D C433 C437 C455 C457 C461 C46F C473 C487 C491 C499 C49D C4A5 C4B7 C4BB C4C9 C4CF C4D3 C4EB C4F1 C4F7 C509 C51B C51D C541 C547 C551 C55F C56B C56F C575 C577 C595 C59B C59F C5A1 C5A7 C5C3 C5D7 C5DB C5EF C5FB C613 C623 C635 C641 C64F C655 C659 C665 C685 C691 C697 C6A1 C6A9 C6B3 C6B9 C6CB C6CD C6DD C6EB C6F1 C707 C70D C719 C71B C72D C731 C739 C757 C763 C767 C773 C775 C77F C7A5 C7BB C7BD C7C1 C7CF C7D5 C7E1 C7F9 C7FD C7FF C803 C811 C81D C827 C829 C839 C83F C853 C857 C86B C881 C88D C88F C893 C895 C8A1 C8B7 C8CF C8D5 C8DB C8DD C8E3 C8E7 C8ED C8EF C8F9 C905 C911 C917 C919 C91F C92F C937 C93D C941 C953 C95F C96B C979 C97D C989 C98F C997 C99D C9AF C9B5 C9BF C9CB C9D9 C9DF C9E3 C9EB CA01 CA07 CA09 CA25 CA37 CA39 CA4B CA55 CA5B CA69 CA73 CA75 CA7F CA8D CA93 CA9D CA9F CAB5 CABB CAC3 CAC9 CAD9 CAE5 CAED CB03 CB05 CB09 CB17 CB29 CB35 CB3B CB53 CB59 CB63 CB65 CB71 CB87 CB99 CB9F CBB3 CBB9 CBC3 CBD1 CBD5 CBD7 CBDD CBE9 CBFF CC0D CC19 CC1D CC23 CC2B CC41 CC43 CC4D CC59 CC61 CC89 CC8B CC91 CC9B CCA3 CCA7 CCD1 CCE5 CCE9 CD09 CD15 CD1F CD25 CD31 CD3D CD3F CD49 CD51 CD57 CD5B CD63 CD67 CD81 CD93 CD97 CD9F CDBB CDC1 CDD3 CDD9 CDE5 CDE7 CDF1 CDF7 CDFD CE0B CE15 CE21 CE2F CE47 CE4D CE51 CE65 CE7B CE7D CE8F CE93 CE99 CEA5 CEA7 CEB7 CEC9 CED7 CEDD CEE3 CEE7 CEED CEF5 CF07 CF0B CF19 CF37 CF3B CF4D CF55 CF5F CF61 CF65 CF6D CF79 CF7D CF89 CF9B CF9D CFA9 CFB3 CFB5 CFC5 CFCD CFD1 CFEF CFF1 CFF7 D013 D015 D01F D021 D033 D03D D04B D04F D069 D06F D081 D085 D099 D09F D0A3 D0AB D0BD D0C1 D0CD D0E7 D0FF D103 D117 D12D D12F D141 D157 D159 D15D D169 D16B D171 D177 D17D D181 D187 D195 D199 D1B1 D1BD D1C3 D1D5 D1D7 D1E3 D1FF D20D D211 D217 D21F D235 D23B D247 D259 D261 D265 D279 D27F D283 D289 D28B D29D D2A3 D2A7 D2B3 D2BF D2C7 D2E3 D2E9 D2F1 D2FB D2FD D315 D321 D32B D343 D34B D355 D369 D375 D37B D387 D393 D397 D3A5 D3B1 D3C9 D3EB D3FD D405 D40F D415 D427 D42F D433 D43B D44B D459 D45F D463 D469 D481 D483 D489 D48D D493 D495 D4A5 D4AB D4B1 D4C5 D4DD D4E1 D4E3 D4E7 D4F5 D4F9 D50B D50D D513 D51F D523 D531 D535 D537 D549 D559 D55F D565 D567 D577 D58B D591 D597 D5B5 D5B9 D5C1 D5C7 D5DF D5EF D5F5 D5FB D603 D60F D62D D631 D643 D655 D65D D661 D67B D685 D687 D69D D6A5 D6AF D6BD D6C3 D6C7 D6D9 D6E1 D6ED D709 D70B D711 D715 D721 D727 D73F D745 D74D D757 D76B D77B D783 D7A1 D7A7 D7AD D7B1 D7B3 D7BD D7CB D7D1 D7DB D7FB D811 D823 D825 D829 D82B D82F D837 D84D D855 D867 D873 D88F D891 D8A1 D8AD D8BF D8CD D8D7 D8E9 D8F5 D8FB D91B D925 D933 D939 D943 D945 D94F D951 D957 D96D D96F D973 D979 D981 D98B D991 D99F D9A5 D9A9 D9B5 D9D3 D9EB D9F1 D9F7 D9FF DA05 DA09 DA0B DA0F DA15 DA1D DA23 DA29 DA3F DA51 DA59 DA5D DA5F DA71 DA77 DA7B DA7D DA8D DA9F DAB3 DABD DAC3 DAC9 DAE7 DAE9 DAF5 DB11 DB17 DB1D DB23 DB25 DB31 DB3B DB43 DB55 DB67 DB6B DB73 DB85 DB8F DB91 DBAD DBAF DBB9 DBC7 DBCB DBCD DBEB DBF7 DC0D DC27 DC31 DC39 DC3F DC49 DC51 DC61 DC6F DC75 DC7B DC85 DC93 DC99 DC9D DC9F DCA9 DCB5 DCB7 DCBD DCC7 DCCF DCD3 DCD5 DCDF DCF9 DD0F DD15 DD17 DD23 DD35 DD39 DD53 DD57 DD5F DD69 DD6F DD7D DD87 DD89 DD9B DDA1 DDAB DDBF DDC5 DDCB DDCF DDE7 DDE9 DDED DDF5 DDFB DE0B DE19 DE29 DE3B DE3D DE41 DE4D DE4F DE59 DE5B DE61 DE6D DE77 DE7D DE83 DE97 DE9D DEA1 DEA7 DECD DED1 DED7 DEE3 DEF1 DEF5 DF01 DF09 DF13 DF1F DF2B DF33 DF37 DF3D DF4B DF55 DF5B DF67 DF69 DF73 DF85 DF87 DF99 DFA3 DFAB DFB5 DFB7 DFC3 DFC7 DFD5 DFF1 DFF3 E003 E005 E017 E01D E027 E02D E035 E045 E053 E071 E07B E08F E095 E09F E0B7 E0B9 E0D5 E0D7 E0E3 E0F3 E0F9 E101 E125 E129 E131 E135 E143 E14F E159 E161 E16D E171 E177 E17F E183 E189 E197 E1AD E1B5 E1BB E1BF E1C1 E1CB E1D1 E1E5 E1EF E1F7 E1FD E203 E219 E22B E22D E23D E243 E257 E25B E275 E279 E287 E29D E2AB E2AF E2BB E2C1 E2C9 E2CD E2D3 E2D9 E2F3 E2FD E2FF E311 E323 E327 E329 E339 E33B E34D E351 E357 E35F E363 E369 E375 E377 E37D E383 E39F E3C5 E3C9 E3D1 E3E1 E3FB E3FF E401 E40B E417 E419 E423 E42B E431 E43B E447 E449 E453 E455 E46D E471 E48F E4A9 E4AF E4B5 E4C7 E4CD E4D3 E4E9 E4EB E4F5 E507 E521 E525 E537 E53F E545 E54B E557 E567 E56D E575 E585 E58B E593 E5A3 E5A5 E5CF E609 E611 E615 E61B E61D E621 E629 E639 E63F E653 E657 E663 E66F E675 E681 E683 E68D E68F E695 E6AB E6AD E6B7 E6BD E6C5 E6CB E6D5 E6E3 E6E9 E6EF E6F3 E705 E70D E717 E71F E72F E73D E747 E749 E753 E755 E761 E767 E76B E77F E789 E791 E7C5 E7CD E7D7 E7DD E7DF E7E9 E7F1 E7FB E801 E807 E80F E819 E81B E831 E833 E837 E83D E84B E84F E851 E869 E875 E879 E893 E8A5 E8A9 E8AF E8BD E8DB E8E1 E8E5 E8EB E8ED E903 E90B E90F E915 E917 E92D E933 E93B E94B E951 E95F E963 E969 E97B E983 E98F E995 E9A1 E9B9 E9D7 E9E7 E9EF EA11 EA19 EA2F EA35 EA43 EA4D EA5F EA6D EA71 EA7D EA85 EA89 EAAD EAB3 EAB9 EABB EAC5 EAC7 EACB EADF EAE5 EAEB EAF5 EB01 EB07 EB09 EB31 EB39 EB3F EB5B EB61 EB63 EB6F EB81 EB85 EB9D EBAB EBB1 EBB7 EBC1 EBD5 EBDF EBED EBFD EC0B EC1B EC21 EC29 EC4D EC51 EC5D EC69 EC6F EC7B ECAD ECB9 ECBF ECC3 ECC9 ECCF ECD7 ECDD ECE7 ECE9 ECF3 ECF5 ED07 ED11 ED1F ED2F ED37 ED3D ED41 ED55 ED59 ED5B ED65 ED6B ED79 ED8B ED95 EDBB EDC5 EDD7 EDD9 EDE3 EDE5 EDF1 EDF5 EDF7 EDFB EE09 EE0F EE19 EE21 EE49 EE4F EE63 EE67 EE73 EE7B EE81 EEA3 EEAB EEC1 EEC9 EED5 EEDF EEE1 EEF1 EF1B EF27 EF2F EF45 EF4D EF63 EF6B EF71 EF93 EF95 EF9B EF9F EFAD EFB3 EFC3 EFC5 EFDB EFE1 EFE9 F001 F017 F01D F01F F02B F02F F035 F043 F047 F04F F067 F06B F071 F077 F079 F08F F0A3 F0A9 F0AD F0BB F0BF F0C5 F0CB F0D3 F0D9 F0E3 F0E9 F0F1 F0F7 F107 F115 F11B F121 F137 F13D F155 F175 F17B F18D F193 F1A5 F1AF F1B7 F1D5 F1E7 F1ED F1FD F209 F20F F21B F21D F223 F227 F233 F23B F241 F257 F25F F265 F269 F277 F281 F293 F2A7 F2B1 F2B3 F2B9 F2BD F2BF F2DB F2ED F2EF F2F9 F2FF F305 F30B F319 F341 F359 F35B F35F F367 F373 F377 F38B F38F F3AF F3C1 F3D1 F3D7 F3FB F403 F409 F40D F413 F421 F425 F42B F445 F44B F455 F463 F475 F47F F485 F48B F499 F4A3 F4A9 F4AF F4BD F4C3 F4DB F4DF F4ED F503 F50B F517 F521 F529 F535 F547 F551 F563 F56B F583 F58D F595 F599 F5B1 F5B7 F5C9 F5CF F5D1 F5DB F5F9 F5FB F605 F607 F60B F60D F635 F637 F653 F65B F661 F667 F679 F67F F689 F697 F69B F6AD F6CB F6DD F6DF F6EB F709 F70F F72D F731 F743 F74F F751 F755 F763 F769 F773 F779 F781 F787 F791 F79D F79F F7A5 F7B1 F7BB F7BD F7CF F7D3 F7E7 F7EB F7F1 F7FF F805 F80B F821 F827 F82D F835 F847 F859 F863 F865 F86F F871 F877 F87B F881 F88D F89F F8A1 F8AB F8B3 F8B7 F8C9 F8CB F8D1 F8D7 F8DD F8E7 F8EF F8F9 F8FF F911 F91D F925 F931 F937 F93B F941 F94F F95F F961 F96D F971 F977 F99D F9A3 F9A9 F9B9 F9CD F9E9 F9FD FA07 FA0D FA13 FA21 FA25 FA3F FA43 FA51 FA5B FA6D FA7B FA97 FA99 FA9D FAAB FABB FABD FAD9 FADF FAE7 FAED FB0F FB17 FB1B FB2D FB2F FB3F FB47 FB4D FB75 FB7D FB8F FB93 FBB1 FBB7 FBC3 FBC5 FBE3 FBE9 FBF3 FC01 FC29 FC37 FC41 FC43 FC4F FC59 FC61 FC65 FC6D FC73 FC79 FC95 FC97 FC9B FCA7 FCB5 FCC5 FCCD FCEB FCFB FD0D FD0F FD19 FD2B FD31 FD51 FD55 FD67 FD6D FD6F FD7B FD85 FD97 FD99 FD9F FDA9 FDB7 FDC9 FDE5 FDEB FDF3 FE03 FE05 FE09 FE1D FE27 FE2F FE41 FE4B FE4D FE57 FE5F FE63 FE69 FE75 FE7B FE8F FE93 FE95 FE9B FE9F FEB3 FEBD FED7 FEE9 FEF3 FEF5 FF07 FF0D FF1D FF2B FF2F FF49 FF4D FF5B FF65 FF71 FF7F FF85 FF8B FF8F FF9D FFA7 FFA9 FFC7 FFD9 FFEF FFF1 -Execution halted after 2743229 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/16x16Life.out b/Tests/expected/16x16Life.out index 724d752..2690f2a 100644 --- a/Tests/expected/16x16Life.out +++ b/Tests/expected/16x16Life.out @@ -222,5 +222,5 @@ -Execution stopped after 3000000 cycles. (cycle limit reached) +Execution stopped. (cycle limit reached) [exit 0] diff --git a/Tests/expected/16x16LifeModern.out b/Tests/expected/16x16LifeModern.out index 724d752..2690f2a 100644 --- a/Tests/expected/16x16LifeModern.out +++ b/Tests/expected/16x16LifeModern.out @@ -222,5 +222,5 @@ -Execution stopped after 3000000 cycles. (cycle limit reached) +Execution stopped. (cycle limit reached) [exit 0] diff --git a/Tests/expected/32bitFibonacci.out b/Tests/expected/32bitFibonacci.out index 6665a29..08435e4 100644 --- a/Tests/expected/32bitFibonacci.out +++ b/Tests/expected/32bitFibonacci.out @@ -1,3 +1,3 @@ 00000000 00000001 00000001 00000002 00000003 00000005 00000008 0000000D 00000015 00000022 00000037 00000059 00000090 000000E9 00000179 00000262 000003DB 0000063D 00000A18 00001055 00001A6D 00002AC2 0000452F 00006FF1 0000B520 00012511 0001DA31 0002FF42 0004D973 0007D8B5 000CB228 00148ADD 00213D05 0035C7E2 005704E7 008CCCC9 00E3D1B0 01709E79 02547029 03C50EA2 06197ECB 09DE8D6D 0FF80C38 19D699A5 29CEA5DD 43A53F82 6D73E55F -Execution halted after 10610 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/8bitFibonacci.out b/Tests/expected/8bitFibonacci.out index 84d38e4..3271353 100644 --- a/Tests/expected/8bitFibonacci.out +++ b/Tests/expected/8bitFibonacci.out @@ -1,3 +1,3 @@ 0 1 1 2 3 5 8 13 21 34 55 89 144 233 -Execution halted after 1506 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/8bitSieve.out b/Tests/expected/8bitSieve.out index b513462..6f5836d 100644 --- a/Tests/expected/8bitSieve.out +++ b/Tests/expected/8bitSieve.out @@ -1,3 +1,3 @@ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 -Execution halted after 54061 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/bankBoundsTest.out b/Tests/expected/bankBoundsTest.out index 4b0f8d4..a22a877 100644 --- a/Tests/expected/bankBoundsTest.out +++ b/Tests/expected/bankBoundsTest.out @@ -1,4 +1,4 @@ Fault: The device on port 233 refused the access at Program Address 0x001D, and nothing is installed to deal with it. O -Execution halted after 16 cycles. +Execution halted. [exit 1] diff --git a/Tests/expected/blitTest.out b/Tests/expected/blitTest.out index c46c5fb..07a899d 100644 --- a/Tests/expected/blitTest.out +++ b/Tests/expected/blitTest.out @@ -3,5 +3,5 @@ blitted DE AD untouched ABABCDEFGH -Execution halted after 464 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/branchTest.out b/Tests/expected/branchTest.out index 5805e3e..71edac2 100644 --- a/Tests/expected/branchTest.out +++ b/Tests/expected/branchTest.out @@ -1,4 +1,4 @@ QAB C qab c 9876543210 -Execution halted after 176 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/consoleInterruptTest.out b/Tests/expected/consoleInterruptTest.out index 4b7d27d..8c01fcf 100644 --- a/Tests/expected/consoleInterruptTest.out +++ b/Tests/expected/consoleInterruptTest.out @@ -3,5 +3,5 @@ asked for: 0D ready keys interrupts what arrived: keys at the end: 02 ended -Execution halted after 1597 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/consoleModeTest.out b/Tests/expected/consoleModeTest.out index 76d6e45..9366e7c 100644 --- a/Tests/expected/consoleModeTest.out +++ b/Tests/expected/consoleModeTest.out @@ -6,5 +6,5 @@ hi at the end: 06 ended keys line mode: 02 ended -Execution halted after 891 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/consoleTest.out b/Tests/expected/consoleTest.out index 16384ca..13555f7 100644 --- a/Tests/expected/consoleTest.out +++ b/Tests/expected/consoleTest.out @@ -10,5 +10,5 @@ lines read: [SplitBit] 8 [a line that is f] 16 end of input -Execution halted after 6064 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/controllerReadTest.out b/Tests/expected/controllerReadTest.out index aae6dc2..a76183a 100644 --- a/Tests/expected/controllerReadTest.out +++ b/Tests/expected/controllerReadTest.out @@ -1,5 +1,5 @@ DE AD BE EF 01 FF 00 00 -Execution halted after 315 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/controllerWriteTest.out b/Tests/expected/controllerWriteTest.out index 99b64c4..8ed444f 100644 --- a/Tests/expected/controllerWriteTest.out +++ b/Tests/expected/controllerWriteTest.out @@ -2,5 +2,5 @@ AA BB readonly nobank done -Execution halted after 245 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmos.out b/Tests/expected/cosmos.out index cf2ee82..df5ec0f 100644 --- a/Tests/expected/cosmos.out +++ b/Tests/expected/cosmos.out @@ -1,7 +1,9 @@ CosmOS > dir list what is on the disk load read a program off the disk -run start what was loaded +run [words] start what was loaded, and tell it those words +delete take it off the disk +rename call it something else dump sixty four bytes of memory, and again for more dump
help this @@ -21,5 +23,5 @@ aName22CharactersLong! 22 12 files > > I do not know: frobnicate > halted -Execution halted after 12376 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosDump.out b/Tests/expected/cosmosDump.out index ca41811..294d722 100644 --- a/Tests/expected/cosmosDump.out +++ b/Tests/expected/cosmosDump.out @@ -19,5 +19,5 @@ CosmOS 0020 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 ................ 0030 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 ................ > halted -Execution halted after 23512 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosEdit.out b/Tests/expected/cosmosEdit.out new file mode 100644 index 0000000..081b902 --- /dev/null +++ b/Tests/expected/cosmosEdit.out @@ -0,0 +1,21 @@ +CosmOS +> loaded, starting at 2000 +> poem.txt, 0 lines +> : : : : > : : > 1: alpha +2: INSERTED +3: beta +4: gamma +> : > > 1: CHANGED +2: INSERTED +3: beta +> written, 22 bytes +> finished +> poem.txt, 3 lines +> 1: CHANGED +2: INSERTED +3: beta +> there is no such line +> finished +> halted +Execution halted. +[exit 0] diff --git a/Tests/expected/cosmosFiles.out b/Tests/expected/cosmosFiles.out new file mode 100644 index 0000000..d00c519 --- /dev/null +++ b/Tests/expected/cosmosFiles.out @@ -0,0 +1,17 @@ +CosmOS +> one.txt 13 +two.txt 14 +2 files +> renamed +> first.txt 13 +two.txt 14 +2 files +> gone +> two.txt 14 +1 file +> no such file +> rename what to what? +> there is no such file, or that name is taken +> halted +Execution halted. +[exit 0] diff --git a/Tests/expected/cosmosHello.out b/Tests/expected/cosmosHello.out index 709730e..c3907af 100644 --- a/Tests/expected/cosmosHello.out +++ b/Tests/expected/cosmosHello.out @@ -5,5 +5,5 @@ finished > Hello, World! finished > halted -Execution halted after 2702 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosKeys.out b/Tests/expected/cosmosKeys.out index 9a7281a..2b63bd9 100644 --- a/Tests/expected/cosmosKeys.out +++ b/Tests/expected/cosmosKeys.out @@ -13,5 +13,5 @@ FE10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FE20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FE30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ > halted -Execution halted after 10055 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosLife.out b/Tests/expected/cosmosLife.out index d64311c..bbf7892 100644 --- a/Tests/expected/cosmosLife.out +++ b/Tests/expected/cosmosLife.out @@ -869,5 +869,5 @@ the board has settled finished > halted -Execution halted after 11671230 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosLifeKey.out b/Tests/expected/cosmosLifeKey.out index 3fa4a8e..b0f422c 100644 --- a/Tests/expected/cosmosLifeKey.out +++ b/Tests/expected/cosmosLifeKey.out @@ -21,5 +21,5 @@ stopped finished > > halted -Execution halted after 26243 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosNoDisk.out b/Tests/expected/cosmosNoDisk.out index 7563634..0c7e54b 100644 --- a/Tests/expected/cosmosNoDisk.out +++ b/Tests/expected/cosmosNoDisk.out @@ -3,5 +3,5 @@ no filesystem on the disk > no filesystem on the disk > halted -Execution halted after 636 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosRun.out b/Tests/expected/cosmosRun.out index 4b10e3a..8bcb69f 100644 --- a/Tests/expected/cosmosRun.out +++ b/Tests/expected/cosmosRun.out @@ -5,8 +5,9 @@ hello.sbx 52 Life.sbx 1411 Snake.sbx 2175 Keys.sbx 663 +Say.sbx 155 notes.txt 21 -6 files +7 files > load what? > no such file > not a program @@ -18,5 +19,5 @@ finished what should I call you? hello, Claude. that is all I do. finished > halted -Execution halted after 14083 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/cosmosSay.out b/Tests/expected/cosmosSay.out new file mode 100644 index 0000000..3515623 --- /dev/null +++ b/Tests/expected/cosmosSay.out @@ -0,0 +1,11 @@ +CosmOS +> loaded, starting at 2000 +> nothing was said +finished +> it says: notes.txt +finished +> it says: a longer thing with spaces +finished +> halted +Execution halted. +[exit 0] diff --git a/Tests/expected/cosmosSnake.out b/Tests/expected/cosmosSnake.out index 654c117..2fcc164 100644 --- a/Tests/expected/cosmosSnake.out +++ b/Tests/expected/cosmosSnake.out @@ -289,5 +289,5 @@ you ran into something finished > halted -Execution halted after 1910693 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/dataPointerTest.out b/Tests/expected/dataPointerTest.out index 43daeb6..cd1fe05 100644 --- a/Tests/expected/dataPointerTest.out +++ b/Tests/expected/dataPointerTest.out @@ -1,3 +1,3 @@ ABCZ -Execution halted after 21 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/deviceTest.out b/Tests/expected/deviceTest.out index 22a0cd1..dc68690 100644 --- a/Tests/expected/deviceTest.out +++ b/Tests/expected/deviceTest.out @@ -1,5 +1,5 @@ O K ! -Execution halted after 19 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/diskProtectTest.out b/Tests/expected/diskProtectTest.out index 2a993f5..ebb96bb 100644 --- a/Tests/expected/diskProtectTest.out +++ b/Tests/expected/diskProtectTest.out @@ -1,5 +1,5 @@ 04 04 06 -Execution halted after 114 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/diskTest.out b/Tests/expected/diskTest.out index 17ff3af..9fa0f53 100644 --- a/Tests/expected/diskTest.out +++ b/Tests/expected/diskTest.out @@ -1,5 +1,5 @@ 00 from the disk 02 -Execution halted after 245 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/dispatchTest.out b/Tests/expected/dispatchTest.out index 07f62ec..511f440 100644 --- a/Tests/expected/dispatchTest.out +++ b/Tests/expected/dispatchTest.out @@ -2,5 +2,5 @@ one two three done -Execution halted after 126 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/faultResumeTest.out b/Tests/expected/faultResumeTest.out index 6f47687..d3ad41d 100644 --- a/Tests/expected/faultResumeTest.out +++ b/Tests/expected/faultResumeTest.out @@ -1,4 +1,4 @@ O K -Execution halted after 17 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/faultTest.out b/Tests/expected/faultTest.out index 4290ce5..d2b436d 100644 --- a/Tests/expected/faultTest.out +++ b/Tests/expected/faultTest.out @@ -1,3 +1,3 @@ Fault: 0xFE at Program Address 0x0002 is not an instruction. -Execution halted after 2 cycles. +Execution halted. [exit 1] diff --git a/Tests/expected/fenceTest.out b/Tests/expected/fenceTest.out index c21a738..2af5212 100644 --- a/Tests/expected/fenceTest.out +++ b/Tests/expected/fenceTest.out @@ -4,5 +4,5 @@ caught 01FC read ok lowered ok fenced 05 -Execution halted after 535 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/hello.out b/Tests/expected/hello.out index cb4c900..c345b37 100644 --- a/Tests/expected/hello.out +++ b/Tests/expected/hello.out @@ -1,3 +1,3 @@ Hello, World! -Execution halted after 70 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/inputTest.out b/Tests/expected/inputTest.out index dfe6cfd..2900656 100644 --- a/Tests/expected/inputTest.out +++ b/Tests/expected/inputTest.out @@ -1,4 +1,4 @@ Input Test: Will echo anything you put in. Hello SplitBit -Execution halted after 406 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/inputTestOld.out b/Tests/expected/inputTestOld.out index dfe6cfd..2900656 100644 --- a/Tests/expected/inputTestOld.out +++ b/Tests/expected/inputTestOld.out @@ -1,4 +1,4 @@ Input Test: Will echo anything you put in. Hello SplitBit -Execution halted after 406 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/int16print.out b/Tests/expected/int16print.out index f3fbc4a..2f0c739 100644 --- a/Tests/expected/int16print.out +++ b/Tests/expected/int16print.out @@ -1,4 +1,4 @@ 00 00 00 00 01 1 -Execution halted after 4707 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/interruptExample.out b/Tests/expected/interruptExample.out index de2fd9e..48a70bd 100644 --- a/Tests/expected/interruptExample.out +++ b/Tests/expected/interruptExample.out @@ -1,5 +1,5 @@ ready trap device -Execution halted after 105 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/interruptFlagTest.out b/Tests/expected/interruptFlagTest.out index c83d9fd..8f462d9 100644 --- a/Tests/expected/interruptFlagTest.out +++ b/Tests/expected/interruptFlagTest.out @@ -1,3 +1,3 @@ OKC -Execution halted after 19 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/loader.out b/Tests/expected/loader.out index 510c212..0dec242 100644 --- a/Tests/expected/loader.out +++ b/Tests/expected/loader.out @@ -1,4 +1,4 @@ loader loaded off a disk, with a string and a loop of its own -Execution halted after 1098 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/loaderTest.out b/Tests/expected/loaderTest.out index 5fbf46f..c8d3054 100644 --- a/Tests/expected/loaderTest.out +++ b/Tests/expected/loaderTest.out @@ -1,5 +1,5 @@ before loaded back -Execution halted after 132 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/maskTest.out b/Tests/expected/maskTest.out index 33bee68..34a284b 100644 --- a/Tests/expected/maskTest.out +++ b/Tests/expected/maskTest.out @@ -1,5 +1,5 @@ Fault: The device on port 16 interrupted at Program Address 0x0019, and hardware vector 16 has no handler installed. M S -Execution halted after 16 cycles. +Execution halted. [exit 1] diff --git a/Tests/expected/mathTest.out b/Tests/expected/mathTest.out index 0a3e7bb..e7200cc 100644 --- a/Tests/expected/mathTest.out +++ b/Tests/expected/mathTest.out @@ -1,3 +1,3 @@ 0000 0032 -Execution halted after 1134 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/moveQTest.out b/Tests/expected/moveQTest.out index 944b1a5..90c5993 100644 --- a/Tests/expected/moveQTest.out +++ b/Tests/expected/moveQTest.out @@ -1,3 +1,3 @@ AAA -Execution halted after 24 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/paddingTest.out b/Tests/expected/paddingTest.out index 80bb92d..804d9d5 100644 --- a/Tests/expected/paddingTest.out +++ b/Tests/expected/paddingTest.out @@ -1,3 +1,3 @@ 00 31 -Execution halted after 78 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/pinnedVectorTest.out b/Tests/expected/pinnedVectorTest.out index 87740db..a5f039f 100644 --- a/Tests/expected/pinnedVectorTest.out +++ b/Tests/expected/pinnedVectorTest.out @@ -3,5 +3,5 @@ twenty sixty three automatic done -Execution halted after 272 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/pointerTableTest.out b/Tests/expected/pointerTableTest.out index aa0fe31..c82218a 100644 --- a/Tests/expected/pointerTableTest.out +++ b/Tests/expected/pointerTableTest.out @@ -1,5 +1,5 @@ Hello World H -Execution halted after 79 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/printHello.out b/Tests/expected/printHello.out index 0781814..1a8731b 100644 --- a/Tests/expected/printHello.out +++ b/Tests/expected/printHello.out @@ -1,4 +1,4 @@ Hello, World! 42 is the great answer. -Execution halted after 295 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/printTest.out b/Tests/expected/printTest.out index b6c53f5..5252a13 100644 --- a/Tests/expected/printTest.out +++ b/Tests/expected/printTest.out @@ -9,5 +9,5 @@ Testing printByteHex... 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF Testing complete! -Execution halted after 71185 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/refusalFaultTest.out b/Tests/expected/refusalFaultTest.out index 102b5d5..a172e18 100644 --- a/Tests/expected/refusalFaultTest.out +++ b/Tests/expected/refusalFaultTest.out @@ -1,4 +1,4 @@ Fault: The device on port 17 refused the access at Program Address 0x000A, and nothing is installed to deal with it. O -Execution halted after 6 cycles. +Execution halted. [exit 1] diff --git a/Tests/expected/refusalTest.out b/Tests/expected/refusalTest.out index 9b3f291..749330e 100644 --- a/Tests/expected/refusalTest.out +++ b/Tests/expected/refusalTest.out @@ -1,5 +1,5 @@ caught caught done -Execution halted after 136 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/registerBankTest.out b/Tests/expected/registerBankTest.out index 140a969..e9ccd8e 100644 --- a/Tests/expected/registerBankTest.out +++ b/Tests/expected/registerBankTest.out @@ -3,5 +3,5 @@ flags 01 5A 5A refused refused -Execution halted after 443 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/registryTest.out b/Tests/expected/registryTest.out index e421c18..d243fcc 100644 --- a/Tests/expected/registryTest.out +++ b/Tests/expected/registryTest.out @@ -2,5 +2,5 @@ 10 10 00 FF 01 00 05 00 00 -Execution halted after 440 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/sbfsEditTest.out b/Tests/expected/sbfsEditTest.out new file mode 100644 index 0000000..de19a82 --- /dev/null +++ b/Tests/expected/sbfsEditTest.out @@ -0,0 +1,8 @@ +here.txt 0002 already here +doc.txt 0003 first draft +doc.txt 0004 a second draft, which is longer than the first +notes.txt 0004 a second draft, which is longer than the first +doc.txt gone +notes.txt gone +Execution halted. +[exit 0] diff --git a/Tests/expected/sbfsReadTest.out b/Tests/expected/sbfsReadTest.out index 032328e..41370b7 100644 --- a/Tests/expected/sbfsReadTest.out +++ b/Tests/expected/sbfsReadTest.out @@ -3,5 +3,5 @@ across.txt 0002 BC ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI aName22CharactersLong! 0000 16 exactly twenty two!!!! empty.txt 0000 00 absent.txt missing -Execution halted after 19230 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/sbfsWalkTest.out b/Tests/expected/sbfsWalkTest.out index 9bce0a9..7df5dac 100644 --- a/Tests/expected/sbfsWalkTest.out +++ b/Tests/expected/sbfsWalkTest.out @@ -11,5 +11,5 @@ across.txt 700 empty.txt 0 aName22CharactersLong! 22 files: 12 -Execution halted after 9498 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/sbfsWriteTest.out b/Tests/expected/sbfsWriteTest.out index 97bc8bd..1a783bd 100644 --- a/Tests/expected/sbfsWriteTest.out +++ b/Tests/expected/sbfsWriteTest.out @@ -1,5 +1,5 @@ here.txt 0002 already here first.txt 0003 written by SplitBit itself second.txt 0004 and a second one after it -Execution halted after 5888 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/stackPointerTest.out b/Tests/expected/stackPointerTest.out index 71b2916..31f28a0 100644 --- a/Tests/expected/stackPointerTest.out +++ b/Tests/expected/stackPointerTest.out @@ -1,3 +1,3 @@ OK -Execution halted after 14 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/stackReclaimTest.out b/Tests/expected/stackReclaimTest.out index 5f2078e..eccdd23 100644 --- a/Tests/expected/stackReclaimTest.out +++ b/Tests/expected/stackReclaimTest.out @@ -5,5 +5,5 @@ reclaimed: FFFF still good: 33 borrowed: 7 and 9 back home: FFFF -Execution halted after 1054 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/staticTableTest.out b/Tests/expected/staticTableTest.out index f436217..f83eec1 100644 --- a/Tests/expected/staticTableTest.out +++ b/Tests/expected/staticTableTest.out @@ -2,5 +2,5 @@ one two three AFTER -Execution halted after 122 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/swiFaultTest.out b/Tests/expected/swiFaultTest.out index 79f7f77..61743f5 100644 --- a/Tests/expected/swiFaultTest.out +++ b/Tests/expected/swiFaultTest.out @@ -1,4 +1,4 @@ Fault: Software vector 20, dispatched from Program Address 0x0008, has no handler installed. O -Execution halted after 5 cycles. +Execution halted. [exit 1] diff --git a/Tests/expected/textTest.out b/Tests/expected/textTest.out index 1b5c2ee..1c5ae5c 100644 --- a/Tests/expected/textTest.out +++ b/Tests/expected/textTest.out @@ -4,5 +4,5 @@ same: yes no no no hex: 2000 00FF 00FF BEEF FFFF 0000 0 is a fine way to begin a string no number here -Execution halted after 2730 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/twoPointerCopy.out b/Tests/expected/twoPointerCopy.out index fae471e..8c54b18 100644 --- a/Tests/expected/twoPointerCopy.out +++ b/Tests/expected/twoPointerCopy.out @@ -1,3 +1,3 @@ Two pointers, no stack shenanigans. -Execution halted after 395 cycles. +Execution halted. [exit 0] diff --git a/Tests/expected/vectorTest.out b/Tests/expected/vectorTest.out index 427b2f3..2b4cf86 100644 --- a/Tests/expected/vectorTest.out +++ b/Tests/expected/vectorTest.out @@ -1,5 +1,5 @@ OK! good AFTER -Execution halted after 77 cycles. +Execution halted. [exit 0] diff --git a/Tests/input/cosmosEdit.in b/Tests/input/cosmosEdit.in new file mode 100644 index 0000000..2632f77 --- /dev/null +++ b/Tests/input/cosmosEdit.in @@ -0,0 +1,22 @@ +load Edit.sbx +run poem.txt +a +alpha +beta +gamma +. +i 2 +INSERTED +. +l +c 1 +CHANGED +d 4 +l +w +q +run poem.txt +l +d 99 +q +exit diff --git a/Tests/input/cosmosFiles.in b/Tests/input/cosmosFiles.in new file mode 100644 index 0000000..bda2f9b --- /dev/null +++ b/Tests/input/cosmosFiles.in @@ -0,0 +1,9 @@ +dir +rename one.txt first.txt +dir +delete first.txt +dir +delete first.txt +rename two.txt +rename two.txt two.txt +exit diff --git a/Tests/input/cosmosSay.in b/Tests/input/cosmosSay.in new file mode 100644 index 0000000..43d2d1a --- /dev/null +++ b/Tests/input/cosmosSay.in @@ -0,0 +1,5 @@ +load Say.sbx +run +run notes.txt +run a longer thing with spaces +exit diff --git a/Tests/makedisks.sh b/Tests/makedisks.sh index a88a51c..5d838a9 100755 --- a/Tests/makedisks.sh +++ b/Tests/makedisks.sh @@ -59,7 +59,7 @@ for i in 1 2 3 4 5 6 7 8; do "$TOOL" put "$DISKS/sbfs.img" "filler$i.txt" >/dev/ # to the hardware, so something has to check that one still gives the machine back. # # notes.txt is there so that loading something that is not a program can be tried too. -"$TOOL" format "$DISKS/cosmos.img" 32 1 >/dev/null +"$TOOL" format "$DISKS/cosmos.img" 256 2 >/dev/null "$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \ "$ROOT/Programs/CosmOS/Apps/greet.asm" -o "$WORK/greet.sbx" >/dev/null "$TOOL" put "$DISKS/cosmos.img" "$WORK/greet.sbx" >/dev/null @@ -86,6 +86,11 @@ for i in 1 2 3 4 5 6 7 8; do "$TOOL" put "$DISKS/sbfs.img" "filler$i.txt" >/dev/ "$ROOT/Assembler" -I "$ROOT/Programs/Libraries" -I "$ROOT/Programs/CosmOS/Source" \ "$ROOT/Programs/CosmOS/Apps/Keys.asm" -o "$WORK/Keys.sbx" >/dev/null "$TOOL" put "$DISKS/cosmos.img" "$WORK/Keys.sbx" >/dev/null +# Say.sbx is the first program that can be told anything. Everything before it did the same +# thing however it was started. +"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \ + "$ROOT/Programs/CosmOS/Apps/Say.asm" -o "$WORK/Say.sbx" >/dev/null +"$TOOL" put "$DISKS/cosmos.img" "$WORK/Say.sbx" >/dev/null printf 'this is not a program' > notes.txt "$TOOL" put "$DISKS/cosmos.img" notes.txt >/dev/null @@ -94,3 +99,29 @@ printf 'this is not a program' > notes.txt "$TOOL" format "$DISKS/write.img" 32 1 >/dev/null printf 'already here' > here.txt "$TOOL" put "$DISKS/write.img" here.txt >/dev/null + +# A disk of its own for the editing test, which deletes and renames things and would +# otherwise leave the writing test's disk looking nothing like the writing test expects. +# It starts with one file on it so that a document written here has to be placed around +# something, and so that the disk can be compared afterwards against one that never had +# any of it: the metadata should come back exactly as it was. +"$TOOL" format "$DISKS/edit.img" 32 1 >/dev/null +"$TOOL" put "$DISKS/edit.img" here.txt >/dev/null + +# A disk for the shell's delete and rename, which is its own because those change what is +# on it. A fixture whose name has a directory in it is used as it stands rather than being +# made fresh per test, so a test that writes to a shared one would quietly change what +# every test after it sees. +"$TOOL" format "$DISKS/files.img" 32 1 >/dev/null +printf 'the first one' > one.txt +printf 'the second one' > two.txt +"$TOOL" put "$DISKS/files.img" one.txt >/dev/null +"$TOOL" put "$DISKS/files.img" two.txt >/dev/null + +# A disk for the editor, holding nothing but the editor. Its own, because the whole point +# of it is that it writes: a document made on a shared fixture would turn up in the file +# listing of every test that came after it. +"$TOOL" format "$DISKS/editor.img" 256 2 >/dev/null +"$ROOT/Assembler" -I "$ROOT/Programs/Libraries" -I "$ROOT/Programs/CosmOS/Source" \ + "$ROOT/Programs/CosmOS/Apps/Edit.asm" -o "$WORK/Edit.sbx" >/dev/null +"$TOOL" put "$DISKS/editor.img" "$WORK/Edit.sbx" >/dev/null diff --git a/Tests/manifest b/Tests/manifest index 82724d3..f5d3d22 100644 --- a/Tests/manifest +++ b/Tests/manifest @@ -77,6 +77,11 @@ sbfsWalkTest | testPrograms/sbfsWalkTest.asm | run | - # Writing a filesystem, then reading back what was written. The disk starts with a file # on it, so allocation has to find room rather than start at the beginning. sbfsWriteTest | testPrograms/sbfsWriteTest.asm | run | - | - | disks/write.img +# Deleting, renaming, and saving over something already there, which is what any tool that +# edits a document needs and what none of the tests above touch. The interesting line is +# the third: saving a longer version moves the file, because files here are contiguous and +# do not grow. The last two lines are a rename and a delete having actually happened. +sbfsEditTest | testPrograms/sbfsEditTest.asm | run | - | - | disks/edit.img # Loading a program off a disk and running it. Everything below this line existed before # the loader did; the only new part is the sixteen bytes on the front of a loadable @@ -238,6 +243,26 @@ cosmosSnake | CosmOS/Source/cosmos.asm | run | cosmosSna # console's slot at FE00 is zero again, and CosmOS's own disk handler further along is # untouched by a program having installed over the top of it. cosmosKeys | CosmOS/Source/cosmos.asm | run | cosmosKeys.in | - | disks/cosmos.img +# The shell taking things off a disk and calling them something else, which is the last of +# CosmOS's original four verbs to be built and the first time anything has changed a disk +# from the shell. Its own image, because it changes what is on it: a fixture named with a +# directory is used as it stands, so a test that writes to a shared one changes what every +# test after it sees. The refusals are here too - deleting what is not there, renaming with +# a name missing, and renaming something to a name already taken. +cosmosFiles | CosmOS/Source/cosmos.asm | run | cosmosFiles.in | - | disks/files.img +# A program being told what it is for. Nothing loaded before this could be told anything, +# so every app did the same thing however it was started - which is fine for a demo and no +# use at all to a tool that edits a named document. Run three times: with nothing, with a +# name, and with several words, since what arrives is the rest of the line rather than a +# list and it is the program's business what to make of it. +cosmosSay | CosmOS/Source/cosmos.asm | run | cosmosSay.in | - | disks/cosmos.img +# The editor, which is the first program on this machine that makes a file a person typed: +# every byte on every other image here was put there by the host tool. It is run twice in +# one session, and that is the test rather than a flourish - the second run reads back what +# the first one wrote, so the whole path is checked at once: read a name from the argument, +# split a file into lines, edit them, build a file back out of them, and save it over +# something that was already there and is now a different size. +cosmosEdit | CosmOS/Source/cosmos.asm | run | cosmosEdit.in | - | disks/editor.img # The programs CosmOS loads, checked on their own so that a failure here reads as "the app # does not assemble" rather than as a broken disk image. app-greet | CosmOS/Apps/greet.asm | assemble | - | - @@ -245,6 +270,8 @@ app-hello | CosmOS/Apps/hello.asm | assemble | - app-Life | CosmOS/Apps/Life.asm | assemble | - | - app-Snake | CosmOS/Apps/Snake.asm | assemble | - | - app-Keys | CosmOS/Apps/Keys.asm | assemble | - | - +app-Say | CosmOS/Apps/Say.asm | assemble | - | - +app-Edit | CosmOS/Apps/Edit.asm | assemble | - | - # ---- Programs driven by console input ---- inputTest | inputTest.asm | run | inputTest.in | - diff --git a/Tests/run.sh b/Tests/run.sh index f1905ac..7996ac3 100755 --- a/Tests/run.sh +++ b/Tests/run.sh @@ -84,6 +84,24 @@ trim() { printf '%s' "$v" } +# Takes the cycle count out of the emulator's last line, in place. +# +# HOW MANY CYCLES A PROGRAM TOOK IS NOT WHAT ANY OF THESE TESTS ARE ABOUT, and having it in +# every recorded result made every one of them fragile in the same way: two instructions +# added to CosmOS moved the count in six unrelated files at once, so a real difference +# would have arrived in a crowd of meaningless ones and had to be picked out by hand. +# +# WHETHER a program stopped on its own or ran into its limit is kept, because that is +# behaviour and several tests exist to check it. Only the number goes. +# +# Anything that genuinely wants to measure cycles should say so out loud in a test of its +# own rather than every test carrying the measurement and nothing asserting anything about +# it. +settle() { + sed -i -E 's/^Execution halted after [0-9]+ cycles\.$/Execution halted./; + s/^Execution stopped after [0-9]+ cycles\. \(cycle limit reached\)$/Execution stopped. (cycle limit reached)/' "$1" +} + check() { # check local name="$1" actual="$2" golden="$EXPECTED/$1.out" @@ -205,6 +223,7 @@ while IFS='|' read -r name src mode stdin limit disk; do # supposed to exit non zero, and that should be just as pinned down as # what it printed. printf '[exit %d]\n' "$STATUS" >> "$OUT" + settle "$OUT" check "$name" "$OUT" ;; *) diff --git a/Tests/terminal.sh b/Tests/terminal.sh new file mode 100755 index 0000000..a7e9863 --- /dev/null +++ b/Tests/terminal.sh @@ -0,0 +1,259 @@ +#!/usr/bin/env bash +# Checks the things a recorded output cannot see. +# +# Every other test in this suite pipes standard input in and standard output to a file, and +# compares what came out against what came out last time. That answers "what does this +# program print", which is the right question almost always, and it is blind to two whole +# classes of behaviour: +# +# WHEN something is printed. Piped output is fully buffered and flushed when the process +# ends, so a prompt that appears before input is read and a prompt that appears an hour +# later produce byte-identical files. A prompt printed after the answer it was asking for +# is invisible to every other test here. +# +# WHAT HAPPENS TO THE TERMINAL. Key mode only touches a terminal when there is one, so +# with input from a file there is nothing to put into another state and nothing to put +# back. A machine that leaves the terminal without echo passes all 92 other tests. +# +# Both of those have gone wrong in this repository, and both were found by a person whose +# terminal stopped working rather than by anything here. So this runs the emulator under a +# pseudo-terminal, which is what makes those questions askable at all. +# +# Written by Anachronaut + +set -u +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" || exit 1 + +BUILD="$ROOT/Tests/build/terminal" +mkdir -p "$BUILD" + +[ -x "$ROOT/SplitBit" ] || { echo "The emulator is not built."; exit 1; } +[ -x "$ROOT/Assembler" ] || { echo "The assembler is not built."; exit 1; } + +# A program that asks for key mode and then waits for a key that never comes. Every check +# below needs a machine that is sitting in key mode with the terminal in its hands. +cat > "$BUILD/keywait.asm" <<'ASM' +#Program +start: + INIA 0x01 + OUTA 0x02 + INA 0x00 + HALT +ASM + +# A program that prints something with no newline after it and then waits, which is the +# shape of a prompt and the shape the buffering problem hides in. +cat > "$BUILD/prompt.asm" <<'ASM' +#Program +start: + INIA 0d62 ; '>' + OUTA 0x00 + INIA 0x20 + OUTA 0x00 + INA 0x00 + HALT +ASM + +"$ROOT/Assembler" "$BUILD/keywait.asm" -o "$BUILD/keywait.bin" >/dev/null 2>&1 || { + echo "Could not assemble the terminal test programs."; exit 1; } +"$ROOT/Assembler" "$BUILD/prompt.asm" -o "$BUILD/prompt.bin" >/dev/null 2>&1 || { + echo "Could not assemble the terminal test programs."; exit 1; } + +python3 - "$ROOT" "$BUILD" <<'PY' +import os +import pty +import select +import signal +import sys +import time + +root, build = sys.argv[1], sys.argv[2] +emulator = os.path.join(root, "SplitBit") + +passed = 0 +problems = [] + + +def report(ok, what, detail=""): + global passed + if ok: + passed += 1 + print(" [ok ] %s" % what) + else: + problems.append(what if not detail else "%s: %s" % (what, detail)) + print(" [FAIL] %s%s" % (what, (" - " + detail) if detail else "")) + + +def underPty(script, seconds=10): + """Runs a shell script with a pseudo-terminal for its controlling terminal, and + gives back everything the terminal saw.""" + pid, fd = pty.fork() + if pid == 0: + os.execv("/bin/bash", ["/bin/bash", "-c", script]) + seen = b"" + end = time.time() + seconds + while time.time() < end: + ready, _, _ = select.select([fd], [], [], 0.2) + if ready: + try: + chunk = os.read(fd, 4096) + except OSError: + break + if not chunk: + break + seen += chunk + if os.waitpid(pid, os.WNOHANG)[0]: + break + try: + os.kill(pid, signal.SIGKILL) + except ProcessLookupError: + pass + try: + os.waitpid(pid, 0) + except ChildProcessError: + pass + os.close(fd) + return seen + + +# ---- A prompt is shown before the answer to it is asked for ---- +# +# The machine writes "> " and then waits. Nothing more will ever be printed, so if the two +# characters have not arrived after a second of waiting, they are sitting in a buffer and +# the person at the terminal is looking at nothing and being asked to answer it. +# +# This is exactly the bug that getchar used to hide: reading through stdio flushed the line +# buffered streams first, and reading with read() does not. +pid, fd = pty.fork() +if pid == 0: + os.execv(emulator, [emulator, "--fast", os.path.join(build, "prompt.bin")]) +seen = b"" +end = time.time() + 1.5 +while time.time() < end: + ready, _, _ = select.select([fd], [], [], 0.2) + if ready: + try: + seen += os.read(fd, 1024) + except OSError: + break +report(b">" in seen, "a prompt is shown before its answer is read", + "" if b">" in seen else "nothing arrived in 1.5s, so it is stuck in a buffer") +try: + os.kill(pid, signal.SIGKILL) + os.waitpid(pid, 0) +except (ProcessLookupError, ChildProcessError): + pass +os.close(fd) + + +# ---- A key arrives without Return ---- +# +# Which is the whole of what key mode is for. In line mode the terminal holds what is typed +# until Return, so a machine that failed to ask for key mode would wait here for ever. +pid, fd = pty.fork() +if pid == 0: + os.execv(emulator, [emulator, "--fast", os.path.join(build, "keywait.bin")]) +time.sleep(0.5) +os.write(fd, b"x") # No newline, on purpose. +finished = False +end = time.time() + 2 +while time.time() < end: + if os.waitpid(pid, os.WNOHANG)[0]: + finished = True + break + time.sleep(0.05) +report(finished, "a single keystroke arrives without Return", + "" if finished else "the machine was still waiting, so the key was held by the terminal") +try: + os.kill(pid, signal.SIGKILL) + os.waitpid(pid, 0) +except (ProcessLookupError, ChildProcessError): + pass +os.close(fd) + + +# ---- The terminal is handed back however the machine dies ---- +# +# atexit covers stopping on purpose and nothing else: it does not run when a process is +# killed by a signal. SIGHUP is the one that matters most, because it is what arrives when +# whatever launched the machine dies and takes the terminal with it - and a terminal left +# in key mode has no echo and no line editing, which is a far worse failure than anything +# the program was doing. +for name in ("HUP", "INT", "QUIT", "ABRT", "SEGV", "TERM"): + # Cleared first. Without this a run that dies before it can measure leaves the PREVIOUS + # signal's files in place, and the check compares those and passes - which is how the + # SIGQUIT case came to be reporting success while proving nothing at all. + for leftover in ("before.txt", "after.txt"): + try: + os.remove(os.path.join(build, leftover)) + except FileNotFoundError: + pass + script = ( + # No core files. Two of these signals dump core by default, and a test suite has no + # business leaving those around every time it runs. It also keeps the measuring + # shell alive through SIGQUIT, which otherwise takes it down before it can look. + "ulimit -c 0\n" + "stty -g > {b}/before.txt\n" + "{e} --fast {b}/keywait.bin < /dev/tty &\n" + "P=$!\n" + "sleep 0.5\n" + "kill -{s} $P 2>/dev/null\n" + "wait $P 2>/dev/null\n" + "sleep 0.3\n" + "stty -g > {b}/after.txt\n" + ).format(b=build, e=emulator, s=name) + # < /dev/tty is load bearing. A background job in a non-interactive shell gets its + # standard input from /dev/null, so without it the machine never sees a terminal, never + # enters key mode, and has nothing to fail to put back - and this check would pass + # against a machine that restores nothing at all. + underPty(script) + try: + before = open(os.path.join(build, "before.txt")).read().strip() + after = open(os.path.join(build, "after.txt")).read().strip() + except FileNotFoundError: + # A failure, and for SIGQUIT this is the shape the failure takes: a machine that + # does not handle it dies in a way that takes the measuring shell with it, so what + # is reported is not "the terminal was left wrong" but "nothing got as far as + # looking". Both mean the same thing here, which is that the signal is unhandled. + report(False, "the terminal is restored after SIG%s" % name, "could not measure") + continue + report(before == after, "the terminal is restored after SIG%s" % name, + "" if before == after else "left as %s, was %s" % (after[:24], before[:24])) + + +# ---- Suspending is not dying ---- +# +# Ctrl-Z has to hand the terminal back while the machine is stopped, because whoever gets it +# next is entitled to find it as they left it, and take key mode again on resume, because +# the machine has not finished with it. +script = ( + "ulimit -c 0\n" + "stty -g > {b}/t0.txt\n" + "{e} --fast {b}/keywait.bin < /dev/tty &\n" + "P=$!\n" + "sleep 0.5\n" + "kill -TSTP $P; sleep 0.4\n" + "stty -g > {b}/t1.txt\n" + "kill -CONT $P; sleep 0.4\n" + "stty -g > {b}/t2.txt\n" + "kill -TERM $P; sleep 0.2\n" +).format(b=build, e=emulator) +underPty(script) +try: + t0 = open(os.path.join(build, "t0.txt")).read().strip() + t1 = open(os.path.join(build, "t1.txt")).read().strip() + t2 = open(os.path.join(build, "t2.txt")).read().strip() + report(t1 == t0, "the terminal is handed back while suspended") + report(t2 != t0, "key mode is taken again on resume") +except FileNotFoundError: + report(False, "suspending and resuming", "could not measure") + +print() +if problems: + print("The terminal does not survive everything it should:") + for p in problems: + print(" " + p) + sys.exit(1) +print("All %d terminal checks passed." % passed) +PY diff --git a/makefile b/makefile index 942dd03..61e2bcc 100644 --- a/makefile +++ b/makefile @@ -76,6 +76,8 @@ test: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) @echo @./Tests/disk.sh @echo + @./Tests/terminal.sh + @echo @./Tests/docs.sh # Rebuild both tools with the address and undefined behaviour sanitizers and run @@ -96,6 +98,8 @@ sanitize: @$(MAKE) --no-print-directory CFLAGS="$(SANITIZE_FLAGS)" @echo "Running the test suite under AddressSanitizer and UndefinedBehaviorSanitizer." @./Tests/run.sh + @echo + @./Tests/terminal.sh @$(MAKE) --no-print-directory clean @$(MAKE) --no-print-directory @echo "Sanitizer run finished cleanly. Normal binaries rebuilt."