Commit | Line | Data |
---|---|---|
8bed3ccd AT |
1 | #ifndef VVS_STDLIB_STDIO |
2 | #define VVS_STDLIB_STDIO | |
3 | ||
4 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
bb21580a | 5 | @ Name: |
b8b65c17 | 6 | @ printstackstring (1000100) |
8bed3ccd | 7 | @ Description: |
bb21580a | 8 | @ Prints a null-terminated string from the stack. |
8bed3ccd AT |
9 | @ Call Stack: |
10 | @ null-terminator (ASCII '\0') | |
11 | @ char n | |
12 | @ ... | |
13 | @ char 2 | |
14 | @ char 1 <-- TOS | |
15 | @ Return Stack: | |
16 | @ <empty> | |
17 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
b8b65c17 | 18 | NSSVTSSSTSSN | Mark: 1000100 (print string from stack) |
32c440bf | 19 | SNS | DUP |
b8b65c17 | 20 | NTSSTSSSTSSSSSSSSSTN | BRZ > 01000100 00000001 |
32c440bf | 21 | TNSS | Print character |
b8b65c17 AT |
22 | NSNTSSSTSSN | JMP > 1000100 |
23 | NSSVSTSSSTSSSSSSSSSTN | Mark: 01000100 00000001 | |
32c440bf AT |
24 | SNN | DROP |
25 | NTN | RTS | |
26 | ||
8bed3ccd | 27 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
bb21580a | 28 | @ Name: |
b8b65c17 | 29 | @ printheapstring (1000101) |
8bed3ccd | 30 | @ Description: |
bb21580a | 31 | @ Prints a null-terminated string from the heap. |
8bed3ccd AT |
32 | @ Call Stack: |
33 | @ pointer to first character <-- TOS | |
34 | @ Return Stack: | |
35 | @ <empty> | |
36 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
b8b65c17 | 37 | NSSVTSSSTSTN | Mark: 1000101 (print string from heap) |
32c440bf AT |
38 | SNS | DUP |
39 | TTT | LOAD | |
40 | SNS | DUP | |
b8b65c17 | 41 | NTSSTSSSTSTSSSSSSSTN | BRZ > 01000101 00000001 |
32c440bf AT |
42 | TNSS | Print character |
43 | SSSTN | Push +1 | |
44 | TSSS | ADD | |
b8b65c17 AT |
45 | NSNTSSSTSTN | JMP > 1000101 |
46 | NSSVSTSSSTSTSSSSSSSTN | Mark: 01000101 00000001 | |
32c440bf AT |
47 | SNN | DROP |
48 | SNN | DROP | |
49 | NTN | RTS | |
8bed3ccd | 50 | |
3625ff3a | 51 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
bb21580a | 52 | @ Name: |
23d17247 | 53 | @ printstacknumber (1001) |
3625ff3a | 54 | @ Description: |
bb21580a | 55 | @ Prints 'number' from the stack in sign-magnitude format. |
3625ff3a AT |
56 | @ Leading zeros are suppressed. |
57 | @ Call Stack: | |
bb21580a | 58 | @ number <-- TOS |
3625ff3a AT |
59 | @ Return Stack: |
60 | @ <empty> | |
61 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
23d17247 | 62 | NSSVTSSTN | Mark: 1001 (print number from stack) |
3625ff3a | 63 | SNS | DUP |
ae1f85a1 AT |
64 | NSTTSSSSTSN | JSR > 1000010 |
65 | NSTTSSSSTTN | JSR > 1000011 | |
3625ff3a AT |
66 | NTN | RTS |
67 | ||
68 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
bb21580a | 69 | @ Name: |
ae1f85a1 | 70 | @ printstacknumbersign (1000010) |
3625ff3a | 71 | @ Description: |
bb21580a | 72 | @ Prints the sign of 'number' from the stack. |
3625ff3a | 73 | @ Call Stack: |
bb21580a | 74 | @ number <-- TOS |
3625ff3a AT |
75 | @ Return Stack: |
76 | @ <empty> | |
77 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
ae1f85a1 AT |
78 | NSSVTSSSSTSN | Mark: 1000010 (print sign of number from stack) |
79 | NTTSTSSSSTSSSSSSSSTN | BMI > 01000010 00000001 | |
3625ff3a | 80 | SSSTSTSTTN | PUSH ASCII '+' |
ae1f85a1 AT |
81 | NSNSTSSSSTSSSSSSSTSN | JMP > 01000010 00000010 |
82 | NSSVSTSSSSTSSSSSSSSTN | Mark: 01000010 00000001 | |
3625ff3a | 83 | SSSTSTTSTN | PUSH ASCII '-' |
ae1f85a1 | 84 | NSSVSTSSSSTSSSSSSSTSN | Mark: 01000010 00000010 |
3625ff3a AT |
85 | TNSS | PUTC |
86 | NTN | RTS | |
87 | ||
88 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
bb21580a | 89 | @ Name: |
ae1f85a1 | 90 | @ printstacknumbermagnitude (1000011) |
3625ff3a | 91 | @ Description: |
bb21580a | 92 | @ Prints the magnitude of 'number' from the stack. |
3625ff3a | 93 | @ Call Stack: |
bb21580a | 94 | @ number <-- TOS |
3625ff3a AT |
95 | @ Return Stack: |
96 | @ <empty> | |
97 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
bb21580a | 98 | #include <math.pvvs> |
ae1f85a1 | 99 | NSSVTSSSSTTN | Mark: 1000011 (print magnitude of number from stack) |
3625ff3a AT |
100 | NSTTSSSTN | JSR > 10001 (absolute value) |
101 | ||
102 | SSSSN | PUSH ASCII '\0' | |
103 | SNT | SWAP | |
104 | ||
105 | @ Pick off one digit on each pass through this loop. | |
ae1f85a1 | 106 | NSSVSTSSSSTTSSSSSSSSN | Mark: 01000011 00000000 |
3625ff3a AT |
107 | SNS | DUP |
108 | ||
109 | @ Mod-off a digit, convert to ASCII, store on stack as part of the string. | |
110 | SSSTSTSN | PUSH +10 | |
111 | TSTT | MODULO | |
112 | SSSTTSSSSN | PUSH ASCII '0' | |
113 | TSSS | ADD | |
114 | SNT | SWAP | |
115 | ||
116 | @ Divide down to next digit and keep looping if number != 0 yet. | |
117 | SSSTSTSN | PUSH +10 | |
118 | TSTS | DIVIDE | |
119 | SNS | DUP | |
ae1f85a1 AT |
120 | NTSSTSSSSTTSSSSSSSTN | BRZ > 01000011 00000001 |
121 | NSNSTSSSSTTSSSSSSSSN | JMP > 01000011 00000000 | |
3625ff3a AT |
122 | |
123 | @ Print the string we have built on the stack. | |
ae1f85a1 | 124 | NSSVSTSSSSTTSSSSSSSTN | Mark: 01000011 00000001 |
3625ff3a | 125 | SNN | DROP |
45abb94e | 126 | NSTTSSSTSSN | JSR > 1000100 (print string from stack) |
3625ff3a AT |
127 | NTN | RTS |
128 | ||
23d17247 AT |
129 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
130 | @ Name: | |
131 | @ printf | |
132 | @ Description: | |
133 | @ If printing a static string (i.e. no substitutions), pass | |
134 | @ 'number of substitutions' as 0, immediately followed by 'string word 1'. | |
135 | @ If printing a string from the heap instead of stack, pass an empty string | |
136 | @ on the stack followed by a pointer to the first word of the | |
137 | @ null-terminated string on the heap. | |
138 | @ For example: | |
139 | @ pointer | |
140 | @ ASCII '\0' | |
141 | @ substitution n | |
142 | @ <remainder of call stack is unchanged> | |
143 | @ Maximum of 7 substitutions. | |
144 | @ Call Stack: | |
145 | @ ACSII '\0' | |
146 | @ string word n | |
147 | @ ... | |
148 | @ string word 1 | |
149 | @ substitution n | |
150 | @ ... | |
151 | @ substitution 1 | |
152 | @ number of substitutions <-- TOS | |
153 | @ Return Stack: | |
154 | @ <empty> | |
155 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
156 | #include <heap.pvvs> | |
157 | #include <string.pvvs> | |
158 | NSSVTSSSN | Mark: 1000 (printf) | |
159 | ||
160 | @ Copy any substitution words into heap registers. | |
161 | NSTTSSSSSTN | JSR > 1000001 (spewreg) | |
162 | ||
163 | @ heap[8] will track the current substitution register. | |
164 | SSSTSSSN | PUSH 8 (ptr) | |
165 | SSSTN | PUSH 1 | |
166 | TTS | STORE | |
167 | ||
168 | @ If the stack contains an empty string (i.e. just an ASCII '\0'), the next | |
169 | @ word is a pointer we must use to load the string from the heap. | |
170 | @ Do the test this way so we can keep the code inline. | |
171 | SNS | DUP | |
172 | SSTTN | PUSH -1 | |
173 | TSSN | MULTIPLY | |
174 | NTTSSSSTSSSSSSSSSSTN | BMI > 00001000 00000001 | |
175 | SNN | DROP | |
176 | SNS | DUP | |
177 | NSTTSSSSSN | JSR > 100000 (strlen) | |
178 | NSTTTTTSN | JSR > 11110 (slurp) | |
179 | ||
180 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
181 | @ Initialization is now complete. | |
182 | @ Stack contains a printf-compatible, null-terminated string. | |
183 | @ heap[1]-heap[7] contain the substitutions, if any. | |
184 | @ heap[8] tracks which substitution is next. | |
185 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
186 | ||
187 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
188 | @ The rest of printf parses a string according to the following information. | |
189 | @ ASCII '\ ': | |
190 | @ ASCII '\ ': putchar '\ ' | |
191 | @ ASCII '%': putchar '%' | |
192 | @ ASCII 'n': putchar '\n' | |
193 | @ ASCII 't': putchar '\t' | |
194 | @ ASCII '%': | |
195 | @ ASCII 'c': (print character) | |
196 | @ ASCII 's': (print string) | |
197 | @ ASCII 'd': (print decimal digit) | |
198 | @ ASCII 'u': (print abs(integer), w/o sign) | |
199 | @ ASCII 'i': (print integer w/sign) | |
200 | @ ASCII '\0': | |
201 | @ cleanup and exit | |
202 | @ default: | |
203 | @ putchar | |
204 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
205 | ||
206 | @@@@@@@@@@@@@@@@@@@@ | |
207 | @ The next block tests the TOS against all possible level 1 branches (see above). | |
208 | @ If there is a match, execution jumps to the appropriate level 2 branch label. | |
209 | @ If no match is found, print the character and move on. | |
210 | @@@@@@@@@@@@@@@@@@@@ | |
211 | NSSVSSSSTSSSSSSSSSSTN | Mark: 00001000 00000001 | |
212 | @ TOS is an ASCII '\ '. Jump to process the possible level 2 branches. | |
213 | SNS | DUP | |
214 | SSSTSTTTSSN | PUSH ASCII slash | |
215 | TSST | SUBTRACT | |
216 | NTSSSSSTSSSSSSSSSTSN | BRZ > 00001000 00000010 | |
217 | @ TOS is an ASCII '%'. Jump to process the possible level 2 branches. | |
218 | SNS | DUP | |
219 | SSSTSSTSTN | PUSH ASCII '%' | |
220 | TSST | SUBTRACT | |
221 | NTSSSSSTSSSSSSSSSTTN | BRZ > 00001000 00000011 | |
222 | @ TOS is an ASCII "\0". Jump to clean-up-and-exit. | |
223 | SNS | DUP | |
224 | NTSSSSSTSSSSSSSSSSSN | BRZ > 00001000 00000000 | |
225 | @ TOS is a normal character. Print it and loop again. | |
226 | TNSS | PUTC | |
227 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
228 | ||
229 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
230 | @ Level 2 - ASCII '\ ' - Escapes | |
231 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
232 | ||
233 | @@@@@@@@@@@@@@@@@@@@ | |
234 | @ The level 1 match was an ASCII '\ '. | |
235 | @ Now look for level 2 matches that trigger a character substitution (n -> newline, etc). | |
236 | @ If no matches are found, print the character directly (e.g. "\%" -> '%') | |
237 | @ When finished, loop back to testing level 1 branches. | |
238 | @@@@@@@@@@@@@@@@@@@@ | |
239 | NSSVSSSSTSSSSSSSSSTSN | Mark: 00001000 00000010 | |
240 | SNN | DROP | |
241 | @ Check for ASCII '\n' | |
242 | SNS | DUP | |
243 | SSSTTSTTTSN | PUSH ASCII 'n' | |
244 | TSST | SUBTRACT | |
245 | NTSSSSSTSSSSSSSSTSSN | BRZ > 00001000 00000100 | |
246 | @ Check for ASCII '\t' | |
247 | SNS | DUP | |
248 | SSSTSSTN | PUSH ASCII '\t' | |
249 | TSST | SUBTRACT | |
250 | NTSSSSSTSSSSSSSSTSTN | BRZ > 00001000 00000101 | |
251 | @ No substitution necessary. Print literally. | |
252 | TNSS | PUTC | |
253 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
254 | ||
255 | @@@@@@@@@@@@@@@@@@@@ | |
256 | @ These are utility labels to output the appropriate non-printable ASCII character. | |
257 | @ After output, they loop back to testing level 1 branches. | |
258 | @@@@@@@@@@@@@@@@@@@@ | |
259 | ||
260 | @ Print a newline and loop for the next character. | |
261 | NSSVSSSSTSSSSSSSSTSSN | Mark: 00001000 00000100 | |
262 | SNN | DROP | |
263 | SSSTSTSN | PUSH ASCII '\n' | |
264 | TNSS | PUTC | |
265 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
266 | ||
267 | @ Print a horizontal tab and loop for the next character. | |
268 | NSSVSSSSTSSSSSSSSTSTN | Mark: 00001000 00000101 | |
269 | SNN | DROP | |
270 | SSSTSSTN | PUSH ASCII '\t' | |
271 | TNSS | PUTC | |
272 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
273 | ||
274 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
275 | @ Level 2 - ASCII '%' - Substitutions | |
276 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
277 | ||
278 | @@@@@@@@@@@@@@@@@@@@ | |
279 | @ The level 1 match was an ASCII '%'. | |
280 | @ Now look for level 2 matches that trigger a substitution. | |
281 | @ When finished, loop back to testing level 1 branches. | |
282 | @@@@@@@@@@@@@@@@@@@@ | |
283 | NSSVSSSSTSSSSSSSSSTTN | Mark: 00001000 00000011 | |
284 | SNN | DROP | |
285 | @ Check for ASCII 'c' - Print character | |
286 | SNS | DUP | |
287 | SSSTTSSSTTN | PUSH ASCII 'c' | |
288 | TSST | SUBTRACT | |
289 | NTSSSSSTSSSSSSSSTTSN | BRZ > 00001000 00000110 | |
290 | @ Check for ASCII 's' - Print string | |
291 | SNS | DUP | |
292 | SSSTTTSSTTN | PUSH ASCII 's' | |
293 | TSST | SUBTRACT | |
294 | NTSSSSSTSSSSSSSSTTTN | BRZ > 00001000 00000111 | |
295 | @ Check for ASCII 'd' - Print decimal digit | |
296 | SNS | DUP | |
297 | SSSTTSSTSSN | PUSH ASCII 'd' | |
298 | TSST | SUBTRACT | |
299 | NTSSSSSTSSSSSSSTSSSN | BRZ > 00001000 00001000 | |
300 | @ Check for ASCII 'u' - Print unsigned number | |
301 | SNS | DUP | |
302 | SSSTTTSTSTN | PUSH ASCII 'u' | |
303 | TSST | SUBTRACT | |
304 | NTSSSSSTSSSSSSSTSSTN | BRZ > 00001000 00001001 | |
305 | @ Check for ASCII 'i' - Print signed number | |
306 | SNS | DUP | |
307 | SSSTTSTSSTN | PUSH ASCII 'i' | |
308 | TSST | SUBTRACT | |
309 | NTSSSSSTSSSSSSSTSTSN | BRZ > 00001000 00001010 | |
310 | @ Unrecognized substitution specifier. | |
311 | @ For now, silently consume it and continue. | |
312 | @ Do not increment the substitution counter. | |
313 | @ TODO: Is this really what I want to do here? | |
314 | SNN | DROP | |
315 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
316 | ||
317 | ||
318 | @@@@@@@@@@@@@@@@@@@@ | |
319 | @ These are utility labels to call the appropriate type of output subroutine. | |
320 | @ After output, they increment the substition counter (heap[8]) | |
321 | @ and loop back to testing level 1 branches. | |
322 | @@@@@@@@@@@@@@@@@@@@ | |
323 | ||
324 | @ Print a character | |
325 | NSSVSSSSTSSSSSSSSTTSN | Mark: 00001000 00000110 | |
326 | SNN | DROP | |
327 | SSSTSSSN | PUSH 8 (ptr) | |
328 | TTT | LOAD | |
329 | TTT | LOAD | |
330 | TNSS | PUTC | |
331 | NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) | |
332 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
333 | @ Print a string | |
334 | NSSVSSSSTSSSSSSSSTTTN | Mark: 00001000 00000111 | |
335 | SNN | DROP | |
336 | SSSTSSSN | PUSH 8 (ptr) | |
337 | TTT | LOAD | |
338 | TTT | LOAD | |
339 | NSTTSSSTSTN | JSR > 1000101 (print string from heap) | |
340 | NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) | |
341 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
342 | @ Print a decimal digit | |
343 | NSSVSSSSTSSSSSSSTSSSN | Mark: 00001000 00001000 | |
344 | SNN | DROP | |
345 | SSSTSSSN | PUSH 8 (ptr) | |
346 | TTT | LOAD | |
347 | TTT | LOAD | |
348 | TNST | PUTDIGIT | |
349 | NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) | |
350 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
351 | @ Print an unsigned integer | |
352 | NSSVSSSSTSSSSSSSTSSTN | Mark: 00001000 00001001 | |
353 | SNN | DROP | |
354 | SSSTSSSN | PUSH 8 (ptr) | |
355 | TTT | LOAD | |
356 | TTT | LOAD | |
357 | NSTTSSSSTTN | JSR > 1000011 (print magnitude of number from stack) | |
358 | NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) | |
359 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
360 | @ Print a signed integer | |
361 | NSSVSSSSTSSSSSSSTSTSN | Mark: 00001000 00001010 | |
362 | SNN | DROP | |
363 | SSSTSSSN | PUSH 8 (ptr) | |
364 | TTT | LOAD | |
365 | TTT | LOAD | |
366 | NSTTSSTN | JSR > 1001 (print number from stack) | |
367 | NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8]) | |
368 | NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001 | |
369 | ||
370 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
371 | @ These are misc labels associated with the printf function. | |
372 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | |
373 | ||
374 | @ Increments heap[8]. Used after a substitution is complete. | |
375 | NSSVSSSSTSSSTSSSSSSSN | Mark: 00001000 10000000 (increment heap[8]) | |
376 | SSSTSSSN | PUSH 8 (ptr) | |
377 | TTT | LOAD | |
378 | SSSTN | PUSH 1 | |
379 | TSSS | ADD | |
380 | SSSTSSSN | PUSH 8 (ptr) | |
381 | SNT | SWAP | |
382 | TTS | STORE | |
383 | NTN | RTS | |
384 | ||
385 | @ Found an ASCII "\0" when processing the format string. Clean up and exit. | |
386 | NSSVSSSSTSSSSSSSSSSSN | Mark: 00001000 00000000 | |
387 | SNN | DROP | |
388 | NTN | RTS | |
389 | ||
8bed3ccd | 390 | #endif |