| 1 | @ (c) 2020 Aaron Taylor <ataylor at subgeniuskitty dot com> |
| 2 | @ See LICENSE.txt file for copyright and license details. |
| 3 | |
| 4 | #ifndef VVS_STDLIB_STDIO |
| 5 | #define VVS_STDLIB_STDIO |
| 6 | |
| 7 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 8 | @ Name: |
| 9 | @ printstackstring (1000100) |
| 10 | @ Description: |
| 11 | @ Prints a null-terminated string from the stack. |
| 12 | @ Call Stack: |
| 13 | @ null-terminator (ASCII '\0') |
| 14 | @ char n |
| 15 | @ ... |
| 16 | @ char 2 |
| 17 | @ char 1 <-- TOS |
| 18 | @ Return Stack: |
| 19 | @ <empty> |
| 20 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 21 | NSSVTSSSTSSN | Mark: 1000100 (print string from stack) |
| 22 | SNS | DUP |
| 23 | NTSSTSSSTSSSSSSSSSTN | BRZ > 01000100 00000001 |
| 24 | TNSS | Print character |
| 25 | NSNTSSSTSSN | JMP > 1000100 |
| 26 | NSSVSTSSSTSSSSSSSSSTN | Mark: 01000100 00000001 |
| 27 | SNN | DROP |
| 28 | NTN | RTS |
| 29 | |
| 30 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 31 | @ Name: |
| 32 | @ printheapstring (1000101) |
| 33 | @ Description: |
| 34 | @ Prints a null-terminated string from the heap. |
| 35 | @ Call Stack: |
| 36 | @ pointer to first character <-- TOS |
| 37 | @ Return Stack: |
| 38 | @ <empty> |
| 39 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 40 | NSSVTSSSTSTN | Mark: 1000101 (print string from heap) |
| 41 | SNS | DUP |
| 42 | TTT | LOAD |
| 43 | SNS | DUP |
| 44 | NTSSTSSSTSTSSSSSSSTN | BRZ > 01000101 00000001 |
| 45 | TNSS | Print character |
| 46 | SSSTN | Push +1 |
| 47 | TSSS | ADD |
| 48 | NSNTSSSTSTN | JMP > 1000101 |
| 49 | NSSVSTSSSTSTSSSSSSSTN | Mark: 01000101 00000001 |
| 50 | SNN | DROP |
| 51 | SNN | DROP |
| 52 | NTN | RTS |
| 53 | |
| 54 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 55 | @ Name: |
| 56 | @ printstacknumber (1001) |
| 57 | @ Description: |
| 58 | @ Prints 'number' from the stack in sign-magnitude format. |
| 59 | @ Leading zeros are suppressed. |
| 60 | @ Call Stack: |
| 61 | @ number <-- TOS |
| 62 | @ Return Stack: |
| 63 | @ <empty> |
| 64 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 65 | NSSVTSSTN | Mark: 1001 (print number from stack) |
| 66 | SNS | DUP |
| 67 | NSTTSSSSTSN | JSR > 1000010 (printstacknumbersign) |
| 68 | NSTTSSSSTTN | JSR > 1000011 (printstacknumbermagnitude) |
| 69 | NTN | RTS |
| 70 | |
| 71 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 72 | @ Name: |
| 73 | @ printstacknumbersign (1000010) |
| 74 | @ Description: |
| 75 | @ Prints the sign of 'number' from the stack. |
| 76 | @ Call Stack: |
| 77 | @ number <-- TOS |
| 78 | @ Return Stack: |
| 79 | @ <empty> |
| 80 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 81 | NSSVTSSSSTSN | Mark: 1000010 (print sign of number from stack) |
| 82 | NTTSTSSSSTSSSSSSSSTN | BMI > 01000010 00000001 |
| 83 | SSSTSTSTTN | PUSH ASCII '+' |
| 84 | NSNSTSSSSTSSSSSSSTSN | JMP > 01000010 00000010 |
| 85 | NSSVSTSSSSTSSSSSSSSTN | Mark: 01000010 00000001 |
| 86 | SSSTSTTSTN | PUSH ASCII '-' |
| 87 | NSSVSTSSSSTSSSSSSSTSN | Mark: 01000010 00000010 |
| 88 | TNSS | PUTC |
| 89 | NTN | RTS |
| 90 | |
| 91 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 92 | @ Name: |
| 93 | @ printstacknumbermagnitude (1000011) |
| 94 | @ Description: |
| 95 | @ Prints the magnitude of 'number' from the stack. |
| 96 | @ Call Stack: |
| 97 | @ number <-- TOS |
| 98 | @ Return Stack: |
| 99 | @ <empty> |
| 100 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 101 | #include <math.pvvs> |
| 102 | NSSVTSSSSTTN | Mark: 1000011 (print magnitude of number from stack) |
| 103 | |
| 104 | @ Catch -(2^63) as a special case since its absolute value will overflow |
| 105 | @ a twos-complement 64-bit word. |
| 106 | SNS | DUP |
| 107 | SSTTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSN | -(2^63) |
| 108 | TSST | SUBTRACT |
| 109 | NTSSTSSSSTTSSSSSSTSN | BRZ > 01000011 00000010 |
| 110 | |
| 111 | @ No special case applies. Prepare for computation by converting the number |
| 112 | @ to absolute value and preparing a string on the stack. |
| 113 | NSTTSSSTN | JSR > 10001 (absolute value) |
| 114 | SSSSN | PUSH ASCII '\0' |
| 115 | SNT | SWAP |
| 116 | |
| 117 | @ Pick off one digit on each pass through this loop. |
| 118 | NSSVSTSSSSTTSSSSSSSSN | Mark: 01000011 00000000 |
| 119 | SNS | DUP |
| 120 | |
| 121 | @ Mod-off a digit, convert to ASCII, store on stack as part of the string. |
| 122 | SSSTSTSN | PUSH +10 |
| 123 | TSTT | MODULO |
| 124 | SSSTTSSSSN | PUSH ASCII '0' |
| 125 | TSSS | ADD |
| 126 | SNT | SWAP |
| 127 | |
| 128 | @ Divide down to next digit and keep looping if number != 0 yet. |
| 129 | SSSTSTSN | PUSH +10 |
| 130 | TSTS | DIVIDE |
| 131 | SNS | DUP |
| 132 | NTSSTSSSSTTSSSSSSSTN | BRZ > 01000011 00000001 |
| 133 | NSNSTSSSSTTSSSSSSSSN | JMP > 01000011 00000000 |
| 134 | |
| 135 | @ Print the string we have built on the stack. |
| 136 | NSSVSTSSSSTTSSSSSSSTN | Mark: 01000011 00000001 |
| 137 | SNN | DROP |
| 138 | NSTTSSSTSSN | JSR > 1000100 (print string from stack) |
| 139 | NTN | RTS |
| 140 | |
| 141 | @ Replace the number on the stack with its decimal ASCII representation. |
| 142 | NSSVSTSSSSTTSSSSSSTSN | BRZ > 01000011 00000010 |
| 143 | SNN | DROP |
| 144 | A"-9223372036854775808" |
| 145 | NSNSTSSSSTTSSSSSSSTN | JMP > 01000011 00000001 |
| 146 | |
| 147 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 148 | @ Name: |
| 149 | @ printf |
| 150 | @ Description: |
| 151 | @ If printing a static string (i.e. no substitutions), pass |
| 152 | @ 'number of substitutions' as 0, immediately followed by 'string word 1'. |
| 153 | @ If printing a string from the heap instead of stack, pass an empty string |
| 154 | @ on the stack followed by a pointer to the first word of the |
| 155 | @ null-terminated string on the heap. |
| 156 | @ For example: |
| 157 | @ pointer |
| 158 | @ ASCII '\0' |
| 159 | @ substitution n |
| 160 | @ <remainder of call stack is unchanged> |
| 161 | @ Maximum substitutions determined by upper heap limit in stackrotate and |
| 162 | @ stackrotatereverse subroutines. |
| 163 | @ Call Stack: |
| 164 | @ ACSII '\0' |
| 165 | @ string word n |
| 166 | @ ... |
| 167 | @ string word 1 |
| 168 | @ substitution n |
| 169 | @ ... |
| 170 | @ substitution 1 |
| 171 | @ number of substitutions <-- TOS |
| 172 | @ Return Stack: |
| 173 | @ <empty> |
| 174 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 175 | #include <stack.pvvs> |
| 176 | NSSVTSSSN | Mark: 1000 (printf) |
| 177 | |
| 178 | @ If the stack contains an empty string (i.e. just an ASCII '\0'), the next |
| 179 | @ word is a pointer we must use to load the string from the heap. |
| 180 | @ This will leave the stack looking exactly like the example call stack above. |
| 181 | @ Do the test this way so we can keep the code inline. |
| 182 | SNS | DUP |
| 183 | SSSTSN | PUSH 2 |
| 184 | TSSS | ADD |
| 185 | NSTTTSSN | JSR > 1100 (deepdup) |
| 186 | SSTTN | PUSH -1 |
| 187 | TSSN | MULTIPLY |
| 188 | NTTSSSSTSSSSSSSSSSTN | BMI > 00001000 00000001 |
| 189 | SNS | DUP |
| 190 | SSSTSN | PUSH 2 |
| 191 | TSSS | ADD |
| 192 | NSTTSTTN | JSR > 1011 (stackrotatereverse) |
| 193 | SNN | DROP |
| 194 | SNS | DUP |
| 195 | SSSTSN | PUSH 2 |
| 196 | TSSS | ADD |
| 197 | NSTTSTTN | JSR > 1011 (stackrotatereverse) |
| 198 | NSTSSSSTSSSTSSSTTSSN | JSR > 00001000 10001100 (printf_deepslurp) |
| 199 | |
| 200 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 201 | @ The rest of printf parses a string according to the following information. |
| 202 | @ ASCII '\ ': |
| 203 | @ ASCII '\ ': putchar '\ ' |
| 204 | @ ASCII '%': putchar '%' |
| 205 | @ ASCII 'n': putchar '\n' |
| 206 | @ ASCII 't': putchar '\t' |
| 207 | @ ASCII '%': |
| 208 | @ ASCII 'c': (print character) |
| 209 | @ ASCII 's': (print string) |
| 210 | @ ASCII 'd': (print decimal digit) |
| 211 | @ ASCII 'u': (print abs(integer), w/o sign) |
| 212 | @ ASCII 'i': (print integer w/sign) |
| 213 | @ ASCII '\0': |
| 214 | @ cleanup and exit |
| 215 | @ default: |
| 216 | @ putchar |
| 217 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 218 | |
| 219 | @@@@@@@@@@@@@@@@@@@@ |
| 220 | @ The next block tests the char against all possible level 1 branches (see above). |
| 221 | @ If there is a match, execution jumps to the appropriate level 2 branch label. |
| 222 | @ If no match is found, print the character and move on. |
| 223 | @@@@@@@@@@@@@@@@@@@@ |
| 224 | NSSVSSSSTSSSSSSSSSSTN | Mark: 00001000 00000001 |
| 225 | @ Move the next character of the string to TOS. |
| 226 | NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) |
| 227 | @ TOS is an ASCII '\ '. Jump to process the possible level 2 branches. |
| 228 | SNS | DUP |
| 229 | SSSTSTTTSSN | PUSH ASCII slash |
| 230 | TSST | SUBTRACT |
| 231 | NTSSSSSTSSSSSSSSSTSN | BRZ > 00001000 00000010 |
| 232 | @ TOS is an ASCII '%'. Jump to process the possible level 2 branches. |
| 233 | SNS | DUP |
| 234 | SSSTSSTSTN | PUSH ASCII '%' |
| 235 | TSST | SUBTRACT |
| 236 | NTSSSSSTSSSSSSSSSTTN | BRZ > 00001000 00000011 |
| 237 | @ TOS is an ASCII "\0". Jump to clean-up-and-exit. |
| 238 | SNS | DUP |
| 239 | NTSSSSSTSSSSSSSSSSSN | BRZ > 00001000 00000000 |
| 240 | @ TOS is a normal character. Print it and loop again. |
| 241 | TNSS | PUTC |
| 242 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 243 | |
| 244 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 245 | @ Level 2 - ASCII '\ ' - Escapes |
| 246 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 247 | |
| 248 | @@@@@@@@@@@@@@@@@@@@ |
| 249 | @ The level 1 match was an ASCII '\ '. |
| 250 | @ Now look for level 2 matches that trigger a character substitution (n -> newline, etc). |
| 251 | @ If no matches are found, print the character directly (e.g. "\%" -> '%') |
| 252 | @ When finished, loop back to testing level 1 branches. |
| 253 | @@@@@@@@@@@@@@@@@@@@ |
| 254 | NSSVSSSSTSSSSSSSSSTSN | Mark: 00001000 00000010 |
| 255 | SNN | DROP |
| 256 | @ Move the next character of the string to TOS. |
| 257 | NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) |
| 258 | @ Check for ASCII '\n' |
| 259 | SNS | DUP |
| 260 | SSSTTSTTTSN | PUSH ASCII 'n' |
| 261 | TSST | SUBTRACT |
| 262 | NTSSSSSTSSSSSSSSTSSN | BRZ > 00001000 00000100 |
| 263 | @ Check for ASCII '\t' |
| 264 | SNS | DUP |
| 265 | SSSTTTSTSSN | PUSH ASCII 't' |
| 266 | TSST | SUBTRACT |
| 267 | NTSSSSSTSSSSSSSSTSTN | BRZ > 00001000 00000101 |
| 268 | @ No substitution necessary. Print literally. |
| 269 | TNSS | PUTC |
| 270 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 271 | |
| 272 | @@@@@@@@@@@@@@@@@@@@ |
| 273 | @ These are utility labels to output the appropriate non-printable ASCII character. |
| 274 | @ After output, they loop back to testing level 1 branches. |
| 275 | @@@@@@@@@@@@@@@@@@@@ |
| 276 | |
| 277 | @ Print a newline and loop for the next character. |
| 278 | NSSVSSSSTSSSSSSSSTSSN | Mark: 00001000 00000100 |
| 279 | SNN | DROP |
| 280 | SSSTSTSN | PUSH ASCII '\n' |
| 281 | TNSS | PUTC |
| 282 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 283 | |
| 284 | @ Print a horizontal tab and loop for the next character. |
| 285 | NSSVSSSSTSSSSSSSSTSTN | Mark: 00001000 00000101 |
| 286 | SNN | DROP |
| 287 | SSSTSSTN | PUSH ASCII '\t' |
| 288 | TNSS | PUTC |
| 289 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 290 | |
| 291 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 292 | @ Level 2 - ASCII '%' - Substitutions |
| 293 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 294 | |
| 295 | @@@@@@@@@@@@@@@@@@@@ |
| 296 | @ The level 1 match was an ASCII '%'. |
| 297 | @ Now look for level 2 matches that trigger a substitution. |
| 298 | @ When finished, loop back to testing level 1 branches. |
| 299 | @@@@@@@@@@@@@@@@@@@@ |
| 300 | NSSVSSSSTSSSSSSSSSTTN | Mark: 00001000 00000011 |
| 301 | SNN | DROP |
| 302 | @ Move the next character of the string to TOS. |
| 303 | NSTSSSSTSSSTSSSTSTTN | JSR > 00001000 10001011 (next char to TOS) |
| 304 | @ Check for ASCII 'c' - Print character |
| 305 | SNS | DUP |
| 306 | SSSTTSSSTTN | PUSH ASCII 'c' |
| 307 | TSST | SUBTRACT |
| 308 | NTSSSSSTSSSSSSSSTTSN | BRZ > 00001000 00000110 |
| 309 | @ Check for ASCII 's' - Print string |
| 310 | SNS | DUP |
| 311 | SSSTTTSSTTN | PUSH ASCII 's' |
| 312 | TSST | SUBTRACT |
| 313 | NTSSSSSTSSSSSSSSTTTN | BRZ > 00001000 00000111 |
| 314 | @ Check for ASCII 'd' - Print decimal digit |
| 315 | SNS | DUP |
| 316 | SSSTTSSTSSN | PUSH ASCII 'd' |
| 317 | TSST | SUBTRACT |
| 318 | NTSSSSSTSSSSSSSTSSSN | BRZ > 00001000 00001000 |
| 319 | @ Check for ASCII 'u' - Print unsigned number |
| 320 | SNS | DUP |
| 321 | SSSTTTSTSTN | PUSH ASCII 'u' |
| 322 | TSST | SUBTRACT |
| 323 | NTSSSSSTSSSSSSSTSSTN | BRZ > 00001000 00001001 |
| 324 | @ Check for ASCII 'i' - Print signed number |
| 325 | SNS | DUP |
| 326 | SSSTTSTSSTN | PUSH ASCII 'i' |
| 327 | TSST | SUBTRACT |
| 328 | NTSSSSSTSSSSSSSTSTSN | BRZ > 00001000 00001010 |
| 329 | @ Unrecognized substitution specifier. |
| 330 | @ For now, silently consume it and continue. |
| 331 | @ Do not increment the substitution counter. |
| 332 | @ TODO: Is this really what I want to do here? |
| 333 | SNN | DROP |
| 334 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 335 | |
| 336 | |
| 337 | @@@@@@@@@@@@@@@@@@@@ |
| 338 | @ These are utility labels to call the appropriate type of output subroutine. |
| 339 | @ After output, they decrement the substition counter and loop back to testing |
| 340 | @ level 1 branches. |
| 341 | @@@@@@@@@@@@@@@@@@@@ |
| 342 | |
| 343 | @ Print a character |
| 344 | NSSVSSSSTSSSSSSSSTTSN | Mark: 00001000 00000110 |
| 345 | SNN | DROP |
| 346 | SNT | SWAP |
| 347 | TNSS | PUTC |
| 348 | SSSTN | PUSH 1 |
| 349 | TSST | SUBTRACT |
| 350 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 351 | @ Print a string |
| 352 | NSSVSSSSTSSSSSSSSTTTN | Mark: 00001000 00000111 |
| 353 | SNN | DROP |
| 354 | SNT | SWAP |
| 355 | NSTTSSSTSTN | JSR > 1000101 (print string from heap) |
| 356 | SSSTN | PUSH 1 |
| 357 | TSST | SUBTRACT |
| 358 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 359 | @ Print a decimal digit |
| 360 | NSSVSSSSTSSSSSSSTSSSN | Mark: 00001000 00001000 |
| 361 | SNN | DROP |
| 362 | SNT | SWAP |
| 363 | TNST | PUTDIGIT |
| 364 | SSSTN | PUSH 1 |
| 365 | TSST | SUBTRACT |
| 366 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 367 | @ Print an unsigned integer |
| 368 | NSSVSSSSTSSSSSSSTSSTN | Mark: 00001000 00001001 |
| 369 | SNN | DROP |
| 370 | SNT | SWAP |
| 371 | NSTTSSSSTTN | JSR > 1000011 (print magnitude of number from stack) |
| 372 | SSSTN | PUSH 1 |
| 373 | TSST | SUBTRACT |
| 374 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 375 | @ Print a signed integer |
| 376 | NSSVSSSSTSSSSSSSTSTSN | Mark: 00001000 00001010 |
| 377 | SNN | DROP |
| 378 | SNT | SWAP |
| 379 | NSTTSSTN | JSR > 1001 (print number from stack) |
| 380 | SSSTN | PUSH 1 |
| 381 | TSST | SUBTRACT |
| 382 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 |
| 383 | |
| 384 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 385 | @ These are misc labels associated with the printf function. |
| 386 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 387 | |
| 388 | @ Found an ASCII "\0" when processing the format string. Clean up and exit. |
| 389 | NSSVSSSSTSSSSSSSSSSSN | Mark: 00001000 00000000 |
| 390 | SNN | DROP |
| 391 | SNN | DROP |
| 392 | NTN | RTS |
| 393 | |
| 394 | @ Move the next string character to TOS. |
| 395 | @ Stack should look like the printf call stack, with num-of-subs at TOS. |
| 396 | NSSVSSSSTSSSTSSSTSTTN | Mark: 00001000 10001011 (next char to TOS) |
| 397 | SNS | DUP |
| 398 | SSSTSN | PUSH 2 |
| 399 | TSSS | ADD |
| 400 | NSTTSTTN | JSR > 1011 (stackrotatereverse) |
| 401 | NTN | RTS |
| 402 | |
| 403 | @ Slurps a string from the heap to the stack, storing it behind the substitutions. |
| 404 | @ Call Stack: |
| 405 | @ substitution n |
| 406 | @ ... |
| 407 | @ substitution 1 |
| 408 | @ number of substitutions <-- TOS |
| 409 | @ pointer to string |
| 410 | @ Return Stack: |
| 411 | @ ACSII '\0' |
| 412 | @ string word n |
| 413 | @ ... |
| 414 | @ string word 1 |
| 415 | @ substitution n |
| 416 | @ ... |
| 417 | @ substitution 1 |
| 418 | @ number of substitutions <-- TOS |
| 419 | @ TODO: This, along with a deepspew, should probably be stdlib routines. |
| 420 | NSSVSSSSTSSSTSSSTTSSN | Mark: 00001000 10001100 (printf_deepslurp) |
| 421 | SNS | DUP |
| 422 | @ Advance a duplicate copy of the pointer until it points to the null-terminator. |
| 423 | NSSVSSSSTSSSTSSSTTSTN | Mark: 00001000 10001101 |
| 424 | SNS | DUP |
| 425 | TTT | LOAD |
| 426 | NTSSSSSTSSSTSSSTTTSN | BRZ > 00001000 10001110 |
| 427 | SSSTN | PUSH 1 |
| 428 | TSSS | ADD |
| 429 | NSNSSSSTSSSTSSSTTSTN | JMP > 00001000 10001101 |
| 430 | @ Load a character to the stack on each pass through this loop. |
| 431 | NSSVSSSSTSSSTSSSTTTSN | Mark: 00001000 10001110 |
| 432 | SNS | DUP |
| 433 | TTT | LOAD |
| 434 | SSSTSSN | PUSH 4 |
| 435 | NSTTTSSN | JSR > 1100 (deepdup) |
| 436 | SSSTSSN | PUSH 4 |
| 437 | TSSS | ADD |
| 438 | NSTTSTSN | JSR > 1010 (stackrotate) |
| 439 | @ Test for end of loop. |
| 440 | SNS | DUP |
| 441 | SSSTTN | PUSH 3 |
| 442 | NSTTTSSN | JSR > 1100 (deepdup) |
| 443 | TSST | SUBTRACT |
| 444 | NTSSSSSTSSSTSSSTTTTN | BRZ > 00001000 10001111 |
| 445 | @ Decrement pointer to end of string, loop again. |
| 446 | SSSTN | PUSH 1 |
| 447 | TSST | SUBTRACT |
| 448 | NSNSSSSTSSSTSSSTTTSN | JMP > 00001000 10001110 |
| 449 | @ Clean up and return. |
| 450 | NSSVSSSSTSSSTSSSTTTTN | Mark: 00001000 10001111 |
| 451 | SNN | DROP |
| 452 | SNN | DROP |
| 453 | NTN | RTS |
| 454 | |
| 455 | #endif |