inweb-bootstrap/docs/inweb/3-ti.html
2020-03-23 15:04:43 +00:00

887 lines
126 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>3/ts</title>
<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="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '3/ti' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Indexer</b></li></ul><p class="purpose">To construct indexes of the material woven, following a template.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Cover sheets</a></li><li><a href="#SP4">&#167;4. Full index pages</a></li><li><a href="#SP5">&#167;5. Running the interpreter</a></li><li><a href="#SP5_2">&#167;5.2. File handling</a></li><li><a href="#SP5_1_1">&#167;5.1.1. The repeat stack and loops</a></li><li><a href="#SP5_1_8">&#167;5.1.8. Variable substitutions</a></li><li><a href="#SP6">&#167;6. Transcribing CSS</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Cover sheets. </b>The indexer offers two basic services. One, which is much simpler, makes
cover sheets, and has only simple escapes (except that it has the ability
to call the fuller indexing service if need be, using <code class="display"><span class="extract">[[Template T]]</span></code>).
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::cover_sheet_maker</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">unextended_leafname</span><span class="plain">,</span>
<span class="reserved">weave_target</span><span class="plain"> *</span><span class="identifier">wt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">halves</span><span class="plain">) {</span>
<span class="reserved">cover_sheet_state</span><span class="plain"> </span><span class="identifier">state</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Clear the cover sheet state</span> <span class="cwebmacronumber">1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">extended_leafname</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">extended_leafname</span><span class="plain">, </span><span class="string">"%S%S"</span><span class="plain">, </span><span class="identifier">unextended_leafname</span><span class="plain">, </span><span class="functiontext">Formats::file_extension</span><span class="plain">(</span><span class="identifier">wt</span><span class="plain">-</span><span class="element">&gt;format</span><span class="plain">));</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">cs_filename</span><span class="plain"> = </span><span class="functiontext">Patterns::obtain_filename</span><span class="plain">(</span><span class="identifier">wt</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">, </span><span class="identifier">extended_leafname</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">extended_leafname</span><span class="plain">);</span>
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">cs_filename</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="string">"can't open cover sheet file"</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">,</span>
<span class="functiontext">Indexer::scan_cover_line</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) &amp;</span><span class="identifier">state</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::cover_sheet_maker is used in <a href="#SP2_1_1">&#167;2.1.1</a>, 3/tw (<a href="3-tw.html#SP1_2">&#167;1.2</a>, <a href="3-tw.html#SP1_4">&#167;1.4</a>), 5/hf (<a href="5-hf.html#SP6">&#167;6</a>, <a href="5-hf.html#SP25">&#167;25</a>).</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>The cover-sheet-maker has the ability to weave only the top half, or only
the bottom half, of the template; they are divided by the marker <code class="display"><span class="extract">[[Code]]</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">WEAVE_FIRST_HALF</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">WEAVE_SECOND_HALF</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">IN_SECOND_HALF</span><span class="plain"> 4</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">cover_sheet_state</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">WEAVE_COVER_TO</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">halves</span><span class="plain">; </span> <span class="comment">a bitmap of the above values</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">weave_target</span><span class="plain"> *</span><span class="identifier">target</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">cover_sheet_state</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure cover_sheet_state is private to this section.</p>
<p class="inwebparagraph"><a id="SP1_2"></a><b>&#167;1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Clear the cover sheet state</span> <span class="cwebmacronumber">1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">state</span><span class="element">.halves</span><span class="plain"> = </span><span class="identifier">halves</span><span class="plain">;</span>
<span class="identifier">state</span><span class="element">.WEAVE_COVER_TO</span><span class="plain"> = </span><span class="identifier">OUT</span><span class="plain">;</span>
<span class="identifier">state</span><span class="element">.target</span><span class="plain"> = </span><span class="identifier">wt</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The above, then, iterates the following routine on each line of the template
file one by one, passing it a pointer to an instance of the above state
structure.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::scan_cover_line</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">, </span><span class="reserved">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">v_state</span><span class="plain">) {</span>
<span class="reserved">cover_sheet_state</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain"> = (</span><span class="reserved">cover_sheet_state</span><span class="plain"> *) </span><span class="identifier">v_state</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;WEAVE_COVER_TO</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">include</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> &amp; </span><span class="constant">WEAVE_FIRST_HALF</span><span class="plain">) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> &amp; </span><span class="constant">IN_SECOND_HALF</span><span class="plain">) == 0)) ||</span>
<span class="plain">((</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> &amp; </span><span class="constant">WEAVE_SECOND_HALF</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> &amp; </span><span class="constant">IN_SECOND_HALF</span><span class="plain">))) </span><span class="identifier">include</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">include</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;self_contained</span><span class="plain">) || (</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">-</span><span class="element">&gt;embed_CSS</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *%&lt;link href=%\</span><span class="plain">"</span><span class="string">(%c+?)\</span><span class="plain">"</span><span class="string">%c*"</span><span class="plain">))) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">CSS_file</span><span class="plain"> = </span><span class="functiontext">Patterns::obtain_filename</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="functiontext">Indexer::transcribe_CSS</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">CSS_file</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*?)%[%[(%c*?)%]%](%c*)"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0];</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">command</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[1];</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[2];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">left</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Deal with a double-squares escape in a cover sheet</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">right</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::scan_cover_line is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Deal with a double-squares escape in a cover sheet</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr2</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">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">"Code"</span><span class="plain">)) {</span>
<span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> |= </span><span class="constant">IN_SECOND_HALF</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="functiontext">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">"Cover Sheet"</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span>&lt;<span class="cwebmacro">Weave in the parent pattern's cover sheet</span> <span class="cwebmacronumber">2.1.1</span>&gt;<span class="character">;</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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr2</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Navigation"</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span>&lt;<span class="cwebmacro">Weave in navigation</span> <span class="cwebmacronumber">2.1.2</span>&gt;<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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr2</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Template (%c*?)"</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span>&lt;<span class="cwebmacro">Weave in an index</span> <span class="cwebmacronumber">2.1.3</span>&gt;<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="functiontext">Bibliographic::data_exists</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">include</span><span class="plain">) </span>&lt;<span class="cwebmacro">Weave in the value of this variable name</span> <span class="cwebmacronumber">2.1.4</span>&gt;<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">include</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr2</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_1_1"></a><b>&#167;2.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Weave in the parent pattern's cover sheet</span> <span class="cwebmacronumber">2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">-</span><span class="element">&gt;based_on</span><span class="plain">) {</span>
<span class="reserved">weave_pattern</span><span class="plain"> *</span><span class="identifier">saved</span><span class="plain"> = </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">;</span>
<span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain"> = </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">-</span><span class="element">&gt;based_on</span><span class="plain">;</span>
<span class="functiontext">Indexer::cover_sheet_maker</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">,</span>
<span class="identifier">I</span><span class="string">"cover-sheet"</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;halves</span><span class="plain"> &amp; (</span><span class="constant">WEAVE_FIRST_HALF</span><span class="plain"> + </span><span class="constant">WEAVE_SECOND_HALF</span><span class="plain">)));</span>
<span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain"> = </span><span class="identifier">saved</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Errors::in_text_file</span><span class="plain">(</span><span class="string">"cover sheet recursively includes itself"</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP2_1_2"></a><b>&#167;2.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Weave in navigation</span> <span class="cwebmacronumber">2.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Filenames::get_path_to</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_to</span><span class="plain">);</span>
<span class="functiontext">Indexer::nav_column</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="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_range</span><span class="plain">,</span>
<span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;navigation</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP2_1_3"></a><b>&#167;2.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Weave in an index</span> <span class="cwebmacronumber">2.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Filenames::get_path_to</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_to</span><span class="plain">);</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">CF</span><span class="plain"> = </span><span class="functiontext">Patterns::obtain_filename</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">, </span><span class="identifier">mr2</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">CF</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Errors::in_text_file</span><span class="plain">(</span><span class="string">"pattern does not provide this template file"</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Indexer::run</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_range</span><span class="plain">,</span>
<span class="identifier">CF</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">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;pattern</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;navigation</span><span class="plain">,</span>
<span class="identifier">NULL</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP2_1_4"></a><b>&#167;2.1.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Weave in the value of this variable name</span> <span class="cwebmacronumber">2.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">state</span><span class="plain">-</span><span class="element">&gt;target</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::nav_column</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">range</span><span class="plain">,</span>
<span class="reserved">weave_pattern</span><span class="plain"> *</span><span class="identifier">pattern</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">nav</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nav</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TextFiles::exists</span><span class="plain">(</span><span class="identifier">nav</span><span class="plain">))</span>
<span class="functiontext">Indexer::run</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">range</span><span class="plain">, </span><span class="identifier">nav</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">pattern</span><span class="plain">, </span><span class="identifier">P</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="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Errors::fatal_with_file</span><span class="plain">(</span><span class="string">"unable to find navigation file"</span><span class="plain">, </span><span class="identifier">nav</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">pattern</span><span class="plain">-</span><span class="element">&gt;hierarchical</span><span class="plain">) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="functiontext">Pathnames::up</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">), </span><span class="identifier">I</span><span class="string">"nav.html"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TextFiles::exists</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">))</span>
<span class="functiontext">Indexer::run</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">range</span><span class="plain">, </span><span class="identifier">F</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">pattern</span><span class="plain">, </span><span class="identifier">P</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="constant">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"nav.html"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TextFiles::exists</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">))</span>
<span class="functiontext">Indexer::run</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">range</span><span class="plain">, </span><span class="identifier">F</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">pattern</span><span class="plain">, </span><span class="identifier">P</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="constant">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::nav_column is used in <a href="#SP2_1_2">&#167;2.1.2</a>, <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Full index pages. </b>This is a much more substantial service, and operates as a little processor
interpreting a meta-language all of its very own, with a stack for holding
nested repeat loops, and a program counter and &mdash; well, and nothing else to
speak of, in fact, except for the slightly unusual way that loop variables
provide context by changing the subject of what is discussed rather than by
being accessed directly.
</p>
<p class="inwebparagraph">The current state of the processor is recorded in the following.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_TEMPLATE_LINES</span><span class="plain"> 256 </span> <span class="comment">maximum number of lines in template</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_STACK_CAPACITY</span><span class="plain"> 8 </span> <span class="comment">maximum recursion of chapter/section iteration</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">contents_processor</span><span class="plain"> {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tlines</span><span class="plain">[</span><span class="constant">MAX_TEMPLATE_LINES</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_tlines</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">repeat_stack_level</span><span class="plain">[</span><span class="constant">CI_STACK_CAPACITY</span><span class="plain">];</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">repeat_stack_variable</span><span class="plain">[</span><span class="constant">CI_STACK_CAPACITY</span><span class="plain">];</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">repeat_stack_threshold</span><span class="plain">[</span><span class="constant">CI_STACK_CAPACITY</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">repeat_stack_startpos</span><span class="plain">[</span><span class="constant">CI_STACK_CAPACITY</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">stack_pointer</span><span class="plain">; </span> <span class="comment">And this is our stack pointer for tracking of loops</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">restrict_to_range</span><span class="plain">;</span>
<span class="reserved">web</span><span class="plain"> *</span><span class="identifier">nav_web</span><span class="plain">;</span>
<span class="reserved">weave_pattern</span><span class="plain"> *</span><span class="identifier">nav_pattern</span><span class="plain">;</span>
<span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">nav_path</span><span class="plain">;</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">nav_file</span><span class="plain">;</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">crumbs</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">docs_mode</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">contents_processor</span><span class="plain">;</span>
<span class="reserved">contents_processor</span><span class="plain"> </span><span class="functiontext">Indexer::new_processor</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">range</span><span class="plain">) {</span>
<span class="reserved">contents_processor</span><span class="plain"> </span><span class="identifier">cp</span><span class="plain">;</span>
<span class="identifier">cp</span><span class="element">.no_tlines</span><span class="plain"> = 0;</span>
<span class="identifier">cp</span><span class="element">.restrict_to_range</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">range</span><span class="plain">);</span>
<span class="identifier">cp</span><span class="element">.stack_pointer</span><span class="plain"> = 0;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cp</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::new_processor is used in <a href="#SP5">&#167;5</a>.</p>
<p class="endnote">The structure contents_processor is accessed in 3/ts, 5/hf and here.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Running the interpreter. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">TRACE_CI_EXECUTION</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain"> </span> <span class="comment">set true for debugging</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::run</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">range</span><span class="plain">,</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">template_filename</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">contents_page_leafname</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">write_to</span><span class="plain">,</span><span class="reserved"> weave_pattern</span><span class="plain"> *</span><span class="identifier">pattern</span><span class="plain">, </span><span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">nav_file</span><span class="plain">,</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">crumbs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">docs</span><span class="plain">) {</span>
<span class="reserved">contents_processor</span><span class="plain"> </span><span class="identifier">actual_cp</span><span class="plain"> = </span><span class="functiontext">Indexer::new_processor</span><span class="plain">(</span><span class="identifier">range</span><span class="plain">);</span>
<span class="identifier">actual_cp</span><span class="element">.nav_web</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">actual_cp</span><span class="element">.nav_pattern</span><span class="plain"> = </span><span class="identifier">pattern</span><span class="plain">;</span>
<span class="identifier">actual_cp</span><span class="element">.nav_path</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">;</span>
<span class="identifier">actual_cp</span><span class="element">.nav_file</span><span class="plain"> = </span><span class="identifier">nav_file</span><span class="plain">;</span>
<span class="identifier">actual_cp</span><span class="element">.crumbs</span><span class="plain"> = </span><span class="identifier">crumbs</span><span class="plain">;</span>
<span class="identifier">actual_cp</span><span class="element">.docs_mode</span><span class="plain"> = </span><span class="identifier">docs</span><span class="plain">;</span>
<span class="reserved">contents_processor</span><span class="plain"> *</span><span class="identifier">cp</span><span class="plain"> = &amp;</span><span class="identifier">actual_cp</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> </span><span class="identifier">TO_struct</span><span class="plain">; </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = &amp;</span><span class="identifier">TO_struct</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Read in the source file containing the contents page template</span> <span class="cwebmacronumber">5.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Open the contents page file to be constructed</span> <span class="cwebmacronumber">5.4</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lpos</span><span class="plain"> = 0; </span> <span class="comment">This is our program counter: a line number in the template</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">lpos</span><span class="plain"> &lt; </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;no_tlines</span><span class="plain">) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;tlines</span><span class="plain">[</span><span class="identifier">lpos</span><span class="plain">++]); </span> <span class="comment">Fetch the line at the program counter and advance</span>
&lt;<span class="cwebmacro">Make any necessary substitutions to turn tl into final output</span> <span class="cwebmacronumber">5.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">); </span> <span class="comment">Copy the now finished line to the output</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">);</span>
<span class="identifier">CYCLE</span><span class="plain">: ;</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">write_to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::run is used in <a href="#SP2_1_3">&#167;2.1.3</a>, <a href="#SP3">&#167;3</a>, 3/ts (<a href="3-ts.html#SP3">&#167;3</a>).</p>
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Make any necessary substitutions to turn tl into final output</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*?) "</span><span class="plain">)) </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]); </span> <span class="comment">Strip trailing spaces</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="constant">TRACE_CI_EXECUTION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Print line and contents of repeat stack</span> <span class="cwebmacronumber">5.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pattern</span><span class="plain">-</span><span class="element">&gt;embed_CSS</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *%&lt;link href=%\</span><span class="plain">"</span><span class="string">(%c+?)\</span><span class="plain">"</span><span class="string">%c*"</span><span class="plain">))) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">CSS_file</span><span class="plain"> = </span><span class="functiontext">Patterns::obtain_filename</span><span class="plain">(</span><span class="identifier">pattern</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="functiontext">Indexer::transcribe_CSS</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">CSS_file</span><span class="plain">);</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%[%[(%c+)%]%]"</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" %[%[(%c+)%]%]"</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="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
&lt;<span class="cwebmacro">Deal with a Select command</span> <span class="cwebmacronumber">5.1.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Deal with a Repeat command</span> <span class="cwebmacronumber">5.1.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Deal with a Repeat End command</span> <span class="cwebmacronumber">5.1.4</span>&gt;<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="plain">}</span>
&lt;<span class="cwebmacro">Skip line if inside an empty loop</span> <span class="cwebmacronumber">5.1.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Make substitutions of square-bracketed variables in line</span> <span class="cwebmacronumber">5.1.8</span>&gt;<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="SP5_2"></a><b>&#167;5.2. File handling. </b></p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read in the source file containing the contents page template</span> <span class="cwebmacronumber">5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">template_filename</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">,</span>
<span class="string">"can't find contents template"</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">, </span><span class="functiontext">Indexer::save_template_line</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="constant">TRACE_CI_EXECUTION</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"Read template &lt;%f&gt;: %d line(s)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">template_filename</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;no_tlines</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="SP5_3"></a><b>&#167;5.3. </b>With the following iterator:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::save_template_line</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">, </span><span class="reserved">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">void_cp</span><span class="plain">) {</span>
<span class="reserved">contents_processor</span><span class="plain"> *</span><span class="identifier">cp</span><span class="plain"> = (</span><span class="reserved">contents_processor</span><span class="plain"> *) </span><span class="identifier">void_cp</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;no_tlines</span><span class="plain"> &lt; </span><span class="constant">MAX_TEMPLATE_LINES</span><span class="plain">)</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;tlines</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;no_tlines</span><span class="plain">++] = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::save_template_line is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_4"></a><b>&#167;5.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Open the contents page file to be constructed</span> <span class="cwebmacronumber">5.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">H</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;redirect_weaves_to</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">H</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">H</span><span class="plain"> = </span><span class="functiontext">Reader::woven_folder</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">write_to</span><span class="plain">) </span><span class="identifier">OUT</span><span class="plain"> = </span><span class="identifier">write_to</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">Contents</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">H</span><span class="plain">, </span><span class="identifier">contents_page_leafname</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">STREAM_OPEN_TO_FILE</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Contents</span><span class="plain">, </span><span class="constant">ISO_ENC</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext">Errors::fatal_with_file</span><span class="plain">(</span><span class="string">"unable to write contents file"</span><span class="plain">, </span><span class="identifier">Contents</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;as_ebook</span><span class="plain">)</span>
<span class="functiontext">Epub::note_page</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;as_ebook</span><span class="plain">, </span><span class="identifier">Contents</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Index"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"index"</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[Index file: %f]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">Contents</span><span class="plain">);</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="SP5_1_1"></a><b>&#167;5.1.1. The repeat stack and loops. </b></p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print line and contents of repeat stack</span> <span class="cwebmacronumber">5.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"%04d: %S\</span><span class="plain">n</span><span class="string">Stack:"</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">-1, </span><span class="identifier">tl</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">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" %d: %S/%S"</span><span class="plain">,</span>
<span class="identifier">j</span><span class="plain">, ((</span><span class="reserved">chapter</span><span class="plain"> *) </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="reserved">chapter</span><span class="plain">))-</span><span class="element">&gt;ch_range</span><span class="plain">,</span>
<span class="plain">((</span><span class="reserved">chapter</span><span class="plain"> *) </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="reserved">chapter</span><span class="plain">))-</span><span class="element">&gt;ch_range</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">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">SECTION_LEVEL</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" %d: %S/%S"</span><span class="plain">,</span>
<span class="identifier">j</span><span class="plain">, ((</span><span class="reserved">section</span><span class="plain"> *) </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="reserved">section</span><span class="plain">))-</span><span class="element">&gt;range</span><span class="plain">,</span>
<span class="plain">((</span><span class="reserved">section</span><span class="plain"> *) </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="reserved">section</span><span class="plain">))-</span><span class="element">&gt;range</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_2"></a><b>&#167;5.1.2. </b>We start the direct commands with Select, which is implemented as a
one-iteration loop in which the loop variable has the given section or
chapter as its value during the sole iteration.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with a Select command</span> <span class="cwebmacronumber">5.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Select (%c*)"</span><span class="plain">)) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">)</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;sections</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;range</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0])) {</span>
<span class="functiontext">Indexer::start_CI_loop</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="constant">SECTION_LEVEL</span><span class="plain">, </span><span class="identifier">S_item</span><span class="plain">, </span><span class="identifier">S_item</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_range</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0])) {</span>
<span class="functiontext">Indexer::start_CI_loop</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">, </span><span class="identifier">C_item</span><span class="plain">, </span><span class="identifier">C_item</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Errors::at_position</span><span class="plain">(</span><span class="string">"don't recognise the chapter or section abbreviation range"</span><span class="plain">,</span>
<span class="identifier">template_filename</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_3"></a><b>&#167;5.1.3. </b>Next, a genuine loop beginning:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with a Repeat command</span> <span class="cwebmacronumber">5.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">loop_level</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Repeat Chapter"</span><span class="plain">)) </span><span class="identifier">loop_level</span><span class="plain"> = </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Repeat Section"</span><span class="plain">)) </span><span class="identifier">loop_level</span><span class="plain"> = </span><span class="constant">SECTION_LEVEL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">loop_level</span><span class="plain"> != 0) {</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">CI</span><span class="plain"> = </span><span class="identifier">FIRST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">CI</span><span class="plain">) &amp;&amp; (</span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">CI</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">)-</span><span class="element">&gt;imported</span><span class="plain">))</span>
<span class="identifier">CI</span><span class="plain"> = </span><span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">CI</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">loop_level</span><span class="plain"> == </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">) {</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="identifier">CI</span><span class="plain">;</span>
<span class="identifier">to</span><span class="plain"> = </span><span class="identifier">LAST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;restrict_to_range</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"0"</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_range</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;restrict_to_range</span><span class="plain">)) {</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="identifier">C_item</span><span class="plain">; </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="reserved">break</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">loop_level</span><span class="plain"> == </span><span class="constant">SECTION_LEVEL</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">within_chapter</span><span class="plain"> =</span>
<span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="functiontext">Indexer::heading_topmost_on_stack</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">), </span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">within_chapter</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">CI</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain"> = </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span><span class="identifier">CI</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="identifier">FIRST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;sections</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">LC</span><span class="plain"> = </span><span class="identifier">LAST_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LC</span><span class="plain">) </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">LAST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">, </span><span class="identifier">LC</span><span class="plain">-</span><span class="element">&gt;sections</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="identifier">FIRST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">, </span><span class="identifier">within_chapter</span><span class="plain">-</span><span class="element">&gt;sections</span><span class="plain">);</span>
<span class="identifier">to</span><span class="plain"> = </span><span class="identifier">LAST_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">, </span><span class="identifier">within_chapter</span><span class="plain">-</span><span class="element">&gt;sections</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">from</span><span class="plain">) </span><span class="functiontext">Indexer::start_CI_loop</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="identifier">loop_level</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_4"></a><b>&#167;5.1.4. </b>And at the other bookend:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with a Repeat End command</span> <span class="cwebmacronumber">5.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"End Repeat"</span><span class="plain">)) || (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"End Select"</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain"> &lt;= 0)</span>
<span class="functiontext">Errors::at_position</span><span class="plain">(</span><span class="string">"stack underflow on contents template"</span><span class="plain">, </span><span class="identifier">template_filename</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1] == </span><span class="constant">SECTION_LEVEL</span><span class="plain">) {</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">SI</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">SI</span><span class="plain"> == </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1]) ||</span>
<span class="plain">(</span><span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">SI</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="functiontext">Indexer::end_CI_loop</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1] =</span>
<span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">SI</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">);</span>
<span class="identifier">lpos</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_startpos</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1]; </span> <span class="comment">Back round loop</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">CI</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">CI</span><span class="plain"> == </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1])</span>
<span class="functiontext">Indexer::end_CI_loop</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1] =</span>
<span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">CI</span><span class="plain">, </span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="identifier">lpos</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_startpos</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1]; </span> <span class="comment">Back round loop</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_5"></a><b>&#167;5.1.5. </b>It can happen that a section loop, at least, is empty:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Skip line if inside an empty loop</span> <span class="cwebmacronumber">5.1.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">rstl</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1; </span><span class="identifier">rstl</span><span class="plain"> &gt;= 0; </span><span class="identifier">rstl</span><span class="plain">--)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1] == </span><span class="constant">SECTION_LEVEL</span><span class="plain">) {</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">SI</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NEXT_ITEM_IN_LINKED_LIST</span><span class="plain">(</span><span class="identifier">SI</span><span class="plain">, </span><span class="reserved">section</span><span class="plain">) ==</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1])</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">CYCLE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_6"></a><b>&#167;5.1.6. </b>If called with level <code class="display"><span class="extract">CHAPTER_LEVEL</span></code>, this returns the topmost chapter number
on the stack; and similarly for <code class="display"><span class="extract">SECTION_LEVEL</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CHAPTER_LEVEL</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">SECTION_LEVEL</span><span class="plain"> 2</span>
</pre>
<pre class="display">
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="functiontext">Indexer::heading_topmost_on_stack</span><span class="plain">(</span><span class="reserved">contents_processor</span><span class="plain"> *</span><span class="identifier">cp</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">level</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">rstl</span><span class="plain"> = </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">-1; </span><span class="identifier">rstl</span><span class="plain"> &gt;= 0; </span><span class="identifier">rstl</span><span class="plain">--)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">rstl</span><span class="plain">] == </span><span class="identifier">level</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">rstl</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::heading_topmost_on_stack is used in <a href="#SP5_1_3">&#167;5.1.3</a>, <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_7"></a><b>&#167;5.1.7. </b>This is the code for starting a loop, which stacks up the details, and
similarly for ending it by popping them again:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::start_CI_loop</span><span class="plain">(</span><span class="reserved">contents_processor</span><span class="plain"> *</span><span class="identifier">cp</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">level</span><span class="plain">,</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain"> &lt; </span><span class="constant">CI_STACK_CAPACITY</span><span class="plain">) {</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_level</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">] = </span><span class="identifier">level</span><span class="plain">;</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_variable</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">] = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_threshold</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">] = </span><span class="identifier">to</span><span class="plain">;</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;repeat_stack_startpos</span><span class="plain">[</span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">++] = </span><span class="identifier">pos</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">Indexer::end_CI_loop</span><span class="plain">(</span><span class="reserved">contents_processor</span><span class="plain"> *</span><span class="identifier">cp</span><span class="plain">) {</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;stack_pointer</span><span class="plain">--;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::start_CI_loop is used in <a href="#SP5_1_2">&#167;5.1.2</a>, <a href="#SP5_1_3">&#167;5.1.3</a>.</p>
<p class="endnote">The function Indexer::end_CI_loop is used in <a href="#SP5_1_4">&#167;5.1.4</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_8"></a><b>&#167;5.1.8. Variable substitutions. </b>We can now forget about this tiny stack machine: the one task left is to
take a line from the template, and make substitutions of variables into
its square-bracketed parts.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make substitutions of square-bracketed variables in line</span> <span class="cwebmacronumber">5.1.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">slen</span><span class="plain">, </span><span class="identifier">spos</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">spos</span><span class="plain"> = </span><span class="functiontext">Regexp::find_expansion</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="character">'['</span><span class="plain">, </span><span class="character">'['</span><span class="plain">, </span><span class="character">']'</span><span class="plain">, </span><span class="character">']'</span><span class="plain">, &amp;</span><span class="identifier">slen</span><span class="plain">)) &gt;= 0) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">left_part</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">varname</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">right_part</span><span class="plain">);</span>
<span class="functiontext">Str::substr</span><span class="plain">(</span><span class="identifier">left_part</span><span class="plain">, </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">), </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">spos</span><span class="plain">));</span>
<span class="functiontext">Str::substr</span><span class="plain">(</span><span class="identifier">varname</span><span class="plain">, </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">spos</span><span class="plain">+2), </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">spos</span><span class="plain">+</span><span class="identifier">slen</span><span class="plain">-2));</span>
<span class="functiontext">Str::substr</span><span class="plain">(</span><span class="identifier">right_part</span><span class="plain">, </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="identifier">spos</span><span class="plain">+</span><span class="identifier">slen</span><span class="plain">), </span><span class="functiontext">Str::end</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">));</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">);</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Bibliographic::data_exists</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Substitute any bibliographic datum named</span> <span class="cwebmacronumber">5.1.8.1</span>&gt;<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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Navigation"</span><span class="plain">)) {</span>
<span class="functiontext">Indexer::nav_column</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;nav_path</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;nav_web</span><span class="plain">,</span>
<span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;restrict_to_range</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;nav_pattern</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;nav_file</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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Breadcrumbs"</span><span class="plain">)) {</span>
<span class="functiontext">HTMLFormat::drop_initial_breadcrumbs</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;crumbs</span><span class="plain">, </span><span class="identifier">cp</span><span class="plain">-</span><span class="element">&gt;docs_mode</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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Chapter (%c+)"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">detail</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0];</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain"> = </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span>
<span class="functiontext">Indexer::heading_topmost_on_stack</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="constant">CHAPTER_LEVEL</span><span class="plain">), </span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">C</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Errors::at_position</span><span class="plain">(</span><span class="string">"no chapter is currently selected"</span><span class="plain">,</span>
<span class="identifier">template_filename</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Substitute a detail about the currently selected Chapter</span> <span class="cwebmacronumber">5.1.8.3</span>&gt;<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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Section (%c+)"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">detail</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0];</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">CONTENT_IN_ITEM</span><span class="plain">(</span>
<span class="functiontext">Indexer::heading_topmost_on_stack</span><span class="plain">(</span><span class="identifier">cp</span><span class="plain">, </span><span class="constant">SECTION_LEVEL</span><span class="plain">), </span><span class="reserved">section</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">NULL</span><span class="plain">)</span>
<span class="functiontext">Errors::at_position</span><span class="plain">(</span><span class="string">"no section is currently selected"</span><span class="plain">,</span>
<span class="identifier">template_filename</span><span class="plain">, </span><span class="identifier">lpos</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Substitute a detail about the currently selected Section</span> <span class="cwebmacronumber">5.1.8.4</span>&gt;<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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Complete (%c+)"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">detail</span><span class="plain"> = </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0];</span>
&lt;<span class="cwebmacro">Substitute a detail about the complete PDF</span> <span class="cwebmacronumber">5.1.8.2</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"&lt;b&gt;%S&lt;/b&gt;"</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">tl</span><span class="plain">, </span><span class="string">"%S%S%S"</span><span class="plain">, </span><span class="identifier">left_part</span><span class="plain">, </span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">right_part</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">left_part</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">varname</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">right_part</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_8_1"></a><b>&#167;5.1.8.1. </b>This is why, for instance, <code class="display"><span class="extract">[[Author]]</span></code> is replaced by the author's name:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Substitute any bibliographic datum named</span> <span class="cwebmacronumber">5.1.8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_8_2"></a><b>&#167;5.1.8.2. </b>We store little about the complete-web-in-one-file PDF:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Substitute a detail about the complete PDF</span> <span class="cwebmacronumber">5.1.8.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">swarm_leader</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Formats::substitute_post_processing_data</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">swarm_leader</span><span class="plain">, </span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">pattern</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%S for complete web"</span><span class="plain">, </span><span class="identifier">detail</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_8_3"></a><b>&#167;5.1.8.3. </b>And here for Chapters:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Substitute a detail about the currently selected Chapter</span> <span class="cwebmacronumber">5.1.8.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Title"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_title</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Code"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_range</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Purpose"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;rubric</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="functiontext">Formats::substitute_post_processing_data</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_weave</span><span class="plain">, </span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">pattern</span><span class="plain">)) {</span>
<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%S for %S"</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">-</span><span class="element">&gt;ch_title</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP5_1_8_4"></a><b>&#167;5.1.8.4. </b>And this, finally, is a very similar construction for Sections.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Substitute a detail about the currently selected Section</span> <span class="cwebmacronumber">5.1.8.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Title"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_title</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Purpose"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_purpose</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Code"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;range</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Lines"</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_extent</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Source"</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%f"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;source_file_for_section</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Page"</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">linkto</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">linkto</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;range</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">linkto</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="character">'/'</span><span class="plain">) || (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="character">' '</span><span class="plain">))</span>
<span class="functiontext">Str::put</span><span class="plain">(</span><span class="identifier">P</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">linkto</span><span class="plain">, </span><span class="string">".html"</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">linkto</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">linkto</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Paragraphs"</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_paragraphs</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="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Mean"</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">denom</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_paragraphs</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">denom</span><span class="plain"> == 0) </span><span class="identifier">denom</span><span class="plain"> = 1;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_extent</span><span class="plain">/</span><span class="identifier">denom</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="functiontext">Formats::substitute_post_processing_data</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_weave</span><span class="plain">, </span><span class="identifier">detail</span><span class="plain">, </span><span class="identifier">pattern</span><span class="plain">)) {</span>
<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">substituted</span><span class="plain">, </span><span class="string">"%S for %S"</span><span class="plain">, </span><span class="identifier">varname</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;sect_title</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_1_8">&#167;5.1.8</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Transcribing CSS. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::transcribe_CSS</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">CSS_file</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;style type=\</span><span class="plain">"</span><span class="string">text/css\</span><span class="plain">"</span><span class="string">&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">CSS_file</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="string">"can't open CSS file"</span><span class="plain">,</span>
<span class="constant">TRUE</span><span class="plain">, </span><span class="functiontext">Indexer::copy_CSS</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">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">&lt;/style&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Indexer::copy_CSS</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">, </span><span class="reserved">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">X</span><span class="plain">) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = (</span><span class="reserved">text_stream</span><span class="plain"> *) </span><span class="identifier">X</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Indexer::transcribe_CSS is used in <a href="#SP2">&#167;2</a>, <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="endnote">The function Indexer::copy_CSS appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="3-ts.html">Back to 'The Swarm'</a></li><li><a href="3-tw.html">Continue with 'The Weaver'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>