1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/problems-module/2-pl2.html
2020-02-27 01:43:11 +00:00

723 lines
84 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/pl1</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/pl2' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">problems</a></li><li><a href="index.html#2">Chapter 2: Problems</a></li><li><b>Problems, Level 2</b></li></ul><p class="purpose">To assemble and format problem messages within the problem buffer.</p>
<ul class="toc"><li><a href="#SP4">&#167;4. Problem quotations</a></li><li><a href="#SP7">&#167;7. Short and long forms</a></li><li><a href="#SP9">&#167;9. How problems begin and end</a></li><li><a href="#SP10">&#167;10. Appending source</a></li><li><a href="#SP11">&#167;11. Issuing a segment of a problem message</a></li><li><a href="#SP13">&#167;13. Problems report and index</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>Problem messages begin with an indication of where in the source text the
problem occurs, in terms of headings and subheadings written in the
source text, and it is this indication that we consider first. For
example,
</p>
<blockquote>
<p>In Part the First, Chapter 1 - Attic Area:</p>
</blockquote>
<p class="inwebparagraph">There can be up to 10 levels in the hierarchy of headings and
subheadings, with level 0 the top level and level 9 the lowest.
</p>
<p class="inwebparagraph">When we need to issue a problem at sentence <code class="display"><span class="extract">S</span></code>, we work out what the
current heading is (if any) at each of the 10 levels. We do this by
trekking right through the whole linked list of sentences until we reach
<code class="display"><span class="extract">S</span></code>, changing the current headings whenever we pass one. This sounds
inefficient, but of course few problems are issued, and in any case we
cannot optimise by simply cacheing the heading level from one problem to
the next because it is not true that problems are always issued in source
code order.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::find_headings_at</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">sentence</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">problem_headings</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">ParseTree::traverse_ppn_nocs</span><span class="plain">(</span><span class="functiontext">Problems::visit_for_headings</span><span class="plain">, &amp;</span><span class="identifier">sentence</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ParseTree::get_problem_falls_under</span><span class="plain">(</span><span class="identifier">sentence</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">heading_level_ANNOT</span><span class="plain">);</span>
<span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">L</span><span class="plain">] = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ParseTree::get_problem_falls_under</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Problems::visit_for_headings</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">sentence</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == *</span><span class="identifier">sentence</span><span class="plain">) {</span>
<span class="identifier">ParseTree::set_problem_falls_under</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">HEADING_NT</span><span class="plain">) {</span>
<span class="identifier">ParseTree::set_problem_falls_under</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::find_headings_at is used in <a href="#SP3">&#167;3</a>.</p>
<p class="endnote">The function Problems::visit_for_headings appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>A further refinement is that we remember the last set of headings used
for an error message, and only mention what has changed about the location.
Thus we might next print:
</p>
<blockquote>
<p>In Chapter 2 - Cellar Area:</p>
</blockquote>
<p class="inwebparagraph">omitting to mention "Part the First" this time, since that part has not
changed. (And we never print internally made level 0, File, headings.)
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_problem_headings</span><span class="plain">[</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Now for the actual displaying of the location text. The outcome image
is a trickier thing to get right than might appear. By being in this
routine, we know that a problem has been issued: the run will therefore
not have been a success, and we can issue the "NI failed" outcome
image. A success image cannot be placed until right at the end of the
run, when all possibility of problems has been passed: so there's no
single point in NI where a single line of code could choose between
the two possibilities.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">do_not_locate_problems</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::show_problem_location</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == 0) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">internal_error_thrown</span><span class="plain">)</span>
<span class="identifier">HTMLFiles::html_outcome_image</span><span class="plain">(</span><span class="identifier">problems_file</span><span class="plain">, </span><span class="string">"ni_failed_badly"</span><span class="plain">, </span><span class="string">"Failed"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">HTMLFiles::html_outcome_image</span><span class="plain">(</span><span class="identifier">problems_file</span><span class="plain">, </span><span class="string">"ni_failed"</span><span class="plain">, </span><span class="string">"Failed"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">last_problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">do_not_locate_problems</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="functiontext">Problems::find_headings_at</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">, </span><span class="identifier">problem_headings</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] != </span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
&lt;<span class="cwebmacro">Print the heading position</span> <span class="cwebmacronumber">3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">last_problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::show_problem_location is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. </b>We print only the part of the heading position which differs from that
of the previous one quoted: <code class="display"><span class="extract">i</span></code> is at this point the highest level at
which they differ.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print the heading position</span> <span class="cwebmacronumber">3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">Problems::Buffer::clear</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&gt;---&gt; "</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"In&lt;b&gt;"</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">=</span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] != </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Sentences::Headings::get_text</span><span class="plain">(</span><span class="identifier">ParseTree::get_embodying_heading</span><span class="plain">(</span><span class="identifier">problem_headings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]));</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">", "</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">" "</span><span class="plain">);</span>
<span class="identifier">f</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Problems::Buffer::copy_text_into_problem_buffer</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">" the main source text"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pos</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">INBUILD_MODULE</span>
<span class="identifier">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&lt;/b&gt; in the extension &lt;b&gt;%X"</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-&gt;</span><span class="identifier">as_copy</span><span class="plain">-&gt;</span><span class="identifier">edition</span><span class="plain">-&gt;</span><span class="identifier">work</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&lt;/b&gt;:"</span><span class="plain">);</span>
<span class="functiontext">Problems::Buffer::output_problem_buffer</span><span class="plain">(0);</span>
<span class="functiontext">Problems::Buffer::clear</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Problem quotations. </b>Problem messages are printed using a printf-like formatting system.
Unlike printf, though, where <code class="display"><span class="extract">%s</span></code> means a string and <code class="display"><span class="extract">%d</span></code> a number, here
the escape codes do not indicate the type of the data: they are simply
<code class="display"><span class="extract">%1</span></code>, <code class="display"><span class="extract">%2</span></code>, <code class="display"><span class="extract">%3</span></code>, ..., <code class="display"><span class="extract">%9</span></code>. This is to prevent horrendous crashes when
type mismatches occur: using a pointer to a phrase when trying to print a
source code reference, for instance.
</p>
<p class="inwebparagraph">The texts to be substituted in place of <code class="display"><span class="extract">%1</span></code>, <code class="display"><span class="extract">%2</span></code>, ..., are called the
"quotations". The value is either a range of words in the source text, or
else a pointer to some data structure, depending on the type. The type is a
single character code. (This coding system is used only here, and could
easily be changed, but there seems no reason to.)
</p>
<p class="inwebparagraph">The type codes are S(ource), W(ords), B(inary predicate), E(xtension),
(p)H(rase), I(nvocation), N(umber), O(bject), P(roperty name), T(ext),
(t)Y(pe specification).
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">problem_quotation</span><span class="plain"> {</span>
<span class="reserved">char</span><span class="plain"> </span><span class="identifier">quotation_type</span><span class="plain">; </span> <span class="comment">one of the above</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wording_based</span><span class="plain">; </span> <span class="comment">which of the following:</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">structure_quoted</span><span class="plain">; </span> <span class="comment">if false</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">expander</span><span class="plain">)(</span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *); </span> <span class="comment">if false</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">text_quoted</span><span class="plain">; </span> <span class="comment">if true</span>
<span class="plain">} </span><span class="reserved">problem_quotation</span><span class="plain">;</span>
<span class="reserved">problem_quotation</span><span class="plain"> </span><span class="identifier">problem_quotations</span><span class="plain">[10];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure problem_quotation is private to this section.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>When some higher-level part of NI wants to issue a formatted problem
message, it first declares the contents of any quotations it will make.
It does this using the routines <code class="display"><span class="extract">Problems::quote_object</span></code>, <code class="display"><span class="extract">Problems::quote_spec</span></code>, ...
below. Thus <code class="display"><span class="extract">Problems::quote_spec(2, SP)</span></code> specifies that <code class="display"><span class="extract">%2</span></code> should be
printed as the inference <code class="display"><span class="extract">SP</span></code>.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">v</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *)) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain">&lt;0) || (</span><span class="identifier">t</span><span class="plain"> &gt; 10)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"problem quotation number out of range"</span><span class="plain">);</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.structure_quoted</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.expander</span><span class="plain"> = </span><span class="identifier">f</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.quotation_type</span><span class="plain"> = </span><span class="character">'?'</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.wording_based</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> </span><span class="identifier">type</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain">&lt;0) || (</span><span class="identifier">t</span><span class="plain"> &gt; 10)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"problem quotation number out of range"</span><span class="plain">);</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.structure_quoted</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.quotation_type</span><span class="plain"> = </span><span class="identifier">type</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.wording_based</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::problem_quote is used in <a href="#SP6">&#167;6</a>.</p>
<p class="endnote">The function Problems::problem_quote_textual is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Here are the three public routines for quoting from text: either via a node
in the parse tree, or with a literal word range.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_source</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'S'</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Problems::quote_wording_as_source</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_source_eliding_begin</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'S'</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;, 1);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'S'</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wording</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) { </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'W'</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">); }</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wording_tinted_green</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) { </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'g'</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">); }</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wording_tinted_red</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) { </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'r'</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">); }</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wording_as_source</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) { </span><span class="functiontext">Problems::problem_quote_textual</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="character">'S'</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">); }</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_text</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Problems::expand_text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_text</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%s"</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wide_text</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Problems::expand_wide_text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_wide_text</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%w"</span><span class="plain">, (</span><span class="identifier">wchar_t</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_stream</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Problems::expand_stream</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_stream</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, (</span><span class="identifier">text_stream</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_wa</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">word_assemblage</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Problems::expand_wa</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_wa</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%A"</span><span class="plain">, (</span><span class="identifier">word_assemblage</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_text_within_reason</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::truncate</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="constant">QUOTATION_TOLERANCE_LIMIT</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%&lt;W"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::quote_number</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">Problems::problem_quote</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Problems::expand_number</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::expand_number</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d"</span><span class="plain">, *((</span><span class="reserved">int</span><span class="plain"> *) </span><span class="identifier">p</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::quote_source is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP15">&#167;15</a>, <a href="2-pl3.html#SP16">&#167;16</a>, <a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function Problems::quote_source_eliding_begin appears nowhere else.</p>
<p class="endnote">The function Problems::quote_wording is used in 2/pl3 (<a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function Problems::quote_wording_tinted_green appears nowhere else.</p>
<p class="endnote">The function Problems::quote_wording_tinted_red appears nowhere else.</p>
<p class="endnote">The function Problems::quote_wording_as_source appears nowhere else.</p>
<p class="endnote">The function Problems::quote_text is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP12">&#167;12</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP15">&#167;15</a>, <a href="2-pl3.html#SP16">&#167;16</a>, <a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function Problems::expand_text appears nowhere else.</p>
<p class="endnote">The function Problems::quote_wide_text is used in 2/pl3 (<a href="2-pl3.html#SP13">&#167;13</a>).</p>
<p class="endnote">The function Problems::expand_wide_text appears nowhere else.</p>
<p class="endnote">The function Problems::quote_stream is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP14">&#167;14</a>).</p>
<p class="endnote">The function Problems::expand_stream appears nowhere else.</p>
<p class="endnote">The function Problems::quote_wa appears nowhere else.</p>
<p class="endnote">The function Problems::expand_wa appears nowhere else.</p>
<p class="endnote">The function Problems::expand_text_within_reason appears nowhere else.</p>
<p class="endnote">The function Problems::quote_number is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function Problems::expand_number appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Short and long forms. </b>Most of the error messages have a short form, giving the main factual
information, and a long form which also has an explanation attached.
Some of the text is common to both versions, but other parts are specific
to either one or the other, and variables record the status of our current
position in scanning and transcribing the problem message.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">shorten_problem_message</span><span class="plain">; </span> <span class="comment">give short form of this previously-seen problem</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">reading_text_specific_to_short_version</span><span class="plain">; </span> <span class="comment">modes during problem message writing</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">reading_text_specific_to_long_version</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>We do not want to keep wittering on with the same old explanations,
so we remember which ones we've given before (i.e., in previous problem
messages during the same run of NI). Eventually our patience is exhausted
and we give no further explanation in any circumstances.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">PATIENCE_EXHAUSTION_POINT</span><span class="plain"> 100</span>
</pre>
<pre class="display">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">explanations</span><span class="plain">[</span><span class="constant">PATIENCE_EXHAUSTION_POINT</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_explanations</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Problems::explained_before</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_explanations</span><span class="plain"> == </span><span class="constant">PATIENCE_EXHAUSTION_POINT</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">no_explanations</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">explanation</span><span class="plain"> == </span><span class="identifier">explanations</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">explanations</span><span class="plain">[</span><span class="identifier">no_explanations</span><span class="plain">++] = </span><span class="identifier">explanation</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::explained_before is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. How problems begin and end. </b>During the construction of a problem message, we will be running through a
standard text, and at any point might be considering matter which should
appear only in the long form, or only in the short form.
</p>
<p class="inwebparagraph">If the text of a message begins with an asterisk, then it is a
continuation of a message already partly issued. Otherwise we can
sensibly find out whether this is one we've seen before. Either way, we
set <code class="display"><span class="extract">shorten_problem_message</span></code> to remember whether to use the short or long
form.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">) {</span>
<span class="functiontext">Problems::Buffer::clear</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">strcmp</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="string">"*"</span><span class="plain">) == 0) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&gt;++&gt;"</span><span class="plain">);</span>
<span class="identifier">shorten_problem_message</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">strcmp</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="string">"****"</span><span class="plain">) == 0) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&gt;++++&gt;"</span><span class="plain">);</span>
<span class="identifier">shorten_problem_message</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">strcmp</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="string">"***"</span><span class="plain">) == 0) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&gt;+++&gt;"</span><span class="plain">);</span>
<span class="identifier">shorten_problem_message</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">strcmp</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="string">"**"</span><span class="plain">) == 0) {</span>
<span class="identifier">shorten_problem_message</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Problems::show_problem_location</span><span class="plain">();</span>
<span class="identifier">problem_count</span><span class="plain">++;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"&gt;--&gt; "</span><span class="plain">);</span>
<span class="identifier">shorten_problem_message</span><span class="plain"> = </span><span class="functiontext">Problems::explained_before</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">reading_text_specific_to_short_version</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">reading_text_specific_to_long_version</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::issue_problem_end</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">compiling_text_routines_mode</span><span class="plain">) </span><span class="identifier">Strings::TextSubstitutions::append_text_substitution_proviso</span><span class="plain">();</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="functiontext">Problems::Buffer::output_problem_buffer</span><span class="plain">(1);</span>
<span class="functiontext">Problems::Issue::problem_documentation_links</span><span class="plain">(</span><span class="identifier">problems_file</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">crash_on_all_errors</span><span class="plain">) </span><span class="functiontext">Problems::Fatal::force_crash</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::issue_problem_begin is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP11">&#167;11</a>, <a href="2-pl3.html#SP12">&#167;12</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP14">&#167;14</a>, <a href="2-pl3.html#SP15">&#167;15</a>, <a href="2-pl3.html#SP16">&#167;16</a>, <a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function Problems::issue_problem_end is used in 2/pl3 (<a href="2-pl3.html#SP2">&#167;2</a>, <a href="2-pl3.html#SP12">&#167;12</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP14">&#167;14</a>, <a href="2-pl3.html#SP15">&#167;15</a>, <a href="2-pl3.html#SP16">&#167;16</a>, <a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Appending source. </b></p>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">appended_source</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::append_source</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">appended_source</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::transcribe_appended_source</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">appended_source</span><span class="plain">))</span>
<span class="functiontext">Problems::Buffer::copy_source_reference_into_problem_buffer</span><span class="plain">(</span><span class="identifier">appended_source</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::append_source is used in <a href="#SP11_1_2">&#167;11.1.2</a>.</p>
<p class="endnote">The function Problems::transcribe_appended_source is used in <a href="#SP11_1_2">&#167;11.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Issuing a segment of a problem message. </b>Here is the routine which performs the substitution of quotations into
problem messages and sends them on their way: which is called
<code class="display"><span class="extract">Problems::issue_problem_segment</span></code> since it only appends a further piece of text, and may
be used several times to build up complicated messages.
</p>
<p class="inwebparagraph">We have seen that, within problem message texts, the escapes <code class="display"><span class="extract">%1</span></code> to <code class="display"><span class="extract">%9</span></code>
are to produce quotations. Four further escape codes switch between problem
message versions, as follows: we have <code class="display"><span class="extract">%L</span></code>, which indicates that the text
which follows should only be used in the long form of the error message;
<code class="display"><span class="extract">%S</span></code>, the same for the short form; <code class="display"><span class="extract">%%</span></code>, which cancels either of these
settings and restores the text to appearing in both forms, which is the
default. A percentage sign followed by a vertical stroke acts more simply
as a divider between the brief message and the explanation text in many
simple problem messages which do not use the elaborations of the other
three escapes.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'%'</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'L'</span><span class="plain">: </span><span class="identifier">reading_text_specific_to_long_version</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'S'</span><span class="plain">: </span><span class="identifier">reading_text_specific_to_short_version</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'%'</span><span class="plain">: </span><span class="identifier">reading_text_specific_to_short_version</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">reading_text_specific_to_long_version</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'|'</span><span class="plain">: </span><span class="identifier">reading_text_specific_to_short_version</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">reading_text_specific_to_long_version</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">shorten_problem_message</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"."</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">reading_text_specific_to_short_version</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">shorten_problem_message</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">reading_text_specific_to_long_version</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">shorten_problem_message</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Act on the problem message text, since it is now contextually allowed</span> <span class="cwebmacronumber">11.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::issue_problem_segment is used in 2/pl3 (<a href="2-pl3.html#SP3">&#167;3</a>, <a href="2-pl3.html#SP12">&#167;12</a>, <a href="2-pl3.html#SP13">&#167;13</a>, <a href="2-pl3.html#SP14">&#167;14</a>, <a href="2-pl3.html#SP15">&#167;15</a>, <a href="2-pl3.html#SP16">&#167;16</a>, <a href="2-pl3.html#SP17">&#167;17</a>, <a href="2-pl3.html#SP19">&#167;19</a>, <a href="2-pl3.html#SP20">&#167;20</a>).</p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b>Ordinarily we just append the new character, but we also act on the escapes
<code class="display"><span class="extract">%P</span></code> and <code class="display"><span class="extract">%1</span></code> to <code class="display"><span class="extract">%9</span></code>. <code class="display"><span class="extract">%P</span></code> forces a paragraph break, or at any rate, it does
in the eventual HTML version of the problem message. Note that these escapes
are acted on only if they occur in a contextually allowed part of the problem
message (e.g., if they occur in the short form only, they will only be acted
on when the shortened form is the one being issued).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Act on the problem message text, since it is now contextually allowed</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'%'</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'P'</span><span class="plain">: </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="constant">FORCE_NEW_PARA_CHAR</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1])) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = ((</span><span class="reserved">int</span><span class="plain">) (</span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]))-((</span><span class="reserved">int</span><span class="plain">) </span><span class="character">'0'</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain">&gt;=1) &amp;&amp; (</span><span class="identifier">t</span><span class="plain">&lt;=9)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.wording_based</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Expand wording-based escape</span> <span class="cwebmacronumber">11.1.1</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Expand structure-based escape</span> <span class="cwebmacronumber">11.1.2</span>&gt;
<span class="plain">}</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_1_1"></a><b>&#167;11.1.1. </b>This is where a quotation escape, such as <code class="display"><span class="extract">%2</span></code>, is expanded: by looking up
its type, stored internally as a single character.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Expand wording-based escape</span> <span class="cwebmacronumber">11.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.quotation_type</span><span class="plain">) {</span>
<span class="comment">Monochrome wording</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'S'</span><span class="plain">: </span><span class="functiontext">Problems::Buffer::copy_source_reference_into_problem_buffer</span><span class="plain">(</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'W'</span><span class="plain">: </span><span class="functiontext">Problems::Buffer::copy_text_into_problem_buffer</span><span class="plain">(</span>
<span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="comment">Tinted wording</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'r'</span><span class="plain">: </span>&lt;<span class="cwebmacro">Quote a red-tinted word range in a problem message</span> <span class="cwebmacronumber">11.1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'g'</span><span class="plain">: </span>&lt;<span class="cwebmacro">Quote a green-tinted word range in a problem message</span> <span class="cwebmacronumber">11.1.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown error token type"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_1">&#167;11.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_1_1_1"></a><b>&#167;11.1.1.1. </b>Tinting text involves some HTML, of course:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Quote a red-tinted word range in a problem message</span> <span class="cwebmacronumber">11.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"800000"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain">);</span>
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Spool temporary stream text to the problem buffer</span> <span class="cwebmacronumber">11.1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_1_1">&#167;11.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_1_1_2"></a><b>&#167;11.1.1.2. </b>And:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Quote a green-tinted word range in a problem message</span> <span class="cwebmacronumber">11.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"008000"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.text_quoted</span><span class="plain">);</span>
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Spool temporary stream text to the problem buffer</span> <span class="cwebmacronumber">11.1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_1_1">&#167;11.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_1_2"></a><b>&#167;11.1.2. </b>More generally, the reference is to some structure we can't write
ourselves, and must delegate to:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Expand structure-based escape</span> <span class="cwebmacronumber">11.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Problems::append_source</span><span class="plain">(</span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">(</span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.expander</span><span class="plain">)(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">problem_quotations</span><span class="plain">[</span><span class="identifier">t</span><span class="plain">]</span><span class="element">.structure_quoted</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Spool temporary stream text to the problem buffer</span> <span class="cwebmacronumber">11.1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="functiontext">Problems::transcribe_appended_source</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_1">&#167;11.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_1_1_1_1"></a><b>&#167;11.1.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Spool temporary stream text to the problem buffer</span> <span class="cwebmacronumber">11.1.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">OUT</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'&lt;'</span><span class="plain">) </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">PROTECTED_LT_CHAR</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'&gt;'</span><span class="plain">) </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">PROTECTED_GT_CHAR</span><span class="plain">;</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_1_1_1">&#167;11.1.1.1</a>, <a href="#SP11_1_1_2">&#167;11.1.1.2</a>, <a href="#SP11_1_2">&#167;11.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>This version is much shorter, since escapes aren't allowed:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::issue_problem_segment_from_stream</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">PBUFF</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::issue_problem_segment_from_stream appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Problems report and index. </b>That gives us enough infrastructure to produce the final report. Note the use
of error redirection to in order to put pseudo-problem messages &mdash; actually
informational &mdash; into the report. In the case where the run was successful and
there we no Problem messages, we have to be careful to reset <code class="display"><span class="extract">problem_count</span></code>
&mdash; it will have been increased by the issuing of these pseudo-problems, and we
need it to remain 0 so that <code class="display"><span class="extract">main()</span></code> can finally return back to the operating
system without an error code.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tail_of_report_written</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::write_reports</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">disaster_struck</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tail_of_report_written</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">tail_of_report_written</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">crash_on_all_errors</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_FINAL_REPORTER</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pc</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="identifier">PROBLEMS_FINAL_REPORTER</span><span class="plain">(</span><span class="identifier">disaster_struck</span><span class="plain">, </span><span class="identifier">problem_count</span><span class="plain">);</span>
<span class="identifier">problem_count</span><span class="plain"> = </span><span class="identifier">pc</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">HTML::end_body</span><span class="plain">(</span><span class="identifier">problems_file</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::write_reports is used in 2/pl3 (<a href="2-pl3.html#SP2">&#167;2</a>, <a href="2-pl3.html#SP12">&#167;12</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-pl1.html">Back to 'Problems, Level 1'</a></li><li><a href="2-pl3.html">Continue with 'Problems, Level 3'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>