1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/3-rst.html
2019-10-02 23:04:15 +01:00

392 lines
44 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/si</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 '3/rst' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#3">Chapter 3: Bridge to Words Module</a></li><li><b>Read Source Text</b></li></ul><p class="purpose">This is where source text is read in, whether from extension files or from the main source text file, and fed into the lexer.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The source text is drawn almost entirely from the primary source file and
the extensions, but Inform does also inject small amounts of source text of
its own (for instance, when a new kind is created, the kind interpreter
does this).
</p>
<p class="inwebparagraph">In particular, every source text read into Inform is automatically prefixed by
the following eight words &mdash; if Inform were a computer, this would be the BIOS
which boots up its operating system. (In that the rest of the creation of the
I7 world model is handled by source text in the Standard Rules.)
</p>
<p class="inwebparagraph">Because of this mandatory insertion, one extension, the Standard Rules, is
compulsorily included in every run. So there will certainly be at least two
files of source text to be read, and quite possibly more.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MANDATORY_INSERTED_TEXT</span><span class="plain"> </span><span class="identifier">L</span><span class="string">"Include Basic Inform by Graham Nelson. Include the Standard Rules by Graham Nelson.\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span>
</pre>
<pre class="display">
<span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">primary_source_file</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">first to be opened</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>There is no real difference between the loading of the primary source text
and the loading of an extension's text, except for the descriptions we
supply in case of any problem messages which might need to be issued,
and for the fact that the mandatory insertion text is loaded before the
primary source text.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_extension_source_text</span><span class="plain">(</span><span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">EF</span><span class="plain">,</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">synopsis</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">documentation_only</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">SourceFiles::read_file</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">, </span><span class="identifier">documentation_only</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Log::aspect_switched_on</span><span class="plain">(</span><span class="identifier">LEXICAL_OUTPUT_DA</span><span class="plain">)) </span><span class="identifier">Word::log_lexer_output</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_primary_source_text</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">Feeds::feed_text</span><span class="plain">(</span><span class="constant">MANDATORY_INSERTED_TEXT</span><span class="plain">);</span>
<span class="functiontext">SourceFiles::read_further_mandatory_text</span><span class="plain">();</span>
<span class="functiontext">SourceFiles::read_file</span><span class="plain">(</span><span class="identifier">filename_of_i7_source</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"your source text"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::read_extension_source_text is used in 8/ie (<a href="8-ie.html#SP5_2">&#167;5.2</a>).</p>
<p class="endnote">The function SourceFiles::read_primary_source_text is used in 1/mr (<a href="1-mr.html#SP4_8">&#167;4.8</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The following reads in the text of the optional file of use options, if
this has been created, producing no problem message if it hasn't.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">SENTENCE_COUNT_MONITOR</span><span class="plain"> </span><span class="functiontext">SourceFiles::increase_sentence_count</span>
</pre>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">options_file_wording</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING_INIT</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_further_mandatory_text</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">TextFiles::read</span><span class="plain">(</span><span class="identifier">filename_of_options</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">,</span>
<span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="functiontext">SourceFiles::read_further_mandatory_text_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">options_file_wording</span><span class="plain"> = </span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_further_mandatory_text_helper</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">,</span>
<span class="identifier">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">unused_state</span><span class="plain">) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">use</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">shape</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="functiontext">UseOptions::set_immediate_option_flags</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">SourceFiles::increase_sentence_count</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::within</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">options_file_wording</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::read_further_mandatory_text is used in <a href="#SP3">&#167;3</a>.</p>
<p class="endnote">The function SourceFiles::read_further_mandatory_text_helper appears nowhere else.</p>
<p class="endnote">The function SourceFiles::increase_sentence_count appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Either way, we use the following code. The <code class="display"><span class="extract">SourceFiles::read_file</span></code> function returns
one of the following values to indicate the source of the source: the value
only really tells us something we didn't know in the case of extensions,
but in that event the Extensions.w routines do indeed want to know this.
(Area 51 is reserved for extensions of alien origin, but the relevant
source code is classified.)
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">ORIGIN_WAS_PRIMARY_SOURCE</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA</span><span class="plain"> 1 </span> <span class="comment">must match <code class="display"><span class="extract">*_FS_AREA</span></code> numbers plus 1</span>
<span class="definitionkeyword">define</span> <span class="constant">ORIGIN_WAS_USER_EXTENSIONS_AREA</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA</span><span class="plain"> 3</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_file</span><span class="plain">(</span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">synopsis</span><span class="plain">, </span><span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">EF</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">documentation_only</span><span class="plain">) {</span>
<span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">sf</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">area</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">EF</span><span class="plain">)</span>
<span class="identifier">area</span><span class="plain"> = </span><span class="functiontext">SourceFiles::read_file_inner</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">,</span>
<span class="identifier">pathname_of_extensions</span><span class="plain">, </span><span class="constant">NO_FS_AREAS</span><span class="plain"> + 1, </span><span class="identifier">documentation_only</span><span class="plain">, &amp;</span><span class="identifier">sf</span><span class="plain">,</span>
<span class="identifier">STORE_POINTER_extension_file</span><span class="plain">(</span><span class="identifier">EF</span><span class="plain">), </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">area</span><span class="plain"> = </span><span class="functiontext">SourceFiles::read_file_inner</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">,</span>
<span class="identifier">NULL</span><span class="plain">, 0, </span><span class="identifier">documentation_only</span><span class="plain">, &amp;</span><span class="identifier">sf</span><span class="plain">,</span>
<span class="identifier">STORE_POINTER_extension_file</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">), </span><span class="identifier">TRUE</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">area</span><span class="plain"> == -1) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">EF</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Author: %W\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">-</span><span class="element">&gt;author_text</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Title: %W\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">-</span><span class="element">&gt;title_text</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_stream</span><span class="plain">(2, </span><span class="identifier">synopsis</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BogusExtension</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I can't find the extension '%2', which seems not to be installed, "</span>
<span class="string">"but was requested by: %1. %P"</span>
<span class="string">"You can get hold of extensions which people have made public at "</span>
<span class="string">"the Inform website, www.inform7.com, or by using the Public "</span>
<span class="string">"Library in the Extensions panel."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::Fatal::filename_related</span><span class="plain">(</span>
<span class="string">"Error: can't open source text file"</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</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">EF</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">primary_source_file</span><span class="plain"> = </span><span class="identifier">sf</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Extensions::Files::set_corresponding_source_file</span><span class="plain">(</span><span class="identifier">EF</span><span class="plain">, </span><span class="identifier">sf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">documentation_only</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Tell console output about the file</span> <span class="cwebmacronumber">5.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">area</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::read_file is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b>This is where messages like
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">I've also read Standard Rules by Graham Nelson, which is 27204 words long.</span>
</pre>
<p class="inwebparagraph">are printed to <code class="display"><span class="extract">stdout</span></code> (not <code class="display"><span class="extract">stderr</span></code>), in something of an affectionate nod
to TeX's traditional console output, though occasionally I think silence is
golden and that the messages could go. It's a moot point for almost all users,
though, because the console output is concealed from them by the Inform
application.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Tell console output about the file</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wc</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="reserved">if</span><span class="plain"> (</span><span class="identifier">EF</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">message</span><span class="plain"> = </span><span class="string">"I've now read %S, which is %d words long.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">message</span><span class="plain"> = </span><span class="string">"I've also read %S, which is %d words long.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">;</span>
<span class="identifier">wc</span><span class="plain"> = </span><span class="identifier">TextFromFiles::total_word_count</span><span class="plain">(</span><span class="identifier">sf</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">STDOUT</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">, </span><span class="identifier">wc</span><span class="plain">);</span>
<span class="identifier">STREAM_FLUSH</span><span class="plain">(</span><span class="identifier">STDOUT</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">synopsis</span><span class="plain">, </span><span class="identifier">wc</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">SourceFiles::read_file_inner</span><span class="plain">(</span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">synopsis</span><span class="plain">,</span>
<span class="identifier">pathname</span><span class="plain"> **</span><span class="identifier">list</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">list_len</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">documentation_only</span><span class="plain">, </span><span class="identifier">source_file</span><span class="plain"> **</span><span class="identifier">S</span><span class="plain">,</span>
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">ref</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">primary</span><span class="plain">, </span><span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">EF</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">origin_tried</span><span class="plain"> = 1;</span>
<span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">eventual</span><span class="plain"> = </span><span class="identifier">F</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Set pathname and filename, and open file</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">handle</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">leaf</span><span class="plain"> = </span><span class="identifier">Filenames::get_leafname</span><span class="plain">(</span><span class="identifier">eventual</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">primary</span><span class="plain">) </span><span class="identifier">leaf</span><span class="plain"> = </span><span class="identifier">I</span><span class="string">"main source text"</span><span class="plain">;</span>
<span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">sf</span><span class="plain"> = </span><span class="identifier">TextFromFiles::feed_open_file_into_lexer</span><span class="plain">(</span><span class="identifier">eventual</span><span class="plain">, </span><span class="identifier">handle</span><span class="plain">,</span>
<span class="identifier">leaf</span><span class="plain">, </span><span class="identifier">documentation_only</span><span class="plain">, </span><span class="identifier">ref</span><span class="plain">);</span>
<span class="identifier">fclose</span><span class="plain">(</span><span class="identifier">handle</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">S</span><span class="plain"> = </span><span class="identifier">sf</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">origin_tried</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::read_file_inner is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b>The primary source text must be found where we expect it, or a fatal
error is issued. An extension, however, can be in one of two places: the
user's own repository of installed extensions, or the built-in stock. We
must try each possibility &mdash; in that order, so that the user can supplant
the built-in extensions by installing hacked versions of her own &mdash; and in
the event of failing, we issue only a standard Inform problem message and
continue. While meaningful compilation is unlikely to succeed now, this is
not a fatal error, because fatality would cause the user interface
application to communicate the problem badly.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Set pathname and filename, and open file</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">handle</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">list</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">author_name</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">author_name</span><span class="plain">, </span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">-</span><span class="element">&gt;author_text</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">, </span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">EF</span><span class="plain">-</span><span class="element">&gt;title_text</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">area</span><span class="plain">=0; </span><span class="identifier">area</span><span class="plain">&lt;</span><span class="identifier">list_len</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">handle</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">[</span><span class="identifier">area</span><span class="plain">];</span>
<span class="identifier">origin_tried</span><span class="plain"> = </span><span class="identifier">area</span><span class="plain"> + 1;</span>
<span class="identifier">eventual</span><span class="plain"> = </span><span class="functiontext">Locations::of_extension</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">author_name</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">Filenames::fopen_caseless</span><span class="plain">(</span><span class="identifier">eventual</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">handle</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">eventual</span><span class="plain"> = </span><span class="functiontext">Locations::of_extension</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">author_name</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">Filenames::fopen_caseless</span><span class="plain">(</span><span class="identifier">eventual</span><span class="plain">, </span><span class="string">"r"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">author_name</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">handle</span><span class="plain"> = </span><span class="identifier">Filenames::fopen</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="string">"r"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b></p>
<pre class="display">
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="functiontext">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">sf</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">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_extension_file</span><span class="plain">(</span><span class="identifier">sf</span><span class="plain">-&gt;</span><span class="identifier">your_ref</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::get_extension_corresponding is used in 4/am (<a href="4-am.html#SP26_1">&#167;26.1</a>), 6/nv (<a href="6-nv.html#SP14_1">&#167;14.1</a>), 7/hdn (<a href="7-hdn.html#SP16">&#167;16</a>, <a href="7-hdn.html#SP33_1_1">&#167;33.1.1</a>), 8/ef (<a href="8-ef.html#SP21">&#167;21</a>), 9/tfa (<a href="9-tfa.html#SP11_1">&#167;11.1</a>), 17/rs (<a href="17-rs.html#SP7_3_1">&#167;7.3.1</a>), 21/rl2 (<a href="21-rl2.html#SP23_10_1">&#167;23.10.1</a>, <a href="21-rl2.html#SP24">&#167;24</a>), 25/ci (<a href="25-ci.html#SP3_2_3_6">&#167;3.2.3.6</a>), 26/uo (<a href="26-uo.html#SP11_1">&#167;11.1</a>, <a href="26-uo.html#SP13_1">&#167;13.1</a>, <a href="26-uo.html#SP16">&#167;16</a>), 27/cm (<a href="27-cm.html#SP2">&#167;2</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And the following converts lexer error conditions into I7 problem messages.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">LEXER_PROBLEM_HANDLER</span><span class="plain"> </span><span class="functiontext">SourceFiles::lexer_problem_handler</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">SourceFiles::lexer_problem_handler</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">err</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">problem_source_description</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">word</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">err</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MEMORY_OUT_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Fatal::issue</span><span class="plain">(</span><span class="string">"Out of memory: unable to create lexer workspace"</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="identifier">STRING_TOO_LONG_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TooMuchQuotedText</span><span class="plain">),</span>
<span class="string">"Too much text in quotation marks"</span><span class="plain">, </span><span class="identifier">word</span><span class="plain">,</span>
<span class="string">"...\</span><span class="plain">"</span><span class="string"> The maximum length is very high, so this is more "</span>
<span class="string">"likely to be because a close quotation mark was "</span>
<span class="string">"forgotten."</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="identifier">WORD_TOO_LONG_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WordTooLong</span><span class="plain">),</span>
<span class="string">"Word too long"</span><span class="plain">, </span><span class="identifier">word</span><span class="plain">,</span>
<span class="string">"(Individual words of unquoted text can run up to "</span>
<span class="string">"128 letters long, which ought to be plenty. The longest "</span>
<span class="string">"recognised place name in the English speaking world is "</span>
<span class="string">"a hill in New Zealand called Taumatawhakatang-"</span>
<span class="string">"ihangakoauauot-amateaturipukaka-pikimaunga-"</span>
<span class="string">"horonuku-pokaiwhenuak-itanatahu. (You say tomato, "</span>
<span class="string">"I say taumatawhakatang-...) The longest word found in a "</span>
<span class="string">"classic novel is bababadalgharaghtakamminarronnkonnbronntonn"</span>
<span class="string">"erronntuonnthunntrovarrhounawnskawntoohoohoordenenthurnuk, "</span>
<span class="string">"creation's thunderclap from Finnegan's Wake. And both of those "</span>
<span class="string">"words are fine.)"</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="identifier">I6_TOO_LONG_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">Untestable</span><span class="plain">), </span> <span class="comment">well, not at all conveniently</span>
<span class="string">"Verbatim Inform 6 extract too long"</span><span class="plain">, </span><span class="identifier">word</span><span class="plain">,</span>
<span class="string">"... -). The maximum length is quite high, so this "</span>
<span class="string">"may be because a '-)' was forgotten. Still, if "</span>
<span class="string">"you do need to paste a huge I6 program in, try "</span>
<span class="string">"using several verbatim inclusions in a row."</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="identifier">STRING_NEVER_ENDS_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem_S</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnendingQuote</span><span class="plain">),</span>
<span class="string">"Some source text ended in the middle of quoted text"</span><span class="plain">,</span>
<span class="identifier">problem_source_description</span><span class="plain">,</span>
<span class="string">"This probably means that a quotation mark is missing "</span>
<span class="string">"somewhere. If you are using Inform with syntax colouring, "</span>
<span class="string">"look for where the quoted-text colour starts. (Sometimes "</span>
<span class="string">"this problem turns up because a piece of quoted text contains "</span>
<span class="string">"a text substitution in square brackets which in turn contains "</span>
<span class="string">"another piece of quoted text - this is not allowed, and causes "</span>
<span class="string">"me to lose track.)"</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="identifier">COMMENT_NEVER_ENDS_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem_S</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnendingComment</span><span class="plain">),</span>
<span class="string">"Some source text ended in the middle of a comment"</span><span class="plain">,</span>
<span class="identifier">problem_source_description</span><span class="plain">,</span>
<span class="string">"This probably means that a ']' is missing somewhere. "</span>
<span class="string">"(If you are using Inform with syntax colouring, look for "</span>
<span class="string">"where the comment colour starts.) Inform's convention on "</span>
<span class="string">"'nested comments' is that each '[' in a comment must be "</span>
<span class="string">"matched by a corresponding ']': so for instance '[This "</span>
<span class="string">"[even nested like so] acts as a comment]' is a single "</span>
<span class="string">"comment - the first ']' character matches the second '[' "</span>
<span class="string">"and so doesn't end the comment: only the second ']' ends "</span>
<span class="string">"the comment."</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="identifier">I6_NEVER_ENDS_LEXERERROR</span><span class="plain">:</span>
<span class="identifier">Problems::Issue::lexical_problem_S</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnendingI6</span><span class="plain">),</span>
<span class="string">"Some source text ended in the middle of a verbatim passage "</span>
<span class="string">"of Inform 6 code"</span><span class="plain">,</span>
<span class="identifier">problem_source_description</span><span class="plain">,</span>
<span class="string">"This probably means that a '-)' is missing."</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown lexer error"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function SourceFiles::lexer_problem_handler appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 3: Bridge to Words Module.)</i></li><li><a href="3-nl.html">Continue with 'Natural Languages'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>