X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/32c440bf6f1f2199c3e925f32bd3b621039605e6..23d1724712fae7dc9645d862d57d030cf3e2e764:/stdlib/stdio.pvvs diff --git a/stdlib/stdio.pvvs b/stdlib/stdio.pvvs index d9184ad..950ad6c 100644 --- a/stdlib/stdio.pvvs +++ b/stdlib/stdio.pvvs @@ -1,42 +1,390 @@ -################################################################################ -# Description: -# This function prints a null-terminated string from the stack. -# Call Stack: -# null-terminator (ASCII '\0') -# char n -# ... -# char 2 -# char 1 <-- TOS -# Return Stack: -# -################################################################################ -NSSVTSSSN | Mark: 1000 (print string from stack) -SNS | DUP -NTSSSSSTSSSSSSSSSSTN | BRZ > 00001000 00000001 +#ifndef VVS_STDLIB_STDIO +#define VVS_STDLIB_STDIO + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ printstackstring (1000100) +@ Description: +@ Prints a null-terminated string from the stack. +@ Call Stack: +@ null-terminator (ASCII '\0') +@ char n +@ ... +@ char 2 +@ char 1 <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +NSSVTSSSTSSN | Mark: 1000100 (print string from stack) +SNS | DUP +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 -################################################################################ -# Description: -# This function prints a null-terminated string from the heap. -# Call Stack: -# pointer to first character <-- TOS -# Return Stack: -# -################################################################################ -NSSVTSSTN | Mark: 1001 (print string from heap) +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ printheapstring (1000101) +@ Description: +@ Prints a null-terminated string from the heap. +@ Call Stack: +@ pointer to first character <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +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 (1001) +@ Description: +@ Prints 'number' from the stack in sign-magnitude format. +@ Leading zeros are suppressed. +@ Call Stack: +@ number <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +NSSVTSSTN | Mark: 1001 (print number from stack) +SNS | DUP +NSTTSSSSTSN | JSR > 1000010 +NSTTSSSSTTN | JSR > 1000011 +NTN | RTS + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ printstacknumbersign (1000010) +@ Description: +@ Prints the sign of 'number' from the stack. +@ Call Stack: +@ number <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +NSSVTSSSSTSN | Mark: 1000010 (print sign of number from stack) +NTTSTSSSSTSSSSSSSSTN | BMI > 01000010 00000001 +SSSTSTSTTN | PUSH ASCII '+' +NSNSTSSSSTSSSSSSSTSN | JMP > 01000010 00000010 +NSSVSTSSSSTSSSSSSSSTN | Mark: 01000010 00000001 +SSSTSTTSTN | PUSH ASCII '-' +NSSVSTSSSSTSSSSSSSTSN | Mark: 01000010 00000010 +TNSS | PUTC +NTN | RTS + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Name: +@ printstacknumbermagnitude (1000011) +@ Description: +@ Prints the magnitude of 'number' from the stack. +@ Call Stack: +@ number <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#include +NSSVTSSSSTTN | Mark: 1000011 (print magnitude of number from stack) +NSTTSSSTN | JSR > 10001 (absolute value) + +SSSSN | PUSH ASCII '\0' +SNT | SWAP + +@ Pick off one digit on each pass through this loop. +NSSVSTSSSSTTSSSSSSSSN | Mark: 01000011 00000000 +SNS | DUP + +@ Mod-off a digit, convert to ASCII, store on stack as part of the string. +SSSTSTSN | PUSH +10 +TSTT | MODULO +SSSTTSSSSN | PUSH ASCII '0' +TSSS | ADD +SNT | SWAP + +@ Divide down to next digit and keep looping if number != 0 yet. +SSSTSTSN | PUSH +10 +TSTS | DIVIDE +SNS | DUP +NTSSTSSSSTTSSSSSSSTN | BRZ > 01000011 00000001 +NSNSTSSSSTTSSSSSSSSN | JMP > 01000011 00000000 + +@ Print the string we have built on the stack. +NSSVSTSSSSTTSSSSSSSTN | Mark: 01000011 00000001 +SNN | DROP +NSTTSSSTSSN | JSR > 1000100 (print string from stack) +NTN | RTS + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ 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 of 7 substitutions. +@ Call Stack: +@ ACSII '\0' +@ string word n +@ ... +@ string word 1 +@ substitution n +@ ... +@ substitution 1 +@ number of substitutions <-- TOS +@ Return Stack: +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#include +#include +NSSVTSSSN | Mark: 1000 (printf) + +@ Copy any substitution words into heap registers. +NSTTSSSSSTN | JSR > 1000001 (spewreg) + +@ heap[8] will track the current substitution register. +SSSTSSSN | PUSH 8 (ptr) +SSSTN | PUSH 1 +TTS | STORE + +@ 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. +@ Do the test this way so we can keep the code inline. +SNS | DUP +SSTTN | PUSH -1 +TSSN | MULTIPLY +NTTSSSSTSSSSSSSSSSTN | BMI > 00001000 00000001 +SNN | DROP +SNS | DUP +NSTTSSSSSN | JSR > 100000 (strlen) +NSTTTTTSN | JSR > 11110 (slurp) + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ Initialization is now complete. +@ Stack contains a printf-compatible, null-terminated string. +@ heap[1]-heap[7] contain the substitutions, if any. +@ heap[8] tracks which substitution is next. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ 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 TOS 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 +@ 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 +@ Check for ASCII '\n' +SNS | DUP +SSSTTSTTTSN | PUSH ASCII 'n' +TSST | SUBTRACT +NTSSSSSTSSSSSSSSTSSN | BRZ > 00001000 00000100 +@ Check for ASCII '\t' +SNS | DUP +SSSTSSTN | 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 +@ 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 increment the substition counter (heap[8]) +@ and loop back to testing level 1 branches. +@@@@@@@@@@@@@@@@@@@@ + +@ Print a character +NSSVSSSSTSSSSSSSSTTSN | Mark: 00001000 00000110 +SNN | DROP +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +TTT | LOAD +TNSS | PUTC +NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a string +NSSVSSSSTSSSSSSSSTTTN | Mark: 00001000 00000111 +SNN | DROP +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +TTT | LOAD +NSTTSSSTSTN | JSR > 1000101 (print string from heap) +NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a decimal digit +NSSVSSSSTSSSSSSSTSSSN | Mark: 00001000 00001000 +SNN | DROP +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +TTT | LOAD +TNST | PUTDIGIT +NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print an unsigned integer +NSSVSSSSTSSSSSSSTSSTN | Mark: 00001000 00001001 +SNN | DROP +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +TTT | LOAD +NSTTSSSSTTN | JSR > 1000011 (print magnitude of number from stack) +NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 +@ Print a signed integer +NSSVSSSSTSSSSSSSTSTSN | Mark: 00001000 00001010 +SNN | DROP +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +TTT | LOAD +NSTTSSTN | JSR > 1001 (print number from stack) +NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) +NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ These are misc labels associated with the printf function. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@ Increments heap[8]. Used after a substitution is complete. +NSSVSSSSTSSSTSSSSSSSN | Mark: 00001000 10000000 (increment heap[8]) +SSSTSSSN | PUSH 8 (ptr) +TTT | LOAD +SSSTN | PUSH 1 +TSSS | ADD +SSSTSSSN | PUSH 8 (ptr) +SNT | SWAP +TTS | STORE +NTN | RTS + +@ Found an ASCII "\0" when processing the format string. Clean up and exit. +NSSVSSSSTSSSSSSSSSSSN | Mark: 00001000 00000000 +SNN | DROP +NTN | RTS + +#endif