about summary refs log tree commit diff stats
path: root/125write-stream-data.subx
blob: 0cc8ba6551d1920b3fa62cc01ab97e5972bb97a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
== code
#   instruction                     effective address                                                   register    displacement    immediate
# . op          subop               mod             rm32          base        index         scale       r32
# . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes

# write an entire stream's contents to a buffered-file
# ways to do this:
#   - construct a 'maximal slice' and pass it to write-slice-buffered
#   - flush the buffered-file and pass the stream directly to its fd (disabling buffering)
# we'll go with the first way for now
write-stream-data:  # f: (addr buffered-file), s: (addr stream byte)
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    # . save registers
    50/push-eax
    51/push-ecx
    56/push-esi
    # esi = s
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
    # var slice/ecx: slice = {s->data, &s->data[s->write]}
    # . push &s->data[s->write]
    8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
    8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
    50/push-eax
    # . push s->data
    8d/copy-address                 1/mod/*+disp8   6/rm32/esi    .           .             .           0/r32/eax   0xc/disp8       .                 # copy esi+12 to eax
    50/push-eax
    # . ecx = esp
    89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
    # write-slice-buffered(f, slice)
    # . . push args
    51/push-ecx
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-slice-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
$write-stream-data:end:
    # . restore locals
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # . restore registers
    5e/pop-to-esi
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

test-write-stream-data:
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    # setup
    # . clear-stream(_test-output-stream)
    # . . push args
    68/push  _test-output-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # . clear-stream($_test-output-buffered-file->buffer)
    # . . push args
    68/push  $_test-output-buffered-file->buffer/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # . clear-stream(_test-input-stream)
    # . . push args
    68/push  _test-input-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # initialize input
    # . write(_test-input-stream, "abcd")
    # . . push args
    68/push  "abcd"/imm32
    68/push  _test-input-stream/imm32
    # . . call
    e8/call  write/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # write-stream-data(_test-output-buffered-file, _test-input-stream)
    # . . push args
    68/push  _test-input-stream/imm32
    68/push  _test-output-buffered-file/imm32
    # . . call
    e8/call  write-stream-data/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # check that the write happened as expected
    # . flush(_test-output-buffered-file)
    # . . push args
    68/push  _test-output-buffered-file/imm32
    # . . call
    e8/call  flush/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # . check-stream-equal(_test-output-stream, "abcd", msg)
    # . . push args
    68/push  "F - test-write-stream-data"/imm32
    68/push  "abcd"/imm32
    68/push  _test-output-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return
n class="p">; } .muControl { color: #c0a020; } .muRecipe { color: #ff8700; } --> </style> <script type='text/javascript'> <!-- --> </script> </head> <body> <pre id='vimCodeElement'> <span class="Comment"># Wrappers around interaction primitives that take a potentially fake object</span> <span class="Comment"># and are thus easier to test.</span> exclusive-container event [ text:character keycode:number <span class="Comment"># keys on keyboard without a unicode representation</span> touch:touch-event <span class="Comment"># mouse, track ball, etc.</span> <span class="Comment"># update the assume-console handler if you add more variants</span> ] container touch-event [ type:number row:number column:number ] container console [ index:number data:address:array:event ] <span class="muRecipe">recipe</span> new-fake-console [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span> result:address:console<span class="Special"> &lt;- </span>new console:type buf:address:address:array:character<span class="Special"> &lt;- </span>get-address result:address:console/deref, data:offset <span class="CommentedCode">#? $start-tracing #? 1</span> buf:address:address:array:character/deref<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="CommentedCode">#? $stop-tracing #? 1</span> idx:address:number<span class="Special"> &lt;- </span>get-address result:address:console/deref, index:offset idx:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span> <span class="muControl">reply</span> result:address:console ] <span class="muRecipe">recipe</span> read-event [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span> x:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> x:address:console idx:address:number<span class="Special"> &lt;- </span>get-address x:address:console/deref, index:offset buf:address:array:event<span class="Special"> &lt;- </span>get x:address:console/deref, data:offset <span class="Delimiter">{</span> max:number<span class="Special"> &lt;- </span>length buf:address:array:event/deref done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx:address:number/deref, max:number <span class="muControl">break-unless</span> done?:boolean dummy:address:event<span class="Special"> &lt;- </span>new event:type <span class="muControl">reply</span> dummy:address:event/deref, x:address:console/same-as-ingredient:0, <span class="Constant">1:literal/found</span>, <span class="Constant">1:literal/quit</span> <span class="Delimiter">}</span> result:event<span class="Special"> &lt;- </span>index buf:address:array:event/deref, idx:address:number/deref idx:address:number/deref<span class="Special"> &lt;- </span>add idx:address:number/deref, <span class="Constant">1:literal</span> <span class="muControl">reply</span> result:event, x:address:console/same-as-ingredient:0, <span class="Constant">1:literal/found</span>, <span class="Constant">0:literal/quit</span> <span class="Delimiter">}</span> <span class="Comment"># real event source is infrequent; avoid polling it too much</span> switch result:event, found?:boolean<span class="Special"> &lt;- </span>check-for-interaction <span class="muControl">reply</span> result:event, x:address:console/same-as-ingredient:0, found?:boolean, <span class="Constant">0:literal/quit</span> ] <span class="Comment"># variant of read-event for just keyboard events. Discards everything that</span> <span class="Comment"># isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get</span> <span class="Comment"># newlines, tabs, ctrl-d..</span> <span class="muRecipe">recipe</span> read-key [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span> <span class="CommentedCode">#? $print default-space:address:array:location #? 1</span> <span class="CommentedCode">#? $exit #? 1</span> <span class="CommentedCode">#? $start-tracing #? 1</span> console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> x:event, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console:address <span class="CommentedCode">#? $print [aaa 1] #? 1</span> <span class="muControl">reply-if</span> quit?:boolean, <span class="Constant">0:literal</span>, console:address/same-as-ingredient:0, found?:boolean, quit?:boolean <span class="CommentedCode">#? $print [aaa 2] #? 1</span> <span class="muControl">reply-unless</span> found?:boolean, <span class="Constant">0:literal</span>, console:address/same-as-ingredient:0, found?:boolean, quit?:boolean <span class="CommentedCode">#? $print [aaa 3] #? 1</span> c:address:character<span class="Special"> &lt;- </span>maybe-convert x:event, text:variant <span class="muControl">reply-unless</span> c:address:character, <span class="Constant">0:literal</span>, console:address/same-as-ingredient:0, <span class="Constant">0:literal/found</span>, <span class="Constant">0:literal/quit</span> <span class="CommentedCode">#? $print [aaa 4] #? 1</span> <span class="muControl">reply</span> c:address:character/deref, console:address/same-as-ingredient:0, <span class="Constant">1:literal/found</span>, <span class="Constant">0:literal/quit</span> ] <span class="muRecipe">recipe</span> send-keys-to-channel [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span> console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> c:character, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-key console:address <span class="muControl">loop-unless</span> found?:boolean <span class="muControl">break-if</span> quit?:boolean assert c:character, <span class="Constant">[invalid event, expected text]</span> print-character screen:address, c:character chan:address:channel<span class="Special"> &lt;- </span>write chan:address:channel, c:character <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muRecipe">recipe</span> wait-for-event [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span> console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> _, console:address, found?:boolean<span class="Special"> &lt;- </span>read-event console:address <span class="muControl">loop-unless</span> found?:boolean <span class="Delimiter">}</span> ] </pre> </body> </html> <!-- vim: set foldmethod=manual : -->