Commit | Line | Data |
---|---|---|
e5d2b9bf AT |
1 | # Overview # |
2 | ||
3 | This example uses `get_user_string` and `atoi` combined with `printf` to print | |
4 | a string containing two user inputs of type string and integer, both supplied | |
5 | by the user at runtime. | |
6 | ||
7 | # Code Commentary # | |
8 | ||
9 | Since 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 | ||
22 | We will begin by putting the null terminated ASCII string on the stack, | |
23 | followed by building up the substitutions. Put a string on the stack as | |
24 | introduced 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 | ||
28 | Prompt the user for a name. Since we call `printf`, we also `PUSH 0` since this | |
29 | is a static string. | |
30 | ||
31 | A"What is your name?\n" | |
32 | SSSSN | PUSH 0 | |
33 | NSTTSSSN | JSR > 1000 (printf) | |
34 | ||
35 | Call `get_user_string` from the stdlib. From its call stack we see that it | |
36 | wants the location of a buffer and the size of that buffer. Since we have the | |
37 | whole heap available, let us start at address `0x1000` and define the buffer to | |
38 | be `0x1000` words long. | |
39 | ||
40 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_size) | |
41 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_addr) | |
42 | NSTTSSSTSN | JSR > 100010 (get_user_string) | |
43 | ||
44 | Since users always cooperate, we now have a null terminated string containing | |
45 | the user name stored at `0x1000`. For now, just remember that address. | |
46 | ||
47 | Prompt 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 | ||
53 | Call `get_user_string` again, same as before, but this time at address `0x2000` | |
54 | so 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 | ||
60 | Now call `atoi` to convert the ASCII number typed by the user into an integer. | |
61 | Per the call stack documentation, first push the address of the start of the | |
62 | buffer (`0x2000`). | |
63 | ||
64 | SSSTSSSSSSSSSSSSSN | PUSH 0x2000 (buf_addr) | |
65 | NSTTTSSSSN | JSR > 110000 (atoi) | |
66 | ||
67 | We do not care about anything else that might be in that string, so we `DROP` | |
68 | the TOS which, per the return stack documentation, was a pointer to the last | |
69 | parsed character. All we keep is the converted integer, which we leave on the | |
70 | stack. | |
71 | ||
72 | SNN | DROP | |
73 | ||
74 | At 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 | |
76 | string, per the `printf` documentation, we push the address of our user name | |
77 | buffer (`0x1000`) back onto the stack. | |
78 | ||
79 | SSSTSSSSSSSSSSSSN | PUSH 0x1000 (buf_addr) | |
80 | ||
81 | With all the substitutions on the stack and in order, we `PUSH 2` which is the | |
82 | number of substitutions. | |
83 | ||
84 | SSSTSN | PUSH 2 | |
85 | ||
86 | The call stack is fully prepared. At the top we have the number of | |
87 | substitutions in the string followed by the two substitutions in order, first a | |
88 | pointer to a string and then an integer. Finally, we have the string itself, | |
89 | with a null terminator at the end. | |
90 | ||
21213140 | 91 | It is time to call `printf` and then exit. |
e5d2b9bf AT |
92 | |
93 | NSTTSSSN | JSR > 1000 (printf) | |
94 | NNN | Terminate program | |
95 | ||
21213140 AT |
96 | Do not forget to include the library files for any subroutines called. These |
97 | must be placed outside the path of normal execution flow. The end of the file | |
98 | is usually suitable. | |
e5d2b9bf AT |
99 | |
100 | #include <stdio.pvvs> | |
101 | #include <string.pvvs> | |
102 | #include <convert.pvvs> | |
103 | ||
21213140 AT |
104 | That's the whole program. The file `hello.pvvs` contains an uncommented version |
105 | of this exact source code and may be executed with a `make run` in this | |
106 | directory. | |
e5d2b9bf | 107 | |
4be3f03f AT |
108 | # Example Output # |
109 | ||
110 | vvhitespace/examples/basic-user-interaction % make run | |
111 | What is your name? | |
112 | Rolf | |
113 | How old age you? | |
114 | 42 | |
115 | Hello, Rolf! In a trusting world, 42 is older than I am. | |
116 |