1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 00:24:22 +03:00
inform7/docs/words-module/3-tff.html
2023-05-16 08:58:36 +01:00

243 lines
40 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Text From Files</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Text From Files' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">words</a></li><li><a href="index.html#3">Chapter 3: Words in Sequence</a></li><li><b>Text From Files</b></li></ul></div>
<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="3-tff.html#SP1">&#167;1. Source files</a></li><li><a href="3-tff.html#SP2">&#167;2. Feeding whole files into the lexer</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Source files. </b>Each separate file of text read into the lexer has its identity docketed
in a <span class="extract"><span class="extract-syntax">source_file</span></span> structure, as follows.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">words_of_source</span><span class="plain-syntax">; </span><span class="comment-syntax"> word count, omitting comments and verbatim matter</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_read</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">words_of_quoted_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> word count for text in double-quotes</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">handle</span><span class="plain-syntax">; </span><span class="comment-syntax"> file handle while open</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">your_ref</span><span class="plain-syntax">; </span><span class="comment-syntax"> for the client to attach some meaning</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">source_file</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure source_file is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Feeding whole files into the lexer. </b>This is one of the two feeder routines for the lexer, the other being in
Lexical Writing Back.w: see Lexer.w for its obligations.
</p>
<p class="commentary">We feed characters from an open file into the lexer, and continue until there
is nothing left in it. Inform is used on operating systems which between them
use all four of the sequences <span class="extract"><span class="extract-syntax">0a</span></span>, <span class="extract"><span class="extract-syntax">0d</span></span>, <span class="extract"><span class="extract-syntax">0a0d</span></span> and <span class="extract"><span class="extract-syntax">0d0a</span></span> to divide lines in
text files, so each of these is converted to a single <span class="extract"><span class="extract-syntax">'\n'</span></span>. Tabs are treated
as if spaces in most contexts, but not when parsing formatted tables, for
instance, so they are not similarly converted.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="function-syntax">TextFromFiles::feed_open_file_into_lexer</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">TextFromFiles::feed_open_file_into_lexer</span></span>:<br/><a href="3-tff.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">handle</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leaf</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">documentation_only</span><span class="plain-syntax">, </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">ref</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">source_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">words_of_source</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">words_of_quoted_text</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">your_ref</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ref</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">F</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">handle</span><span class="plain-syntax"> = </span><span class="identifier-syntax">handle</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">source_location</span><span class="plain-syntax"> </span><span class="identifier-syntax">top_of_file</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">last_cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">read_cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">unicode_file_buffer</span><span class="plain-syntax"> </span><span class="identifier-syntax">ufb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TextFiles::create_filtered_ufb</span><span class="plain-syntax">(</span><span class="identifier-syntax">mode</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">top_of_file</span><span class="plain-syntax">.</span><span class="element-syntax">file_of_origin</span><span class="plain-syntax"> = </span><span class="identifier-syntax">sf</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">top_of_file</span><span class="plain-syntax">.</span><span class="element-syntax">line_number</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-lxr.html#SP25" class="function-link"><span class="function-syntax">Lexer::feed_begins</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">top_of_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">documentation_only</span><span class="plain-syntax">) </span><span class="identifier-syntax">lexer_wait_for_dashes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">last_cr</span><span class="plain-syntax"> = </span><span class="character-syntax">' '</span><span class="plain-syntax">; </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="character-syntax">' '</span><span class="plain-syntax">; </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TextFiles::utf8_fgetc</span><span class="plain-syntax">(</span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">handle</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">ufb</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">next_cr</span><span class="plain-syntax"> == </span><span class="constant-syntax">0xFEFF</span><span class="plain-syntax">) </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TextFiles::utf8_fgetc</span><span class="plain-syntax">(</span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">handle</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">ufb</span><span class="plain-syntax">); </span><span class="comment-syntax"> Unicode BOM code</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">next_cr</span><span class="plain-syntax"> != </span><span class="identifier-syntax">EOF</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (((</span><span class="identifier-syntax">read_cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TextFiles::utf8_fgetc</span><span class="plain-syntax">(</span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">handle</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">ufb</span><span class="plain-syntax">)), </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax">) != </span><span class="identifier-syntax">EOF</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">last_cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">cr</span><span class="plain-syntax">; </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax">; </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">read_cr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">cr</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\x0a'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> == </span><span class="character-syntax">'\x0d'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">; </span><span class="comment-syntax"> suppress </span><span class="extract"><span class="extract-syntax">0x000A</span></span><span class="comment-syntax"> when it follows </span><span class="extract"><span class="extract-syntax">0x000D</span></span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="identifier-syntax">cr</span><span class="plain-syntax">; </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="character-syntax">'\n'</span><span class="plain-syntax">; </span><span class="comment-syntax"> and otherwise convert to </span><span class="extract"><span class="extract-syntax">'\n'</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\x0d'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> == </span><span class="character-syntax">'\x0a'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">continue</span><span class="plain-syntax">; </span><span class="comment-syntax"> suppress </span><span class="extract"><span class="extract-syntax">0x000D</span></span><span class="comment-syntax"> when it follows </span><span class="extract"><span class="extract-syntax">0x000A</span></span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="identifier-syntax">cr</span><span class="plain-syntax">; </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="character-syntax">'\n'</span><span class="plain-syntax">; </span><span class="comment-syntax"> and otherwise convert to </span><span class="extract"><span class="extract-syntax">'\n'</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newline_char</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="3-lxr.html#SP26" class="function-link"><span class="function-syntax">Lexer::feed_triplet</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">last_cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">text_read</span><span class="plain-syntax"> = </span><a href="3-lxr.html#SP25" class="function-link"><span class="function-syntax">Lexer::feed_ends</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-tff.html#SP2_1" class="named-paragraph-link"><span class="named-paragraph">Word count the new material</span><span class="named-paragraph-number">2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2_1" class="paragraph-anchor"></a><b>&#167;2.1. </b>We word count all source files, both as to their source text and their
quoted text (i.e., their text within double-quotes).
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Word count the new material</span><span class="named-paragraph-number">2.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">wc</span><span class="plain-syntax">, </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">text_read</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">words_of_source</span><span class="plain-syntax"> += </span><a href="3-tff.html#SP4" class="function-link"><span class="function-syntax">TextFromFiles::word_count</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wc</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-tff.html#SP2">&#167;2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>A much simpler version:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="function-syntax">TextFromFiles::feed_into_lexer</span><span class="plain-syntax">(</span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">ref</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">handle</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Filenames::fopen</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="string-syntax">"r"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">handle</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax"> = </span><a href="3-tff.html#SP2" class="function-link"><span class="function-syntax">TextFromFiles::feed_open_file_into_lexer</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">handle</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Filenames::get_leafname</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">), </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">ref</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNICODE_UFBHM</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fclose</span><span class="plain-syntax">(</span><span class="identifier-syntax">handle</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">TextFromFiles::word_count</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">TextFromFiles::word_count</span></span>:<br/><a href="3-tff.html#SP2_1">&#167;2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wc</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="character-syntax">'"'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> inside quoted text, each run of non-whitespace counts as 1 word</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">++; </span><span class="comment-syntax"> skip opening quotation mark</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="character-syntax">' '</span><span class="plain-syntax">) || (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NEWLINE_IN_STRING</span><span class="plain-syntax">)) </span><span class="identifier-syntax">p</span><span class="plain-syntax">++; </span><span class="comment-syntax"> move past white space</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="character-syntax">'"'</span><span class="plain-syntax">) || (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="reserved-syntax">break</span><span class="plain-syntax">; </span><span class="comment-syntax"> stop if this reaches the end</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">++; </span><span class="comment-syntax"> otherwise we have a word</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="character-syntax">' '</span><span class="plain-syntax">) &amp;&amp; (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NEWLINE_IN_STRING</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> &amp;&amp; (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="character-syntax">'"'</span><span class="plain-syntax">) &amp;&amp; (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="identifier-syntax">p</span><span class="plain-syntax">++; </span><span class="comment-syntax"> move to white space or end</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> outside quoted text, each lexer word not wholly composed of punctuation scores 1</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP19" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wc</span><span class="plain-syntax">) != </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-lxr.html#SP17" class="function-link"><span class="function-syntax">Lexer::is_punctuation</span></a><span class="plain-syntax">(*</span><span class="identifier-syntax">p</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (*</span><span class="identifier-syntax">p</span><span class="plain-syntax"> != </span><span class="character-syntax">'|'</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>At present, though, the only use made of these two word counts is via
the following routine, which combines them into one.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">TextFromFiles::total_word_count</span><span class="plain-syntax">(</span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">words_of_source</span><span class="plain-syntax"> + </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">words_of_quoted_text</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">TextFromFiles::last_lexed_word</span><span class="plain-syntax">(</span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-wrd.html#SP7" class="function-link"><span class="function-syntax">Wordings::last_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">text_read</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>Finally, we translate between the tiresomely many representations of
files we seem to be stuck with. The method used by <span class="extract"><span class="extract-syntax">TextFromFiles::filename_to_source_file</span></span>
looks vulnerable to case-insensitive filename issues, but isn't, because
each filename is present in Inform in only one form.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="function-syntax">TextFromFiles::get_filename</span><span class="plain-syntax">(</span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to read filename of null source file"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="function-syntax">TextFromFiles::filename_to_source_file</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">l2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">name2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">sf</span><span class="plain-syntax">, </span><span class="reserved-syntax">source_file</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">name1</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">name1</span><span class="plain-syntax">, </span><span class="string-syntax">"%f"</span><span class="plain-syntax">, </span><span class="identifier-syntax">sf</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">l1</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">name1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">minl</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">l1</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">l2</span><span class="plain-syntax">)?</span><span class="identifier-syntax">l1:l2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::suffix_eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">name1</span><span class="plain-syntax">, </span><span class="identifier-syntax">name2</span><span class="plain-syntax">, </span><span class="identifier-syntax">minl</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sf</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="3-wrd.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresssection"><a href="3-lxr.html">lxr</a></li><li class="progresssection"><a href="3-wrd.html">wrd</a></li><li class="progresscurrent">tff</li><li class="progresssection"><a href="3-fds.html">fds</a></li><li class="progresssection"><a href="3-idn.html">idn</a></li><li class="progresschapter"><a href="4-ap.html">4</a></li><li class="progressnext"><a href="3-fds.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>