X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/bb21580a5abba6a1e6666e9fb363f68d40f785d7..08a3a286a6602752c2818e86f65d92fa35b806e3:/stdlib/stdio.pvvs diff --git a/stdlib/stdio.pvvs b/stdlib/stdio.pvvs index 12e0ed7..2b77d1d 100644 --- a/stdlib/stdio.pvvs +++ b/stdlib/stdio.pvvs @@ -3,7 +3,7 @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ printstackstring (1000) +@ printstackstring (1000100) @ Description: @ Prints a null-terminated string from the stack. @ Call Stack: @@ -15,18 +15,18 @@ @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -NSSVTSSSN | Mark: 1000 (print string from stack) +NSSVTSSSTSSN | Mark: 1000100 (print string from stack) SNS | DUP -NTSSSSSTSSSSSSSSSSTN | BRZ > 00001000 00000001 +NTSSTSSSTSSSSSSSSSTN | BRZ > 01000100 00000001 TNSS | Print character -NSNTSSSN | JMP > 1000 -NSSVSSSSTSSSSSSSSSSTN | Mark: 00001000 00000001 +NSNTSSSTSSN | JMP > 1000100 +NSSVSTSSSTSSSSSSSSSTN | Mark: 01000100 00000001 SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ printheapstring (1001) +@ printheapstring (1000101) @ Description: @ Prints a null-terminated string from the heap. @ Call Stack: @@ -34,23 +34,23 @@ NTN | RTS @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -NSSVTSSTN | Mark: 1001 (print string from heap) +NSSVTSSSTSTN | Mark: 1000101 (print string from heap) SNS | DUP TTT | LOAD SNS | DUP -NTSSSSSTSSTSSSSSSSTN | BRZ > 00001001 00000001 +NTSSTSSSTSTSSSSSSSTN | BRZ > 01000101 00000001 TNSS | Print character SSSTN | Push +1 TSSS | ADD -NSNTSSTN | JMP > 1001 -NSSVSSSSTSSTSSSSSSSTN | Mark: 00001001 00000001 +NSNTSSSTSTN | JMP > 1000101 +NSSVSTSSSTSTSSSSSSSTN | Mark: 01000101 00000001 SNN | DROP SNN | DROP NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ printstacknumber (1010) +@ printstacknumber (1001) @ Description: @ Prints 'number' from the stack in sign-magnitude format. @ Leading zeros are suppressed. @@ -59,15 +59,15 @@ NTN | RTS @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -NSSVTSTSN | Mark: 1010 (print number from stack) +NSSVTSSTN | Mark: 1001 (print number from stack) SNS | DUP -NSTTSSSSSSN | JSR > 1000000 -NSTTSSSSSTN | JSR > 1000001 +NSTTSSSSTSN | JSR > 1000010 (printstacknumbersign) +NSTTSSSSTTN | JSR > 1000011 (printstacknumbermagnitude) NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ printstacknumbersign (1000000) +@ printstacknumbersign (1000010) @ Description: @ Prints the sign of 'number' from the stack. @ Call Stack: @@ -75,19 +75,19 @@ NTN | RTS @ Return Stack: @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -NSSVTSSSSSSN | Mark: 1000000 (print sign of number from stack) -NTTSTSSSSSSSSSSSSSTN | BMI > 010000000 00000001 +NSSVTSSSSTSN | Mark: 1000010 (print sign of number from stack) +NTTSTSSSSTSSSSSSSSTN | BMI > 01000010 00000001 SSSTSTSTTN | PUSH ASCII '+' -NSNSTSSSSSSSSSSSSTSN | JMP > 010000000 00000010 -NSSVSTSSSSSSSSSSSSSTN | Mark: 010000000 00000001 +NSNSTSSSSTSSSSSSSTSN | JMP > 01000010 00000010 +NSSVSTSSSSTSSSSSSSSTN | Mark: 01000010 00000001 SSSTSTTSTN | PUSH ASCII '-' -NSSVSTSSSSSSSSSSSSTSN | Mark: 010000000 00000010 +NSSVSTSSSSTSSSSSSSTSN | Mark: 01000010 00000010 TNSS | PUTC NTN | RTS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ Name: -@ printstacknumbermagnitude (1000001) +@ printstacknumbermagnitude (1000011) @ Description: @ Prints the magnitude of 'number' from the stack. @ Call Stack: @@ -96,14 +96,23 @@ NTN | RTS @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include -NSSVTSSSSSTN | Mark: 1000001 (print magnitude of number from stack) -NSTTSSSTN | JSR > 10001 (absolute value) +NSSVTSSSSTTN | Mark: 1000011 (print magnitude of number from stack) + +@ Catch -(2^63) as a special case since its absolute value will overflow +@ a twos-complement 64-bit word. +SNS | DUP +SSTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSN | -(2^63) +TSST | SUBTRACT +NTSSTSSSSTTSSSSSSTSN | BRZ > 01000011 00000010 +@ No special case applies. Prepare for computation by converting the number +@ to absolute value and preparing a string on the stack. +NSTTSSSTN | JSR > 10001 (absolute value) SSSSN | PUSH ASCII '\0' SNT | SWAP @ Pick off one digit on each pass through this loop. -NSSVSTSSSSSTSSSSSSSSN | Mark: 01000001 00000000 +NSSVSTSSSSTTSSSSSSSSN | Mark: 01000011 00000000 SNS | DUP @ Mod-off a digit, convert to ASCII, store on stack as part of the string. @@ -117,13 +126,326 @@ SNT | SWAP SSSTSTSN | PUSH +10 TSTS | DIVIDE SNS | DUP -NTSSTSSSSSTSSSSSSSTN | BRZ > 01000001 00000001 -NSNSTSSSSSTSSSSSSSSN | JMP > 01000001 00000000 +NTSSTSSSSTTSSSSSSSTN | BRZ > 01000011 00000001 +NSNSTSSSSTTSSSSSSSSN | JMP > 01000011 00000000 @ Print the string we have built on the stack. -NSSVSTSSSSSTSSSSSSSTN | Mark: 01000001 00000001 +NSSVSTSSSSTTSSSSSSSTN | Mark: 01000011 00000001 +SNN | DROP +NSTTSSSTSSN | JSR > 1000100 (print string from stack) +NTN | RTS + +@ Replace the number on the stack with its decimal ASCII representation. +NSSVSTSSSSTTSSSSSSTSN | BRZ > 01000011 00000010 +SNN | DROP +A"-9223372036854775808" +NSNSTSSSSTTSSSSSSSTN | JMP > 01000011 00000001 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ printf +@ Description: +@ If printing a static string (i.e. no substitutions), pass +@ 'number of substitutions' as 0, immediately followed by 'string word 1'. +@ If printing a string from the heap instead of stack, pass an empty string +@ on the stack followed by a pointer to the first word of the +@ null-terminated string on the heap. +@ For example: +@ pointer +@ ASCII '\0' +@ substitution n +@ +@ Maximum substitutions determined by upper heap limit in stackrotate and +@ stackrotatereverse subroutines. +@ Call Stack: +@ ACSII '\0' +@ string word n +@ ... +@ string word 1 +@ substitution n +@ ... +@ substitution 1 +@ number of substitutions <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#include +NSSVTSSSN | Mark: 1000 (printf) + +@ If the stack contains an empty string (i.e. just an ASCII '\0'), the next +@ word is a pointer we must use to load the string from the heap. +@ This will leave the stack looking exactly like the example call stack above. +@ Do the test this way so we can keep the code inline. +SNS | DUP +SSSTSN | PUSH 2 +TSSS | ADD +NSTTTSSN | JSR > 1100 (deepdup) +SSTTN | PUSH -1 +TSSN | MULTIPLY +NTTSSSSTSSSSSSSSSSTN | BMI > 00001000 00000001 +SNS | DUP +SSSTSN | PUSH 2 +TSSS | ADD +NSTTSTTN | JSR > 1011 (stackrotatereverse) +SNN | DROP +SNS | DUP +SSSTSN | PUSH 2 +TSSS | ADD +NSTTSTTN | JSR > 1011 (stackrotatereverse) +NSTSSSSTSSSTSSSTTSSN | JSR > 00001000 10001100 (printf_deepslurp) + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ The rest of printf parses a string according to the following information. +@ ASCII '\ ': +@ ASCII '\ ': putchar '\ ' +@ ASCII '%': putchar '%' +@ ASCII 'n': putchar '\n' +@ ASCII 't': putchar '\t' +@ ASCII '%': +@ ASCII 'c': (print character) +@ ASCII 's': (print string) +@ ASCII 'd': (print decimal digit) +@ ASCII 'u': (print abs(integer), w/o sign) +@ ASCII 'i': (print integer w/sign) +@ ASCII '\0': +@ cleanup and exit +@ default: +@ putchar +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@@@@@@@@@@@@@@@@@@@@ +@ The next block tests the char against all possible level 1 branches (see above). +@ If there is a match, execution jumps to the appropriate level 2 branch label. +@ If no match is found, print the character and move on. +@@@@@@@@@@@@@@@@@@@@ +NSSVSSSSTSSSSSSSSSSTN | Mark: 00001000 00000001 +@ Move the next character of the string to TOS. +NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) +@ TOS is an ASCII '\ '. Jump to process the possible level 2 branches. +SNS | DUP +SSSTSTTTSSN | PUSH ASCII slash +TSST | SUBTRACT +NTSSSSSTSSSSSSSSSTSN | BRZ > 00001000 00000010 +@ TOS is an ASCII '%'. Jump to process the possible level 2 branches. +SNS | DUP +SSSTSSTSTN | PUSH ASCII '%' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSSTTN | BRZ > 00001000 00000011 +@ TOS is an ASCII "\0". Jump to clean-up-and-exit. +SNS | DUP +NTSSSSSTSSSSSSSSSSSN | BRZ > 00001000 00000000 +@ TOS is a normal character. Print it and loop again. +TNSS | PUTC +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Level 2 - ASCII '\ ' - Escapes +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@@@@@@@@@@@@@@@@@@@@ +@ The level 1 match was an ASCII '\ '. +@ Now look for level 2 matches that trigger a character substitution (n -> newline, etc). +@ If no matches are found, print the character directly (e.g. "\%" -> '%') +@ When finished, loop back to testing level 1 branches. +@@@@@@@@@@@@@@@@@@@@ +NSSVSSSSTSSSSSSSSSTSN | Mark: 00001000 00000010 +SNN | DROP +@ Move the next character of the string to TOS. +NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) +@ Check for ASCII '\n' +SNS | DUP +SSSTTSTTTSN | PUSH ASCII 'n' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSTSSN | BRZ > 00001000 00000100 +@ Check for ASCII '\t' +SNS | DUP +SSSTTTSTSSN | PUSH ASCII 't' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSTSTN | BRZ > 00001000 00000101 +@ No substitution necessary. Print literally. +TNSS | PUTC +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@@@@@@@@@@@@@@@@@@@@ +@ These are utility labels to output the appropriate non-printable ASCII character. +@ After output, they loop back to testing level 1 branches. +@@@@@@@@@@@@@@@@@@@@ + +@ Print a newline and loop for the next character. +NSSVSSSSTSSSSSSSSTSSN | Mark: 00001000 00000100 +SNN | DROP +SSSTSTSN | PUSH ASCII '\n' +TNSS | PUTC +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@ Print a horizontal tab and loop for the next character. +NSSVSSSSTSSSSSSSSTSTN | Mark: 00001000 00000101 +SNN | DROP +SSSTSSTN | PUSH ASCII '\t' +TNSS | PUTC +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Level 2 - ASCII '%' - Substitutions +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@@@@@@@@@@@@@@@@@@@@ +@ The level 1 match was an ASCII '%'. +@ Now look for level 2 matches that trigger a substitution. +@ When finished, loop back to testing level 1 branches. +@@@@@@@@@@@@@@@@@@@@ +NSSVSSSSTSSSSSSSSSTTN | Mark: 00001000 00000011 +SNN | DROP +@ Move the next character of the string to TOS. +NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) +@ Check for ASCII 'c' - Print character +SNS | DUP +SSSTTSSSTTN | PUSH ASCII 'c' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSTTSN | BRZ > 00001000 00000110 +@ Check for ASCII 's' - Print string +SNS | DUP +SSSTTTSSTTN | PUSH ASCII 's' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSTTTN | BRZ > 00001000 00000111 +@ Check for ASCII 'd' - Print decimal digit +SNS | DUP +SSSTTSSTSSN | PUSH ASCII 'd' +TSST | SUBTRACT +NTSSSSSTSSSSSSSTSSSN | BRZ > 00001000 00001000 +@ Check for ASCII 'u' - Print unsigned number +SNS | DUP +SSSTTTSTSTN | PUSH ASCII 'u' +TSST | SUBTRACT +NTSSSSSTSSSSSSSTSSTN | BRZ > 00001000 00001001 +@ Check for ASCII 'i' - Print signed number +SNS | DUP +SSSTTSTSSTN | PUSH ASCII 'i' +TSST | SUBTRACT +NTSSSSSTSSSSSSSTSTSN | BRZ > 00001000 00001010 +@ Unrecognized substitution specifier. +@ For now, silently consume it and continue. +@ Do not increment the substitution counter. +@ TODO: Is this really what I want to do here? +SNN | DROP +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + + +@@@@@@@@@@@@@@@@@@@@ +@ These are utility labels to call the appropriate type of output subroutine. +@ After output, they decrement the substition counter and loop back to testing +@ level 1 branches. +@@@@@@@@@@@@@@@@@@@@ + +@ Print a character +NSSVSSSSTSSSSSSSSTTSN | Mark: 00001000 00000110 +SNN | DROP +SNT | SWAP +TNSS | PUTC +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a string +NSSVSSSSTSSSSSSSSTTTN | Mark: 00001000 00000111 +SNN | DROP +SNT | SWAP +NSTTSSSTSTN | JSR > 1000101 (print string from heap) +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a decimal digit +NSSVSSSSTSSSSSSSTSSSN | Mark: 00001000 00001000 +SNN | DROP +SNT | SWAP +TNST | PUTDIGIT +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print an unsigned integer +NSSVSSSSTSSSSSSSTSSTN | Mark: 00001000 00001001 +SNN | DROP +SNT | SWAP +NSTTSSSSTTN | JSR > 1000011 (print magnitude of number from stack) +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a signed integer +NSSVSSSSTSSSSSSSTSTSN | Mark: 00001000 00001010 +SNN | DROP +SNT | SWAP +NSTTSSTN | JSR > 1001 (print number from stack) +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ These are misc labels associated with the printf function. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@ Found an ASCII "\0" when processing the format string. Clean up and exit. +NSSVSSSSTSSSSSSSSSSSN | Mark: 00001000 00000000 +SNN | DROP +NTN | RTS + +@ Move the next string character to TOS. +@ Stack should look like the printf call stack, with num-of-subs at TOS. +NSSVSSSSTSSSTSSSTSTTN | Mark: 00001000 10001011 (next char to TOS) +SNS | DUP +SSSTSN | PUSH 2 +TSSS | ADD +NSTTSTTN | JSR > 1011 (stackrotatereverse) +NTN | RTS + +@ Slurps a string from the heap to the stack, storing it behind the substitutions. +@ Call Stack: +@ substitution n +@ ... +@ substitution 1 +@ number of substitutions <-- TOS +@ pointer to string +@ Return Stack: +@ ACSII '\0' +@ string word n +@ ... +@ string word 1 +@ substitution n +@ ... +@ substitution 1 +@ number of substitutions <-- TOS +@ TODO: This, along with a deepspew, should probably be stdlib routines. +NSSVSSSSTSSSTSSSTTSSN | Mark: 00001000 10001100 (printf_deepslurp) +SNS | DUP +@ Advance a duplicate copy of the pointer until it points to the null-terminator. +NSSVSSSSTSSSTSSSTTSTN | Mark: 00001000 10001101 +SNS | DUP +TTT | LOAD +NTSSSSSTSSSTSSSTTTSN | BRZ > 00001000 10001110 +SSSTN | PUSH 1 +TSSS | ADD +NSNSSSSTSSSTSSSTTSTN | JMP > 00001000 10001101 +@ Load a character to the stack on each pass through this loop. +NSSVSSSSTSSSTSSSTTTSN | Mark: 00001000 10001110 +SNS | DUP +TTT | LOAD +SSSTSSN | PUSH 4 +NSTTTSSN | JSR > 1100 (deepdup) +SSSTSSN | PUSH 4 +TSSS | ADD +NSTTSTSN | JSR > 1010 (stackrotate) +@ Test for end of loop. +SNS | DUP +SSSTTN | PUSH 3 +NSTTTSSN | JSR > 1100 (deepdup) +TSST | SUBTRACT +NTSSSSSTSSSTSSSTTTTN | BRZ > 00001000 10001111 +@ Decrement pointer to end of string, loop again. +SSSTN | PUSH 1 +TSST | SUBTRACT +NSNSSSSTSSSTSSSTTTSN | JMP > 00001000 10001110 +@ Clean up and return. +NSSVSSSSTSSSTSSSTTTTN | Mark: 00001000 10001111 +SNN | DROP SNN | DROP -NSTTSSSN | JSR > 1000 (print string from stack) NTN | RTS #endif