1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/codegen-module/2-itr.html
2019-09-07 20:43:31 +01:00

821 lines
96 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/lnk</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/itr' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">codegen</a></li><li><a href="index.html#2">Chapter 2: Miscellaneous Pipeline Stages</a></li><li><b>I6 Template Reader</b></li></ul><p class="purpose">Inform 6 meta-language is the language used by template files (with extension |.i6t|). It is not itself I6 code, but a list of instructions for making I6 code: most of the content is to be copied over verbatim, but certain escape sequences cause Inform to insert more elaborate material, or to do something active.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Syntax of I6T files</a></li><li><a href="#SP8_8">&#167;8.8. Acting on I6T commands</a></li><li><a href="#SP9">&#167;9. Template errors</a></li><li><a href="#SP10">&#167;10. Intervention</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b></p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_kit</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_bookmark</span><span class="plain"> *</span><span class="identifier">IBM</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_i6t_file_areas</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">i6t_files</span><span class="plain">[16];</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">raw_callback</span><span class="plain">)(</span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_kit</span><span class="plain"> *);</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">command_callback</span><span class="plain">)(</span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_kit</span><span class="plain"> *);</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">I6T_state</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">I6T_kit</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure I6T_kit is accessed in 2/lnk and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The user (or an extension used by the user) is allowed to register gobbets
of I6T code to be used before, instead of, or after any whole segment or
named part of a segment of the template layer: the following structure holds
such a request.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_intervention</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">intervention_stage</span><span class="plain">; </span> <span class="comment">-1 for before, 0 for instead, 1 for after</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">segment_name</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">part_name</span><span class="plain">; </span> <span class="comment">or NULL to mean the entire segment</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">I6T_matter</span><span class="plain">; </span> <span class="comment">to be used at the given position, or NULL</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">alternative_segment</span><span class="plain">; </span> <span class="comment">to be used at the given position, or NULL</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">segment_found</span><span class="plain">; </span> <span class="comment">did the segment name match one actually read?</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">part_found</span><span class="plain">; </span> <span class="comment">did the part name?</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">where_intervention_requested</span><span class="plain">; </span> <span class="comment">at what sentence?</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">I6T_intervention</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure I6T_intervention is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Syntax of I6T files. </b>The syntax of these files has been designed so that a valid I6T file is
also a valid Inweb section file. This means that no tangling is required to
make the I6T files: they can be, and indeed are, simply copied verbatim
from Appendix B of the source web.
</p>
<p class="inwebparagraph">Formally, an I6T file consists of a preamble followed by one or more parts.
The preamble takes the form:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">B/name: Longer Form of Name.</span>
<span class="plain"> </span>
<span class="plain">@Purpose: ...</span>
<span class="plain"> </span>
<span class="plain">@-------------------------------------------------------------------------------</span>
</pre>
<p class="inwebparagraph">(for some number of dashes). Each part begins with a heading line in the form
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">@p Title.</span>
</pre>
<p class="inwebparagraph">At some point during the part, a heading line
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">@c</span>
</pre>
<p class="inwebparagraph">introduces the code of the part. When Inform interprets an I6T file, it ignores
the preamble and the material in every part before the <code class="display"><span class="extract">@c</span></code> heading: these
are commentary.
</p>
<p class="inwebparagraph">It actually doesn't matter if a template file contains lines longer than
this, so long as they do not occur inside <code class="display"><span class="extract">{-lines:...}</span></code> and <code class="display"><span class="extract">{-endlines}</span></code>,
and so long as no individual braced command <code class="display"><span class="extract">{-...}</span></code> exceeds this length.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_I6T_LINE_LENGTH</span><span class="plain"> 1024</span>
</pre>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>We can regard the whole Inform program as basically a filter: it copies its
input, the <code class="display"><span class="extract">Main.i6t</span></code> template file, directly into its output, but making
certain replacements along the way.
</p>
<p class="inwebparagraph">The code portions of <code class="display"><span class="extract">.i6t</span></code> files are basically written in I6, but with a
special escape syntax:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{-command:argument}</span>
</pre>
<p class="inwebparagraph">tells Inform to act immediately on the I6T command given, with the
argument supplied. One of these commands is special:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{-lines:commandname}</span>
</pre>
<p class="inwebparagraph">tells Inform that all subsequent lines in the I6T file, up to the next
<code class="display"><span class="extract">{-endlines}</span></code>, are to be read as a series of arguments for the
<code class="display"><span class="extract">commandname</span></code> command. Thus,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{-lines:admire}</span>
<span class="plain">Jackson Pollock</span>
<span class="plain">Paul Klee</span>
<span class="plain">Wassily Kandinsky</span>
<span class="plain">{-endlines}</span>
</pre>
<p class="inwebparagraph">is a shorthand form for:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{-admire:Jackson Pollock}{-admire:Paul Klee}{-admire:Wassily Kandinsky}</span>
</pre>
<p class="inwebparagraph">The following comment syntax is useful mainly for commenting out commands:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">{-! Something very clever happens next.}</span>
</pre>
<p class="inwebparagraph">The commands all either instruct Inform to do something (say, traverse the
parse tree and convert its assertions to inferences) but output nothing,
or else to compile some I6 code to the output. There are no control structures,
no variables: I6T commands do not amount to a programming language.
</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>I7 expressions can be included in I6T code exactly as in inline invocation
definitions: thus
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">Constant FROG_CLASS = (+ pond-dwelling amphibian +);</span>
</pre>
<p class="inwebparagraph">will expand "pond-dwelling amphibian" into the I6 translation of the kind
of object with this name. Because of this syntax, one has to watch out for
I6 code like so:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">if (++counter_of_some_kind &gt; 0) ...</span>
</pre>
<p class="inwebparagraph">which can trigger an unwanted <code class="display"><span class="extract">(+</span></code>.
</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>It is not quite true that the following routine acts as a filter from
input to output, because:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(i) It skips the preamble and the commentary portion of each part in the input.
</li></ul>
<ul class="items"><li>(ii) It has an <code class="display"><span class="extract">active</span></code> mode, outside of which it ignores most commands and
copies no output &mdash; it begins in active mode and leaves it only when Inform
issues problem messages, so that subsequent commands almost certainly
cannot safely be used. In a successful compilation run, the interpreter
remains in active mode throughout. Otherwise, generally speaking, it goes
into passive mode as soon as an I6T command has resulted in Problem messages,
and then in stays in passive mode until the output file is closed again;
then it goes back into active mode to carry out some shutting-down-gracefully
steps.
</li></ul>
<ul class="items"><li>(iii) The output stream is not always open. In fact, it starts unopened (and
with <code class="display"><span class="extract">OUT</span></code> set to null); two of the I6T commands open and close it. When
the file isn't open, no output can be written, but I6T commands telling Inform
to do something can still take effect: in fact, the <code class="display"><span class="extract">Main.i6t</span></code> file begins
with dozens of I6T commands before the output file is opened, and concludes
with a couple of dozen more after it has been closed.
</li></ul>
<ul class="items"><li>(iv) It can abort, cleanly exiting Inform when it does so, if a global flag
is set as a result of work done by one of its commands. In fact, this is
used only to exit Inform early after performing an extension census when called
with the command line option <code class="display"><span class="extract">-census</span></code>, and can never happen on a compilation
run, whatever problems or disasters may occur.
</li></ul>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The I6T interpreter is a single routine which implements the description
above:
</p>
<pre class="display">
<span class="reserved">I6T_kit</span><span class="plain"> </span><span class="functiontext">TemplateReader::kit_out</span><span class="plain">(</span><span class="identifier">inter_bookmark</span><span class="plain"> *</span><span class="identifier">IBM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">A</span><span class="plain">)(</span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_kit</span><span class="plain"> *),</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">B</span><span class="plain">)(</span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">I6T_kit</span><span class="plain"> *),</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
<span class="reserved">I6T_kit</span><span class="plain"> </span><span class="identifier">kit</span><span class="plain">;</span>
<span class="identifier">kit</span><span class="element">.IBM</span><span class="plain"> = </span><span class="identifier">IBM</span><span class="plain">;</span>
<span class="identifier">kit</span><span class="element">.raw_callback</span><span class="plain"> = </span><span class="identifier">A</span><span class="plain">;</span>
<span class="identifier">kit</span><span class="element">.command_callback</span><span class="plain"> = </span><span class="identifier">B</span><span class="plain">;</span>
<span class="identifier">kit</span><span class="element">.I6T_state</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="identifier">kit</span><span class="element">.no_i6t_file_areas</span><span class="plain"> = 0;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">kit</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateReader::extract</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">template_file</span><span class="plain">, </span><span class="reserved">I6T_kit</span><span class="plain"> *</span><span class="identifier">kit</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">SP</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="functiontext">TemplateReader::interpret</span><span class="plain">(</span><span class="identifier">SP</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">template_file</span><span class="plain">, -1, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="plain">(*(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;raw_callback</span><span class="plain">))(</span><span class="identifier">SP</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateReader::interpret</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sf</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">segment_name</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N_escape</span><span class="plain">,</span>
<span class="reserved">I6T_kit</span><span class="plain"> *</span><span class="identifier">kit</span><span class="plain">) {</span>
<span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">Input_File</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">default_command</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">heading_name</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">skip_part</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">comment</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">col</span><span class="plain"> = 1, </span><span class="identifier">cr</span><span class="plain">, </span><span class="identifier">sfp</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) &gt; 0) </span><span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">BEFORE_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">kit</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">segment_name</span><span class="plain">) &gt; 0) &amp;&amp; (</span><span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">INSTEAD_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">))) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">OmitFile</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">segment_name</span><span class="plain">) &gt; 0) {</span>
&lt;<span class="cwebmacro">Open the I6 template file</span> <span class="cwebmacronumber">8.1</span>&gt;<span class="plain">;</span>
<span class="identifier">comment</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">comment</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">do</span><span class="plain"> {</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="identifier">NewCharacter</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="identifier">EOF</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'@'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">col</span><span class="plain"> == 1)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inweb_syntax</span><span class="plain"> = -1;</span>
&lt;<span class="cwebmacro">Read the rest of line as an at-heading</span> <span class="cwebmacronumber">8.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Act on the at-heading, going in or out of comment mode as appropriate</span> <span class="cwebmacronumber">8.4</span>&gt;<span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">comment</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">default_command</span><span class="plain">) &gt; 0) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == 10) || (</span><span class="identifier">cr</span><span class="plain"> == 13)) </span><span class="reserved">continue</span><span class="plain">; </span> <span class="comment">skip blank lines here</span>
&lt;<span class="cwebmacro">Set the command to the default, and read rest of line as argument</span> <span class="cwebmacronumber">8.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">) == </span><span class="character">'!'</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">) == 0)) </span><span class="reserved">continue</span><span class="plain">; </span> <span class="comment">skip blanks and comments</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"{-endlines}"</span><span class="plain">)) </span><span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">default_command</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>&gt;<span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'{'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read up to the next close brace as an I6T command and argument</span> <span class="cwebmacronumber">8.6</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">) == </span><span class="character">'!'</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>&gt;<span class="plain">;</span>
<span class="reserved">continue</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">cr</span><span class="plain"> == </span><span class="character">'N'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">N_escape</span><span class="plain"> &gt;= 0)) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'}'</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">N_escape</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"{N"</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">NewCharacter</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> { </span> <span class="comment">otherwise the open brace was a literal</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="character">'{'</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">NewCharacter</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'('</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read up to the next plus close-bracket as an I7 expression</span> <span class="cwebmacronumber">8.7</span>&gt;<span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> { </span> <span class="comment">otherwise the open bracket was a literal</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="character">'('</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">NewCharacter</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">while</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> != </span><span class="identifier">EOF</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Input_File</span><span class="plain">) { </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">DL</span><span class="plain">) </span><span class="identifier">STREAM_FLUSH</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">); </span><span class="identifier">fclose</span><span class="plain">(</span><span class="identifier">Input_File</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">heading_name</span><span class="plain">) &gt; 0) &amp;&amp; (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) &gt; 0))</span>
<span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">AFTER_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">heading_name</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="identifier">OmitFile</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">segment_name</span><span class="plain">) &gt; 0) </span><span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">AFTER_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">default_command</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">heading_name</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function TemplateReader::kit_out is used in 2/lnk (<a href="2-lnk.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function TemplateReader::extract is used in 2/lnk (<a href="2-lnk.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function TemplateReader::interpret is used in <a href="#SP8_8_1">&#167;8.8.1</a>, <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP8_1"></a><b>&#167;8.1. </b>We look for the <code class="display"><span class="extract">.i6t</span></code> files first in the materials folder, then in the
installed area and lastly (but almost always) in the built-in resources.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Open the I6 template file</span> <span class="cwebmacronumber">8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Input_File</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">area</span><span class="plain">=0; </span><span class="identifier">area</span><span class="plain">&lt;</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;no_i6t_file_areas</span><span class="plain">; </span><span class="identifier">area</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Input_File</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">Input_File</span><span class="plain"> = </span><span class="identifier">Filenames::fopen</span><span class="plain">(</span>
<span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;i6t_files</span><span class="plain">[</span><span class="identifier">area</span><span class="plain">], </span><span class="identifier">segment_name</span><span class="plain">), </span><span class="string">"r"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Input_File</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"unable to open the template segment '%S'"</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_2"></a><b>&#167;8.2. </b>I6 template files are encoded as ISO Latin-1, not as Unicode UTF-8, so
ordinary <code class="display"><span class="extract">fgetc</span></code> is used, and no BOM marker is parsed. Lines are assumed
to be terminated with either <code class="display"><span class="extract">0x0a</span></code> or <code class="display"><span class="extract">0x0d</span></code>. (Since blank lines are
harmless, we take no trouble over <code class="display"><span class="extract">0a0d</span></code> or <code class="display"><span class="extract">0d0a</span></code> combinations.) The
built-in template files, almost always the only ones used, are line
terminated <code class="display"><span class="extract">0x0a</span></code> in Unix fashion.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Input_File</span><span class="plain">) </span><span class="identifier">cr</span><span class="plain"> = </span><span class="identifier">fgetc</span><span class="plain">(</span><span class="identifier">Input_File</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">sf</span><span class="plain">) {</span>
<span class="identifier">cr</span><span class="plain"> = </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">sf</span><span class="plain">, </span><span class="identifier">sfp</span><span class="plain">); </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == 0) </span><span class="identifier">cr</span><span class="plain"> = </span><span class="identifier">EOF</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">sfp</span><span class="plain">++;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">cr</span><span class="plain"> = </span><span class="identifier">EOF</span><span class="plain">;</span>
<span class="identifier">col</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == 10) || (</span><span class="identifier">cr</span><span class="plain"> == 13)) </span><span class="identifier">col</span><span class="plain"> = 0;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a> (four times), <a href="#SP8_3">&#167;8.3</a>, <a href="#SP8_5">&#167;8.5</a>, <a href="#SP8_6">&#167;8.6</a>, <a href="#SP8_7">&#167;8.7</a>.</p>
<p class="inwebparagraph"><a id="SP8_3"></a><b>&#167;8.3. </b>Anything following an at-character in the first column is looked at to see if
it's a heading, that is, an Inweb syntax:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">INWEB_PARAGRAPH_SYNTAX</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">INWEB_CODE_SYNTAX</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">INWEB_DASH_SYNTAX</span><span class="plain"> 3</span>
<span class="definitionkeyword">define</span> <span class="constant">INWEB_PURPOSE_SYNTAX</span><span class="plain"> 4</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read the rest of line as an at-heading</span> <span class="cwebmacronumber">8.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0, </span><span class="identifier">committed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">unacceptable_character</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_I6T_LINE_LENGTH</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">committed</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">cr</span><span class="plain"> == 10) || (</span><span class="identifier">cr</span><span class="plain"> == 13) || (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">' '</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"p"</span><span class="plain">)) </span><span class="identifier">inweb_syntax</span><span class="plain"> = </span><span class="constant">INWEB_PARAGRAPH_SYNTAX</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"c"</span><span class="plain">)) </span><span class="identifier">inweb_syntax</span><span class="plain"> = </span><span class="constant">INWEB_CODE_SYNTAX</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">Str::get_first_char</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">) == </span><span class="character">'-'</span><span class="plain">) </span><span class="identifier">inweb_syntax</span><span class="plain"> = </span><span class="constant">INWEB_DASH_SYNTAX</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">Str::begins_with_wide_string</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Purpose:"</span><span class="plain">)) </span><span class="identifier">inweb_syntax</span><span class="plain"> = </span><span class="constant">INWEB_PURPOSE_SYNTAX</span><span class="plain">;</span>
<span class="identifier">committed</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">inweb_syntax</span><span class="plain"> == -1) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unacceptable_character</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="character">'@'</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"heading begins: &lt;%S&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="identifier">Problems::quote_stream</span><span class="plain">(1, </span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::unlocated_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(...),</span>
<span class="string">"An unknown '@...' marker has been found at column 0 in "</span>
<span class="string">"raw Inform 6 template material: specifically, '@%1'. ('@' "</span>
<span class="string">"has a special meaning in this first column, and this "</span>
<span class="string">"might clash with its use to introduce an assembly-language "</span>
<span class="string">"opcode in Inform 6: if that's a problem, you can avoid it "</span>
<span class="string">"simply by putting one or more spaces or tabs in front of "</span>
<span class="string">"the opcode(s) to keep them clear of the left margin.)"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"unknown '@...' marker at column 0 in template matter: '%S'"</span><span class="plain">, </span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (!(((</span><span class="identifier">cr</span><span class="plain"> &gt;= </span><span class="character">'A'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cr</span><span class="plain"> &lt;= </span><span class="character">'Z'</span><span class="plain">)) || ((</span><span class="identifier">cr</span><span class="plain"> &gt;= </span><span class="character">'a'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cr</span><span class="plain"> &lt;= </span><span class="character">'z'</span><span class="plain">))</span>
<span class="plain">|| ((</span><span class="identifier">cr</span><span class="plain"> &gt;= </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cr</span><span class="plain"> &lt;= </span><span class="character">'9'</span><span class="plain">))</span>
<span class="plain">|| (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) || (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'&gt;'</span><span class="plain">) || (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) || (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'_'</span><span class="plain">)))</span>
<span class="identifier">unacceptable_character</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">cr</span><span class="plain"> == 10) || (</span><span class="identifier">cr</span><span class="plain"> == 13)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">I6T_buffer</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_4"></a><b>&#167;8.4. </b>As can be seen, only a small minority of Inweb syntaxes are allowed:
in particular, no definitions<code class="display"><span class="extract"> or angle-bracketed macros. This reader is not
</span></code>a full-fledged tangler.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Act on the at-heading, going in or out of comment mode as appropriate</span> <span class="cwebmacronumber">8.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">inweb_syntax</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INWEB_PARAGRAPH_SYNTAX</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">heading_name</span><span class="plain">) &gt; 0) &amp;&amp; (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) &gt; 0))</span>
<span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">AFTER_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">heading_name</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="identifier">Str::copy_tail</span><span class="plain">(</span><span class="identifier">heading_name</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, 2);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (((</span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">heading_name</span><span class="plain">)) != 0) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">' '</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">)))</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">heading_name</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">heading_name</span><span class="plain">) == 0)</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"Empty heading name in I6 template file"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">comment</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">skip_part</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) &gt; 0) {</span>
<span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">BEFORE_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">heading_name</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">INSTEAD_LINK_STAGE</span><span class="plain">, </span><span class="identifier">segment_name</span><span class="plain">, </span><span class="identifier">heading_name</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">)) </span><span class="identifier">skip_part</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INWEB_CODE_SYNTAX</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">skip_part</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">comment</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">INWEB_DASH_SYNTAX</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">INWEB_PURPOSE_SYNTAX</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_5"></a><b>&#167;8.5. </b>Here we are in <code class="display"><span class="extract">{-lines:...}</span></code> mode, so that the entire line of the file
is to be read as an argument. Note that initial and trailing white space on
the line is deleted: this makes it easier to lay out I6T template files
tidily.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Set the command to the default, and read rest of line as argument</span> <span class="cwebmacronumber">8.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">default_command</span><span class="plain">);</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Characters::is_space_or_tab</span><span class="plain">(</span><span class="identifier">cr</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">at_start</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == 10) || (</span><span class="identifier">cr</span><span class="plain"> == 13)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">at_start</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Characters::is_space_or_tab</span><span class="plain">(</span><span class="identifier">cr</span><span class="plain">))) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">); </span><span class="identifier">at_start</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::is_space_or_tab</span><span class="plain">(</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">)))</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_6"></a><b>&#167;8.6. </b>And here we read a normal command. The command name must not include <code class="display"><span class="extract">}</span></code>
or <code class="display"><span class="extract">:</span></code>. If there is no <code class="display"><span class="extract">:</span></code> then the argument is left unset (so that it will
be the empty string: see above). The argument must not include <code class="display"><span class="extract">}</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read up to the next close brace as an I6T command and argument</span> <span class="cwebmacronumber">8.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">com_mode</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'}'</span><span class="plain">) || (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="identifier">EOF</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">com_mode</span><span class="plain">)) { </span><span class="identifier">com_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">com_mode</span><span class="plain">) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_7"></a><b>&#167;8.7. </b>And similarly, for the <code class="display"><span class="extract">(+</span></code> ... <code class="display"><span class="extract">+)</span></code> notation used to mark I7 material
within I6:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read up to the next plus close-bracket as an I7 expression</span> <span class="cwebmacronumber">8.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">i7_exp</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="identifier">EOF</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">')'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">i7_exp</span><span class="plain">) == </span><span class="character">'+'</span><span class="plain">)) {</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">i7_exp</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">i7_exp</span><span class="plain">, </span><span class="identifier">cr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"SPONG: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i7_exp</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">i7_exp</span><span class="plain">);</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"use of (+ ... +) in the template has been withdrawn: '%S'"</span><span class="plain">, </span><span class="identifier">i7_exp</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_8"></a><b>&#167;8.8. Acting on I6T commands. </b></p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>&gt; =
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Act on the I6T segment command</span> <span class="cwebmacronumber">8.8.1</span>&gt;<span class="plain">;</span>
<span class="plain">(*(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;command_callback</span><span class="plain">))(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a> (twice).</p>
<p class="inwebparagraph"><a id="SP8_8_1"></a><b>&#167;8.8.1. </b>The <code class="display"><span class="extract">{-segment:...}</span></code> command recursively calls the I6T interpreter on the
supplied I6T filename, which means it acts rather like <code class="display"><span class="extract">#include</span></code> in C.
Note that because we pass the current output file handle <code class="display"><span class="extract">of</span></code> through to
this new invocation, it will have the file open if we do, and closed if
we do. It won't run in indexing mode, so <code class="display"><span class="extract">{-segment:...}</span></code> can't be used
safely between <code class="display"><span class="extract">{-open-index}</span></code> and <code class="display"><span class="extract">{-close-index}</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Act on the I6T segment command</span> <span class="cwebmacronumber">8.8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"segment"</span><span class="plain">)) {</span>
<span class="plain">(*(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;raw_callback</span><span class="plain">))(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="functiontext">TemplateReader::interpret</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, -1, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="plain">(*(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">&gt;raw_callback</span><span class="plain">))(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8_8">&#167;8.8</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Template errors. </b>Errors here used to be basically failed assertions, but inevitably people
reported this as a bug (0001596). It was never intended that I6T coding
be part of the outside-facing language, but for a handful of people
using template-hacking there are a handful of cases that can't be avoided, so...
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">quote</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">M</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">M</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">quote</span><span class="plain">);</span>
<span class="identifier">Problems::quote_stream</span><span class="plain">(1, </span><span class="identifier">M</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">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I ran into a mistake in a template file: %1. The I6 "</span>
<span class="string">"template files (or .i6t files) are a very low-level part of Inform, "</span>
<span class="string">"and errors like this will only occur if the standard installation "</span>
<span class="string">"has been amended or damaged. One possibility is that you're using "</span>
<span class="string">"an extension which does some 'template hacking', as it's called, "</span>
<span class="string">"but made a mistake doing so."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">M</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">quote</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function TemplateReader::error is used in <a href="#SP8_1">&#167;8.1</a>, <a href="#SP8_3">&#167;8.3</a>, <a href="#SP8_4">&#167;8.4</a>, <a href="#SP8_7">&#167;8.7</a>, <a href="#SP12">&#167;12</a>, 2/lnk (<a href="2-lnk.html#SP2">&#167;2</a>), 2/rcc (<a href="2-rcc.html#SP2">&#167;2</a>, <a href="2-rcc.html#SP2_4">&#167;2.4</a>, <a href="2-rcc.html#SP2_2_2">&#167;2.2.2</a>, <a href="2-rcc.html#SP2_5">&#167;2.5</a>, <a href="2-rcc.html#SP2_6">&#167;2.6</a>), 2/alm (<a href="2-alm.html#SP2_1_2">&#167;2.1.2</a>, <a href="2-alm.html#SP2_2_1">&#167;2.2.1</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Intervention. </b>This is a system allowing the user to hang explicit code before, instead of
or after any part of any segment of the I6T files in use.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateReader::new_intervention</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">segment</span><span class="plain">,</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">part</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">i6</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">seg</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ref</span><span class="plain">) {</span>
<span class="reserved">I6T_intervention</span><span class="plain"> *</span><span class="identifier">i6ti</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">stage</span><span class="plain"> == </span><span class="identifier">INSTEAD_LINK_STAGE</span><span class="plain">) {</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">, </span><span class="reserved">I6T_intervention</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;intervention_stage</span><span class="plain"> == 0) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">, </span><span class="identifier">part</span><span class="plain">)))</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i6ti</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">i6ti</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">I6T_intervention</span><span class="plain">);</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;intervention_stage</span><span class="plain"> = </span><span class="identifier">stage</span><span class="plain">;</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">segment</span><span class="plain">);</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">part</span><span class="plain">);</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;I6T_matter</span><span class="plain"> = </span><span class="identifier">i6</span><span class="plain">;</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;alternative_segment</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">seg</span><span class="plain">);</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;where_intervention_requested</span><span class="plain"> = (</span><span class="identifier">parse_node</span><span class="plain"> *) </span><span class="identifier">ref</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TEMPLATE_READING</span><span class="plain">, </span><span class="string">"New stage %d Segment %S Part %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">, </span><span class="identifier">part</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function TemplateReader::new_intervention is used in 2/lnk (<a href="2-lnk.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>An intervention "instead" (stage 0) replaces any existing one, but at other
stages &mdash; before and after &mdash; they are accumulated.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">TemplateReader::I6T_file_intervene</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">segment</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">part</span><span class="plain">, </span><span class="reserved">I6T_kit</span><span class="plain"> *</span><span class="identifier">kit</span><span class="plain">) {</span>
<span class="reserved">I6T_intervention</span><span class="plain"> *</span><span class="identifier">i6ti</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">segment</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Main.i6t"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TEMPLATE_READING</span><span class="plain">, </span><span class="string">"Stage %d Segment %S Part %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">, </span><span class="identifier">part</span><span class="plain">);</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">, </span><span class="reserved">I6T_intervention</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">stage</span><span class="plain"> == </span><span class="identifier">CATCH_ALL_LINK_STAGE</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;intervention_stage</span><span class="plain"> == </span><span class="identifier">stage</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">)))) {</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_found</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">, </span><span class="identifier">part</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_found</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;where_intervention_requested</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TEMPLATE_READING</span><span class="plain">, </span><span class="string">"Intervention at stage %d Segment %S Part %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">, </span><span class="identifier">part</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;I6T_matter</span><span class="plain">) {</span>
<span class="functiontext">TemplateReader::interpret</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;I6T_matter</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, -1, </span><span class="identifier">kit</span><span class="plain">);</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">i6ti</span><span class="plain">-</span><span class="element">&gt;alternative_segment</span><span class="plain">) &gt; 0)</span>
<span class="functiontext">TemplateReader::interpret</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;alternative_segment</span><span class="plain">, -1, </span><span class="identifier">kit</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stage</span><span class="plain"> == 0) </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</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">The function TemplateReader::I6T_file_intervene is used in <a href="#SP8">&#167;8</a>, <a href="#SP8_4">&#167;8.4</a>, 2/lnk (<a href="2-lnk.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>At the end of the run, we check to see if any of the interventions were
never acted on. This generally means the user mistyped the name of a section
or part &mdash; which would otherwise be an error very difficult to detect.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateReader::report_unacted_upon_interventions</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">I6T_intervention</span><span class="plain"> *</span><span class="identifier">i6ti</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">, </span><span class="reserved">I6T_intervention</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Main.i6t"</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;where_intervention_requested</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Intervention at stage %d Segment %S Part %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;intervention_stage</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</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">Untestable</span><span class="plain">),</span>
<span class="string">"no template file of that name was ever read in"</span><span class="plain">,</span>
<span class="string">"so this attempt to intervene had no effect. "</span>
<span class="string">"The template files have names like 'Output.i6t', 'Parser.i6t' "</span>
<span class="string">"and so on. (Looking at the typeset form of the template, "</span>
<span class="string">"available at the Inform website, may help.)"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"was asked to intervene on this segment, but never saw it: '%S'"</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Main.i6t"</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;where_intervention_requested</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Intervention at stage %d Segment %S Part %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;intervention_stage</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;segment_name</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</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">Untestable</span><span class="plain">),</span>
<span class="string">"that template file didn't have a part with that name"</span><span class="plain">,</span>
<span class="string">"so this attempt to intervene had no effect. "</span>
<span class="string">"Each template file is divided internally into a number of "</span>
<span class="string">"named parts, and you have to quote their names precisely. "</span>
<span class="string">"(Looking at the typeset form of the template, available at "</span>
<span class="string">"the Inform website, may help.)"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">PROBLEMS_MODULE</span>
<span class="functiontext">TemplateReader::error</span><span class="plain">(</span><span class="string">"was asked to intervene on this part, but never saw it: '%S'"</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">&gt;part_name</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function TemplateReader::report_unacted_upon_interventions appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-lnk.html">Back to 'Linker'</a></li><li><a href="2-plm.html">Continue with 'Parse Linked Matter'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>