mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
821 lines
96 KiB
HTML
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">★</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">§1. Definitions</a></li><li><a href="#SP4">§4. Syntax of I6T files</a></li><li><a href="#SP8_8">§8.8. Acting on I6T commands</a></li><li><a href="#SP9">§9. Template errors</a></li><li><a href="#SP10">§10. Intervention</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§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>§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>§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>§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>§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 > 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>§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 — 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>§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">>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">) > 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">) > 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">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">) > 0) {</span>
|
|
<<span class="cwebmacro">Open the I6 template file</span> <span class="cwebmacronumber">8.1</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="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>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>><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">) && (</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>
|
|
<<span class="cwebmacro">Read the rest of line as an at-heading</span> <span class="cwebmacronumber">8.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Act on the at-heading, going in or out of comment mode as appropriate</span> <span class="cwebmacronumber">8.4</span>><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">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">) > 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>
|
|
<<span class="cwebmacro">Set the command to the default, and read rest of line as argument</span> <span class="cwebmacronumber">8.5</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">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><<span class="cwebmacro">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cr</span><span class="plain"> == </span><span class="character">'{'</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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>
|
|
<<span class="cwebmacro">Read up to the next close brace as an I6T command and argument</span> <span class="cwebmacronumber">8.6</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">command</span><span class="plain">) == </span><span class="character">'!'</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>><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">) && (</span><span class="identifier">N_escape</span><span class="plain"> >= 0)) {</span>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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>
|
|
<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>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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>
|
|
<<span class="cwebmacro">Read up to the next plus close-bracket as an I7 expression</span> <span class="cwebmacronumber">8.7</span>><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">) > 0) && (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) > 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">) > 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">§1</a>).</p>
|
|
|
|
<p class="endnote">The function TemplateReader::extract is used in 2/lnk (<a href="2-lnk.html#SP1">§1</a>).</p>
|
|
|
|
<p class="endnote">The function TemplateReader::interpret is used in <a href="#SP8_8_1">§8.8.1</a>, <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Open the I6 template file</span> <span class="cwebmacronumber">8.1</span>> =
|
|
</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"><</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">>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">>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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>> =
|
|
</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">§8</a> (four times), <a href="#SP8_3">§8.3</a>, <a href="#SP8_5">§8.5</a>, <a href="#SP8_6">§8.6</a>, <a href="#SP8_7">§8.7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Read the rest of line as an at-heading</span> <span class="cwebmacronumber">8.3</span>> =
|
|
</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"><</span><span class="constant">MAX_I6T_LINE_LENGTH</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</span>><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">) && ((</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: <%S>\</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"> >= </span><span class="character">'A'</span><span class="plain">) && (</span><span class="identifier">cr</span><span class="plain"> <= </span><span class="character">'Z'</span><span class="plain">)) || ((</span><span class="identifier">cr</span><span class="plain"> >= </span><span class="character">'a'</span><span class="plain">) && (</span><span class="identifier">cr</span><span class="plain"> <= </span><span class="character">'z'</span><span class="plain">))</span>
|
|
<span class="plain">|| ((</span><span class="identifier">cr</span><span class="plain"> >= </span><span class="character">'0'</span><span class="plain">) && (</span><span class="identifier">cr</span><span class="plain"> <= </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">'>'</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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Act on the at-heading, going in or out of comment mode as appropriate</span> <span class="cwebmacronumber">8.4</span>> =
|
|
</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">) > 0) && (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">segment_name</span><span class="plain">) > 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) &&</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">) > 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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_5"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Set the command to the default, and read rest of line as argument</span> <span class="cwebmacronumber">8.5</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">at_start</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="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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_6"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Read up to the next close brace as an I6T command and argument</span> <span class="cwebmacronumber">8.6</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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><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">) && (</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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_7"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Read up to the next plus close-bracket as an I7 expression</span> <span class="cwebmacronumber">8.7</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Read next character from I6T stream</span> <span class="cwebmacronumber">8.2</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">) && (</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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_8"></a><b>§8.8. Acting on I6T commands. </b></p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on I6T command and argument</span> <span class="cwebmacronumber">8.8</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<<span class="cwebmacro">Act on the I6T segment command</span> <span class="cwebmacronumber">8.8.1</span>><span class="plain">;</span>
|
|
<span class="plain">(*(</span><span class="identifier">kit</span><span class="plain">-</span><span class="element">>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">§8</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_8_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Act on the I6T segment command</span> <span class="cwebmacronumber">8.8.1</span>> =
|
|
</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">>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">>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">§8.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§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">§8.1</a>, <a href="#SP8_3">§8.3</a>, <a href="#SP8_4">§8.4</a>, <a href="#SP8_7">§8.7</a>, <a href="#SP12">§12</a>, 2/lnk (<a href="2-lnk.html#SP2">§2</a>), 2/rcc (<a href="2-rcc.html#SP2">§2</a>, <a href="2-rcc.html#SP2_4">§2.4</a>, <a href="2-rcc.html#SP2_2_2">§2.2.2</a>, <a href="2-rcc.html#SP2_5">§2.5</a>, <a href="2-rcc.html#SP2_6">§2.6</a>), 2/alm (<a href="2-alm.html#SP2_1_2">§2.1.2</a>, <a href="2-alm.html#SP2_2_1">§2.2.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§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">>intervention_stage</span><span class="plain"> == 0) &&</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">>segment_name</span><span class="plain">, </span><span class="identifier">segment</span><span class="plain">)) &&</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">>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">>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">>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">>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">>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">>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">>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">>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">>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">§1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>An intervention "instead" (stage 0) replaces any existing one, but at other
|
|
stages — before and after — 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">>intervention_stage</span><span class="plain"> == </span><span class="identifier">stage</span><span class="plain">) &&</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">>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">>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">>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">>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">>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">>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">>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">>alternative_segment</span><span class="plain">) > 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">>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">§8</a>, <a href="#SP8_4">§8.4</a>, 2/lnk (<a href="2-lnk.html#SP1">§1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§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 — 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">>segment_found</span><span class="plain"> == </span><span class="identifier">FALSE</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">>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">>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">>intervention_stage</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">>segment_name</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">>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">>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">>part_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">>part_name</span><span class="plain">) &&</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">>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">>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">>intervention_stage</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">>segment_name</span><span class="plain">, </span><span class="identifier">i6ti</span><span class="plain">-</span><span class="element">>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">>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>
|
|
|