Added a basic-user-interaction example using `printf`, `atoi` and `get_user_string`.
[vvhitespace] / examples / basic-user-interaction / README.md
CommitLineData
e5d2b9bf
AT
1# Overview #
2
3This example uses `get_user_string` and `atoi` combined with `printf` to print
4a string containing two user inputs of type string and integer, both supplied
5by the user at runtime.
6
7# Code Commentary #
8
9Since we're building up to calling `printf`, refer to its call stack in
10`stdio.pvvs`, reproduced below.
11
12 Call Stack:
13 ACSII '\0'
14 string word n
15 ...
16 string word 1
17 substitution n
18 ...
19 substitution 1
20 number of substitutions <-- TOS
21
22We will begin by putting the null terminated ASCII string on the stack,
23followed by building up the substitutions. Put a string on the stack as
24introduced in the "Hello, World" example. Note the two substitutions.
25
26 A"Hello, %s! In a trusting world, %u is older than I am.\n"
27
28Prompt the user for a name. Since we call `printf`, we also `PUSH 0` since this
29is a static string.
30
31 A"What is your name?\n"
32 SSSSN | PUSH 0
33 NSTTSSSN | JSR > 1000 (printf)
34
35Call `get_user_string` from the stdlib. From its call stack we see that it
36wants the location of a buffer and the size of that buffer. Since we have the
37whole heap available, let us start at address `0x1000` and define the buffer to
38be `0x1000` words long.
39
40 SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_size)
41 SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_addr)
42 NSTTSSSTSN | JSR > 100010 (get_user_string)
43
44Since users always cooperate, we now have a null terminated string containing
45the user name stored at `0x1000`. For now, just remember that address.
46
47Prompt the user for an age, calling `printf` just like we did earlier.
48
49 A"How old age you?\n"
50 SSSSN | PUSH 0
51 NSTTSSSN | JSR > 1000 (printf)
52
53Call `get_user_string` again, same as before, but this time at address `0x2000`
54so we don't overwrite the user's name.
55
56 SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_size)
57 SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (buf_addr)
58 NSTTSSSTSN | JSR > 100010 (get_user_string)
59
60Now call `atoi` to convert the ASCII number typed by the user into an integer.
61Per the call stack documentation, first push the address of the start of the
62buffer (`0x2000`).
63
64 SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (buf_addr)
65 NSTTTSSSSN | JSR > 110000 (atoi)
66
67We do not care about anything else that might be in that string, so we `DROP`
68the TOS which, per the return stack documentation, was a pointer to the last
69parsed character. All we keep is the converted integer, which we leave on the
70stack.
71
72 SNN | DROP
73
74At this point the stack contains our string and one of our two substitutions
75(age). Push the other substitution onto the stack. Since we are substituting a
76string, per the `printf` documentation, we push the address of our user name
77buffer (`0x1000`) back onto the stack.
78
79 SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_addr)
80
81With all the substitutions on the stack and in order, we `PUSH 2` which is the
82number of substitutions.
83
84 SSSTSN | PUSH 2
85
86The call stack is fully prepared. At the top we have the number of
87substitutions in the string followed by the two substitutions in order, first a
88pointer to a string and then an integer. Finally, we have the string itself,
89with a null terminator at the end.
90
91It is time to call `printf and then exit.
92
93 NSTTSSSN | JSR > 1000 (printf)
94 NNN | Terminate program
95
96Do not forget to include the library files for any subroutines called.
97
98 #include <stdio.pvvs>
99 #include <string.pvvs>
100 #include <convert.pvvs>
101
102The file `hello.pvvs` contains the program discussed and may be executed with a
103`make run` in this directory.
104