about summary refs log tree commit diff stats
path: root/html/072scenario_screen.cc.html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-25 22:27:19 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-25 22:27:19 -0700
commitc5ffb6e1cc9c5ff880d037c53b8ebc8562be0008 (patch)
tree2d05d987ec3c81bfbb0c1f598966d9d1b16e9b1f /html/072scenario_screen.cc.html
parentb2757892d553352feb59d70b1e7241ccdafa6905 (diff)
downloadmu-c5ffb6e1cc9c5ff880d037c53b8ebc8562be0008.tar.gz
1459
Diffstat (limited to 'html/072scenario_screen.cc.html')
-rw-r--r--html/072scenario_screen.cc.html169
1 files changed, 122 insertions, 47 deletions
diff --git a/html/072scenario_screen.cc.html b/html/072scenario_screen.cc.html
index 79cc6044..18b70868 100644
--- a/html/072scenario_screen.cc.html
+++ b/html/072scenario_screen.cc.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>~/Desktop/s/mu/072scenario_screen.cc</title>
+<title>072scenario_screen.cc</title>
 <meta name="Generator" content="Vim/7.4">
 <meta name="plugin-version" content="vim7.4_v1">
 <meta name="syntax" content="cpp">
@@ -54,6 +54,22 @@ scenario screen-in-scenario [
 <span class="CommentedCode">#?   $exit</span>
 ]
 
+<span class="Delimiter">:(scenario screen_in_scenario_unicode)</span>
+<span class="Comment"># screen-should-contain can check unicode characters in the fake screen</span>
+scenario screen-in-scenario [
+  assume-screen <span class="Constant">5</span>:literal/width<span class="Delimiter">,</span> <span class="Constant">3</span>:literal/height
+  run [
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">955</span>:literal  <span class="Comment"># 'λ'</span>
+  ]
+  screen-should-contain [
+  <span class="Comment">#  01234</span>
+    <span class="Delimiter">.</span>λ    <span class="Delimiter">.</span>
+    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
+    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
+  ]
+<span class="CommentedCode">#?   $exit</span>
+]
+
 <span class="Delimiter">:(scenario screen_in_scenario_error)</span>
 <span class="CommentedCode">#? % cerr &lt;&lt; &quot;AAA\n&quot;;</span>
 <span class="Special">% Hide_warnings = true;</span>
@@ -69,14 +85,18 @@ scenario screen-in-scenario-error [
     <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
   ]
 ]
-<span class="traceContains">+warn: expected screen location (0, 0) to contain 'b' instead of 'a'</span>
+<span class="traceContains">+warn: expected screen location (0, 0) to contain 98 ('b') instead of 97 ('a')</span>
+
+<span class="Comment">//: allow naming just for 'screen'</span>
+<span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span>
+if <span class="Delimiter">(</span>s == <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 <span class="Comment">// Scenarios may not define default-space, so they should fit within the</span>
 <span class="Comment">// initial area of memory reserved for tests. We'll put the predefined</span>
 <span class="Comment">// variables available to them at the end of that region.</span>
-const size_t Max_variables_in_scenarios = Reserved_for_tests-<span class="Constant">100</span><span class="Delimiter">;</span>
-size_t Next_predefined_global_for_scenarios = Max_variables_in_scenarios<span class="Delimiter">;</span>
+const long long int Max_variables_in_scenarios = Reserved_for_tests-<span class="Constant">100</span><span class="Delimiter">;</span>
+long long int Next_predefined_global_for_scenarios = Max_variables_in_scenarios<span class="Delimiter">;</span>
 <span class="Delimiter">:(before &quot;End Setup&quot;)</span>
 assert<span class="Delimiter">(</span>Next_predefined_global_for_scenarios &lt; Reserved_for_tests<span class="Delimiter">);</span>
 <span class="Delimiter">:(after &quot;transform_all()&quot; following &quot;case RUN:&quot;)</span>
@@ -87,7 +107,7 @@ assert<span class="Delimiter">(</span>Name[tmp_recipe<span class="Delimiter">.</
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 <span class="Comment">// Scenario Globals.</span>
-const size_t SCREEN = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
+const long long int SCREEN = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
 <span class="Comment">// End Scenario Globals.</span>
 <span class="Delimiter">:(before &quot;End Predefined Scenario Locals In Run&quot;)</span>
 Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span>
@@ -117,53 +137,65 @@ case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(before &quot;End Types&quot;)</span>
+<span class="Comment">// scan an array of characters in a unicode-aware, bounds-checked manner</span>
+struct raw_string_stream <span class="Delimiter">{</span>
+  long long int index<span class="Delimiter">;</span>
+  const long long int max<span class="Delimiter">;</span>
+  const char* buf<span class="Delimiter">;</span>
+
+  raw_string_stream<span class="Delimiter">(</span>const string&amp;<span class="Delimiter">);</span>
+  uint32_t get<span class="Delimiter">();</span>  <span class="Comment">// unicode codepoint</span>
+  uint32_t peek<span class="Delimiter">();</span>  <span class="Comment">// unicode codepoint</span>
+  bool at_end<span class="Delimiter">()</span> const<span class="Delimiter">;</span>
+  void skip_whitespace_and_comments<span class="Delimiter">();</span>
+<span class="Delimiter">};</span>
+
 <span class="Delimiter">:(code)</span>
-void check_screen<span class="Delimiter">(</span>const string&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+void check_screen<span class="Delimiter">(</span>const string&amp; expected_contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
 <span class="CommentedCode">//?   cerr &lt;&lt; &quot;Checking screen\n&quot;; //? 1</span>
   assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span>  <span class="Comment">// not supported</span>
-  index_t screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
+  long long int screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
   int data_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">);</span>
   assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  index_t screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
-  index_t screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
+  long long int screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
+  long long int screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
   int width_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span>
-  size_t screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
+  long long int screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
   int height_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span>
-  size_t screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
-  string expected_contents<span class="Delimiter">;</span>
-  istringstream in<span class="Delimiter">(</span>contents<span class="Delimiter">);</span>
-  in &gt;&gt; std::noskipws<span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>index_t row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-    assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span>
-    assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
-    for <span class="Delimiter">(</span>index_t column = <span class="Constant">0</span><span class="Delimiter">;</span> column &lt; screen_width<span class="Delimiter">;</span> ++column<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span>
-      expected_contents += in<span class="Delimiter">.</span>get<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-    assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-<span class="CommentedCode">//?   assert(in.get() == ']');</span>
-  trace<span class="Delimiter">(</span><span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking screen size at &quot;</span> &lt;&lt; screen_data_start<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cout &lt;&lt; expected_contents.size() &lt;&lt; '\n'; //? 1</span>
-  if <span class="Delimiter">(</span>Memory[screen_data_start] &gt; static_cast&lt;signed&gt;<span class="Delimiter">(</span>expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">()))</span>
-    raise &lt;&lt; <span class="Constant">&quot;expected contents are larger than screen size &quot;</span> &lt;&lt; Memory[screen_data_start] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-  ++screen_data_start<span class="Delimiter">;</span>  <span class="Comment">// now skip length</span>
-  for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    trace<span class="Delimiter">(</span><span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; screen_data_start+i<span class="Delimiter">;</span>
-<span class="CommentedCode">//?     cerr &lt;&lt; &quot;comparing &quot; &lt;&lt; i/screen_width &lt;&lt; &quot;, &quot; &lt;&lt; i%screen_width &lt;&lt; &quot;: &quot; &lt;&lt; Memory[screen_data_start+i] &lt;&lt; &quot; vs &quot; &lt;&lt; (int)expected_contents.at(i) &lt;&lt; '\n'; //? 1</span>
-    if <span class="Delimiter">((</span>!Memory[screen_data_start+i] &amp;&amp; !isspace<span class="Delimiter">(</span>expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span>  <span class="Comment">// uninitialized memory =&gt; spaces</span>
-        || <span class="Delimiter">(</span>Memory[screen_data_start+i] &amp;&amp; Memory[screen_data_start+i] != expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;CCC &quot; &lt;&lt; Trace_stream &lt;&lt; &quot; &quot; &lt;&lt; Hide_warnings &lt;&lt; '\n'; //? 1</span>
+  long long int screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
+  raw_string_stream cursor<span class="Delimiter">(</span>expected_contents<span class="Delimiter">);</span>
+  <span class="Comment">// todo: too-long expected_contents should fail</span>
+  long long int addr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
+  for <span class="Delimiter">(</span>long long int row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    cursor<span class="Delimiter">.</span>skip_whitespace_and_comments<span class="Delimiter">();</span>
+    if <span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>at_end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
+    assert<span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
+    for <span class="Delimiter">(</span>long long int column = <span class="Constant">0</span><span class="Delimiter">;</span>  column &lt; screen_width<span class="Delimiter">;</span>  ++column<span class="Delimiter">,</span> ++addr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+      uint32_t curr = cursor<span class="Delimiter">.</span>get<span class="Delimiter">();</span>
+      if <span class="Delimiter">(</span>Memory[addr] == <span class="Constant">0</span> &amp;&amp; isspace<span class="Delimiter">(</span>curr<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
+      if <span class="Delimiter">(</span>Memory[addr] != <span class="Constant">0</span> &amp;&amp; Memory[addr] == curr<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
+      <span class="Comment">// mismatch</span>
+      <span class="Comment">// can't print multi-byte unicode characters in warnings just yet. not very useful for debugging anyway.</span>
+      char expected_pretty[<span class="Constant">10</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span>
+      if <span class="Delimiter">(</span>curr &lt; <span class="Constant">256</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+        <span class="Comment">// &quot; ('&lt;curr&gt;')&quot;</span>
+        expected_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">3</span>] = static_cast&lt;unsigned char&gt;<span class="Delimiter">(</span>curr<span class="Delimiter">),</span> expected_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span>
+      <span class="Delimiter">}</span>
+      char actual_pretty[<span class="Constant">10</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span>
+      if <span class="Delimiter">(</span>Memory[addr] &lt; <span class="Constant">256</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+        <span class="Comment">// &quot; ('&lt;curr&gt;')&quot;</span>
+        actual_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">3</span>] = static_cast&lt;unsigned char&gt;<span class="Delimiter">(</span>Memory[addr]<span class="Delimiter">),</span> actual_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span>
+      <span class="Delimiter">}</span>
+
       if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Hide_warnings<span class="Delimiter">)</span> <span class="Delimiter">{</span>
         <span class="Comment">// genuine test in a mu file</span>
-        raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; i/screen_width &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; i%screen_width &lt;&lt; <span class="Constant">&quot;) to contain '&quot;</span> &lt;&lt; expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' instead of '&quot;</span> &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[screen_data_start+i]<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+        raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr] &lt;&lt; actual_pretty &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
         dump_screen<span class="Delimiter">();</span>
       <span class="Delimiter">}</span>
       else <span class="Delimiter">{</span>
         <span class="Comment">// just testing check_screen</span>
-        raise &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; i/screen_width &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; i%screen_width &lt;&lt; <span class="Constant">&quot;) to contain '&quot;</span> &lt;&lt; expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' instead of '&quot;</span> &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[screen_data_start+i]<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+        raise &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr] &lt;&lt; actual_pretty &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
       <span class="Delimiter">}</span>
       if <span class="Delimiter">(</span>!Hide_warnings<span class="Delimiter">)</span> <span class="Delimiter">{</span>
         Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
@@ -171,6 +203,49 @@ void check_screen<span class="Delimiter">(</span>const string&amp; contents<span
       <span class="Delimiter">}</span>
       <span class="Identifier">return</span><span class="Delimiter">;</span>
     <span class="Delimiter">}</span>
+    assert<span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
+  <span class="Delimiter">}</span>
+  cursor<span class="Delimiter">.</span>skip_whitespace_and_comments<span class="Delimiter">();</span>
+  assert<span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>at_end<span class="Delimiter">());</span>
+<span class="Delimiter">}</span>
+
+raw_string_stream::raw_string_stream<span class="Delimiter">(</span>const string&amp; backing<span class="Delimiter">)</span> :index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> max<span class="Delimiter">(</span>backing<span class="Delimiter">.</span>size<span class="Delimiter">()),</span> buf<span class="Delimiter">(</span>backing<span class="Delimiter">.</span>c_str<span class="Delimiter">())</span> <span class="Delimiter">{}</span>
+
+bool raw_string_stream::at_end<span class="Delimiter">()</span> const <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>index &gt;= max<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  if <span class="Delimiter">(</span>tb_utf8_char_length<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &gt; max-index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; <span class="Constant">&quot;unicode string seems corrupted at index &quot;</span>&lt;&lt; index &lt;&lt; <span class="Constant">&quot; character &quot;</span> &lt;&lt; static_cast&lt;int&gt;<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+    <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+uint32_t raw_string_stream::get<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  assert<span class="Delimiter">(</span>index &lt; max<span class="Delimiter">);</span>  <span class="Comment">// caller must check bounds before calling 'get'</span>
+  uint32_t result = <span class="Constant">0</span><span class="Delimiter">;</span>
+  int length = tb_utf8_char_to_unicode<span class="Delimiter">(</span>&amp;result<span class="Delimiter">,</span> &amp;buf[index]<span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>length != TB_EOF<span class="Delimiter">);</span>
+  index += length<span class="Delimiter">;</span>
+  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+uint32_t raw_string_stream::peek<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  assert<span class="Delimiter">(</span>index &lt; max<span class="Delimiter">);</span>  <span class="Comment">// caller must check bounds before calling 'get'</span>
+  uint32_t result = <span class="Constant">0</span><span class="Delimiter">;</span>
+  int length = tb_utf8_char_to_unicode<span class="Delimiter">(</span>&amp;result<span class="Delimiter">,</span> &amp;buf[index]<span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>length != TB_EOF<span class="Delimiter">);</span>
+  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+void raw_string_stream::skip_whitespace_and_comments<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  while <span class="Delimiter">(</span>!at_end<span class="Delimiter">())</span> <span class="Delimiter">{</span>
+    if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>peek<span class="Delimiter">()))</span> get<span class="Delimiter">();</span>
+    else if <span class="Delimiter">(</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+      <span class="Comment">// skip comment</span>
+      get<span class="Delimiter">();</span>
+      while <span class="Delimiter">(</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> get<span class="Delimiter">();</span>  <span class="Comment">// implicitly also handles CRLF</span>
+    <span class="Delimiter">}</span>
+    else <span class="Identifier">break</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 
@@ -187,21 +262,21 @@ case _DUMP_SCREEN: <span class="Delimiter">{</span>
 <span class="Delimiter">:(code)</span>
 void dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span>  <span class="Comment">// not supported</span>
-  index_t screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
+  long long int screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
   int width_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span>
-  size_t screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
+  long long int screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
   int height_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span>
-  size_t screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
+  long long int screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
   int data_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">);</span>
   assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  index_t screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
-  index_t screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
+  long long int screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
+  long long int screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
 <span class="CommentedCode">//?   cerr &lt;&lt; &quot;data start: &quot; &lt;&lt; screen_data_start &lt;&lt; '\n'; //? 1</span>
   assert<span class="Delimiter">(</span>Memory[screen_data_start] == screen_width*screen_height<span class="Delimiter">);</span>
-  index_t curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
-  for <span class="Delimiter">(</span>index_t row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  long long int curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
+  for <span class="Delimiter">(</span>long long int row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
 <span class="CommentedCode">//?     cerr &lt;&lt; curr &lt;&lt; &quot;:\n&quot;; //? 1</span>
-    for <span class="Delimiter">(</span>index_t col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; screen_width<span class="Delimiter">;</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    for <span class="Delimiter">(</span>long long int col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; screen_width<span class="Delimiter">;</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
       cerr &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">);</span>
       ++curr<span class="Delimiter">;</span>
     <span class="Delimiter">}</span>