1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/inbuild-module/6-inc.html
2020-03-26 19:22:26 +00:00

578 lines
64 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>6/hdn</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 '6/inc' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">inbuild</a></li><li><a href="index.html#6">Chapter 6: Handling Inform Source Text</a></li><li><b>Inclusions</b></li></ul><p class="purpose">To fulfill requests to include extensions, adding their material to the parse tree as needed, and removing INCLUDE nodes.</p>
<ul class="toc"><li><a href="#SP6">&#167;6. Extension loading</a></li><li><a href="#SP8">&#167;8. Checking the begins here and ends here sentences</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>At this point in the narrative of a typical run of Inform, we have read in the
source text supplied by the user. The lexer automatically prefaced this with
"Include Standard Rules by Graham Nelson", and the sentence-breaker
converted all such sentences to nodes of type <code class="display"><span class="extract">INCLUDE_NT</span></code> which are
children of the parse tree root. (The eldest child, therefore, is the
Standard Rules inclusion.)
</p>
<p class="inwebparagraph">We now look through the parse tree in sentence order &mdash; something we shall
do many times, and which we call a "traverse" &mdash; and look for INCLUDE
nodes. Each is replaced with a mass of further nodes for the material in
whatever new extensions were required. This process is repeated until there
are no "Include" sentences left. In principle this could go on forever if
A includes B which includes A, or some such, but we log each extension read
in to ensure that nothing is read twice.
</p>
<p class="inwebparagraph">At the end of this routine, provided no Problems have been issued, there are
guaranteed to be no INCLUDE nodes remaining in the parse tree.
</p>
<pre class="display">
<span class="reserved">inbuild_copy</span><span class="plain"> *</span><span class="identifier">inclusions_errors_to</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">Inclusions::traverse</span><span class="plain">(</span><span class="reserved">inbuild_copy</span><span class="plain"> *</span><span class="identifier">C</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">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">includes_cleared</span><span class="plain">;</span>
<span class="reserved">do</span><span class="plain"> {</span>
<span class="identifier">includes_cleared</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">problem_count</span><span class="plain"> &gt; 0) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">ParseTree::traverse_ppni</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">Inclusions::visit</span><span class="plain">, &amp;</span><span class="identifier">includes_cleared</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">while</span><span class="plain"> (</span><span class="identifier">includes_cleared</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="functiontext">Inclusions::spawned_from_vertex</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">H0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">H0</span><span class="plain">) {</span>
<span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">ParseTree::get_inclusion_of_extension</span><span class="plain">(</span><span class="identifier">H0</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ext</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">-</span><span class="element">&gt;vertex</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inclusions_errors_to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no H0 ext or inclusion"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">inclusions_errors_to</span><span class="plain">-</span><span class="element">&gt;vertex</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Inclusions::visit</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">parse_node</span><span class="plain"> *</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">includes_cleared</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">INCLUDE_NT</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Replace INCLUDE node with sentence nodes for any extensions required</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
<span class="plain">*</span><span class="identifier">includes_cleared</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::traverse is used in 4/em (<a href="4-em.html#SP9">&#167;9</a>), 5/ps (<a href="5-ps.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function Inclusions::spawned_from_vertex is used in <a href="#SP1_1">&#167;1.1</a>, <a href="#SP6_1">&#167;6.1</a>.</p>
<p class="endnote">The function Inclusions::visit appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>The INCLUDE node becomes an INCLUSION, which in turn contains the extension's code.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Replace INCLUDE node with sentence nodes for any extensions required</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (!(&lt;</span><span class="identifier">structural</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">))))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"malformed INCLUDE"</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">title</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">structural</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">&gt;, 1);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">author</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">structural</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">&gt;, 2);</span>
<span class="identifier">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">INCLUSION_NT</span><span class="plain">); </span><span class="identifier">pn</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="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain"> = </span><span class="identifier">ParseTree::push_attachment_point</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="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">Inclusions::fulfill_request_to_include_extension</span><span class="plain">(</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">author</span><span class="plain">);</span>
<span class="identifier">ParseTree::pop_attachment_point</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">l</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span><span class="identifier">c</span><span class="plain">; </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain">-</span><span class="element">&gt;next</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">c</span><span class="plain">) == </span><span class="identifier">HEADING_NT</span><span class="plain">)</span>
<span class="identifier">ParseTree::set_inclusion_of_extension</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">last_H0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="identifier">implied_heading_ANNOT</span><span class="plain">) != </span><span class="identifier">TRUE</span><span class="plain">)) {</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">Inclusions::spawned_from_vertex</span><span class="plain">(</span><span class="identifier">last_H0</span><span class="plain">);</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">EV</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">-</span><span class="element">&gt;vertex</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;buildable_if_copy</span><span class="plain">-</span><span class="element">&gt;edition</span><span class="plain">-</span><span class="element">&gt;work</span><span class="plain">-</span><span class="element">&gt;genre</span><span class="plain"> == </span><span class="identifier">extension_genre</span><span class="plain">)</span>
<span class="functiontext">Graphs::need_this_to_use</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">EV</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Graphs::need_this_to_build</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">EV</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b></p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">IncludeExtQuoted_SYNERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">BogusExtension_SYNERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">ExtVersionTooLow_SYNERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">ExtVersionMalformed_SYNERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">ExtInadequateVM_SYNERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">ExtMisidentifiedEnds_SYNERROR</span>
</pre>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Here we parse requests to include extensions.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">title</span><span class="plain">-</span><span class="identifier">and</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt; ::=</span>
<span class="identifier">version</span><span class="plain"> &lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt; </span><span class="identifier">of</span><span class="plain"> &lt;</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="identifier">version</span><span class="plain"> &lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt; </span><span class="identifier">of</span><span class="plain"> &lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">&gt; | ==&gt; -1</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">&gt; ==&gt; -1</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">-</span><span class="identifier">inner</span><span class="plain">&gt; ( ... ) | ==&gt; 0</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">-</span><span class="identifier">inner</span><span class="plain">&gt; ==&gt; 0</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">-</span><span class="identifier">inner</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">quoted</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">&gt; *** | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_IncludeExtQuoted problem</span> <span class="cwebmacronumber">3.1</span>&gt;
<span class="plain">... ==&gt; 0; &lt;&lt;</span><span class="identifier">t1</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">); &lt;&lt;</span><span class="identifier">t2</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. </b>Quite a popular mistake, this:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_IncludeExtQuoted problem</span> <span class="cwebmacronumber">3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">&lt;&lt;</span><span class="identifier">t1</span><span class="plain">&gt;&gt; = -1; &lt;&lt;</span><span class="identifier">t2</span><span class="plain">&gt;&gt; = -1;</span>
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">IncludeExtQuoted_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>This internal parses version text such as "12/110410".
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> 1 {</span>
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">); </span> <span class="comment">actually, defer parsing by returning a word number here</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b></p>
<pre class="display">
<span class="reserved">inform_extension</span><span class="plain"> *</span><span class="functiontext">Inclusions::fulfill_request_to_include_extension</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">TW</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="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">&lt;&lt;</span><span class="identifier">t1</span><span class="plain">&gt;&gt; = -1; &lt;&lt;</span><span class="identifier">t2</span><span class="plain">&gt;&gt; = -1;</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">title</span><span class="plain">-</span><span class="identifier">and</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt;(</span><span class="identifier">TW</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(&lt;&lt;</span><span class="identifier">t1</span><span class="plain">&gt;&gt;, &lt;&lt;</span><span class="identifier">t2</span><span class="plain">&gt;&gt;);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_word</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Fulfill request to include a single extension</span> <span class="cwebmacronumber">5.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::fulfill_request_to_include_extension is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b>A request consists of author, name and version, the latter being optional.
We obtain the extension file structure corresponding to this: it may have
no text at all (for instance if Inform could not open the file), or it may be
one we have seen before, thanks to an earlier inclusion. Only when it
provided genuinely new text will its <code class="display"><span class="extract">body_text_unbroken</span></code> flag be set,
and then we call the sentence-breaker to graft the new material on to the
parse tree.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fulfill request to include a single extension</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">version_word</span><span class="plain"> &gt;= 0)</span>
<span class="functiontext">Inclusions::parse_version</span><span class="plain">(</span><span class="identifier">version_word</span><span class="plain">); </span> <span class="comment">this checks the formatting of the version number</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain">);</span>
<span class="reserved">inbuild_work</span><span class="plain"> *</span><span class="identifier">work</span><span class="plain"> = </span><span class="functiontext">Works::new</span><span class="plain">(</span><span class="identifier">extension_genre</span><span class="plain">, </span><span class="identifier">exft</span><span class="plain">, </span><span class="identifier">exfa</span><span class="plain">);</span>
<span class="functiontext">Works::add_to_database</span><span class="plain">(</span><span class="identifier">work</span><span class="plain">, </span><span class="constant">LOADED_WDBC</span><span class="plain">);</span>
<span class="identifier">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="identifier">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">version_word</span><span class="plain"> &gt;= 0) </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">Inclusions::parse_version</span><span class="plain">(</span><span class="identifier">version_word</span><span class="plain">);</span>
<span class="identifier">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">VersionNumberRanges::compatibility_range</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="reserved">inbuild_requirement</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain"> = </span><span class="functiontext">Requirements::new</span><span class="plain">(</span><span class="identifier">work</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">);</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">Inclusions::load</span><span class="plain">(</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="identifier">current_sentence</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Extension loading. </b>Note that we ignore a request for an extension which has already been
loaded, except if the new request ups the ante in terms of the minimum
version permitted: in which case we need to record that the requirement has
been tightened. That is, if we previously wanted version 2 of Pantomime
Sausages by Mr Punch, and loaded it, but then read the sentence
</p>
<blockquote>
<p>Include version 3 of Pantomime Sausages by Mr Punch.</p>
</blockquote>
<p class="inwebparagraph">then we need to note that the version requirement on PS has been raised to 3.
</p>
<pre class="display">
<span class="reserved">inform_extension</span><span class="plain"> *</span><span class="functiontext">Inclusions::load</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_H0</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="reserved">inbuild_requirement</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">) {</span>
<span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="reserved">inform_extension</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Requirements::meets</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">-</span><span class="element">&gt;edition</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Copies::source_text_has_been_read</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">))) {</span>
<span class="functiontext">Extensions::must_satisfy</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Read the extension file into the lexer, and break it into body and documentation</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::load is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Read the extension file into the lexer, and break it into body and documentation</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">inbuild_search_result</span><span class="plain"> *</span><span class="identifier">search_result</span><span class="plain"> = </span><span class="functiontext">Nests::first_found</span><span class="plain">(</span><span class="identifier">req</span><span class="plain">, </span><span class="functiontext">Inbuild::nest_list</span><span class="plain">());</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">search_result</span><span class="plain">) {</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">ExtensionManager::from_copy</span><span class="plain">(</span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;copy</span><span class="plain">);</span>
<span class="functiontext">Extensions::set_inclusion_sentence</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Nests::get_tag</span><span class="plain">(</span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;nest</span><span class="plain">) == </span><span class="constant">INTERNAL_NEST_TAG</span><span class="plain">)</span>
<span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;loaded_from_built_in_area</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">compatibility_specification</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">-</span><span class="element">&gt;edition</span><span class="plain">-</span><span class="element">&gt;compatibility</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Compatibility::with</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="functiontext">Inbuild::current_vm</span><span class="plain">()) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem message saying that the VM does not meet requirements</span> <span class="cwebmacronumber">6.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LinkedLists::len</span><span class="plain">(</span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;copy</span><span class="plain">-</span><span class="element">&gt;errors_reading_source_text</span><span class="plain">) == 0) {</span>
<span class="functiontext">Copies::read_source_text_for</span><span class="plain">(</span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;copy</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="functiontext">Copies::list_problems_arising</span><span class="plain">(</span><span class="identifier">STDERR</span><span class="plain">, </span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;copy</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
&lt;<span class="cwebmacro">Issue a cannot-find problem</span> <span class="cwebmacronumber">6.1.2</span>&gt;<span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">RV</span><span class="plain"> = </span><span class="functiontext">Graphs::req_vertex</span><span class="plain">(</span><span class="identifier">req</span><span class="plain">);</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">Inclusions::spawned_from_vertex</span><span class="plain">(</span><span class="identifier">last_H0</span><span class="plain">);</span>
<span class="functiontext">Graphs::need_this_to_build</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">RV</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_1_1"></a><b>&#167;6.1.1. </b>Here the problem is not that the extension is broken in some way: it's
just not what we can currently use. Therefore the correction should be a
matter of removing the inclusion, not of altering the extension, so we
report this problem at the inclusion line.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message saying that the VM does not meet requirements</span> <span class="cwebmacronumber">6.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">ExtInadequateVM_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="functiontext">Extensions::get_inclusion_sentence</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">parsed_from</span><span class="plain">;</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6_1">&#167;6.1</a>.</p>
<p class="inwebparagraph"><a id="SP6_1_2"></a><b>&#167;6.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a cannot-find problem</span> <span class="cwebmacronumber">6.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">inbuild_requirement</span><span class="plain"> *</span><span class="identifier">req2</span><span class="plain"> = </span><span class="functiontext">Requirements::any_version_of</span><span class="plain">(</span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;work</span><span class="plain">);</span>
<span class="identifier">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">inbuild_search_result</span><span class="plain">);</span>
<span class="functiontext">Nests::search_for</span><span class="plain">(</span><span class="identifier">req2</span><span class="plain">, </span><span class="functiontext">Inbuild::nest_list</span><span class="plain">(), </span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LinkedLists::len</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">) == 0) {</span>
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">BogusExtension_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">);</span>
<span class="reserved">inbuild_search_result</span><span class="plain"> *</span><span class="identifier">search_result</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">search_result</span><span class="plain">, </span><span class="reserved">inbuild_search_result</span><span class="plain">, </span><span class="identifier">L</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">versions</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">, </span><span class="string">" or "</span><span class="plain">);</span>
<span class="identifier">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="identifier">search_result</span><span class="plain">-</span><span class="element">&gt;copy</span><span class="plain">-</span><span class="element">&gt;edition</span><span class="plain">-</span><span class="element">&gt;version</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">, </span><span class="string">"an unnumbered version"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">, </span><span class="string">"version %v"</span><span class="plain">, &amp;</span><span class="identifier">V</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">ExtVersionTooLow_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">);</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">versions</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6_1">&#167;6.1</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">last_PM_ExtVersionMalformed_at</span><span class="plain"> = -1;</span>
<span class="identifier">semantic_version_number</span><span class="plain"> </span><span class="functiontext">Inclusions::parse_version</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">vwn</span><span class="plain">) {</span>
<span class="identifier">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="identifier">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">vwn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">version</span><span class="plain">-</span><span class="identifier">number</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">semantic_version_number_holder</span><span class="plain"> *</span><span class="identifier">H</span><span class="plain"> = (</span><span class="identifier">semantic_version_number_holder</span><span class="plain"> *) &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">V</span><span class="plain"> = </span><span class="identifier">H</span><span class="plain">-</span><span class="element">&gt;version</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
&lt;<span class="cwebmacro">Issue a problem message for a malformed version number</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::parse_version is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b>Because we tend to call <code class="display"><span class="extract">Inclusions::parse_version</span></code> repeatedly on
the same word, we want to recover tidily from this problem, and not report it
over and over. We do this by altering the text to <code class="display"><span class="extract">1</span></code>, the lowest well-formed
version number text.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a malformed version number</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_PM_ExtVersionMalformed_at</span><span class="plain"> != </span><span class="identifier">vwn</span><span class="plain">) {</span>
<span class="identifier">last_PM_ExtVersionMalformed_at</span><span class="plain"> = </span><span class="identifier">vwn</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Offending word number %d &lt;%N&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">vwn</span><span class="plain">, </span><span class="identifier">vwn</span><span class="plain">);</span>
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">ExtVersionMalformed_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Checking the begins here and ends here sentences. </b>When a newly loaded extension is being sentence-broken, problem messages
will be turned up unless it contains the matching pair of "begins here"
and "ends here" sentences. Assuming it does, the sentence breaker has no
objection, but it also calls the two routines below to verify that these
sentences have the correct format. (The point of this is to catch a malformed
extension at the earliest possible moment after loading it: it's easy to
mis-install extensions, especially if doing so by hand, and the resulting
problem messages could be quite inscrutable if one extension was wrongly
identified as another.)
</p>
<p class="inwebparagraph">First, we check the "begins here" sentence. We also identify where the
version number is given (if it is), and check that we are not trying to
use an extension which is marked as not working on the current VM.
</p>
<p class="inwebparagraph">It is sufficient to try parsing the version number in order to check it:
we throw away the answer, as we can't use it yet, but this will provoke
problem messages if it is malformed.
</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>This parses the subject noun-phrase in the sentence
</p>
<blockquote>
<p>Version 3 of Pantomime Sausages by Mr Punch begins here.</p>
</blockquote>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">begins</span><span class="plain">-</span><span class="identifier">here</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">subject</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">title</span><span class="plain">-</span><span class="identifier">and</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">&gt; </span><span class="identifier">by</span><span class="plain"> ... |</span>
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue problem</span> <span class="cwebmacronumber">9.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="identifier">ExtNoBeginsHere_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Inclusions::check_begins_here</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">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">inbuild_copy</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">inclusions_errors_to</span><span class="plain">;</span>
<span class="identifier">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">begins</span><span class="plain">-</span><span class="identifier">here</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">subject</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">));</span>
<span class="identifier">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::check_begins_here is used in 6/st (<a href="6-st.html#SP11">&#167;11</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Similarly, we check the "ends here" sentence. Here there are no
side-effects: we merely verify that the name matches the one quoted in
the "begins here". We only check this if the problem count is still 0,
since we don't want to keep on nagging somebody who has already been told
that the extension isn't the one he thinks it is.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">the</span><span class="plain">-</span><span class="identifier">prefix</span><span class="plain">-</span><span class="reserved">for</span><span class="plain">-</span><span class="identifier">extensions</span><span class="plain">&gt; ::=</span>
<span class="identifier">the</span><span class="plain"> ...</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Inclusions::check_ends_here</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">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">inbuild_copy</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">inclusions_errors_to</span><span class="plain">;</span>
<span class="identifier">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">the</span><span class="plain">-</span><span class="identifier">prefix</span><span class="plain">-</span><span class="reserved">for</span><span class="plain">-</span><span class="identifier">extensions</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">the</span><span class="plain">-</span><span class="identifier">prefix</span><span class="plain">-</span><span class="reserved">for</span><span class="plain">-</span><span class="identifier">extensions</span><span class="plain">&gt;, 1);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">-</span><span class="element">&gt;as_copy</span><span class="plain">-</span><span class="element">&gt;edition</span><span class="plain">-</span><span class="element">&gt;work</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">problem_count</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="reserved">copy_error</span><span class="plain"> *</span><span class="identifier">CE</span><span class="plain"> = </span><span class="functiontext">Copies::new_error</span><span class="plain">(</span><span class="constant">SYNTAX_CE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;error_subcategory</span><span class="plain"> = </span><span class="constant">ExtMisidentifiedEnds_SYNERROR</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_node</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">;</span>
<span class="identifier">CE</span><span class="plain">-</span><span class="element">&gt;details_W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">);</span>
<span class="functiontext">Copies::attach</span><span class="plain">(</span><span class="identifier">inclusions_errors_to</span><span class="plain">, </span><span class="identifier">CE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">inclusions_errors_to</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Inclusions::check_ends_here is used in 6/st (<a href="6-st.html#SP11">&#167;11</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="6-hdn.html">Back to 'Headings'</a></li><li><a href="6-cs.html">Continue with 'Control Structures'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>