mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
924 lines
100 KiB
HTML
924 lines
100 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>26/tti</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 '26/iti' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#26">Chapter 26: Compilation Utilities</a></li><li><b>I6 Template Interpreter</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. The entire top-level logic of Inform is carried out by interpreting the |Main.i6t| file in this way.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP3">§3. Syntax of I6T files</a></li><li><a href="#SP7_8">§7.8. Acting on I6T commands</a></li><li><a href="#SP7_8_2">§7.8.2. Indexing commands</a></li><li><a href="#SP7_8_3">§7.8.3. Commands accessing Inform internals</a></li><li><a href="#SP8">§8. Template errors</a></li><li><a href="#SP9">§9. I7 expression evaluation</a></li><li><a href="#SP10">§10. The build constant</a></li><li><a href="#SP11">§11. Registration of sentence handlers</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>The following flag is set by the <code class="display"><span class="extract">-noindex</span></code> command line option.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">do_not_generate_index</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. 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="SP4"></a><b>§4. </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="SP5"></a><b>§5. </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="SP6"></a><b>§6. </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="SP7"></a><b>§7. </b>The I6T interpreter is a single routine which implements the description
|
|
above:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateFiles::interpret</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</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">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">active</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">indexing</span><span class="plain"> = </span><span class="identifier">FALSE</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="cwebmacro">Open the I6 template file</span> <span class="cwebmacronumber">7.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">7.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">7.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">7.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">7.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">7.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">7.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">7.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">7.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">7.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="reserved">if</span><span class="plain"> ((</span><span class="identifier">OUT</span><span class="plain">) && (</span><span class="identifier">active</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">OUT</span><span class="plain">) && (</span><span class="identifier">active</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="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">7.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">7.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="reserved">if</span><span class="plain"> ((</span><span class="identifier">OUT</span><span class="plain">) && (</span><span class="identifier">active</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="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">OUT</span><span class="plain">) && (</span><span class="identifier">active</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="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 TemplateFiles::interpret is used in 1/mr (<a href="1-mr.html#SP4_16">§4.16</a>), 26/i6i (<a href="26-i6i.html#SP7">§7</a>, <a href="26-i6i.html#SP8">§8</a>), 26/uo (<a href="26-uo.html#SP17">§17</a>), 26/pl (<a href="26-pl.html#SP13">§13</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_1"></a><b>§7.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">7.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="constant">NO_FS_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">pathname_of_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="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">STDERR</span><span class="plain">, </span><span class="string">"inform: Unable to open segment <%S>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">segment_name</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="identifier">BelievedImpossible</span><span class="plain">), </span> <span class="comment">or anyway not usefully testable</span>
|
|
<span class="string">"I couldn't open a requested I6T segment: see the console "</span>
|
|
<span class="string">"output for details."</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_2"></a><b>§7.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">7.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">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="#SP7">§7</a> (four times), <a href="#SP7_3">§7.3</a>, <a href="#SP7_5">§7.5</a>, <a href="#SP7_6">§7.6</a>, <a href="#SP7_7">§7.7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_3"></a><b>§7.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">7.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">7.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="reserved">if</span><span class="plain"> ((</span><span class="identifier">OUT</span><span class="plain">) && (</span><span class="identifier">active</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="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="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="identifier">PM_BadTemplateAtSign</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="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="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_4"></a><b>§7.4. </b>As can be seen, only a small minority of Inweb syntaxes are allowed:
|
|
in particular, no <code class="display"><span class="extract">@d</span></code> or angle-bracketed macros. This interpreter is not
|
|
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">7.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="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">TemplateFiles::error</span><span class="plain">(</span><span class="string">"Empty heading name in I6 template file"</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">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="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_5"></a><b>§7.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">7.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">7.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="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_6"></a><b>§7.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">7.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">7.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="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_7"></a><b>§7.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">7.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">7.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="functiontext">TemplateFiles::compile_I7_from_I6</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">OUT</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP7">§7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_8"></a><b>§7.8. Acting on I6T commands. </b>Only a few commands work even in passive mode, but they include file-handling
|
|
because the close-file command needs to be able to get out of passive mode
|
|
and back into active (and besides, because the file still needs to be closed).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The <code class="display"><span class="extract">{-type:...}</span></code> command hands over the argument to a more specific
|
|
interpreter, one which constructs kinds.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">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 will run in active mode, but that's fine, because we're in active
|
|
mode too. 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 I6T command and argument</span> <span class="cwebmacronumber">7.8</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<<span class="cwebmacro">Act on the I6T lines command</span> <span class="cwebmacronumber">7.8.1</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">active</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">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">"type"</span><span class="plain">)) { </span><span class="identifier">Kinds::Interpreter::despatch_kind_command</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">); </span><span class="reserved">continue</span><span class="plain">; }</span>
|
|
<<span class="cwebmacro">Act on the I6T counter command</span> <span class="cwebmacronumber">7.8.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Act on an I6T indexing command</span> <span class="cwebmacronumber">7.8.2</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"command: <%S> argument: <%S>\</span><span class="plain">n</span><span class="string">"</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">Problems::quote_stream</span><span class="plain">(1, </span><span class="identifier">command</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="identifier">PM_TemplateError</span><span class="plain">),</span>
|
|
<span class="string">"In an explicit Inform 6 code insertion, I recognise a few special "</span>
|
|
<span class="string">"notations in the form '{-command}'. This time, though, the unknown notation "</span>
|
|
<span class="string">"{-%1} has been used, and this is an error. (It seems very unlikely indeed "</span>
|
|
<span class="string">"that this could be legal Inform 6 which I'm misreading, but if so, try "</span>
|
|
<span class="string">"adjusting the spacing to make this problem message go away.)"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP7">§7</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_8_1"></a><b>§7.8.1. </b>There is no corresponding code here to act on <code class="display"><span class="extract">{-endlines}</span></code> because it is
|
|
not valid as a free-standing command: it can only occur at the end of a
|
|
<code class="display"><span class="extract">{-lines:...}</span></code> block, and is acted upon above.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on the I6T lines command</span> <span class="cwebmacronumber">7.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">"lines"</span><span class="plain">)) {</span>
|
|
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">default_command</span><span class="plain">, </span><span class="identifier">argument</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="#SP7_8">§7.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_8_2"></a><b>§7.8.2. Indexing commands. </b>Commands in between <code class="display"><span class="extract">{-open-index}</span></code> and <code class="display"><span class="extract">{-close-index}</span></code> are skipped when
|
|
Inform has been called with a command-line switch to disable the index. (As is
|
|
done by <code class="display"><span class="extract">intest</span></code>, to save time.) <code class="display"><span class="extract">{-index:name}</span></code> opens the index file
|
|
called <code class="display"><span class="extract">name</span></code>.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on an I6T indexing command</span> <span class="cwebmacronumber">7.8.2</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">"open-index"</span><span class="plain">)) { </span><span class="identifier">indexing</span><span class="plain"> = </span><span class="identifier">TRUE</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">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">"close-index"</span><span class="plain">)) { </span><span class="identifier">indexing</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">indexing</span><span class="plain">) && (</span><span class="identifier">do_not_generate_index</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">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">"index-complete"</span><span class="plain">)) { </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">indexing</span><span class="plain">) </span><span class="identifier">Index::complete</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">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">"index-page"</span><span class="plain">)) {</span>
|
|
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+?)=(%c+?)=(%c+)"</span><span class="plain">)) {</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">col</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0];</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">titling</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1];</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[2];</span>
|
|
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr2</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">leafname</span><span class="plain"> = </span><span class="identifier">titling</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr2</span><span class="plain">, </span><span class="identifier">titling</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%C+?) (%c+)"</span><span class="plain">)) </span><span class="identifier">leafname</span><span class="plain"> = </span><span class="identifier">mr2</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0];</span>
|
|
<span class="identifier">Index::new_page</span><span class="plain">(</span><span class="identifier">col</span><span class="plain">, </span><span class="identifier">titling</span><span class="plain">, </span><span class="identifier">explanation</span><span class="plain">, </span><span class="identifier">leafname</span><span class="plain">);</span>
|
|
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr2</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad index-page format"</span><span class="plain">);</span>
|
|
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr</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">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">"index-element"</span><span class="plain">)) {</span>
|
|
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%C+) (%c+?)=(%c+)"</span><span class="plain">))</span>
|
|
<span class="identifier">Index::new_segment</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0], </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1], </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[2]);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad index-element format"</span><span class="plain">);</span>
|
|
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr</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">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">"index"</span><span class="plain">)) {</span>
|
|
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+?)=(%c+)"</span><span class="plain">)) {</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">titling</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0];</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">explanation</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1];</span>
|
|
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr2</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">);</span>
|
|
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">, </span><span class="identifier">titling</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr2</span><span class="plain">, </span><span class="identifier">leafname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%C+?) (%c+)"</span><span class="plain">)) </span><span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">, </span><span class="identifier">mr2</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">, </span><span class="string">".html"</span><span class="plain">);</span>
|
|
<span class="identifier">Index::open_file</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">, </span><span class="identifier">titling</span><span class="plain">, -1, </span><span class="identifier">explanation</span><span class="plain">);</span>
|
|
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr2</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">leafname</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad index format"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr</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="#SP7_8">§7.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7_8_3"></a><b>§7.8.3. Commands accessing Inform internals. </b>The following expands to the number of labels produced for a given label namespace.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on the I6T counter command</span> <span class="cwebmacronumber">7.8.3</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">"counter"</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</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="reserved">continue</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="functiontext">JumpLabels::read_counter</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">NOT_APPLICABLE</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="#SP7_8">§7.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. 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">TemplateFiles::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">Problems::quote_text</span><span class="plain">(1, </span><span class="identifier">message</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 command: %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="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function TemplateFiles::error is used in <a href="#SP7_4">§7.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. I7 expression evaluation. </b>This is not quite like regular expression evaluation, because we want
|
|
"room" and "lighted" to be evaluated as the I6 translation of the
|
|
relevant class or property, rather than as code to test the predicate
|
|
"X is a room" or "X is lighted", and similarly for bare names
|
|
of defined adjectives. So:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateFiles::compile_I7_from_I6</span><span class="plain">(</span><span class="identifier">value_holster</span><span class="plain"> *</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">VH</span><span class="plain">) && (</span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_wanted</span><span class="plain"> == </span><span class="identifier">INTER_VOID_VHMODE</span><span class="plain">)) {</span>
|
|
<span class="identifier">Produce::evaluation</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="functiontext">TemplateFiles::compile_I7_from_I6_inner</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">VH</span><span class="plain">) && (</span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_wanted</span><span class="plain"> == </span><span class="identifier">INTER_VOID_VHMODE</span><span class="plain">)) {</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateFiles::compile_I7_from_I6_inner</span><span class="plain">(</span><span class="identifier">value_holster</span><span class="plain"> *</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">LW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="reserved">property</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">>(</span><span class="identifier">LW</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VH</span><span class="plain">)</span>
|
|
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Properties::iname</span><span class="plain">(<<</span><span class="identifier">rp</span><span class="plain">>>));</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"%n"</span><span class="plain">, </span><span class="functiontext">Properties::iname</span><span class="plain">(<<</span><span class="identifier">rp</span><span class="plain">>>));</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">>(</span><span class="identifier">LW</span><span class="plain">)) {</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = <<</span><span class="identifier">rp</span><span class="plain">>>;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VH</span><span class="plain">)</span>
|
|
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Kinds::RunTime::I6_classname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"%n"</span><span class="plain">, </span><span class="functiontext">Kinds::RunTime::I6_classname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">Instances::parse_object</span><span class="plain">(</span><span class="identifier">LW</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VH</span><span class="plain">)</span>
|
|
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Instances::iname</span><span class="plain">(<<</span><span class="identifier">rp</span><span class="plain">>>));</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"%~I"</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">adjectival_phrase</span><span class="plain"> *</span><span class="identifier">aph</span><span class="plain"> = </span><span class="identifier">Adjectives::parse</span><span class="plain">(</span><span class="identifier">LW</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">aph</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Adjectives::Meanings::write_adjective_test_routine</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">aph</span><span class="plain">)) </span><span class="reserved">return</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="identifier">BelievedImpossible</span><span class="plain">),</span>
|
|
<span class="string">"You tried to use '(+' and '+)' to expand to the Inform 6 routine "</span>
|
|
<span class="string">"address of an adjective, but it was an adjective with no meaning."</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_problem_count</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</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">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">>(</span><span class="identifier">LW</span><span class="plain">)) </span><span class="identifier">spec</span><span class="plain"> = <<</span><span class="identifier">rp</span><span class="plain">>>;</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">Specifications::new_UNKNOWN</span><span class="plain">(</span><span class="identifier">LW</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">initial_problem_count</span><span class="plain"> < </span><span class="identifier">problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="functiontext">Dash::check_value</span><span class="plain">(</span><span class="identifier">spec</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">initial_problem_count</span><span class="plain"> < </span><span class="identifier">problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="identifier">COMPILATION_MODE_EXIT</span><span class="plain">(</span><span class="constant">DEREFERENCE_POINTERS_CMODE</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VH</span><span class="plain">)</span>
|
|
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::parse</span><span class="plain">(</span><span class="identifier">LW</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nlv</span><span class="plain">) {</span>
|
|
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">URL_SYMBOL_CHAR</span><span class="plain">);</span>
|
|
<span class="identifier">Inter::SymbolsTables::symbol_to_url_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="functiontext">NonlocalVariables::iname</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">)));</span>
|
|
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">URL_SYMBOL_CHAR</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">value_holster</span><span class="plain"> </span><span class="identifier">VH2</span><span class="plain"> = </span><span class="identifier">Holsters::new</span><span class="plain">(</span><span class="identifier">INTER_DATA_VHMODE</span><span class="plain">);</span>
|
|
<span class="functiontext">Specifications::Compiler::compile_inner</span><span class="plain">(&</span><span class="identifier">VH2</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
|
|
<span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">v1</span><span class="plain"> = 0, </span><span class="identifier">v2</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">Holsters::unholster_pair</span><span class="plain">(&</span><span class="identifier">VH2</span><span class="plain">, &</span><span class="identifier">v1</span><span class="plain">, &</span><span class="identifier">v2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v1</span><span class="plain"> == </span><span class="identifier">ALIAS_IVAL</span><span class="plain">) {</span>
|
|
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">URL_SYMBOL_CHAR</span><span class="plain">);</span>
|
|
<span class="identifier">inter_symbols_table</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">Inter::Packages::scope</span><span class="plain">(</span><span class="functiontext">Emit::current_enclosure</span><span class="plain">()-></span><span class="identifier">actual_package</span><span class="plain">);</span>
|
|
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">Inter::SymbolsTables::symbol_from_id</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain">);</span>
|
|
<span class="identifier">Inter::SymbolsTables::symbol_to_url_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">URL_SYMBOL_CHAR</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">CodeGen::FC::val_from</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Packaging::at</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()), </span><span class="identifier">v1</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="constant">END_COMPILATION_MODE</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 TemplateFiles::compile_I7_from_I6 is used in <a href="#SP7_7">§7.7</a>, 25/cii (<a href="25-cii.html#SP2">§2</a>).</p>
|
|
|
|
<p class="endnote">The function TemplateFiles::compile_I7_from_I6_inner appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. The build constant. </b>That was the end of the template interpreter. Now, since this version-numbering
|
|
constant belongs nowhere else, we provide a single I6T command in this section
|
|
of Inform: the following routine performs <code class="display"><span class="extract">{-callv:TemplateFiles::compile_build_number}</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateFiles::compile_build_number</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">build</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">build</span><span class="plain">, </span><span class="string">"%B"</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">NI_BUILD_COUNT_HL</span><span class="plain">);</span>
|
|
<span class="functiontext">Emit::named_string_constant</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">build</span><span class="plain">);</span>
|
|
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">build</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function TemplateFiles::compile_build_number is used in 1/mr (<a href="1-mr.html#SP4_14">§4.14</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. Registration of sentence handlers. </b>The following routine is placed here, right at the end of the Inform code,
|
|
because at this point all of the sentence handlers — with names like
|
|
<code class="display"><span class="extract">TABLE_SH_handler</span></code> — have now been created.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">TemplateFiles::register_sentence_handlers</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Add sentence handlers for the top-level node types</span> <span class="cwebmacronumber">11.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Add sentence handlers for the SENTENCE/VERB node types</span> <span class="cwebmacronumber">11.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function TemplateFiles::register_sentence_handlers is used in 9/tfa (<a href="9-tfa.html#SP7_3">§7.3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_1"></a><b>§11.1. </b>This is all of the node types still present at the top level of the tree
|
|
at the end of sentence-breaking.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Add sentence handlers for the top-level node types</span> <span class="cwebmacronumber">11.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">TRACE_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">BEGINHERE_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">ENDHERE_SH</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">BIBLIOGRAPHIC_SH</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">INFORM6CODE_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">COMMAND_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">ROUTINE_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">TABLE_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">EQUATION_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">HEADING_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">SENTENCE_SH</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_2"></a><b>§11.2. </b>And here are all of the verb types found in <code class="display"><span class="extract">AVERB_NT</span></code> nodes which are
|
|
first children of <code class="display"><span class="extract">SENTENCE_NT</span></code> nodes.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Add sentence handlers for the SENTENCE/VERB node types</span> <span class="cwebmacronumber">11.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">ASSERT_SH</span><span class="plain">);</span>
|
|
<span class="identifier">REGISTER_SENTENCE_HANDLER</span><span class="plain">(</span><span class="identifier">SPECIAL_MEANING_SH</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="26-tti.html">Back to 'Translate to Identifiers'</a></li><li><a href="26-pl.html">Continue with 'Plugins'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|