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