mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
765 lines
73 KiB
HTML
765 lines
73 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>8/ef</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of '8/ie' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#8">Chapter 8: Extensions</a></li><li><b>Including Extensions</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="#SP5">§5. Extension loading</a></li><li><a href="#SP6">§6. Parsing extension version numbers</a></li><li><a href="#SP7">§7. Checking the begins here and ends here sentences</a></li><li><a href="#SP11">§11. Sentence handlers for begins here and ends here</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§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 — something we shall
|
|
do many times, and which we call a "traverse" — 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">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::traverse</span><span class="plain">(</span><span class="reserved">void</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"> > 0) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">ParseTree::traverse_ppni</span><span class="plain">(</span><span class="functiontext">Extensions::Inclusion::visit</span><span class="plain">, &</span><span class="identifier">elder</span><span class="plain">, &</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="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::visit</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">elder</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>
|
|
<<span class="cwebmacro">Replace INCLUDE node with sentence nodes for any extensions required</span> <span class="cwebmacronumber">1.1</span>><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="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">ROOT_NT</span><span class="plain">) {</span>
|
|
<span class="plain">*</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::traverse is used in 1/mr (<a href="1-mr.html#SP4_9">§4.9</a>).</p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::visit appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP1_1"></a><b>§1.1. </b>The INCLUDE node becomes an INCLUSION, which in turn contains the extension's code.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Replace INCLUDE node with sentence nodes for any extensions required</span> <span class="cwebmacronumber">1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">title</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">>down</span><span class="plain">, *</span><span class="identifier">author</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</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::begin_inclusion</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">);</span>
|
|
<span class="functiontext">Extensions::Inclusion::fulfill_request_to_include_extension</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::end_inclusion</span><span class="plain">(</span><span class="identifier">l</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP1">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>Here we parse requests to include one or more extensions. People mostly
|
|
don't avail themselves of the opportunity, but it is legal to include
|
|
several at once, with a line like:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Include Carrots by Peter Rabbit and Green Lettuce by Flopsy Bunny.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">A consequence of this convention is that "and" is not permitted in the
|
|
name of an extension. We might change this some day.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Here's how an individual title is described. The bracketed text is later
|
|
parsed by <platform-qualifier>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="identifier">version</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">> </span><span class="identifier">of</span><span class="plain"> <</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">> | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="identifier">version</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">> </span><span class="identifier">of</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">> | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="plain"><</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">> | ==> -1</span>
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">> ==> -1</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">unversioned</span><span class="plain">> ::=</span>
|
|
<span class="plain"><</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">> ( ... ) | ==> 0; <<</span><span class="identifier">rest1</span><span class="plain">>> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]); <<</span><span class="identifier">rest2</span><span class="plain">>> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1])</span>
|
|
<span class="plain"><</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">> ==> 0; <<</span><span class="identifier">rest1</span><span class="plain">>> = -1; <<</span><span class="identifier">rest2</span><span class="plain">>> = -1</span>
|
|
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="plain"><</span><span class="identifier">quoted</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">> *** | ==> </span><<span class="cwebmacro">Issue PM_IncludeExtQuoted problem</span> <span class="cwebmacronumber">2.1</span>>
|
|
<span class="plain">... ==> 0; <<</span><span class="identifier">t1</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="identifier">t2</span><span class="plain">>> = </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="SP2_1"></a><b>§2.1. </b>Quite a popular mistake, this:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_IncludeExtQuoted problem</span> <span class="cwebmacronumber">2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain"><<</span><span class="identifier">t1</span><span class="plain">>> = -1; <<</span><span class="identifier">t2</span><span class="plain">>> = -1;</span>
|
|
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_IncludeExtQuoted</span><span class="plain">),</span>
|
|
<span class="string">"the name of an included extension should be given without double "</span>
|
|
<span class="string">"quotes in an Include sentence"</span><span class="plain">,</span>
|
|
<span class="string">"so for instance 'Include Oh My God by Janice Bing.' rather than "</span>
|
|
<span class="string">"'Include \</span><span class="plain">"</span><span class="string">Oh My God\</span><span class="plain">"</span><span class="string"> by Janice Bing.')"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP2">§2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>This internal parses version text such as "12/110410".
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">version</span><span class="plain">> </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="SP4"></a><b>§4. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::fulfill_request_to_include_extension</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">auth_p</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">AND_NT</span><span class="plain">) {</span>
|
|
<span class="functiontext">Extensions::Inclusion::fulfill_request_to_include_extension</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">>down</span><span class="plain">, </span><span class="identifier">auth_p</span><span class="plain">);</span>
|
|
<span class="functiontext">Extensions::Inclusion::fulfill_request_to_include_extension</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain">, </span><span class="identifier">auth_p</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain"><<</span><span class="identifier">rest1</span><span class="plain">>> = -1; <<</span><span class="identifier">rest2</span><span class="plain">>> = -1;</span>
|
|
<span class="plain"><<</span><span class="identifier">t1</span><span class="plain">>> = -1; <<</span><span class="identifier">t2</span><span class="plain">>> = -1;</span>
|
|
<span class="plain"><</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">>(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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">(<<</span><span class="identifier">t1</span><span class="plain">>>, <<</span><span class="identifier">t2</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">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">auth_p</span><span class="plain">);</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(<<</span><span class="identifier">rest1</span><span class="plain">>>, <<</span><span class="identifier">rest2</span><span class="plain">>>);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_word</span><span class="plain"> = <<</span><span class="identifier">r</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">W</span><span class="plain">)) </span><<span class="cwebmacro">Fulfill request to include a single extension</span> <span class="cwebmacronumber">4.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::fulfill_request_to_include_extension is used in <a href="#SP1_1">§1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4_1"></a><b>§4.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 ParseTree::graft the new material on to the
|
|
parse tree.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Fulfill request to include a single extension</span> <span class="cwebmacronumber">4.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">version_word</span><span class="plain"> >= 0)</span>
|
|
<span class="functiontext">Extensions::Inclusion::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="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">requested_extension</span><span class="plain"> =</span>
|
|
<span class="functiontext">Extensions::Inclusion::load</span><span class="plain">(</span><span class="identifier">AW</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">version_word</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">requested_extension</span><span class="plain">-</span><span class="element">>body_text_unbroken</span><span class="plain">) {</span>
|
|
<span class="identifier">Sentences::break</span><span class="plain">(</span><span class="identifier">requested_extension</span><span class="plain">-</span><span class="element">>body_text</span><span class="plain">, </span><span class="identifier">requested_extension</span><span class="plain">);</span>
|
|
<span class="identifier">requested_extension</span><span class="plain">-</span><span class="element">>body_text_unbroken</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">This code is used in <a href="#SP4">§4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. Extension loading. </b>Extensions are loaded here.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="functiontext">Extensions::Inclusion::load</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">T</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_word</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">VMW</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">ef</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">, </span><span class="reserved">extension_file</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>author_text</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">)) && (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>title_text</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)))</span>
|
|
<<span class="cwebmacro">This is an extension already loaded, so note any version number hike and return</span> <span class="cwebmacronumber">5.1</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">ef</span><span class="plain"> = </span><span class="functiontext">Extensions::Files::new</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">VMW</span><span class="plain">, </span><span class="identifier">version_word</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == 0)</span>
|
|
<<span class="cwebmacro">Read the extension file into the lexer, and break it into body and documentation</span> <span class="cwebmacronumber">5.2</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ef</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::load is used in <a href="#SP4_1">§4.1</a>, 8/ed2 (<a href="8-ed2.html#SP3_1">§3.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_1"></a><b>§5.1. </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.
|
|
(This is why version numbers are not checked at load time: in general, we
|
|
can't know at load time what we will ultimately require.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">This is an extension already loaded, so note any version number hike and return</span> <span class="cwebmacronumber">5.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::Inclusion::parse_version</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>min_version_needed</span><span class="plain">) <</span>
|
|
<span class="functiontext">Extensions::Inclusion::parse_version</span><span class="plain">(</span><span class="identifier">version_word</span><span class="plain">)) {</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>min_version_needed</span><span class="plain"> = </span><span class="identifier">version_word</span><span class="plain">;</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>inclusion_sentence</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ef</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5">§5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_2"></a><b>§5.2. </b>We finally make our call out of the Extensions section, down through the
|
|
trap-door into Read Source Text, to seek and open the file.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Read the extension file into the lexer, and break it into body and documentation</span> <span class="cwebmacronumber">5.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">synopsis</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Concoct a synopsis for the extension to be read</span> <span class="cwebmacronumber">5.2.1</span>><span class="plain">;</span>
|
|
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="functiontext">SourceFiles::read_extension_source_text</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">, </span><span class="identifier">census_mode</span><span class="plain">)) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ORIGIN_WAS_USER_EXTENSIONS_AREA</span><span class="plain">:</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>loaded_from_built_in_area</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA</span><span class="plain">:</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>loaded_from_built_in_area</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">default</span><span class="plain">: </span> <span class="comment">which can happen if the extension file cannot be found</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>loaded_from_built_in_area</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">EXW</span><span class="plain"> = </span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</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">EXW</span><span class="plain">)) </span><<span class="cwebmacro">Break the extension's text into body and documentation</span> <span class="cwebmacronumber">5.2.3</span>><span class="character">;</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">synopsis</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5">§5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_2_1"></a><b>§5.2.1. </b>We concoct a textual synopsis in the form
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">"Pantomime Sausages by Mr Punch"</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">to be used by <code class="display"><span class="extract">SourceFiles::read_extension_source_text</span></code> for printing to <code class="display"><span class="extract">stdout</span></code>. Since
|
|
we dare not assume <code class="display"><span class="extract">stdout</span></code> can manage characters outside the basic ASCII
|
|
range, we flatten them from general ISO to plain ASCII.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Concoct a synopsis for the extension to be read</span> <span class="cwebmacronumber">5.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">synopsis</span><span class="plain">, </span><span class="string">"%+W by %+W"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">)</span>
|
|
<span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">,</span>
|
|
<span class="identifier">Characters::make_filename_safe</span><span class="plain">(</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_2">§5.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_2_2"></a><b>§5.2.2. </b>If an extension file contains the special text (outside literal mode) of
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">---- Documentation ----</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">then this is taken as the end of the Inform source, and the beginning of a
|
|
snippet of documentation about the extension; text from that point on is
|
|
saved until later, but not broken into sentences for the parse tree, and it
|
|
is therefore invisible to the rest of Inform. If this division line is not
|
|
present then the extension contains only body source and no documentation.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">body</span><span class="plain">> ::=</span>
|
|
<span class="plain">*** ---- </span><span class="identifier">documentation</span><span class="plain"> ---- ... | ==> </span><span class="identifier">TRUE</span>
|
|
<span class="plain">... ==> </span><span class="identifier">FALSE</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_2_3"></a><b>§5.2.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Break the extension's text into body and documentation</span> <span class="cwebmacronumber">5.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">body</span><span class="plain">>(</span><span class="identifier">EXW</span><span class="plain">);</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>body_text</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">body</span><span class="plain">>, 1);</span>
|
|
<span class="reserved">if</span><span class="plain"> (<<</span><span class="identifier">r</span><span class="plain">>>) </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>documentation_text</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">body</span><span class="plain">>, 2);</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>body_text_unbroken</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">mark this to be sentence-broken</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_2">§5.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Parsing extension version numbers. </b>Extensions can have versions in the form N/DDDDDD, a format which was chosen
|
|
for sentimental reasons: IF enthusiasts know it well from the banner text of
|
|
the Infocom titles of the 1980s. This story file, for instance, was compiled
|
|
at the time of the Reykjavik summit between Presidents Gorbachev and Reagan:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Moonmist</span>
|
|
<span class="plain">Infocom interactive fiction - a mystery story</span>
|
|
<span class="plain">Copyright (c) 1986 by Infocom, Inc. All rights reserved.</span>
|
|
<span class="plain">Moonmist is a trademark of Infocom, Inc.</span>
|
|
<span class="plain">Release number 9 / Serial number 861022</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">Story file collectors customarily abbreviate this in catalogues to <code class="display"><span class="extract">9/861022</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">In our scheme, DDDDDD can be omitted (in which case so must the slash be).
|
|
Spacing is not allowed around the slash (if present), so the version number
|
|
always occupies a single lexical word.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The following routine parses the version number at word <code class="display"><span class="extract">vwn</span></code> to give an
|
|
non-negative integer — in fact it really just construes the whole thing,
|
|
with the slash removed, as a 7-digit number — in such a way that an earlier
|
|
version always has a lower integer than a later one. It is legal for <code class="display"><span class="extract">vwn</span></code>
|
|
to be -1, which means "no version number quoted", and evaluates as
|
|
0 — corresponding to <code class="display"><span class="extract">0/000000</span></code>, lower than the lowest version number it is
|
|
legal to quote explicitly, which is <code class="display"><span class="extract">1</span></code>. (It follows that requiring no
|
|
version in particular is equivalent to requiring <code class="display"><span class="extract">0/000000</span></code> or better, since
|
|
every extension passes that test.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">In order that the numerical form of a version number should be a signed
|
|
32-bit integer which does not overflow, we require that the release number
|
|
<code class="display"><span class="extract">N</span></code> be at most 999. It could in fact rise to 2146 without incident, but
|
|
it seems cleaner to constrain the number of digits than the value.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_VERSION_NUMBER_LENGTH</span><span class="plain"> 10 </span> <span class="comment">for <code class="display"><span class="extract">999/991231</span></code></span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::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="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">rv</span><span class="plain">, </span><span class="identifier">slashes</span><span class="plain"> = 0, </span><span class="identifier">digits</span><span class="plain"> = 0, </span><span class="identifier">slash_at</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, *</span><span class="identifier">q</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vwn</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">an unspecified version equates to <code class="display"><span class="extract">0/000000</span></code></span>
|
|
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">vwn</span><span class="plain">); </span><span class="identifier">q</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] != 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'/'</span><span class="plain">) {</span>
|
|
<span class="identifier">slashes</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain"> == 0) || (</span><span class="identifier">slashes</span><span class="plain"> > 1)) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Malformed</span><span class="plain">;</span>
|
|
<span class="identifier">slash_at</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; </span><span class="identifier">q</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">+1;</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">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]))) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Malformed</span><span class="plain">;</span>
|
|
<span class="identifier">digits</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'0'</span><span class="plain">) || (</span><span class="identifier">digits</span><span class="plain"> == 0)) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Malformed</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">slashes</span><span class="plain"> == 0) && (</span><span class="identifier">digits</span><span class="plain"> <= 3)) </span> <span class="comment">so that <code class="display"><span class="extract">p</span></code> points to 1 to 3 digits, not starting with <code class="display"><span class="extract">0</span></code></span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Wide::atoi</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)*1000000;</span>
|
|
<span class="identifier">p</span><span class="plain">[</span><span class="identifier">slash_at</span><span class="plain">] = 0; </span> <span class="comment">temporarily replace the slash with a null, making <code class="display"><span class="extract">p</span></code> and <code class="display"><span class="extract">q</span></code> distinct C strings</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) > 3) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Malformed</span><span class="plain">; </span> <span class="comment">now <code class="display"><span class="extract">p</span></code> points to 1 to 3 digits, not starting with <code class="display"><span class="extract">0</span></code></span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">q</span><span class="plain">) != 6) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Malformed</span><span class="plain">;</span>
|
|
<span class="reserved">while</span><span class="plain"> (*</span><span class="identifier">q</span><span class="plain"> == </span><span class="character">'0'</span><span class="plain">) </span><span class="identifier">q</span><span class="plain">++; </span> <span class="comment">now <code class="display"><span class="extract">q</span></code> points to 0 to 6 digits, not starting with <code class="display"><span class="extract">0</span></code></span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">q</span><span class="plain">[0] == 0) </span><span class="identifier">q</span><span class="plain">--; </span> <span class="comment">if it was 0 digits, backspace to make it a single digit <code class="display"><span class="extract">0</span></code></span>
|
|
<span class="identifier">rv</span><span class="plain"> = (</span><span class="identifier">Wide::atoi</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)*1000000) + </span><span class="identifier">Wide::atoi</span><span class="plain">(</span><span class="identifier">q</span><span class="plain">);</span>
|
|
<span class="identifier">p</span><span class="plain">[</span><span class="identifier">slash_at</span><span class="plain">] = </span><span class="character">'/'</span><span class="plain">; </span> <span class="comment">put the slash back over the null byte temporarily dividing the string</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
|
|
|
|
<span class="identifier">Malformed</span><span class="plain">: </span><<span class="cwebmacro">Issue a problem message for a malformed version number</span> <span class="cwebmacronumber">6.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::parse_version is used in <a href="#SP4_1">§4.1</a>, <a href="#SP5_1">§5.1</a>, <a href="#SP9">§9</a>, 8/ef (<a href="8-ef.html#SP18">§18</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_1"></a><b>§6.1. </b>Because we tend to call <code class="display"><span class="extract">Extensions::Inclusion::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">
|
|
<<span class="cwebmacrodefn">Issue a problem message for a malformed version number</span> <span class="cwebmacronumber">6.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Offending word number %d <%N>\</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="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtVersionMalformed</span><span class="plain">),</span>
|
|
<span class="string">"a version number must have the form N/DDDDDD"</span><span class="plain">,</span>
|
|
<span class="string">"as in the example '2/040426' for release 2 made on 26 April 2004. "</span>
|
|
<span class="string">"(The DDDDDD part is optional, so '3' is a legal version number too. "</span>
|
|
<span class="string">"N must be between 1 and 999: in particular, there is no version 0.)"</span><span class="plain">);</span>
|
|
<span class="identifier">Vocabulary::change_text_of_word</span><span class="plain">(</span><span class="identifier">vwn</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"1"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> 1000000; </span> <span class="comment">which equates to <code class="display"><span class="extract">1/000000</span></code></span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. 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="SP8"></a><b>§8. </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"><</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">> ::=</span>
|
|
<span class="plain"><</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">> </span><span class="identifier">by</span><span class="plain"> ... | ==> </span><span class="identifier">R</span><span class="plain">[1]; <<</span><span class="identifier">auth1</span><span class="plain">>> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]); <<</span><span class="identifier">auth2</span><span class="plain">>> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]);</span>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue PM_ExtMiswordedBeginsHere problem</span> <span class="cwebmacronumber">8.1</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_1"></a><b>§8.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_ExtMiswordedBeginsHere problem</span> <span class="cwebmacronumber">8.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain"><<</span><span class="identifier">auth1</span><span class="plain">>> = -1; <<</span><span class="identifier">auth2</span><span class="plain">>> = -1;</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtMiswordedBeginsHere</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"has a misworded 'begins here' sentence ('%2'), which contains "</span>
|
|
<span class="string">"no 'by'. Recall that every extension should begin with a "</span>
|
|
<span class="string">"sentence such as 'Quantum Mechanics by Max Planck begins "</span>
|
|
<span class="string">"here.', and end with a matching 'Quantum Mechanics ends "</span>
|
|
<span class="string">"here.', perhaps with documentation to follow."</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::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">extension_file</span><span class="plain"> *</span><span class="identifier">ef</span><span class="plain">) {</span>
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">; </span> <span class="comment">in case problem messages need to be issued</span>
|
|
<span class="functiontext">Problems::quote_extension</span><span class="plain">(1, </span><span class="identifier">ef</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">));</span>
|
|
|
|
<span class="plain"><</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">>(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</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">(<<</span><span class="identifier">t1</span><span class="plain">>>, <<</span><span class="identifier">t2</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::new</span><span class="plain">(<<</span><span class="identifier">auth1</span><span class="plain">>>, <<</span><span class="identifier">auth2</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">AW</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>version_loaded</span><span class="plain"> = <<</span><span class="identifier">r</span><span class="plain">>>;</span>
|
|
<span class="identifier">ef</span><span class="plain">-</span><span class="element">>VM_restriction_text</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(<<</span><span class="identifier">rest1</span><span class="plain">>>, <<</span><span class="identifier">rest2</span><span class="plain">>>);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>version_loaded</span><span class="plain"> >= 0) </span><span class="functiontext">Extensions::Inclusion::parse_version</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>version_loaded</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">ef</span><span class="plain">-</span><span class="element">>VM_restriction_text</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Check that the extension's stipulation about the virtual machine can be met</span> <span class="cwebmacronumber">9.1</span>><span class="character">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>title_text</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="plain">(</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>author_text</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Issue a problem message pointing out that name and author do not agree with filename</span> <span class="cwebmacronumber">9.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::check_begins_here is used in 7/ss (<a href="7-ss.html#SP4">§4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9_1"></a><b>§9.1. </b>On the other hand, we do already know what virtual machine we are compiling
|
|
for, so we can immediately object if the loaded extension cannot be used
|
|
with our VM de jour.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check that the extension's stipulation about the virtual machine can be met</span> <span class="cwebmacronumber">9.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">>(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>VM_restriction_text</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (<<</span><span class="identifier">r</span><span class="plain">>> == </span><span class="constant">PLATFORM_UNMET_HQ</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Issue a problem message saying that the VM does not meet requirements</span> <span class="cwebmacronumber">9.1.2</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<<span class="cwebmacro">Issue a problem message saying that the VM requirements are malformed</span> <span class="cwebmacronumber">9.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP9">§9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9_2"></a><b>§9.2. </b>Suppose we wanted Onion Cookery by Delia Smith. We loaded the extension
|
|
file called Onion Cookery in the Delia Smith folder of the (probably external)
|
|
extensions area: but suppose that file turns out instead to be French Cuisine
|
|
by Elizabeth David, according to its "begins here" sentence? Then the
|
|
following problem message is produced:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message pointing out that name and author do not agree with filename</span> <span class="cwebmacronumber">9.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Problems::quote_extension</span><span class="plain">(1, </span><span class="identifier">ef</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtMisidentified</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"The extension %1, which your source text makes use of, seems to be "</span>
|
|
<span class="string">"misidentified: its 'begins here' sentence declares it as '%2'. "</span>
|
|
<span class="string">"(Perhaps it was wrongly installed?)"</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP9">§9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9_1_1"></a><b>§9.1.1. </b>See Virtual Machines for the grammar of what can be given as a VM
|
|
requirement.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message saying that the VM requirements are malformed</span> <span class="cwebmacronumber">9.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Problems::quote_extension</span><span class="plain">(1, </span><span class="identifier">ef</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>VM_restriction_text</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtMalformedVM</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"Your source text makes use of the extension %1: but my copy "</span>
|
|
<span class="string">"stipulates that it is '%2', which is a description of the required "</span>
|
|
<span class="string">"story file format which I can't understand, and should be "</span>
|
|
<span class="string">"something like '(for Z-machine version 5 or 8 only)'."</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP9_1">§9.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9_1_2"></a><b>§9.1.2. </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">
|
|
<<span class="cwebmacrodefn">Issue a problem message saying that the VM does not meet requirements</span> <span class="cwebmacronumber">9.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>inclusion_sentence</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>title_text</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>author_text</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>VM_restriction_text</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtInadequateVM</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"You wrote %1: but my copy of %2 by %3 stipulates that it "</span>
|
|
<span class="string">"is '%4'. That means it can only be used with certain of "</span>
|
|
<span class="string">"the possible compiled story file formats, and at the "</span>
|
|
<span class="string">"moment, we don't fit the requirements. (You can change "</span>
|
|
<span class="string">"the format used for this project on the Settings panel.)"</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP9_1">§9.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </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="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::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">extension_file</span><span class="plain"> *</span><span class="identifier">ef</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">Articles::remove_the</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"> ((</span><span class="identifier">problem_count</span><span class="plain"> == 0) && (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">-</span><span class="element">>title_text</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="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">;</span>
|
|
<span class="functiontext">Problems::quote_extension</span><span class="plain">(1, </span><span class="identifier">ef</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ExtMisidentifiedEnds</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"The extension %1, which your source text makes use of, seems to be "</span>
|
|
<span class="string">"malformed: its 'begins here' sentence correctly identifies it, but "</span>
|
|
<span class="string">"then the 'ends here' sentence calls it '%2' instead. (They need "</span>
|
|
<span class="string">"to be a matching pair except that the end does not name the "</span>
|
|
<span class="string">"author: for instance, 'Hocus Pocus by Jan Ackerman begins here.' "</span>
|
|
<span class="string">"would match with 'Hocus Pocus ends here.')"</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::check_ends_here is used in 7/ss (<a href="7-ss.html#SP4">§4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. Sentence handlers for begins here and ends here. </b>The main traverses of the assertions are handled by code which calls
|
|
"sentence handler" routines on each node in turn, depending on type.
|
|
Here are the handlers for BEGINHERE and ENDHERE. As can be seen, all
|
|
we really do is start again from a clean piece of paper.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that, because one extension can include another, these nodes may
|
|
well be interleaved: we might find the sequence A begins, B begins,
|
|
B ends, A ends. The careful checking done so far ensures that these
|
|
will always properly nest. We don't at present make use of this, but
|
|
we might in future.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">BEGINHERE_SH_handler</span><span class="plain"> =</span>
|
|
<span class="plain">{ </span><span class="identifier">BEGINHERE_NT</span><span class="plain">, -1, 0, </span><span class="functiontext">Extensions::Inclusion::handle_extension_begins</span><span class="plain"> };</span>
|
|
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">ENDHERE_SH_handler</span><span class="plain"> =</span>
|
|
<span class="plain">{ </span><span class="identifier">ENDHERE_NT</span><span class="plain">, -1, 0, </span><span class="functiontext">Extensions::Inclusion::handle_extension_ends</span><span class="plain"> };</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::handle_extension_begins</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="functiontext">Assertions::Traverse::new_discussion</span><span class="plain">(); </span><span class="identifier">near_start_of_extension</span><span class="plain"> = 1;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Inclusion::handle_extension_ends</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">near_start_of_extension</span><span class="plain"> = 0;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::handle_extension_begins appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Extensions::Inclusion::handle_extension_ends appears nowhere else.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="8-ef.html">Back to 'Extension Files'</a></li><li><a href="8-ei.html">Continue with 'Extension Identifiers'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|