Added bitwise AND subroutine to VVS stdlib.
[vvhitespace] / stdlib / stdio.pvvs
CommitLineData
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 18NSSVTSSSTSSN | Mark: 1000100 (print string from stack)
32c440bf 19SNS | DUP
b8b65c17 20NTSSTSSSTSSSSSSSSSTN | BRZ > 01000100 00000001
32c440bf 21TNSS | Print character
b8b65c17
AT
22NSNTSSSTSSN | JMP > 1000100
23NSSVSTSSSTSSSSSSSSSTN | Mark: 01000100 00000001
32c440bf
AT
24SNN | DROP
25NTN | 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 37NSSVTSSSTSTN | Mark: 1000101 (print string from heap)
32c440bf
AT
38SNS | DUP
39TTT | LOAD
40SNS | DUP
b8b65c17 41NTSSTSSSTSTSSSSSSSTN | BRZ > 01000101 00000001
32c440bf
AT
42TNSS | Print character
43SSSTN | Push +1
44TSSS | ADD
b8b65c17
AT
45NSNTSSSTSTN | JMP > 1000101
46NSSVSTSSSTSTSSSSSSSTN | Mark: 01000101 00000001
32c440bf
AT
47SNN | DROP
48SNN | DROP
49NTN | 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 62NSSVTSSTN | Mark: 1001 (print number from stack)
3625ff3a 63SNS | DUP
ae1f85a1
AT
64NSTTSSSSTSN | JSR > 1000010
65NSTTSSSSTTN | JSR > 1000011
3625ff3a
AT
66NTN | 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
78NSSVTSSSSTSN | Mark: 1000010 (print sign of number from stack)
79NTTSTSSSSTSSSSSSSSTN | BMI > 01000010 00000001
3625ff3a 80SSSTSTSTTN | PUSH ASCII '+'
ae1f85a1
AT
81NSNSTSSSSTSSSSSSSTSN | JMP > 01000010 00000010
82NSSVSTSSSSTSSSSSSSSTN | Mark: 01000010 00000001
3625ff3a 83SSSTSTTSTN | PUSH ASCII '-'
ae1f85a1 84NSSVSTSSSSTSSSSSSSTSN | Mark: 01000010 00000010
3625ff3a
AT
85TNSS | PUTC
86NTN | 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 99NSSVTSSSSTTN | Mark: 1000011 (print magnitude of number from stack)
3625ff3a
AT
100NSTTSSSTN | JSR > 10001 (absolute value)
101
102SSSSN | PUSH ASCII '\0'
103SNT | SWAP
104
105@ Pick off one digit on each pass through this loop.
ae1f85a1 106NSSVSTSSSSTTSSSSSSSSN | Mark: 01000011 00000000
3625ff3a
AT
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
ae1f85a1
AT
120NTSSTSSSSTTSSSSSSSTN | BRZ > 01000011 00000001
121NSNSTSSSSTTSSSSSSSSN | JMP > 01000011 00000000
3625ff3a
AT
122
123@ Print the string we have built on the stack.
ae1f85a1 124NSSVSTSSSSTTSSSSSSSTN | Mark: 01000011 00000001
3625ff3a 125SNN | DROP
45abb94e 126NSTTSSSTSSN | JSR > 1000100 (print string from stack)
3625ff3a
AT
127NTN | 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>
158NSSVTSSSN | Mark: 1000 (printf)
159
160@ Copy any substitution words into heap registers.
161NSTTSSSSSTN | JSR > 1000001 (spewreg)
162
163@ heap[8] will track the current substitution register.
164SSSTSSSN | PUSH 8 (ptr)
165SSSTN | PUSH 1
166TTS | 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.
171SNS | DUP
172SSTTN | PUSH -1
173TSSN | MULTIPLY
174NTTSSSSTSSSSSSSSSSTN | BMI > 00001000 00000001
175SNN | DROP
176SNS | DUP
177NSTTSSSSSN | JSR > 100000 (strlen)
178NSTTTTTSN | 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@@@@@@@@@@@@@@@@@@@@
211NSSVSSSSTSSSSSSSSSSTN | Mark: 00001000 00000001
212@ TOS is an ASCII '\ '. Jump to process the possible level 2 branches.
213SNS | DUP
214SSSTSTTTSSN | PUSH ASCII slash
215TSST | SUBTRACT
216NTSSSSSTSSSSSSSSSTSN | BRZ > 00001000 00000010
217@ TOS is an ASCII '%'. Jump to process the possible level 2 branches.
218SNS | DUP
219SSSTSSTSTN | PUSH ASCII '%'
220TSST | SUBTRACT
221NTSSSSSTSSSSSSSSSTTN | BRZ > 00001000 00000011
222@ TOS is an ASCII "\0". Jump to clean-up-and-exit.
223SNS | DUP
224NTSSSSSTSSSSSSSSSSSN | BRZ > 00001000 00000000
225@ TOS is a normal character. Print it and loop again.
226TNSS | PUTC
227NSNSSSSTSSSSSSSSSSTN | 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@@@@@@@@@@@@@@@@@@@@
239NSSVSSSSTSSSSSSSSSTSN | Mark: 00001000 00000010
240SNN | DROP
241@ Check for ASCII '\n'
242SNS | DUP
243SSSTTSTTTSN | PUSH ASCII 'n'
244TSST | SUBTRACT
245NTSSSSSTSSSSSSSSTSSN | BRZ > 00001000 00000100
246@ Check for ASCII '\t'
247SNS | DUP
248SSSTSSTN | PUSH ASCII '\t'
249TSST | SUBTRACT
250NTSSSSSTSSSSSSSSTSTN | BRZ > 00001000 00000101
251@ No substitution necessary. Print literally.
252TNSS | PUTC
253NSNSSSSTSSSSSSSSSSTN | 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.
261NSSVSSSSTSSSSSSSSTSSN | Mark: 00001000 00000100
262SNN | DROP
263SSSTSTSN | PUSH ASCII '\n'
264TNSS | PUTC
265NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001
266
267@ Print a horizontal tab and loop for the next character.
268NSSVSSSSTSSSSSSSSTSTN | Mark: 00001000 00000101
269SNN | DROP
270SSSTSSTN | PUSH ASCII '\t'
271TNSS | PUTC
272NSNSSSSTSSSSSSSSSSTN | 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@@@@@@@@@@@@@@@@@@@@
283NSSVSSSSTSSSSSSSSSTTN | Mark: 00001000 00000011
284SNN | DROP
285@ Check for ASCII 'c' - Print character
286SNS | DUP
287SSSTTSSSTTN | PUSH ASCII 'c'
288TSST | SUBTRACT
289NTSSSSSTSSSSSSSSTTSN | BRZ > 00001000 00000110
290@ Check for ASCII 's' - Print string
291SNS | DUP
292SSSTTTSSTTN | PUSH ASCII 's'
293TSST | SUBTRACT
294NTSSSSSTSSSSSSSSTTTN | BRZ > 00001000 00000111
295@ Check for ASCII 'd' - Print decimal digit
296SNS | DUP
297SSSTTSSTSSN | PUSH ASCII 'd'
298TSST | SUBTRACT
299NTSSSSSTSSSSSSSTSSSN | BRZ > 00001000 00001000
300@ Check for ASCII 'u' - Print unsigned number
301SNS | DUP
302SSSTTTSTSTN | PUSH ASCII 'u'
303TSST | SUBTRACT
304NTSSSSSTSSSSSSSTSSTN | BRZ > 00001000 00001001
305@ Check for ASCII 'i' - Print signed number
306SNS | DUP
307SSSTTSTSSTN | PUSH ASCII 'i'
308TSST | SUBTRACT
309NTSSSSSTSSSSSSSTSTSN | 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?
314SNN | DROP
315NSNSSSSTSSSSSSSSSSTN | 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
325NSSVSSSSTSSSSSSSSTTSN | Mark: 00001000 00000110
326SNN | DROP
327SSSTSSSN | PUSH 8 (ptr)
328TTT | LOAD
329TTT | LOAD
330TNSS | PUTC
331NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8])
332NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001
333@ Print a string
334NSSVSSSSTSSSSSSSSTTTN | Mark: 00001000 00000111
335SNN | DROP
336SSSTSSSN | PUSH 8 (ptr)
337TTT | LOAD
338TTT | LOAD
339NSTTSSSTSTN | JSR > 1000101 (print string from heap)
340NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8])
341NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001
342@ Print a decimal digit
343NSSVSSSSTSSSSSSSTSSSN | Mark: 00001000 00001000
344SNN | DROP
345SSSTSSSN | PUSH 8 (ptr)
346TTT | LOAD
347TTT | LOAD
348TNST | PUTDIGIT
349NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8])
350NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001
351@ Print an unsigned integer
352NSSVSSSSTSSSSSSSTSSTN | Mark: 00001000 00001001
353SNN | DROP
354SSSTSSSN | PUSH 8 (ptr)
355TTT | LOAD
356TTT | LOAD
357NSTTSSSSTTN | JSR > 1000011 (print magnitude of number from stack)
358NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8])
359NSNSSSSTSSSSSSSSSSTN | JMP > 00001000 00000001
360@ Print a signed integer
361NSSVSSSSTSSSSSSSTSTSN | Mark: 00001000 00001010
362SNN | DROP
363SSSTSSSN | PUSH 8 (ptr)
364TTT | LOAD
365TTT | LOAD
366NSTTSSTN | JSR > 1001 (print number from stack)
367NSTSSSSTSSSTSSSSSSSN | JSR > 00001000 10000000 (increment heap[8])
368NSNSSSSTSSSSSSSSSSTN | 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.
375NSSVSSSSTSSSTSSSSSSSN | Mark: 00001000 10000000 (increment heap[8])
376SSSTSSSN | PUSH 8 (ptr)
377TTT | LOAD
378SSSTN | PUSH 1
379TSSS | ADD
380SSSTSSSN | PUSH 8 (ptr)
381SNT | SWAP
382TTS | STORE
383NTN | RTS
384
385@ Found an ASCII "\0" when processing the format string. Clean up and exit.
386NSSVSSSSTSSSSSSSSSSSN | Mark: 00001000 00000000
387SNN | DROP
388NTN | RTS
389
8bed3ccd 390#endif