inweb-bootstrap/docs/inweb/2-tr.html
2020-04-04 20:46:43 +01:00

672 lines
84 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>1/ptt</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 '2/tr' 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#2">Chapter 2: Parsing a Web</a></li><li><b>The Reader</b></li></ul><p class="purpose">To read the Contents section of the web, and through that each of the other sections in turn, and to collate all of this material.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Web semantics</a></li><li><a href="#SP5">&#167;5. Web reading</a></li><li><a href="#SP7">&#167;7. Woven and Tangled folders</a></li><li><a href="#SP8">&#167;8. Looking up chapters and sections</a></li><li><a href="#SP10">&#167;10. Ranges and containment</a></li><li><a href="#SP11">&#167;11. Tangle targets</a></li><li><a href="#SP14">&#167;14. Additional header files</a></li><li><a href="#SP15">&#167;15. Extent</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Web semantics. </b>There's normally only one web read in during a single run of Inweb, but
this might change if we ever add batch-processing in future. A web is a set
of chapters each of which is a set of sections; webs which don't obviously
divide into chapters will be called "unchaptered", though in fact they do
have a single chapter, called simply "Sections" (and with range "S").
</p>
<p class="inwebparagraph">The program expressed by a web is output, or "tangled", to a number of
stand-alone files called "tangle targets". By default there is just one
of these.
</p>
<p class="inwebparagraph">We use the <code class="display"><span class="extract">WebMetadata::get</span></code> function of <code class="display"><span class="extract">foundation</span></code> to read the structure
of the web in from the file system. This produces a <code class="display"><span class="extract">web_md</span></code> metadata
structure for the web itself, which contains a list of <code class="display"><span class="extract">chapter_md</span></code>
structures for the chapters, each in turn containing a list of <code class="display"><span class="extract">section_md</span></code>s.
We will imitate that structure exactly, but because we want to attach a lot
of semantics at each level, we will make a <code class="display"><span class="extract">web</span></code> with a list of <code class="display"><span class="extract">chapter</span></code>s
each of which has a list of <code class="display"><span class="extract">section</span></code>s.
</p>
<p class="inwebparagraph">Here are the semantics for a web:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">web</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">web_md</span><span class="plain"> *</span><span class="identifier">md</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">chapters</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">chapter</span></code> (including Sections, Preliminaries, etc.)</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_lines</span><span class="plain">; </span><span class="comment">total lines in literate source, excluding contents</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_paragraphs</span><span class="plain">; </span><span class="comment">this will be at least 1</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">main_language</span><span class="plain">; </span><span class="comment">in which most of the sections are written</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">tangle_targets</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">tangle_target</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">headers</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">filename</span></code>: additional header files</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">analysed</span><span class="plain">; </span><span class="comment">has this been scanned for function usage and such?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">c_structures</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">c_structure</span></code>: used only for C-like languages</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ebook</span><span class="plain"> *</span><span class="identifier">as_ebook</span><span class="plain">; </span><span class="comment">when being woven to an ebook</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">pathname</span><span class="plain"> *</span><span class="identifier">redirect_weaves_to</span><span class="plain">; </span><span class="comment">ditto</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">web</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure web is accessed in 1/pc, 1/ptt, 2/tp, 2/pn, 3/ta, 3/ts, 3/ti, 3/tw, 3/tt, 4/cl, 4/is, 5/ptf, 5/tf, 5/hf, 6/mkf, 6/rw and here.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>And for a chapter:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">chapter</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">chapter_md</span><span class="plain"> *</span><span class="identifier">md</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">owning_web</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">sections</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">section</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">weave_target</span><span class="plain"> *</span><span class="identifier">ch_weave</span><span class="plain">; </span><span class="comment"><code class="display"><span class="extract">NULL</span></code> unless this chapter produces a weave of its own</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">titling_line_inserted</span><span class="plain">; </span><span class="comment">has an interleaved chapter heading been added yet?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">ch_language</span><span class="plain">; </span><span class="comment">in which this chapter is written</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">chapter</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure chapter is accessed in 1/pc, 1/ptt, 2/tp, 2/pn, 3/ta, 3/ts, 3/ti, 3/tw, 3/tt, 4/cl, 4/is, 5/ptf, 5/tf, 5/hf, 6/mkf, 6/rw and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>And lastly for a section.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">section</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">section_md</span><span class="plain"> *</span><span class="identifier">md</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">owning_web</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">owning_chapter</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">sect_namespace</span><span class="plain">; </span><span class="comment">e.g., "Text::Languages::"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">sect_purpose</span><span class="plain">; </span><span class="comment">e.g., "To manage the zoo, and feed all penguins"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">sect_range</span><span class="plain">; </span><span class="comment">e.g., "9/tfto"</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">barred</span><span class="plain">; </span><span class="comment">if version 1 syntax, contains a dividing bar?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">sect_language</span><span class="plain">; </span><span class="comment">in which this section is written</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">tangle_target</span><span class="plain"> *</span><span class="identifier">sect_target</span><span class="plain">; </span><span class="comment"><code class="display"><span class="extract">NULL</span></code> unless this section produces a tangle of its own</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">weave_target</span><span class="plain"> *</span><span class="identifier">sect_weave</span><span class="plain">; </span><span class="comment"><code class="display"><span class="extract">NULL</span></code> unless this section produces a weave of its own</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sect_extent</span><span class="plain">; </span><span class="comment">total number of lines in this section</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">first_line</span><span class="plain">; </span><span class="comment">for efficiency's sake not held as a <code class="display"><span class="extract">linked_list</span></code>,</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">last_line</span><span class="plain">; </span><span class="comment">but that's what it is, all the same</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sect_paragraphs</span><span class="plain">; </span><span class="comment">total number of paragraphs in this section</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">paragraphs</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">paragraph</span></code>: the content of this section</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">theme_tag</span><span class="plain"> *</span><span class="identifier">tag_with</span><span class="plain">; </span><span class="comment">automatically tag paras in this section thus</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">macros</span><span class="plain">; </span><span class="comment">of <code class="display"><span class="extract">para_macro</span></code>: those defined in this section</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">scratch_flag</span><span class="plain">; </span><span class="comment">temporary workspace</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">paused_until_at</span><span class="plain">; </span><span class="comment">ignore the top half of the file, until the first <code class="display"><span class="extract">@</span></code> sign</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">printed_number</span><span class="plain">; </span><span class="comment">temporary again: sometimes used in weaving</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">section</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure section is accessed in 1/pc, 1/ptt, 2/tp, 2/pm, 2/tgs, 2/pn, 3/ta, 3/ts, 3/ti, 3/tw, 3/tt, 4/lm, 4/cl, 4/is, 5/ptf, 5/tf, 5/hf, 6/mkf, 6/rw and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The following routine makes the <code class="display"><span class="extract">web</span></code>-<code class="display"><span class="extract">chapter</span></code>-<code class="display"><span class="extract">section</span></code> tree out of a
<code class="display"><span class="extract">web_md</span></code>-<code class="display"><span class="extract">chapter_md</span></code>-<code class="display"><span class="extract">section_md</span></code> tree:
</p>
<pre class="display">
<span class="reserved">web_md</span><span class="plain"> *</span><span class="functiontext">Reader::load_web_md</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">alt_F</span><span class="plain">, </span><span class="reserved">module_search</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">verbosely</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">including_modules</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">WebMetadata::get</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">alt_F</span><span class="plain">, </span><span class="identifier">default_inweb_syntax</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">verbosely</span><span class="plain">,</span>
<span class="identifier">including_modules</span><span class="plain">, </span><span class="identifier">path_to_inweb</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">web</span><span class="plain"> *</span><span class="functiontext">Reader::load_web</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">alt_F</span><span class="plain">, </span><span class="reserved">module_search</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">verbosely</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">including_modules</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="identifier">CREATE</span><span class="plain">(</span><span class="reserved">web</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain"> = </span><span class="functiontext">Reader::load_web_md</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">alt_F</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">verbosely</span><span class="plain">, </span><span class="identifier">including_modules</span><span class="plain">);</span>
<span class="reserved">tangle_target</span><span class="plain"> *</span><span class="identifier">main_target</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Write the Inweb Version bibliographic datum</span> <span class="cwebmacronumber">4.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Initialise the rest of the web structure</span> <span class="cwebmacronumber">4.2</span>&gt;<span class="plain">;</span>
<span class="reserved">chapter_md</span><span class="plain"> *</span><span class="identifier">Cm</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">Cm</span><span class="plain">, </span><span class="reserved">chapter_md</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">chapters_md</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">CREATE</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain"> = </span><span class="identifier">Cm</span><span class="plain">;</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">owning_web</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Initialise the rest of the chapter structure</span> <span class="cwebmacronumber">4.3</span>&gt;<span class="plain">;</span>
<span class="identifier">ADD_TO_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">-&gt;</span><span class="element">chapters</span><span class="plain">);</span>
<span class="reserved">section_md</span><span class="plain"> *</span><span class="identifier">Sm</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">Sm</span><span class="plain">, </span><span class="reserved">section_md</span><span class="plain">, </span><span class="identifier">Cm</span><span class="plain">-&gt;</span><span class="element">sections_md</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">CREATE</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">);</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain"> = </span><span class="identifier">Sm</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_chapter</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_web</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Initialise the rest of the section structure</span> <span class="cwebmacronumber">4.4</span>&gt;<span class="plain">;</span>
<span class="identifier">ADD_TO_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">-&gt;</span><span class="element">sections</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Add the imported headers</span> <span class="cwebmacronumber">4.5</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::load_web_md is used in 6/mkf (<a href="6-mkf.html#SP2_11_1">&#167;2.11.1</a>).</p>
<p class="endnote">The function Reader::load_web is used in 1/pc (<a href="1-pc.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP4_1"></a><b>&#167;4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Write the Inweb Version bibliographic datum</span> <span class="cwebmacronumber">4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">IB</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">IB</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="constant">INWEB_BUILD</span><span class="plain">);</span>
<span class="reserved">web_bibliographic_datum</span><span class="plain"> *</span><span class="identifier">bd</span><span class="plain"> = </span><span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Inweb Version"</span><span class="plain">, </span><span class="identifier">IB</span><span class="plain">);</span>
<span class="identifier">bd</span><span class="plain">-&gt;</span><span class="element">declaration_permitted</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">IB</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP4_2"></a><b>&#167;4.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the rest of the web structure</span> <span class="cwebmacronumber">4.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">chapters</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">headers</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">filename</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">c_structure</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">tangle_targets</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">tangle_target</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">analysed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">as_ebook</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">redirect_weaves_to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain"> = </span><span class="functiontext">Languages::default</span><span class="plain">();</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_lines</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_paragraphs</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">language_name</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Language"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">language_name</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain"> = </span><span class="functiontext">Languages::find_by_name</span><span class="plain">(</span><span class="identifier">language_name</span><span class="plain">);</span>
<span class="identifier">main_target</span><span class="plain"> = </span><span class="functiontext">Reader::add_tangle_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP4_3"></a><b>&#167;4.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the rest of the chapter structure</span> <span class="cwebmacronumber">4.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">ch_weave</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">titling_line_inserted</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">sections</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">section</span><span class="plain">);</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">ch_language</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">Cm</span><span class="plain">-&gt;</span><span class="element">ch_language_name</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">ch_language</span><span class="plain"> = </span><span class="functiontext">Languages::find_by_name</span><span class="plain">(</span><span class="identifier">Cm</span><span class="plain">-&gt;</span><span class="element">ch_language_name</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP4_4"></a><b>&#167;4.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the rest of the section structure</span> <span class="cwebmacronumber">4.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_extent</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">first_line</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">last_line</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_paragraphs</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">paragraphs</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">paragraph</span><span class="plain">);</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">macros</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">para_macro</span><span class="plain">);</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">scratch_flag</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">barred</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">printed_number</span><span class="plain"> = -1;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_weave</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_namespace</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_web</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_language</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="element">ch_language</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_language_name</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_language</span><span class="plain"> = </span><span class="functiontext">Languages::find_by_name</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_language_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_independent_language</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain"> =</span>
<span class="functiontext">Languages::find_by_name</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_independent_language</span><span class="plain">);</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_language</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_target</span><span class="plain"> = </span><span class="functiontext">Reader::add_tangle_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_target</span><span class="plain"> = </span><span class="identifier">main_target</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">tag_with</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="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">Sm</span><span class="plain">-&gt;</span><span class="element">tag_name</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">tag_with</span><span class="plain"> = </span><span class="functiontext">Tags::add_by_name</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">Sm</span><span class="plain">-&gt;</span><span class="element">tag_name</span><span class="plain">);</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_range</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP4_5"></a><b>&#167;4.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add the imported headers</span> <span class="cwebmacronumber">4.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">HF</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">HF</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">header_filenames</span><span class="plain">)</span>
<span class="functiontext">Reader::add_imported_header</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">HF</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Web reading. </b>All of that ran very quickly, but now things will slow down. The next
function is where the actual contents of a web are read &mdash; which means opening
each section and reading it line by line. We read the complete literate source
of the web into memory, which is profligate, but saves time. Most of the lines
come straight from the source files, but a few chapter heading lines are
inserted if this is a multi-chapter web.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Reader::read_web</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">int</span><span class="plain"> </span><span class="identifier">verbosely</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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">sections</span><span class="plain">)</span>
<span class="functiontext">Reader::read_file</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">,</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">source_file_for_section</span><span class="plain">,</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">titling_line_to_insert</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">verbosely</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">single_file</span><span class="plain">)?</span><span class="identifier">TRUE:FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::read_web is used in 1/pc (<a href="1-pc.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Each file, then:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Reader::read_file</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">chapter</span><span class="plain"> *</span><span class="identifier">C</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="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">titling_line</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="reserved">int</span><span class="plain"> </span><span class="identifier">verbosely</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">disregard_top</span><span class="plain">) {</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_chapter</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">disregard_top</span><span class="plain">)</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">paused_until_at</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">paused_until_at</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">titling_line</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_chapter</span><span class="plain">-&gt;</span><span class="element">titling_line_inserted</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Insert an implied chapter heading</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">disregard_top</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Insert an implied section heading, for a single-file web</span> <span class="cwebmacronumber">6.2</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cl</span><span class="plain"> = </span><span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="string">"can't open section file"</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">,</span>
<span class="functiontext">Reader::scan_source_line</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">S</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">verbosely</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"Read section: '%S' (%d lines)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">sect_title</span><span class="plain">, </span><span class="identifier">cl</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::read_file is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insert an implied chapter heading</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">owning_chapter</span><span class="plain">-&gt;</span><span class="element">titling_line_inserted</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">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="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"Chapter Heading"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Accept this as a line belonging to this section and chapter</span> <span class="cwebmacronumber">6.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_2"></a><b>&#167;6.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insert an implied section heading, for a single-file web</span> <span class="cwebmacronumber">6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</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="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"Main."</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Accept this as a line belonging to this section and chapter</span> <span class="cwebmacronumber">6.1.2</span>&gt;<span class="plain">;</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Accept this as a line belonging to this section and chapter</span> <span class="cwebmacronumber">6.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_1_1"></a><b>&#167;6.1.1. </b>Non-implied source lines come from here. Note that we assume here that
trailing whitespace on a line is not significant in the language being
tangled for.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Reader::scan_source_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">state</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="reserved">section</span><span class="plain"> *) </span><span class="identifier">state</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">l</span><span class="plain">&gt;=0) &amp;&amp; (</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="identifier">l</span><span class="plain">)))) </span><span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="identifier">l</span><span class="plain">--);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">paused_until_at</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="constant">0</span><span class="plain">) == </span><span class="character">'@'</span><span class="plain">) </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">paused_until_at</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Accept this as a line belonging to this section and chapter</span> <span class="cwebmacronumber">6.1.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::scan_source_line is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_1_2"></a><b>&#167;6.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Accept this as a line belonging to this section and chapter</span> <span class="cwebmacronumber">6.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">sl</span><span class="plain"> = </span><span class="functiontext">Lines::new_source_line</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">);</span>
<span class="comment">enter this in its section's linked list of lines:</span>
<span class="identifier">sl</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">first_line</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">first_line</span><span class="plain"> = </span><span class="identifier">sl</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">last_line</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain"> = </span><span class="identifier">sl</span><span class="plain">;</span>
<span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">last_line</span><span class="plain"> = </span><span class="identifier">sl</span><span class="plain">;</span>
<span class="comment">we haven't detected paragraph boundaries yet, so:</span>
<span class="identifier">sl</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="comment">and keep count:</span>
<span class="identifier">sl</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">-&gt;</span><span class="element">sect_extent</span><span class="plain">++;</span>
<span class="identifier">sl</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">-&gt;</span><span class="element">owning_chapter</span><span class="plain">-&gt;</span><span class="element">owning_web</span><span class="plain">-&gt;</span><span class="element">no_lines</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6_1">&#167;6.1</a>, <a href="#SP6_2">&#167;6.2</a> (twice), <a href="#SP6_1_1">&#167;6.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Woven and Tangled folders. </b>We abstract these in order to be able to respond well to their not existing:
</p>
<pre class="display">
<span class="reserved">pathname</span><span class="plain"> *</span><span class="functiontext">Reader::woven_folder</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">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">path_to_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Woven"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Pathnames::create_in_file_system</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext">Errors::fatal_with_path</span><span class="plain">(</span><span class="string">"unable to create Woven subdirectory"</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">pathname</span><span class="plain"> *</span><span class="functiontext">Reader::tangled_folder</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">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">path_to_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Tangled"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Pathnames::create_in_file_system</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext">Errors::fatal_with_path</span><span class="plain">(</span><span class="string">"unable to create Tangled subdirectory"</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::woven_folder is used in 1/ptt (<a href="1-ptt.html#SP7">&#167;7</a>), 3/ts (<a href="3-ts.html#SP2_2">&#167;2.2</a>), 3/ti (<a href="3-ti.html#SP5_4">&#167;5.4</a>), 5/hf (<a href="5-hf.html#SP27">&#167;27</a>).</p>
<p class="endnote">The function Reader::tangled_folder is used in 1/pc (<a href="1-pc.html#SP7_2_2">&#167;7.2.2</a>), 3/tt (<a href="3-tt.html#SP1_2">&#167;1.2</a>), 4/is (<a href="4-is.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Looking up chapters and sections. </b>Given a range, which chapter or section does it correspond to? There is no
need for this to be at all quick: there are fewer than 1000 sections even
in large webs, and lookup is performed only a few times.
</p>
<p class="inwebparagraph">Note that range comparison is case sensitive.
</p>
<pre class="display">
<span class="reserved">chapter</span><span class="plain"> *</span><span class="functiontext">Reader::get_chapter_for_range</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">chapter</span><span class="plain"> *</span><span class="identifier">C</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="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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">ch_range</span><span class="plain">, </span><span class="identifier">range</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">C</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>
<span class="reserved">section</span><span class="plain"> *</span><span class="functiontext">Reader::get_section_for_range</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">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="reserved">if</span><span class="plain"> (</span><span class="identifier">W</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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">sect_range</span><span class="plain">, </span><span class="identifier">range</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</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 Reader::get_chapter_for_range is used in 3/ta (<a href="3-ta.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function Reader::get_section_for_range is used in 1/pc (<a href="1-pc.html#SP7_2_2">&#167;7.2.2</a>, <a href="1-pc.html#SP7_2_2_2">&#167;7.2.2.2</a>), 3/ta (<a href="3-ta.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>This clumsy routine is never used in syntax version 2 or later.
</p>
<pre class="display">
<span class="reserved">section</span><span class="plain"> *</span><span class="functiontext">Reader::section_by_filename</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="reserved">filename</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="reserved">if</span><span class="plain"> (</span><span class="identifier">W</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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">sections</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">SFN</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">SFN</span><span class="plain">, </span><span class="string">"%f"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="element">source_file_for_section</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">SFN</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">SFN</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S</span><span class="plain">;</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 Reader::section_by_filename appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Ranges and containment. </b>This provides a sort of partial ordering on ranges, testing if the portion
of the web represented by <code class="display"><span class="extract">range1</span></code> is contained inside the portion represented
by <code class="display"><span class="extract">range2</span></code>. Note that <code class="display"><span class="extract">"0"</span></code> means the entire web, and is what the word <code class="display"><span class="extract">all</span></code>
translates to when it's used on the command line.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Reader::range_within</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">range1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">range2</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">range2</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"0"</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</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">range1</span><span class="plain">, </span><span class="identifier">range2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</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">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">range2</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%c+/%c+"</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">return</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="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">range1</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)/%c+"</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">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0], </span><span class="identifier">range2</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">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::range_within is used in 1/pc (<a href="1-pc.html#SP7_2_3_2">&#167;7.2.3.2</a>), 3/ts (<a href="3-ts.html#SP1">&#167;1</a>), 3/tw (<a href="3-tw.html#SP1_3">&#167;1.3</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Tangle targets. </b>In Knuth's original conception of literate programming, a web produces
just one piece of tangled output &mdash; the program for compilation. But this
assumes that the underlying program is so simple that it won't require
ancillary files, configuration data, and such; and this is often just as
complex and worth explaining as the program itself. So Inweb allows a
web to contain multiple tangle targets, each of which contains a union of
sections. Each section belongs to exactly one tangle target; by default
a web contains just one target, which contains all of the sections.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">tangle_target</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">tangle_language</span><span class="plain">; </span><span class="comment">common to the entire contents</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">hash_table</span><span class="plain"> </span><span class="identifier">symbols</span><span class="plain">; </span><span class="comment">a table of identifiable names in this program</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">tangle_target</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure tangle_target is accessed in 3/ta, 3/tt and here.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b></p>
<pre class="display">
<span class="reserved">tangle_target</span><span class="plain"> *</span><span class="functiontext">Reader::add_tangle_target</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">programming_language</span><span class="plain"> *</span><span class="identifier">language</span><span class="plain">) {</span>
<span class="reserved">tangle_target</span><span class="plain"> *</span><span class="identifier">tt</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">tangle_target</span><span class="plain">);</span>
<span class="identifier">tt</span><span class="plain">-&gt;</span><span class="element">tangle_language</span><span class="plain"> = </span><span class="identifier">language</span><span class="plain">;</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">tt</span><span class="plain">, </span><span class="reserved">tangle_target</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">tangle_targets</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::add_tangle_target is used in <a href="#SP4_2">&#167;4.2</a>, <a href="#SP4_4">&#167;4.4</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>And the following provides a way to iterate through the lines in a tangle,
while keeping the variables <code class="display"><span class="extract">C</span></code>, <code class="display"><span class="extract">S</span></code> and <code class="display"><span class="extract">L</span></code> pointing to the current chapter,
section and line.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">T</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">-&gt;</span><span class="element">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">-&gt;</span><span class="element">sections</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_target</span><span class="plain"> == </span><span class="identifier">T</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">first_line</span><span class="plain">; </span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Additional header files. </b>Some C programs, in particular, may need additional header files added to
any tangle in order for them to compile. (The Inform project uses this to
get around the lack of some POSIX facilities on Windows.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Reader::add_imported_header</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">filename</span><span class="plain"> *</span><span class="identifier">HF</span><span class="plain">) {</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">HF</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">headers</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::add_imported_header is used in <a href="#SP4_5">&#167;4.5</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Extent. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Reader::web_has_one_section</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">if</span><span class="plain"> (</span><span class="functiontext">WebMetadata::section_count</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::web_has_one_section is used in 3/ts (<a href="3-ts.html#SP2_2">&#167;2.2</a>), 3/tw (<a href="3-tw.html#SP1">&#167;1</a>, <a href="3-tw.html#SP1_3_3_1_10_4">&#167;1.3.3.1.10.4</a>).</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>This really serves no purpose, but seems to boost morale.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Reader::print_web_statistics</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="identifier">PRINT</span><span class="plain">(</span><span class="string">"web \</span><span class="plain">"</span><span class="string">%S\</span><span class="plain">"</span><span class="string">: "</span><span class="plain">, </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Title"</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">WebMetadata::chapter_count</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">s</span><span class="plain"> = </span><span class="functiontext">WebMetadata::section_count</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">-&gt;</span><span class="identifier">chaptered</span><span class="plain">) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"%d chapter%s : "</span><span class="plain">,</span>
<span class="identifier">c</span><span class="plain">, (</span><span class="identifier">c</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"%d section%s : %d paragraph%s : %d line%s\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">s</span><span class="plain">, (</span><span class="identifier">s</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">,</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_paragraphs</span><span class="plain">, (</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_paragraphs</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">,</span>
<span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_lines</span><span class="plain">, (</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">no_lines</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Reader::print_web_statistics is used in 1/pc (<a href="1-pc.html#SP7_2">&#167;7.2</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 2: Parsing a Web.)</i></li><li><a href="2-lc.html">Continue with 'Line Categories'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>