1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/problems-module/2-pl3.html
2020-03-19 00:11:25 +00:00

789 lines
94 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/pl2</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<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>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '2/pl3' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler</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 3</b></li></ul><p class="purpose">Here we provide some convenient semi-standardised problem messages, which also serve as examples of how to use the Level 2 problem message routines.</p>
<ul class="toc"><li><a href="#SP4">&#167;4. Nodal errors</a></li><li><a href="#SP8">&#167;8. Sigils</a></li><li><a href="#SP11">&#167;11. Handmade problems</a></li><li><a href="#SP12">&#167;12. Limit problems</a></li><li><a href="#SP13">&#167;13. Problem messages unlocated in the source text</a></li><li><a href="#SP15">&#167;15. Problem messages keyed to positions in the source text</a></li><li><a href="#SP20">&#167;20. Definition problems</a></li><li><a href="#SP21">&#167;21. Creating the Problems report</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>The following internal errors should never occur, whatever the provocation:
if they do, they are symptoms of incorrect code in NI.
</p>
<p class="inwebparagraph">The internal error "functions" used by the rest of NI are in fact macros,
in order that they can supply the current filename and line number
automatically to the actual internal error functions. The result is, for
instance,
</p>
<blockquote>
<p>Problem. An internal error has occurred: Unknown verb code. The current sentence is "A room is a kind"; the error was detected at line 133 of "Chapter 5/Traverse for Objects.w". This should never happen, and I am now halting in abject failure.</p>
</blockquote>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">internal_error_tree_unsafe</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">) </span><span class="functiontext">Problems::Issue::internal_error_tu_fn</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">__FILE__</span><span class="plain">, </span><span class="identifier">__LINE__</span><span class="plain">)</span>
<span class="definitionkeyword">define</span> <span class="identifier">internal_error_if_node_type_wrong</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) </span><span class="functiontext">Problems::Issue::nodal_check</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">__FILE__</span><span class="plain">, </span><span class="identifier">__LINE__</span><span class="plain">)</span>
<span class="definitionkeyword">define</span> <span class="identifier">internal_error_on_node_type</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">) </span><span class="functiontext">Problems::Issue::internal_error_on_node_type_fn</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">__FILE__</span><span class="plain">, </span><span class="identifier">__LINE__</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Internal errors are generated much like any other problem message, except
that we use a variant form of the "end" routine which salvages what it can
from the wreckage, then either forces a crash (to make the stack backtrace
visible in a debugger) or simply exits to the operating system with error
code 1:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::internal_error_end</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="functiontext">Problems::write_reports</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">debugger_mode</span><span class="plain">) </span><span class="functiontext">Problems::Fatal::force_crash</span><span class="plain">();</span>
<span class="functiontext">Problems::Fatal::exit</span><span class="plain">(1);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::internal_error_end is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>And now for the functions which the above macros invoke. There are two
versions: one which cites the current sentence, and another which doesn't,
for use if either there is no current sentence (because NI wasn't traversing
the parse tree at the time) or if the parse tree is unsafe &mdash; it's possible
that the internal error occurred during parse tree construction, so we need
to be cautious.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::internal_error_fn</span><span class="plain">(</span><span class="reserved">void</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="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">internal_error_thrown</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">current_sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext">Problems::Issue::internal_error_tu_fn</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">filename</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_number</span><span class="plain">(4, &amp;</span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"An internal error has occurred: %2. The current sentence is %1; the "</span>
<span class="string">"error was detected at line %4 of \</span><span class="plain">"</span><span class="string">%3\</span><span class="plain">"</span><span class="string">. This should never happen, "</span>
<span class="string">"and I am now halting in abject failure."</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::internal_error_tu_fn</span><span class="plain">(</span><span class="reserved">void</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="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">internal_error_thrown</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">filename</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_number</span><span class="plain">(3, &amp;</span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"An internal error has occurred: %1. The error was detected at "</span>
<span class="string">"line %3 of \</span><span class="plain">"</span><span class="string">%2\</span><span class="plain">"</span><span class="string">. This should never happen, and I am now halting "</span>
<span class="string">"in abject failure."</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::internal_error_tu_fn_S</span><span class="plain">(</span><span class="reserved">void</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="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">internal_error_thrown</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Problems::quote_stream</span><span class="plain">(1, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">filename</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_number</span><span class="plain">(3, &amp;</span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">""</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"An internal error has occurred: %1. The error was detected at "</span>
<span class="string">"line %3 of \</span><span class="plain">"</span><span class="string">%2\</span><span class="plain">"</span><span class="string">. This should never happen, and I am now halting "</span>
<span class="string">"in abject failure."</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::internal_error_fn is used in <a href="#SP4">&#167;4</a>.</p>
<p class="endnote">The function Problems::Issue::internal_error_tu_fn is used in <a href="#SP1">&#167;1</a>, <a href="#SP6">&#167;6</a>.</p>
<p class="endnote">The function Problems::Issue::internal_error_tu_fn_S is used in <a href="#SP4">&#167;4</a>, <a href="#SP5">&#167;5</a>, <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Nodal errors. </b>Very many routines are designed to work only on nodes within the parse
tree of a particular node type. If NI is in working order, then they will
never be called at any other nodes; but it seems best to check this. Any
failure of such an invariant produces a form of internal error called a
"nodal error".
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::nodal_error_fn</span><span class="plain">(</span><span class="identifier">parse_node_tree</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">pn</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="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Internal nodal error at:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_fn</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::nodal_error_fn_S</span><span class="plain">(</span><span class="identifier">parse_node_tree</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">pn</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="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Internal nodal error at:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_tu_fn_S</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::nodal_error_fn appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::nodal_error_fn_S is used in <a href="#SP5">&#167;5</a>, <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Here is a convenient function to check said invariant.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::nodal_check</span><span class="plain">(</span><span class="identifier">parse_node_tree</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">pn</span><span class="plain">, </span><span class="identifier">node_type_t</span><span class="plain"> </span><span class="identifier">node_type_required</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">, </span><span class="string">"NULL node found where type %s expected"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_type_name</span><span class="plain">(</span><span class="identifier">node_type_required</span><span class="plain">));</span>
<span class="functiontext">Problems::Issue::internal_error_tu_fn_S</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">internal_message</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</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">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">) != </span><span class="identifier">node_type_required</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">, </span><span class="string">"Node of type %s found where type %s expected"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_type_name</span><span class="plain">(</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)),</span>
<span class="identifier">ParseTree::get_type_name</span><span class="plain">(</span><span class="identifier">node_type_required</span><span class="plain">));</span>
<span class="functiontext">Problems::Issue::nodal_error_fn_S</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">internal_message</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::nodal_check is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Nodal errors also turn up as the default clauses in switch statements which
act on various selections of node types, and those use the <code class="display"><span class="extract">internal_error_on_node_type</span></code>
macro, which invokes the following:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::internal_error_on_node_type_fn</span><span class="plain">(</span><span class="identifier">parse_node_tree</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">pn</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">filename</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">linenum</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Problems::Issue::internal_error_tu_fn</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Unexpected NULL node found"</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">, </span><span class="string">"Unexpectedly found node of type %s"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_type_name</span><span class="plain">(</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)));</span>
<span class="functiontext">Problems::Issue::nodal_error_fn_S</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">internal_message</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain">, </span><span class="identifier">linenum</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::internal_error_on_node_type_fn is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>The following routines are relics of an era of horrific, primordial upheaval,
when the S-parser was being debugged. An S-subtree is a portion of the parse
tree which represents a proposition.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">latest_s_subtree</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::s_subtree_error_set_position</span><span class="plain">(</span><span class="identifier">parse_node_tree</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="identifier">latest_s_subtree</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::Issue::s_subtree_error</span><span class="plain">(</span><span class="identifier">parse_node_tree</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">mess</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">, </span><span class="string">"S-subtree error: %s"</span><span class="plain">, </span><span class="identifier">mess</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">latest_s_subtree</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Applied to the subtree:\</span><span class="plain">n</span><span class="string">$T"</span><span class="plain">, </span><span class="identifier">latest_s_subtree</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::internal_error_tu_fn_S</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">internal_message</span><span class="plain">, </span><span class="identifier">__FILE__</span><span class="plain">, </span><span class="identifier">__LINE__</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">internal_message</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::s_subtree_error_set_position appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::s_subtree_error appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Sigils. </b>Every problem message in Inform is identified by a sigil, a short
alphanumeric symbol. The <code class="display"><span class="extract">_p_</span></code> notation is used to write these;
see almost every section in later chapters for examples. The naming rules
for sigils are as follows:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) A problem which is thought never to be generated has the sigil
<code class="display"><span class="extract">BelievedImpossible</span></code>. Inform is quite defensively coded, so there are several
dozen of these &mdash; they are safety nets to catch cases we didn't think of.
</li></ul>
<ul class="items"><li>(b) A problem which either cannot be tested by <code class="display"><span class="extract">intest</span></code>, or is just impracticable
to do so, has the sigil <code class="display"><span class="extract">Untestable</span></code>.
</li></ul>
<ul class="items"><li>(c) A problem which can be tested, but for which nobody has yet written a
test case, has the sigil <code class="display"><span class="extract">...</span></code> (these are gradually declining in number, and
eventually, of course, will disappear altogether).
</li></ul>
<ul class="items"><li>(d) Otherwise a problem should have a unique sigil beginning <code class="display"><span class="extract">C</span></code> and then the
chapter number in which it is found: say, <code class="display"><span class="extract">PM_NoSuchHieroglyph</span></code>. The sigil
should have the same name as an <code class="display"><span class="extract">intest</span></code> test case which demonstrates the
problem.
</li></ul>
<ul class="items"><li>(e) A sigil which ends <code class="display"><span class="extract">-G</span></code> should be used for those few problems which appear
only when the virtual machine is Glulx.
</li></ul>
<p class="inwebparagraph">It would be easy for all this to fall out of sync, or for us just to lose track
of odd cases, since there are more than 750 problem messages; so a shell script
called <code class="display"><span class="extract">listproblems.sh</span></code> exists to verify that the above rules have been
adhered to.
</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>As can be seen, <code class="display"><span class="extract">_p_</span></code> is a macro expanding to the sigil's name in double
quotes followed by the source section and line number at which it is generated.
This provides three function arguments matching the <code class="display"><span class="extract">SIGIL_ARGUMENTS</span></code> prototype,
which appears as a pseudo-argument in all of the problem routines below.
</p>
<p class="inwebparagraph">Each such routine should either <code class="display"><span class="extract">ACT_ON_SIGIL</span></code> itself or else pass over to
another problem routine, using <code class="display"><span class="extract">PASS_SIGIL</span></code> as the pseudo-argument.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">sigil</span><span class="plain">) #</span><span class="identifier">sigil</span><span class="plain">, </span><span class="identifier">__FILE__</span><span class="plain">, </span><span class="identifier">__LINE__</span>
<span class="definitionkeyword">define</span> <span class="constant">SIGIL_ARGUMENTS</span><span class="plain"> </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">sigil</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">file</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">line</span>
<span class="definitionkeyword">define</span> <span class="constant">ACT_ON_SIGIL</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Problem %s issued from %s, line %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sigil</span><span class="plain">, </span><span class="identifier">file</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">telemetry_recording</span><span class="plain">) {</span>
<span class="functiontext">Telemetry::ensure_telemetry_file</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">telmy</span><span class="plain">, </span><span class="string">"Problem %s issued from %s, line %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sigil</span><span class="plain">, </span><span class="identifier">file</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sigil_of_latest_problem</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">sigil_of_latest_problem</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">sigil_of_latest_problem</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">sigil</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">sigil_of_latest_problem</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">sigil</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">sigil_of_required_problem</span><span class="plain">, </span><span class="identifier">sigil_of_latest_problem</span><span class="plain">))</span>
<span class="identifier">sigil_of_required_problem_found</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">echo_problem_message_sigils</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">STDERR</span><span class="plain">, </span><span class="string">"Problem__ %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sigil_of_latest_problem</span><span class="plain">);</span>
<span class="definitionkeyword">define</span> <span class="constant">PASS_SIGIL</span><span class="plain"> </span><span class="identifier">sigil</span><span class="plain">, </span><span class="identifier">file</span><span class="plain">, </span><span class="identifier">line</span>
</pre>
<pre class="display">
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sigil_of_latest_problem</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::problem_documentation_links</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">DOCUMENTATION_REFERENCES_PRESENT</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">chap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">sec</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">leaf</span><span class="plain"> = </span><span class="identifier">Index::DocReferences::link_if_possible_once</span><span class="plain">(</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain">, &amp;</span><span class="identifier">chap</span><span class="plain">, &amp;</span><span class="identifier">sec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">leaf</span><span class="plain">) {</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 2, </span><span class="string">"tight"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"href=inform:/%w.html"</span><span class="plain">, </span><span class="identifier">leaf</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 src=inform:/doc_images/help.png"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">chap</span><span class="plain">) &amp;&amp; (</span><span class="identifier">sec</span><span class="plain">)) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;See the manual: %w &amp;gt; %w&lt;/i&gt;"</span><span class="plain">, </span><span class="identifier">chap</span><span class="plain">, </span><span class="identifier">sec</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;See the manual.&lt;/i&gt;"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">telemetry_recording</span><span class="plain">) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">telmy</span><span class="plain">, </span><span class="string">"See the manual: %w &gt; %w\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">chap</span><span class="plain">, </span><span class="identifier">sec</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">sigil_of_latest_unlinked_problem</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Problems::Issue::latest_sigil</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">sigil_of_latest_problem</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::problem_documentation_links is used in 2/pl2 (<a href="2-pl2.html#SP9">&#167;9</a>).</p>
<p class="endnote">The function Problems::Issue::latest_sigil appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>The command-line switch <code class="display"><span class="extract">-sigils</span></code> causes the following flag to be set,
which in turn causes the sigil of any problem to be echoed to standard output
(i.e., printed). This is useful in testing, as it makes it easier to be sure
that the test case <code class="display"><span class="extract">PM_NoSuchHieroglyph.txt</span></code> does indeed generate the
problem <code class="display"><span class="extract">PM_NoSuchHieroglyph</span></code>, and so on.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">echo_problem_message_sigils</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Handmade problems. </b>Those made without using the convenient shorthand forms below:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">""</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::handmade_problem appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Limit problems. </b>Running out of memory, irretrievably: the politest kind of fatal error,
though let's face it, fatal is fatal.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::limit_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">what_has_run_out</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">how_many</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">what_has_run_out</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_number</span><span class="plain">(2, &amp;</span><span class="identifier">how_many</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">""</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I have run out of memory for %1 - there's room for %2, but no more. "</span>
<span class="string">"This is a 'hard limit', hard in the sense of deadlines, or luck: "</span>
<span class="string">"there is no getting around it. You will need to rewrite your source "</span>
<span class="string">"text so that it needs fewer %1."</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="functiontext">Problems::write_reports</span><span class="plain">(</span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="functiontext">Problems::Fatal::exit</span><span class="plain">(1);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::memory_allocation_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">what_has_run_out</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">what_has_run_out</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">""</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I am unable to persuade this computer to let me have memory in "</span>
<span class="string">"which to store the %1. This rarely happens on a modern desktop or laptop, "</span>
<span class="string">"but might occur on a small handheld device - if so, it may be a "</span>
<span class="string">"symptom that the device isn't powerful enough to run me. (See how "</span>
<span class="string">"I pass the blame?)"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="functiontext">Problems::write_reports</span><span class="plain">(</span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="functiontext">Problems::Fatal::exit</span><span class="plain">(1);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::limit_problem appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::memory_allocation_problem appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Problem messages unlocated in the source text. </b>And now the regular problem messages, the ones which are not my fault.
We begin with lexical problems happening when the run is hardly begun:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::lexical_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">concerning</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">exp</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">lexical_explanation</span><span class="plain"> =</span>
<span class="string">"This is a low-level problem happening when I am still reading in the "</span>
<span class="string">"source. Such problems sometimes arise because I have been told to "</span>
<span class="string">"read a source file which is not text at all."</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exp</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">lexical_explanation</span><span class="plain"> = </span><span class="identifier">exp</span><span class="plain">;</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">concerning</span><span class="plain">) </span><span class="functiontext">Problems::quote_wide_text</span><span class="plain">(2, </span><span class="identifier">concerning</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">current_sentence</span><span class="plain">) </span><span class="functiontext">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="string">"&lt;text generated internally&gt;"</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">lexical_explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">lexical_explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1: %2%L.%%%| %3"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::lexical_problem_S</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">concerning</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">exp</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">lexical_explanation</span><span class="plain"> =</span>
<span class="string">"This is a low-level problem happening when I am still reading in the "</span>
<span class="string">"source. Such problems sometimes arise because I have been told to "</span>
<span class="string">"read a source file which is not text at all."</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exp</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">lexical_explanation</span><span class="plain"> = </span><span class="identifier">exp</span><span class="plain">;</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">concerning</span><span class="plain">) </span><span class="functiontext">Problems::quote_stream</span><span class="plain">(2, </span><span class="identifier">concerning</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">current_sentence</span><span class="plain">) </span><span class="functiontext">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="string">"&lt;text generated internally&gt;"</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">lexical_explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">lexical_explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1: %2%L.%%%| %3"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::lexical_problem appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::lexical_problem_S appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>Clearly lexical problems cannot cite positions in the source text, and some
other problems can't either, so:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::unlocated_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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="constant">ACT_ON_SIGIL</span>
<span class="identifier">do_not_locate_problems</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</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="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::unlocated_problem_on_file</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="identifier">do_not_locate_problems</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="string">"%f"</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_stream</span><span class="plain">(1, </span><span class="identifier">fn</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">fn</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::unlocated_problem appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::unlocated_problem_on_file appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Problem messages keyed to positions in the source text. </b>The following routine is used to produce more than 300 different problem
messages, making it the most prolific of all the problem routines: perhaps
that isn't surprising, since it simply quotes the entire sentence at fault
(which is always the current sentence) and issues a message.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"You wrote %1: %Sagain, %%%Lbut %%%2%|, %3"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::sentence_problem is used in <a href="#SP18">&#167;18</a>, <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>And a variant which adds a note in a subsequent paragraph.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::sentence_problem_with_note</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">note</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(4, </span><span class="identifier">note</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"You wrote %1: %Sagain, %%%Lbut %%%2%|, %3 %P%4"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::sentence_problem_with_note appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>And this is a variant which draws particular attention to a word range
which is part of the current sentence.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::sentence_in_detail_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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">char</span><span class="plain"> *</span><span class="identifier">message</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="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, and in particular '%4': %Sagain, %%%Lbut %%%2%|, %3"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::sentence_in_detail_problem appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>A not always helpful problem message which is needed in several places, and
therefore is kept here:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::negative_sentence_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">) {</span>
<span class="functiontext">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">PASS_SIGIL</span><span class="plain">,</span>
<span class="string">"assertions about the initial state of play must be positive, not negative"</span><span class="plain">,</span>
<span class="string">"so 'The cat is an animal' is fine but not 'The cat is not a container'. "</span>
<span class="string">"I have only very feeble powers of deduction - sometimes the implications "</span>
<span class="string">"of a negative statement are obvious to a human reader, but not to me."</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::negative_sentence_problem appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>This is a much more elaborate form of the standard <code class="display"><span class="extract">Problems::Issue::sentence_problem</span></code>,
used when an assertion sentence has gone wrong. Experience from the early
builds of the Public Beta showed that many people tried syntaxes which
Inform did not recognise, and which cause Inform to misread the primary
verb of the sentence. It would then issue a Problem &mdash; because the sentence
would be peculiar &mdash; but this problem report would itself be odd, and
make little sense to the user. So we look to see if the current sentence
is an assertion with a primary verb: and if it is, we hunt through it
for alternative verbs which might have been intended, and try to produce
a message which diagnoses the problem rather better.
</p>
<pre class="display">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">LINGUISTICS_MODULE</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::assertion_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</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">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RTW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; </span> <span class="comment">"rather than" text</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">current_sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">current_sentence</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">) != </span><span class="identifier">AVERB_NT</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(Assertion error reverting to sentence error.)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">PASS_SIGIL</span><span class="plain">, </span><span class="identifier">message</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="plain">}</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(Assertion error: looking for alternative verbs in &lt;%W&gt;.)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">Wordings::trim_both_ends</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain"> != </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">))) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Word::unexpectedly_upper_case</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = &lt;</span><span class="identifier">meaningful</span><span class="plain">-</span><span class="identifier">nonimperative</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">&gt;(</span><span class="identifier">Wordings::from</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</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">j</span><span class="plain"> &gt; 0) </span><span class="identifier">RTW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"You wrote %1: %Sagain, %%%Lbut %%%2%|, %3"</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">RTW</span><span class="plain">)) {</span>
<span class="functiontext">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_wording</span><span class="plain">(5, </span><span class="identifier">RTW</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">( </span> <span class="comment">see also PM_AmbiguousVerb</span>
<span class="string">" %P(It may help to know that I am reading the primary verb here "</span>
<span class="string">"as '%4', not '%5'.)"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Problems::Issue::diagnose_further</span><span class="plain">();</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::diagnose_further</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">current_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="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sqc</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">)) </span><span class="identifier">sqc</span><span class="plain"> += </span><span class="identifier">Word::singly_quoted</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">sqc</span><span class="plain"> &gt;= 2)</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">" %P(I notice what look like single quotation marks in this "</span>
<span class="string">"sentence. If you meant to write some quoted text, it needs to "</span>
<span class="string">"be in double quotes, \</span><span class="plain">"</span><span class="string">like this\</span><span class="plain">"</span><span class="string"> and not 'like this'.)"</span><span class="plain">);</span>
<span class="identifier">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> =</span>
<span class="identifier">ControlStructures::detect</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">)</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">" %P(The way this sentence starts makes me think it might have been "</span>
<span class="string">"intended as part of a rule rather than being a statement about the "</span>
<span class="string">"the way things are at the beginning of play. For example, 'If the "</span>
<span class="string">"player is in the Penalty Zone, say \</span><span class="plain">"</span><span class="string">An alarm sounds.\</span><span class="plain">"</span><span class="string"> is not "</span>
<span class="string">"allowed: it has to be put in the form of a rule showing Inform "</span>
<span class="string">"what circumstances apply - for example 'Every turn: if the player is "</span>
<span class="string">"in the Penalty Zone, say \</span><span class="plain">"</span><span class="string">An alarm sounds.\</span><span class="plain">"</span><span class="string">)"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::assertion_problem appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::diagnose_further appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Definition problems. </b>Sentence problems are a nuisance for "Definition:" definitions, because
those usually occur when the current sentence is rather unhelpfully just the
word "Definition" alone. So we use this routine instead:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::definition_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">q</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">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">q</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"You gave as a definition %1: %Sagain, %%%Lbut %%%2%|, %3"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::adjective_problem</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">SIGIL_ARGUMENTS</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">IX</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">D</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">char</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain">) {</span>
<span class="constant">ACT_ON_SIGIL</span>
<span class="functiontext">Problems::quote_wording</span><span class="plain">(1, </span><span class="identifier">IX</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">D</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(3, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_text</span><span class="plain">(4, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_source</span><span class="plain">(5, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_begin</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"In %5 you defined an adjective by '%1' intending that "</span>
<span class="string">"it would apply to '%2': %Sagain, %%%Lbut %%%3%|, %4"</span><span class="plain">);</span>
<span class="functiontext">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::definition_problem appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::adjective_problem appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Creating the Problems report. </b>We are at last able to print the text which appears at the top of the
Problems report; and this completes the code for errors. In my end is my beginning.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::start_problems_report</span><span class="plain">(</span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_INITIAL_REPORTER</span>
<span class="identifier">PROBLEMS_INITIAL_REPORTER</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Problems::Issue::issue_problems_banner</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">verdict</span><span class="plain">) {</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"BANNER BEGINS"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"table"</span><span class="plain">, </span><span class="string">"cellspacing=\</span><span class="plain">"</span><span class="string">3\</span><span class="plain">"</span><span class="string"> border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> width=\</span><span class="plain">"</span><span class="string">100%%\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"tr"</span><span class="plain">, </span><span class="string">"id=\</span><span class="plain">"</span><span class="string">surround0\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"td"</span><span class="plain">, </span><span class="string">"style=\</span><span class="plain">"</span><span class="string">width:100%%\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"HEADING BEGINS"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">headingbox%s\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">verdict</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">headingtext\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Report on Translation: %s"</span><span class="plain">, </span><span class="identifier">verdict</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">headingrubric\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Produced by %B (build %B)"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"HEADING ENDS"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"td"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"tr"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"table"</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"BANNER ENDS"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Problems::Issue::start_problems_report appears nowhere else.</p>
<p class="endnote">The function Problems::Issue::issue_problems_banner appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-pl2.html">Back to 'Problems, Level 2'</a></li><li><i>(This section ends Chapter 2: Problems.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>