about summary refs log tree commit diff stats
path: root/html/002test.cc.html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-12-26 11:44:14 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-12-26 11:44:14 -0800
commit204dae921abff0c70e017215bb3c91fa6ca11aff (patch)
tree548788d18c881e3f6beb56133c1ca9d733ffa1e8 /html/002test.cc.html
parente5c11a5137d538b7713dd8708ca767c208824c06 (diff)
downloadmu-204dae921abff0c70e017215bb3c91fa6ca11aff.tar.gz
3710
Turns out we don't need to explicitly add anchors for each line. Vim's TOhtml
has magic for that out of the box.
Diffstat (limited to 'html/002test.cc.html')
-rw-r--r--html/002test.cc.html224
1 files changed, 112 insertions, 112 deletions
diff --git a/html/002test.cc.html b/html/002test.cc.html
index a5c12b22..454d5dc8 100644
--- a/html/002test.cc.html
+++ b/html/002test.cc.html
@@ -56,118 +56,118 @@ if ('onhashchange' in window) {
 </head>
 <body onload='JumpToLine();'>
 <pre id='vimCodeElement'>
-<a name="L1"></a><span id="L1" class="LineNr">  1 </span><span class="Comment">//: A simple test harness. To create new tests define functions starting with</span>
-<a name="L2"></a><span id="L2" class="LineNr">  2 </span><span class="Comment">//: 'test_'. To run all tests so defined, run:</span>
-<a name="L3"></a><span id="L3" class="LineNr">  3 </span><span class="Comment">//:   $ ./mu test</span>
-<a name="L4"></a><span id="L4" class="LineNr">  4 </span><span class="Comment">//:</span>
-<a name="L5"></a><span id="L5" class="LineNr">  5 </span><span class="Comment">//: Every layer should include tests, and can reach into previous layers.</span>
-<a name="L6"></a><span id="L6" class="LineNr">  6 </span><span class="Comment">//: However, it seems like a good idea never to reach into tests from previous</span>
-<a name="L7"></a><span id="L7" class="LineNr">  7 </span><span class="Comment">//: layers. Every test should be a contract that always passes as originally</span>
-<a name="L8"></a><span id="L8" class="LineNr">  8 </span><span class="Comment">//: written, regardless of any later layers. Avoid writing 'temporary' tests</span>
-<a name="L9"></a><span id="L9" class="LineNr">  9 </span><span class="Comment">//: that are only meant to work until some layer.</span>
-<a name="L10"></a><span id="L10" class="LineNr"> 10 </span>
-<a name="L11"></a><span id="L11" class="LineNr"> 11 </span><span class="Delimiter">:(before &quot;End Types&quot;)</span>
-<a name="L12"></a><span id="L12" class="LineNr"> 12 </span><span class="Normal">typedef</span> <span class="Normal">void</span> <span class="Delimiter">(</span>*test_fn<span class="Delimiter">)(</span><span class="Normal">void</span><span class="Delimiter">);</span>
-<a name="L13"></a><span id="L13" class="LineNr"> 13 </span><span class="Delimiter">:(before &quot;Globals&quot;)</span>
-<a name="L14"></a><span id="L14" class="LineNr"> 14 </span><span class="Comment">// move a global ahead into types that we can't generate an extern declaration for</span>
-<a name="L15"></a><span id="L15" class="LineNr"> 15 </span><span class="Normal">const</span> test_fn Tests[] = <span class="Delimiter">{</span>
-<a name="L16"></a><span id="L16" class="LineNr"> 16 </span><span class="PreProc">  #include </span><span class="Constant">&quot;test_list&quot;</span>  <span class="Comment">// auto-generated; see 'build' script</span>
-<a name="L17"></a><span id="L17" class="LineNr"> 17 </span><span class="Delimiter">};</span>
-<a name="L18"></a><span id="L18" class="LineNr"> 18 </span>
-<a name="L19"></a><span id="L19" class="LineNr"> 19 </span><span class="Delimiter">:(before &quot;End Globals&quot;)</span>
-<a name="L20"></a><span id="L20" class="LineNr"> 20 </span><span class="Normal">bool</span> Run_tests = <span class="Constant">false</span><span class="Delimiter">;</span>
-<a name="L21"></a><span id="L21" class="LineNr"> 21 </span><span class="Normal">bool</span> Passed = <span class="Constant">true</span><span class="Delimiter">;</span>  <span class="Comment">// set this to false inside any test to indicate failure</span>
-<a name="L22"></a><span id="L22" class="LineNr"> 22 </span><span class="Normal">long</span> Num_failures = <span class="Constant">0</span><span class="Delimiter">;</span>
-<a name="L23"></a><span id="L23" class="LineNr"> 23 </span>
-<a name="L24"></a><span id="L24" class="LineNr"> 24 </span><span class="Delimiter">:(before &quot;End Includes&quot;)</span>
-<a name="L25"></a><span id="L25" class="LineNr"> 25 </span><span class="PreProc">#define CHECK(X) \</span>
-<a name="L26"></a><span id="L26" class="LineNr"> 26 </span><span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; !(X)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
-<a name="L27"></a><span id="L27" class="LineNr"> 27 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): &quot;</span><span class="PreProc"> &lt;&lt; #X &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
-<a name="L28"></a><span id="L28" class="LineNr"> 28 </span><span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
-<a name="L29"></a><span id="L29" class="LineNr"> 29 </span><span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span>
-<a name="L30"></a><span id="L30" class="LineNr"> 30 </span><span class="PreProc">  </span><span class="Delimiter">}</span>
-<a name="L31"></a><span id="L31" class="LineNr"> 31 </span>
-<a name="L32"></a><span id="L32" class="LineNr"> 32 </span><span class="PreProc">#define CHECK_EQ(X</span><span class="Delimiter">,</span><span class="PreProc"> Y) \</span>
-<a name="L33"></a><span id="L33" class="LineNr"> 33 </span><span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; (X) != (Y)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
-<a name="L34"></a><span id="L34" class="LineNr"> 34 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): &quot;</span><span class="PreProc"> &lt;&lt; #X &lt;&lt; </span><span class="Constant">&quot; == &quot;</span><span class="PreProc"> &lt;&lt; #Y &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
-<a name="L35"></a><span id="L35" class="LineNr"> 35 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;  got &quot;</span><span class="PreProc"> &lt;&lt; (X) &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> BEWARE: multiple eval </span><span class="Comment">*/</span><span class="PreProc"> \</span>
-<a name="L36"></a><span id="L36" class="LineNr"> 36 </span><span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
-<a name="L37"></a><span id="L37" class="LineNr"> 37 </span><span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span>
-<a name="L38"></a><span id="L38" class="LineNr"> 38 </span><span class="PreProc">  </span><span class="Delimiter">}</span>
-<a name="L39"></a><span id="L39" class="LineNr"> 39 </span>
-<a name="L40"></a><span id="L40" class="LineNr"> 40 </span><span class="Delimiter">:(before &quot;End Setup&quot;)</span>
-<a name="L41"></a><span id="L41" class="LineNr"> 41 </span>Passed = <span class="Constant">true</span><span class="Delimiter">;</span>
-<a name="L42"></a><span id="L42" class="LineNr"> 42 </span>
-<a name="L43"></a><span id="L43" class="LineNr"> 43 </span><span class="Delimiter">:(before &quot;End Commandline Parsing&quot;)</span>
-<a name="L44"></a><span id="L44" class="LineNr"> 44 </span><span class="Normal">if</span> <span class="Delimiter">(</span>argc &gt; <span class="Constant">1</span> &amp;&amp; is_equal<span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;test&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span>
-<a name="L45"></a><span id="L45" class="LineNr"> 45 </span>  Run_tests = <span class="Constant">true</span><span class="Delimiter">;</span>  --argc<span class="Delimiter">;</span>  ++argv<span class="Delimiter">;</span>  <span class="Comment">// shift 'test' out of commandline args</span>
-<a name="L46"></a><span id="L46" class="LineNr"> 46 </span><span class="Delimiter">}</span>
-<a name="L47"></a><span id="L47" class="LineNr"> 47 </span>
-<a name="L48"></a><span id="L48" class="LineNr"> 48 </span><span class="Delimiter">:(before &quot;End Main&quot;)</span>
-<a name="L49"></a><span id="L49" class="LineNr"> 49 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L50"></a><span id="L50" class="LineNr"> 50 </span>  <span class="Comment">// Test Runs</span>
-<a name="L51"></a><span id="L51" class="LineNr"> 51 </span>  <span class="Comment">// we run some tests and then exit; assume no state need be maintained afterward</span>
-<a name="L52"></a><span id="L52" class="LineNr"> 52 </span>
-<a name="L53"></a><span id="L53" class="LineNr"> 53 </span>  <span class="Comment">// End Test Run Initialization</span>
-<a name="L54"></a><span id="L54" class="LineNr"> 54 </span>  <span class="Normal">time_t</span> t<span class="Delimiter">;</span>  time<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
-<a name="L55"></a><span id="L55" class="LineNr"> 55 </span>  cerr &lt;&lt; <span class="Constant">&quot;C tests: &quot;</span> &lt;&lt; ctime<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
-<a name="L56"></a><span id="L56" class="LineNr"> 56 </span>  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">size_t</span> i=<span class="Constant">0</span><span class="Delimiter">;</span>  i &lt; <span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/<span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">);</span>  ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L57"></a><span id="L57" class="LineNr"> 57 </span><span class="CommentedCode">//?     cerr &lt;&lt; i &lt;&lt; '\n';</span>
-<a name="L58"></a><span id="L58" class="LineNr"> 58 </span>    run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
-<a name="L59"></a><span id="L59" class="LineNr"> 59 </span>  <span class="Delimiter">}</span>
-<a name="L60"></a><span id="L60" class="LineNr"> 60 </span>  cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-<a name="L61"></a><span id="L61" class="LineNr"> 61 </span>  <span class="Comment">// End Tests</span>
-<a name="L62"></a><span id="L62" class="LineNr"> 62 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>Num_failures &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L63"></a><span id="L63" class="LineNr"> 63 </span>    cerr &lt;&lt; Num_failures &lt;&lt; <span class="Constant">&quot; failure&quot;</span>
-<a name="L64"></a><span id="L64" class="LineNr"> 64 </span>         &lt;&lt; <span class="Delimiter">(</span>Num_failures &gt; <span class="Constant">1</span> ? <span class="Constant">&quot;s&quot;</span> : <span class="Constant">&quot;&quot;</span><span class="Delimiter">)</span>
-<a name="L65"></a><span id="L65" class="LineNr"> 65 </span>         &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-<a name="L66"></a><span id="L66" class="LineNr"> 66 </span>    <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>
-<a name="L67"></a><span id="L67" class="LineNr"> 67 </span>  <span class="Delimiter">}</span>
-<a name="L68"></a><span id="L68" class="LineNr"> 68 </span>  <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
-<a name="L69"></a><span id="L69" class="LineNr"> 69 </span><span class="Delimiter">}</span>
-<a name="L70"></a><span id="L70" class="LineNr"> 70 </span>
-<a name="L71"></a><span id="L71" class="LineNr"> 71 </span><span class="Delimiter">:(code)</span>
-<a name="L72"></a><span id="L72" class="LineNr"> 72 </span><span class="Normal">void</span> run_test<span class="Delimiter">(</span><span class="Normal">size_t</span> i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L73"></a><span id="L73" class="LineNr"> 73 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>i &gt;= <span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/<span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span>
-<a name="L74"></a><span id="L74" class="LineNr"> 74 </span>    cerr &lt;&lt; <span class="Constant">&quot;no test &quot;</span> &lt;&lt; i &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-<a name="L75"></a><span id="L75" class="LineNr"> 75 </span>    <span class="Identifier">return</span><span class="Delimiter">;</span>
-<a name="L76"></a><span id="L76" class="LineNr"> 76 </span>  <span class="Delimiter">}</span>
-<a name="L77"></a><span id="L77" class="LineNr"> 77 </span>  setup<span class="Delimiter">();</span>
-<a name="L78"></a><span id="L78" class="LineNr"> 78 </span>  <span class="Comment">// End Test Setup</span>
-<a name="L79"></a><span id="L79" class="LineNr"> 79 </span>  <span class="Delimiter">(</span>*Tests[i]<span class="Delimiter">)();</span>
-<a name="L80"></a><span id="L80" class="LineNr"> 80 </span>  <span class="Comment">// End Test Teardown</span>
-<a name="L81"></a><span id="L81" class="LineNr"> 81 </span>  teardown<span class="Delimiter">();</span>
-<a name="L82"></a><span id="L82" class="LineNr"> 82 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr &lt;&lt; <span class="Constant">'.'</span><span class="Delimiter">;</span>
-<a name="L83"></a><span id="L83" class="LineNr"> 83 </span>  <span class="Normal">else</span> ++Num_failures<span class="Delimiter">;</span>
-<a name="L84"></a><span id="L84" class="LineNr"> 84 </span><span class="Delimiter">}</span>
-<a name="L85"></a><span id="L85" class="LineNr"> 85 </span>
-<a name="L86"></a><span id="L86" class="LineNr"> 86 </span><span class="Normal">bool</span> is_integer<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L87"></a><span id="L87" class="LineNr"> 87 </span>  <span class="Identifier">return</span> s<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789-&quot;</span><span class="Delimiter">)</span> == string::npos  <span class="Comment">// no other characters</span>
-<a name="L88"></a><span id="L88" class="LineNr"> 88 </span>      &amp;&amp; s<span class="Delimiter">.</span>find_first_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos  <span class="Comment">// at least one digit</span>
-<a name="L89"></a><span id="L89" class="LineNr"> 89 </span>      &amp;&amp; s<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">'-'</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">;</span>  <span class="Comment">// '-' only at first position</span>
-<a name="L90"></a><span id="L90" class="LineNr"> 90 </span><span class="Delimiter">}</span>
-<a name="L91"></a><span id="L91" class="LineNr"> 91 </span>
-<a name="L92"></a><span id="L92" class="LineNr"> 92 </span><span class="Normal">int</span> to_integer<span class="Delimiter">(</span>string n<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<a name="L93"></a><span id="L93" class="LineNr"> 93 </span>  <span class="Normal">char</span>* end = <span class="Constant">NULL</span><span class="Delimiter">;</span>
-<a name="L94"></a><span id="L94" class="LineNr"> 94 </span>  <span class="Comment">// safe because string.c_str() is guaranteed to be null-terminated</span>
-<a name="L95"></a><span id="L95" class="LineNr"> 95 </span>  <span class="Normal">int</span> result = strtoll<span class="Delimiter">(</span>n<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &amp;end<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">any base</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span>
-<a name="L96"></a><span id="L96" class="LineNr"> 96 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>*end != <span class="cSpecial">'\0'</span><span class="Delimiter">)</span> cerr &lt;&lt; <span class="Constant">&quot;tried to convert &quot;</span> &lt;&lt; n &lt;&lt; <span class="Constant">&quot; to number</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-<a name="L97"></a><span id="L97" class="LineNr"> 97 </span>  assert<span class="Delimiter">(</span>*end == <span class="cSpecial">'\0'</span><span class="Delimiter">);</span>
-<a name="L98"></a><span id="L98" class="LineNr"> 98 </span>  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
-<a name="L99"></a><span id="L99" class="LineNr"> 99 </span><span class="Delimiter">}</span>
-<a name="L100"></a><span id="L100" class="LineNr">100 </span>
-<a name="L101"></a><span id="L101" class="LineNr">101 </span><span class="Normal">void</span> test_is_integer<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-<a name="L102"></a><span id="L102" class="LineNr">102 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;1234&quot;</span><span class="Delimiter">));</span>
-<a name="L103"></a><span id="L103" class="LineNr">103 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-1&quot;</span><span class="Delimiter">));</span>
-<a name="L104"></a><span id="L104" class="LineNr">104 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;234.0&quot;</span><span class="Delimiter">));</span>
-<a name="L105"></a><span id="L105" class="LineNr">105 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-567&quot;</span><span class="Delimiter">));</span>
-<a name="L106"></a><span id="L106" class="LineNr">106 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;89-0&quot;</span><span class="Delimiter">));</span>
-<a name="L107"></a><span id="L107" class="LineNr">107 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-&quot;</span><span class="Delimiter">));</span>
-<a name="L108"></a><span id="L108" class="LineNr">108 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;1e3&quot;</span><span class="Delimiter">));</span>  <span class="Comment">// not supported</span>
-<a name="L109"></a><span id="L109" class="LineNr">109 </span><span class="Delimiter">}</span>
-<a name="L110"></a><span id="L110" class="LineNr">110 </span>
-<a name="L111"></a><span id="L111" class="LineNr">111 </span><span class="Delimiter">:(before &quot;End Includes&quot;)</span>
-<a name="L112"></a><span id="L112" class="LineNr">112 </span><span class="PreProc">#include </span><span class="Constant">&lt;stdlib.h&gt;</span>
+<span id="L1" class="LineNr">  1 </span><span class="Comment">//: A simple test harness. To create new tests define functions starting with</span>
+<span id="L2" class="LineNr">  2 </span><span class="Comment">//: 'test_'. To run all tests so defined, run:</span>
+<span id="L3" class="LineNr">  3 </span><span class="Comment">//:   $ ./mu test</span>
+<span id="L4" class="LineNr">  4 </span><span class="Comment">//:</span>
+<span id="L5" class="LineNr">  5 </span><span class="Comment">//: Every layer should include tests, and can reach into previous layers.</span>
+<span id="L6" class="LineNr">  6 </span><span class="Comment">//: However, it seems like a good idea never to reach into tests from previous</span>
+<span id="L7" class="LineNr">  7 </span><span class="Comment">//: layers. Every test should be a contract that always passes as originally</span>
+<span id="L8" class="LineNr">  8 </span><span class="Comment">//: written, regardless of any later layers. Avoid writing 'temporary' tests</span>
+<span id="L9" class="LineNr">  9 </span><span class="Comment">//: that are only meant to work until some layer.</span>
+<span id="L10" class="LineNr"> 10 </span>
+<span id="L11" class="LineNr"> 11 </span><span class="Delimiter">:(before &quot;End Types&quot;)</span>
+<span id="L12" class="LineNr"> 12 </span><span class="Normal">typedef</span> <span class="Normal">void</span> <span class="Delimiter">(</span>*test_fn<span class="Delimiter">)(</span><span class="Normal">void</span><span class="Delimiter">);</span>
+<span id="L13" class="LineNr"> 13 </span><span class="Delimiter">:(before &quot;Globals&quot;)</span>
+<span id="L14" class="LineNr"> 14 </span><span class="Comment">// move a global ahead into types that we can't generate an extern declaration for</span>
+<span id="L15" class="LineNr"> 15 </span><span class="Normal">const</span> test_fn Tests[] = <span class="Delimiter">{</span>
+<span id="L16" class="LineNr"> 16 </span><span class="PreProc">  #include </span><span class="Constant">&quot;test_list&quot;</span>  <span class="Comment">// auto-generated; see 'build' script</span>
+<span id="L17" class="LineNr"> 17 </span><span class="Delimiter">};</span>
+<span id="L18" class="LineNr"> 18 </span>
+<span id="L19" class="LineNr"> 19 </span><span class="Delimiter">:(before &quot;End Globals&quot;)</span>
+<span id="L20" class="LineNr"> 20 </span><span class="Normal">bool</span> Run_tests = <span class="Constant">false</span><span class="Delimiter">;</span>
+<span id="L21" class="LineNr"> 21 </span><span class="Normal">bool</span> Passed = <span class="Constant">true</span><span class="Delimiter">;</span>  <span class="Comment">// set this to false inside any test to indicate failure</span>
+<span id="L22" class="LineNr"> 22 </span><span class="Normal">long</span> Num_failures = <span class="Constant">0</span><span class="Delimiter">;</span>
+<span id="L23" class="LineNr"> 23 </span>
+<span id="L24" class="LineNr"> 24 </span><span class="Delimiter">:(before &quot;End Includes&quot;)</span>
+<span id="L25" class="LineNr"> 25 </span><span class="PreProc">#define CHECK(X) \</span>
+<span id="L26" class="LineNr"> 26 </span><span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; !(X)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
+<span id="L27" class="LineNr"> 27 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): &quot;</span><span class="PreProc"> &lt;&lt; #X &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
+<span id="L28" class="LineNr"> 28 </span><span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
+<span id="L29" class="LineNr"> 29 </span><span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span>
+<span id="L30" class="LineNr"> 30 </span><span class="PreProc">  </span><span class="Delimiter">}</span>
+<span id="L31" class="LineNr"> 31 </span>
+<span id="L32" class="LineNr"> 32 </span><span class="PreProc">#define CHECK_EQ(X</span><span class="Delimiter">,</span><span class="PreProc"> Y) \</span>
+<span id="L33" class="LineNr"> 33 </span><span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; (X) != (Y)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
+<span id="L34" class="LineNr"> 34 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): &quot;</span><span class="PreProc"> &lt;&lt; #X &lt;&lt; </span><span class="Constant">&quot; == &quot;</span><span class="PreProc"> &lt;&lt; #Y &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
+<span id="L35" class="LineNr"> 35 </span><span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;  got &quot;</span><span class="PreProc"> &lt;&lt; (X) &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> BEWARE: multiple eval </span><span class="Comment">*/</span><span class="PreProc"> \</span>
+<span id="L36" class="LineNr"> 36 </span><span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
+<span id="L37" class="LineNr"> 37 </span><span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span>
+<span id="L38" class="LineNr"> 38 </span><span class="PreProc">  </span><span class="Delimiter">}</span>
+<span id="L39" class="LineNr"> 39 </span>
+<span id="L40" class="LineNr"> 40 </span><span class="Delimiter">:(before &quot;End Setup&quot;)</span>
+<span id="L41" class="LineNr"> 41 </span>Passed = <span class="Constant">true</span><span class="Delimiter">;</span>
+<span id="L42" class="LineNr"> 42 </span>
+<span id="L43" class="LineNr"> 43 </span><span class="Delimiter">:(before &quot;End Commandline Parsing&quot;)</span>
+<span id="L44" class="LineNr"> 44 </span><span class="Normal">if</span> <span class="Delimiter">(</span>argc &gt; <span class="Constant">1</span> &amp;&amp; is_equal<span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;test&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span>
+<span id="L45" class="LineNr"> 45 </span>  Run_tests = <span class="Constant">true</span><span class="Delimiter">;</span>  --argc<span class="Delimiter">;</span>  ++argv<span class="Delimiter">;</span>  <span class="Comment">// shift 'test' out of commandline args</span>
+<span id="L46" class="LineNr"> 46 </span><span class="Delimiter">}</span>
+<span id="L47" class="LineNr"> 47 </span>
+<span id="L48" class="LineNr"> 48 </span><span class="Delimiter">:(before &quot;End Main&quot;)</span>
+<span id="L49" class="LineNr"> 49 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L50" class="LineNr"> 50 </span>  <span class="Comment">// Test Runs</span>
+<span id="L51" class="LineNr"> 51 </span>  <span class="Comment">// we run some tests and then exit; assume no state need be maintained afterward</span>
+<span id="L52" class="LineNr"> 52 </span>
+<span id="L53" class="LineNr"> 53 </span>  <span class="Comment">// End Test Run Initialization</span>
+<span id="L54" class="LineNr"> 54 </span>  <span class="Normal">time_t</span> t<span class="Delimiter">;</span>  time<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
+<span id="L55" class="LineNr"> 55 </span>  cerr &lt;&lt; <span class="Constant">&quot;C tests: &quot;</span> &lt;&lt; ctime<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
+<span id="L56" class="LineNr"> 56 </span>  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">size_t</span> i=<span class="Constant">0</span><span class="Delimiter">;</span>  i &lt; <span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/<span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">);</span>  ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L57" class="LineNr"> 57 </span><span class="CommentedCode">//?     cerr &lt;&lt; i &lt;&lt; '\n';</span>
+<span id="L58" class="LineNr"> 58 </span>    run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
+<span id="L59" class="LineNr"> 59 </span>  <span class="Delimiter">}</span>
+<span id="L60" class="LineNr"> 60 </span>  cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+<span id="L61" class="LineNr"> 61 </span>  <span class="Comment">// End Tests</span>
+<span id="L62" class="LineNr"> 62 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>Num_failures &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L63" class="LineNr"> 63 </span>    cerr &lt;&lt; Num_failures &lt;&lt; <span class="Constant">&quot; failure&quot;</span>
+<span id="L64" class="LineNr"> 64 </span>         &lt;&lt; <span class="Delimiter">(</span>Num_failures &gt; <span class="Constant">1</span> ? <span class="Constant">&quot;s&quot;</span> : <span class="Constant">&quot;&quot;</span><span class="Delimiter">)</span>
+<span id="L65" class="LineNr"> 65 </span>         &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+<span id="L66" class="LineNr"> 66 </span>    <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>
+<span id="L67" class="LineNr"> 67 </span>  <span class="Delimiter">}</span>
+<span id="L68" class="LineNr"> 68 </span>  <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
+<span id="L69" class="LineNr"> 69 </span><span class="Delimiter">}</span>
+<span id="L70" class="LineNr"> 70 </span>
+<span id="L71" class="LineNr"> 71 </span><span class="Delimiter">:(code)</span>
+<span id="L72" class="LineNr"> 72 </span><span class="Normal">void</span> run_test<span class="Delimiter">(</span><span class="Normal">size_t</span> i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L73" class="LineNr"> 73 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>i &gt;= <span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/<span class="Normal">sizeof</span><span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span>
+<span id="L74" class="LineNr"> 74 </span>    cerr &lt;&lt; <span class="Constant">&quot;no test &quot;</span> &lt;&lt; i &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+<span id="L75" class="LineNr"> 75 </span>    <span class="Identifier">return</span><span class="Delimiter">;</span>
+<span id="L76" class="LineNr"> 76 </span>  <span class="Delimiter">}</span>
+<span id="L77" class="LineNr"> 77 </span>  setup<span class="Delimiter">();</span>
+<span id="L78" class="LineNr"> 78 </span>  <span class="Comment">// End Test Setup</span>
+<span id="L79" class="LineNr"> 79 </span>  <span class="Delimiter">(</span>*Tests[i]<span class="Delimiter">)();</span>
+<span id="L80" class="LineNr"> 80 </span>  <span class="Comment">// End Test Teardown</span>
+<span id="L81" class="LineNr"> 81 </span>  teardown<span class="Delimiter">();</span>
+<span id="L82" class="LineNr"> 82 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr &lt;&lt; <span class="Constant">'.'</span><span class="Delimiter">;</span>
+<span id="L83" class="LineNr"> 83 </span>  <span class="Normal">else</span> ++Num_failures<span class="Delimiter">;</span>
+<span id="L84" class="LineNr"> 84 </span><span class="Delimiter">}</span>
+<span id="L85" class="LineNr"> 85 </span>
+<span id="L86" class="LineNr"> 86 </span><span class="Normal">bool</span> is_integer<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L87" class="LineNr"> 87 </span>  <span class="Identifier">return</span> s<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789-&quot;</span><span class="Delimiter">)</span> == string::npos  <span class="Comment">// no other characters</span>
+<span id="L88" class="LineNr"> 88 </span>      &amp;&amp; s<span class="Delimiter">.</span>find_first_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos  <span class="Comment">// at least one digit</span>
+<span id="L89" class="LineNr"> 89 </span>      &amp;&amp; s<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">'-'</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">;</span>  <span class="Comment">// '-' only at first position</span>
+<span id="L90" class="LineNr"> 90 </span><span class="Delimiter">}</span>
+<span id="L91" class="LineNr"> 91 </span>
+<span id="L92" class="LineNr"> 92 </span><span class="Normal">int</span> to_integer<span class="Delimiter">(</span>string n<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span id="L93" class="LineNr"> 93 </span>  <span class="Normal">char</span>* end = <span class="Constant">NULL</span><span class="Delimiter">;</span>
+<span id="L94" class="LineNr"> 94 </span>  <span class="Comment">// safe because string.c_str() is guaranteed to be null-terminated</span>
+<span id="L95" class="LineNr"> 95 </span>  <span class="Normal">int</span> result = strtoll<span class="Delimiter">(</span>n<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &amp;end<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">any base</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span>
+<span id="L96" class="LineNr"> 96 </span>  <span class="Normal">if</span> <span class="Delimiter">(</span>*end != <span class="cSpecial">'\0'</span><span class="Delimiter">)</span> cerr &lt;&lt; <span class="Constant">&quot;tried to convert &quot;</span> &lt;&lt; n &lt;&lt; <span class="Constant">&quot; to number</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+<span id="L97" class="LineNr"> 97 </span>  assert<span class="Delimiter">(</span>*end == <span class="cSpecial">'\0'</span><span class="Delimiter">);</span>
+<span id="L98" class="LineNr"> 98 </span>  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
+<span id="L99" class="LineNr"> 99 </span><span class="Delimiter">}</span>
+<span id="L100" class="LineNr">100 </span>
+<span id="L101" class="LineNr">101 </span><span class="Normal">void</span> test_is_integer<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+<span id="L102" class="LineNr">102 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;1234&quot;</span><span class="Delimiter">));</span>
+<span id="L103" class="LineNr">103 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-1&quot;</span><span class="Delimiter">));</span>
+<span id="L104" class="LineNr">104 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;234.0&quot;</span><span class="Delimiter">));</span>
+<span id="L105" class="LineNr">105 </span>  CHECK<span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-567&quot;</span><span class="Delimiter">));</span>
+<span id="L106" class="LineNr">106 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;89-0&quot;</span><span class="Delimiter">));</span>
+<span id="L107" class="LineNr">107 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;-&quot;</span><span class="Delimiter">));</span>
+<span id="L108" class="LineNr">108 </span>  CHECK<span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span><span class="Constant">&quot;1e3&quot;</span><span class="Delimiter">));</span>  <span class="Comment">// not supported</span>
+<span id="L109" class="LineNr">109 </span><span class="Delimiter">}</span>
+<span id="L110" class="LineNr">110 </span>
+<span id="L111" class="LineNr">111 </span><span class="Delimiter">:(before &quot;End Includes&quot;)</span>
+<span id="L112" class="LineNr">112 </span><span class="PreProc">#include </span><span class="Constant">&lt;stdlib.h&gt;</span>
 </pre>
 </body>
 </html>
esp # check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-trace-scan-skips-lines-until-found"/imm32 68/push 1/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # pop into *Trace-stream 8f 0/subop/pop 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # pop into *Trace-stream # . end c3/return test-trace-second-scan-starts-where-first-left-off: # push *Trace-stream ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream # setup # . *Trace-stream = _test-trace-stream b8/copy-to-eax _test-trace-stream/imm32 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Trace-stream/disp32 # copy eax to *Trace-stream # . clear-trace-stream() e8/call clear-trace-stream/disp32 # . trace("Ab") # . . push args 68/push "Ab"/imm32 # . . call e8/call trace/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # . eax = trace-scan("Ab") # . . push args 68/push "Ab"/imm32 # . . call e8/call trace-scan/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # second scan fails # . eax = trace-scan("Ab") # . . push args 68/push "Ab"/imm32 # . . call e8/call trace-scan/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-trace-second-scan-starts-where-first-left-off"/imm32 68/push 0/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # pop into *Trace-stream 8f 0/subop/pop 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # pop into *Trace-stream # . end c3/return test-trace-scan-failure-leaves-read-index-untouched: # push *Trace-stream ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream # setup # . *Trace-stream = _test-trace-stream b8/copy-to-eax _test-trace-stream/imm32 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Trace-stream/disp32 # copy eax to *Trace-stream # . clear-trace-stream() e8/call clear-trace-stream/disp32 # . trace("Ab") # . . push args 68/push "Ab"/imm32 # . . call e8/call trace/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # . check-ints-equal(_test-trace-stream->read, 0, msg) # . . push args 68/push "F - test-trace-second-scan-starts-where-first-left-off/precondition-failure"/imm32 68/push 0/imm32 b8/copy-to-eax _test-trace-stream/imm32 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # perform a failing scan # . eax = trace-scan("Ax") # . . push args 68/push "Ax"/imm32 # . . call e8/call trace-scan/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # no change in read index # . check-ints-equal(_test-trace-stream->read, 0, msg) # . . push args 68/push "F - test-trace-second-scan-starts-where-first-left-off"/imm32 68/push 0/imm32 b8/copy-to-eax _test-trace-stream/imm32 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # pop into *Trace-stream 8f 0/subop/pop 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # pop into *Trace-stream # . end c3/return next-line-matches?: # t : (addr stream byte), line : (addr array byte) -> result/eax : boolean # pseudocode: # while true: # if (currl >= maxl) break # if (currt >= maxt) return false # if (*currt != *currl) return false # ++currt # ++currl # return *currt == '\n' # # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx 52/push-edx 53/push-ebx 56/push-esi 57/push-edi # edx = line 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx # var currl/esi : (addr byte) = line->data # . esi = line/edx->data 8d/copy-address 1/mod/*+disp8 2/rm32/edx . . . 6/r32/esi 4/disp8 . # copy edx+4 to esi # var maxl/ecx : (addr byte) = &line->data[line->size] # . eax = line/edx->size 8b/copy 0/mod/indirect 2/rm32/edx . . 0/r32/eax . . # copy *edx to eax # . maxl = &line->data[line->size] 8d/copy-address 0/mod/indirect 4/rm32/sib 6/base/esi 0/index/eax . 1/r32/ecx . . # copy edx+eax to ecx # edi = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi # var ebx : (addr byte) = t->data 8d/copy-address 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 0xc/disp8 . # copy edi+12 to ebx # var maxt/edx : (addr byte) = &t->data[t->write] # . eax = t->write 8b/copy 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax # . maxt = &t->data[t->write] 8d/copy-address 0/mod/indirect 4/rm32/sib 3/base/ebx 0/index/eax . 2/r32/edx . . # copy ebx+eax to edx # var currt/edi : (addr byte) = &t->data[t->read] # . eax = t/edi->read 8b/copy 1/mod/*+disp8 7/rm32/edi . . 0/r32/eax 4/disp8 . # copy *(edi+4) to eax # . currt = &t->data[t->read] 8d/copy-address 0/mod/indirect 4/rm32/sib 3/base/ebx 0/index/eax . 7/r32/edi . . # copy ebx+eax to edi $next-line-matches?:loop: # if (currl >= maxl) break 39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi and ecx 73/jump-if-greater-or-equal-unsigned $next-line-matches?:break/disp8 # if (currt >= maxt) return false # . eax = false b8/copy-to-eax 0/imm32/false 39/compare 3/mod/direct 7/rm32/edi . . . 2/r32/edx . . # compare edi and edx 73/jump-if-greater-or-equal-unsigned $next-line-matches?:end/disp8 # if (*currt != *currl) return false 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 31/xor 3/mod/direct 3/rm32/eax . . . 3/r32/eax . . # clear ebx # . eax : byte = *currt 8a/copy-byte 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax # . ebx : byte = *currl 8a/copy-byte 0/mod/indirect 6/rm32/esi . . 3/r32/ebx . . # copy *esi to ebx # . eax >= ebx 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx # . eax = false b8/copy-to-eax 0/imm32/false 75/jump-if-not-equal $next-line-matches?:end/disp8 # ++currt 47/increment-edi # ++currl 46/increment-esi eb/jump $next-line-matches?:loop/disp8 $next-line-matches?:break: # return *currt == '\n' 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax # . eax : byte = *currt 8a/copy-byte 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax 3d/compare-eax-and 0xa/imm32/newline # . eax = false b8/copy-to-eax 1/imm32/true 74/jump-if-equal $next-line-matches?:end/disp8 b8/copy-to-eax 0/imm32/true $next-line-matches?:end: # . restore registers 5f/pop-to-edi 5e/pop-to-esi 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-next-line-matches?-no-match-1: # next line of "ABABA" does not match "blah blah" # . eax = next-line-matches?(_test-stream-line-ABABA, "blah blah") # . . push args 68/push "blah blah"/imm32 68/push _test-stream-line-ABABA/imm32 # . . call e8/call next-line-matches?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-next-line-matches?-no-match-1"/imm32 68/push 0/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-next-line-matches?-no-match-2: # next line of "ABABA" does not match "" # . eax = next-line-matches?(_test-stream-line-ABABA, "") # . . push args 68/push ""/imm32 68/push _test-stream-line-ABABA/imm32 # . . call e8/call next-line-matches?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-next-line-matches?-no-match-2"/imm32 68/push 0/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-next-line-matches?-no-match-3: # next line of "ABABA" does not match "AA" # . eax = next-line-matches?(_test-stream-line-ABABA, "AA") # . . push args 68/push "AA"/imm32 68/push _test-stream-line-ABABA/imm32 # . . call e8/call next-line-matches?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . check-ints-equal(eax, 0, msg) # . . push args 68/push "F - test-next-line-matches?-no-match-3"/imm32 68/push 0/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-next-line-matches?-match: # next line of "ABABA" matches "ABABA" # . eax = next-line-matches?(_test-stream-line-ABABA, "ABABA") # . . push args 68/push "ABABA"/imm32 68/push _test-stream-line-ABABA/imm32 # . . call e8/call next-line-matches?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . check-ints-equal(eax, 1, msg) # . . push args 68/push "F - test-next-line-matches?-match"/imm32 68/push 1/imm32 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return # move t->read to _after_ next newline skip-next-line: # t : (addr stream byte) # pseudocode: # max = &t->data[t->write] # i = t->read # curr = &t->data[t->read] # while true # if (curr >= max) break # ++i # if (*curr == '\n') break # ++curr # t->read = i # # . 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 52/push-edx 53/push-ebx # ecx = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = t->data 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 0xc/disp8 . # copy ecx+12 to edx # eax = t->write 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax # var max/ebx : (addr byte) = &t->data[t->write] 8d/copy-address 0/mod/indirect 4/rm32/sib 2/base/edx 0/index/eax . 3/r32/ebx . . # copy edx+eax to ebx # eax = t->read 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to edx # var curr/ecx : (addr byte) = &t->data[t->read] 8d/copy-address 0/mod/indirect 4/rm32/sib 2/base/edx 0/index/eax . 1/r32/ecx . . # copy edx+eax to ecx # var i/edx : int = t->read 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx $skip-next-line:loop: # if (curr >= max) break 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx and ebx 73/jump-if-greater-or-equal-unsigned $skip-next-line:end/disp8 # ++i 42/increment-edx # if (*curr == '\n') break 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax 3d/compare-eax-and 0a/imm32/newline 74/jump-if-equal $skip-next-line:end/disp8 # ++curr 41/increment-ecx # loop eb/jump $skip-next-line:loop/disp8 $skip-next-line:end: # ecx = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # t->read = i 89/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy edx to *(ecx+4) # . restore registers 5b/pop-to-ebx 5a/pop-to-edx 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-skip-next-line-empty: # skipping next line in empty stream leaves read pointer at 0 # . skip-next-line(_test-stream-empty) # . . push args 68/push _test-stream-empty/imm32 # . . call e8/call skip-next-line/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # . check-ints-equal(_test-stream-empty->read, 0, msg) # . . push args 68/push "F - test-skip-next-line-empty"/imm32 68/push 0/imm32 b8/copy-to-eax _test-stream-empty/imm32 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return test-skip-next-line-filled: # skipping next line increments read pointer by length of line + 1 (for newline) # . skip-next-line(_test-stream-filled) # . . push args 68/push _test-stream-filled/imm32 # . . call e8/call skip-next-line/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # . check-ints-equal(_test-stream-filled->read, 5, msg) # . . push args 68/push "F - test-skip-next-line-filled"/imm32 68/push 5/imm32 b8/copy-to-eax _test-stream-filled/imm32 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax 50/push-eax # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp c3/return clear-trace-stream: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # clear-stream(*Trace-stream) # . . push args ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream # . . call e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp $clear-trace-stream:end: # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return # - helpers # 3-argument variant of _append _append-3: # out : (addr byte), outend : (addr byte), s : (addr array byte) -> num_bytes_appended/eax # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx # eax = _append-4(out, outend, &s->data[0], &s->data[s->length]) # . . push &s->data[s->length] 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 51/push-ecx # . . push &s->data[0] 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx 51/push-ecx # . . push outend ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . push out ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call _append-4/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $_append-3:end: # . restore registers 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return # 4-argument variant of _append _append-4: # out : (addr byte), outend : (addr byte), in : (addr byte), inend : (addr byte) -> num_bytes_appended/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx 52/push-edx 53/push-ebx 56/push-esi 57/push-edi # num_bytes_appended = 0 b8/copy-to-eax 0/imm32 # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi # edx = outend 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx # esi = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0x10/disp8 . # copy *(ebp+16) to esi # ecx = inend 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x14/disp8 . # copy *(ebp+20) to ecx $_append-4:loop: # if (in >= inend) break 39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi with ecx 73/jump-if-greater-or-equal-unsigned $_append-4:end/disp8 # if (out >= outend) abort # just to catch test failures fast 39/compare 3/mod/direct 7/rm32/edi . . . 2/r32/edx . . # compare edi with edx 73/jump-if-greater-or-equal-unsigned $_append-4:abort/disp8 # *out = *in 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 3/r32/BL . . # copy byte at *esi to BL 88/copy-byte 0/mod/indirect 7/rm32/edi . . . 3/r32/BL . . # copy byte at BL to *edi # ++num_bytes_appended 40/increment-eax # ++in 46/increment-esi # ++out 47/increment-edi eb/jump $_append-4:loop/disp8 $_append-4:end: # . restore registers 5f/pop-to-edi 5e/pop-to-esi 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return $_append-4:abort: # . _write(2/stderr, error) # . . push args 68/push "stream overflow\n"/imm32 68/push 2/imm32/stderr # . . call e8/call _write/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . syscall(exit, 1) bb/copy-to-ebx 1/imm32 b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 # never gets here == data _test-stream-line-ABABA: # (stream byte) # write 8/imm32 # read 0/imm32 # length 8/imm32 # data 41 42 41 42 41 0a 00 00 # 8 bytes _test-stream-empty: # (stream byte) # write 0/imm32 # read 0/imm32 # length 8/imm32 # data 00 00 00 00 00 00 00 00 # 8 bytes _test-stream-filled: # (stream byte) # write 8/imm32 # read 0/imm32 # length 8/imm32 # data 41 41 41 41 0a 41 41 41 # 8 bytes # . . vim:nowrap:textwidth=0