1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/7-hdn.html
2020-04-15 23:49:59 +01:00

758 lines
87 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Headings</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="../index.html">
<img src="../docs-src/Figures/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="index.html"><span class="selectedlink">core</span></a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Shared Modules</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Headings' generated by 7-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Inform7 Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#7">Chapter 7: Sentences</a></li><li><b>Headings</b></li></ul><p class="purpose">To keep track of the hierarchy of headings and subheadings found in the source text.</p>
<ul class="toc"><li><a href="7-hdn.html#SP1">&#167;1. World objects under each heading</a></li><li><a href="7-hdn.html#SP3">&#167;3. The noun search list</a></li><li><a href="7-hdn.html#SP9">&#167;9. Handling headings during the main traverses</a></li><li><a href="7-hdn.html#SP10">&#167;10. Describing the heading structure, 1: to the debugging log</a></li><li><a href="7-hdn.html#SP12">&#167;12. Describing the heading structure, 2: to the index</a></li><li><a href="7-hdn.html#SP13">&#167;13. Describing the heading structure, 3: to a freestanding XML file</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. World objects under each heading. </b>Every heading must carry with it a linked list of the nametags created in
sentences which belong to it. So when any noun is created, the following
is called to let the current sentence's heading know that it has a new
friend.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">nt</span><span class="plain">=</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">list_of_contents</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">=</span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">next_under_heading</span><span class="plain">)</span>
</pre>
<pre class="display">
<span class="identifier">name_resolution_data</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::name_resolution_data<button class="popup" onclick="togglePopup('usagePopup442')">...<span class="popuptext" id="usagePopup442">Usage of <b>Sentences::Headings::name_resolution_data</b>:<br><a href="7-hdn.html#SP2">&#167;2</a>, <a href="7-hdn.html#SP4">&#167;4</a>, <a href="7-hdn.html#SP7_1">&#167;7.1</a>, <a href="7-hdn.html#SP8">&#167;8</a></span></button></span><span class="plain">(</span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to fetch resolution data for null tag"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> &amp;(</span><span class="identifier">t</span><span class="plain">-&gt;</span><span class="identifier">name_resolution</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_tags_attached</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::attach_noun<button class="popup" onclick="togglePopup('usagePopup443')">...<span class="popuptext" id="usagePopup443">Usage of <b>Sentences::Headings::attach_noun</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">new_tag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">Headings::of_wording</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</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="reserved">return</span><span class="plain">;</span>
<span class="identifier">no_tags_attached</span><span class="plain">++;</span>
<span class="identifier">name_resolution_data</span><span class="plain"> *</span><span class="identifier">nrd</span><span class="plain"> = </span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">new_tag</span><span class="plain">);</span>
<span class="identifier">nrd</span><span class="plain">-&gt;</span><span class="identifier">next_to_search</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">h</span><span class="plain">-&gt;</span><span class="identifier">last_in_list_of_contents</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">list_of_contents</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">last_in_list_of_contents</span><span class="plain">)-&gt;</span><span class="identifier">next_under_heading</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
<span class="identifier">nrd</span><span class="plain">-&gt;</span><span class="identifier">next_under_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">last_in_list_of_contents</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The following verification checks that every noun is listed
in the list for exactly one heading. The point of the check is not so much
to make sure the tag lists are properly formed, as the code making those
is pretty elementary: it's really a test that the source text is well-formed
with everything placed under a heading, and no sentence having fallen
through a crack.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::verify_divisions<button class="popup" onclick="togglePopup('usagePopup444')">...<span class="popuptext" id="usagePopup444">Usage of <b>Sentences::Headings::verify_divisions</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">total</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">noun</span><span class="plain">)</span>
<span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">heading_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">heading</span><span class="plain">)</span>
<span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">)</span>
<span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">heading_count</span><span class="plain">++, </span><span class="identifier">total</span><span class="plain">++;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">noun</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">heading_count</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$z occurs under %d headings\n"</span><span class="plain">,</span>
<span class="identifier">nt</span><span class="plain">, </span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">heading_count</span><span class="plain">);</span>
<span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">total</span><span class="plain"> != </span><span class="identifier">no_tags_attached</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d tags != %d attached\n"</span><span class="plain">,</span>
<span class="identifier">total</span><span class="plain">, </span><span class="identifier">no_tags_attached</span><span class="plain">);</span>
<span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">disaster</span><span class="plain">) </span><span class="identifier">internal_error_tree_unsafe</span><span class="plain">(</span><span class="string">"heading contents list failed verification"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. The noun search list. </b>Identifying noun phrases is tricky. Many plausible phrases could refer in
principle to several different instances: "east", for instance, might
mean the direction or, say, "east garden". And what if the source
mentions many chairs, and now refers simply to "the chair"? This problem
is not so acute for nouns referring to abstractions, where we can simply
forbid duplicate definitions and require an exact wording when talking
about them. But for names of IF objects &mdash; which represent the solid and often
repetitive items and places of a simulated world &mdash; it cannot be ducked.
We can hardly tell an Inform author to create at most one item whose
name contains the word "jar", for instance.
</p>
<p class="inwebparagraph">All programming languages face similar problems. In C, for instance, a local
variable named <code class="display"><span class="extract">east</span></code> will be recognised in preference to a global one of the
same name (to some extent external linking provides a third level again).
The way this is done is usually explained in terms of the "scope" of a
definition, the part of the source for which it is valid: the winner, in
cases of ambiguity, being the definition of narrowest scope which is valid
at the position in question. In our terms, a stand-alone C program has a
heading tree like so, with two semantically meaningful heading levels,
File (0) and Routine (1), and then sublevels provided by braced blocks:
</p>
<pre class="display">
<span class="plain">File</span>
<span class="plain">main()</span>
<span class="plain">routine1()</span>
<span class="plain">interior block of a loop</span>
<span class="plain">...</span>
<span class="plain">routine2()</span>
<span class="plain">...</span>
</pre>
<p class="inwebparagraph">The resolution of a name at a given position P is unambiguous: find the
heading H to which P belongs; if the name is defined there, accept that;
if not move H upwards and try again; if it is not defined even at File (0)
level, issue an error: the term is undefined.
</p>
<p class="inwebparagraph">Inform is different in two respects, one trivial, the other not. The trivial
difference is that an Inform name can be defined midway through the matter
(though as a result of the PM_ revision, ANSI C now also allows variables
to be created mid-block, in fact: and some C compilers even implement this).
</p>
<p class="inwebparagraph">The big difference is that in Inform, names are always visible across
headings. They can be used before being defined; Section 2 of Part II is
free to mention the elephant defined in Section 7 of Part VIII, say.
English text is like this: a typical essay has one great big namespace.
</p>
<p class="inwebparagraph">We resolve this by searching backwards through recent noun creations in
the current heading, then in the current heading level above that, and so
on up to the top conceptual level of the source. Thus a "chair" in the
current chapter will always have priority over any in previous chapters,
and so on. However, kinds are always given priority over mere instances,
in order that "door" will retain its generic meaning even if, say,
"an oak door" is created.
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>This means that, under every heading, the search sequence is different.
So for the sake of efficiency we construct a linked list of world
objects in priority order the first time we search under a new heading,
then simply use that thereafter: we also keep track of the tail of this
list. Sections other than this one cannot read the list itself, and
use the following definition to iterate through it.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">nt</span><span class="plain"> = </span><span class="identifier">nt_search_start</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain"> = </span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">next_to_search</span><span class="plain">)</span>
</pre>
<pre class="display">
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The search sequence is, in effect, a cache storing a former computation,
and like all caches it can fall out of date if the circumstances change so
that the same computation would now produce a different outcome. That can
only happen here if a new noun is to be created: the assertion-maker
calls the following routine to let us know.
</p>
<pre class="display">
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment"> initially it's unbuilt</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::disturb<button class="popup" onclick="togglePopup('usagePopup445')">...<span class="popuptext" id="usagePopup445">Usage of <b>Sentences::Headings::disturb</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">noun_search_list_valid_for_this_heading</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="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Leaving aside the cache, then, we build a list as initially empty, then
all nametags of priority 1 as found by recursively searching headings, then all
nametags of priority 2, and so on.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::construct_noun_search_list<button class="popup" onclick="togglePopup('usagePopup446')">...<span class="popuptext" id="usagePopup446">Usage of <b>Sentences::Headings::construct_noun_search_list</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Work out the heading from which we wish to search</span> <span class="cwebmacronumber">6.1</span>&gt;<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="identifier">noun_search_list_valid_for_this_heading</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">; </span><span class="comment"> rely on the cache</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">HEADINGS</span><span class="plain">, </span><span class="string">"Rebuilding noun search list from: $H\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Start the search list empty</span> <span class="cwebmacronumber">6.2</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">MAX_NOUN_PRIORITY</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext"><a href="7-hdn.html#SP7">Sentences::Headings::build_search_list_from</a></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">i</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Verify that the search list indeed contains every noun just once</span> <span class="cwebmacronumber">6.3</span>&gt;<span class="plain">;</span>
<span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b>Basically, we calculate the search list from the point of view of the
current sentence:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out the heading from which we wish to search</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">current_sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">))))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"cannot establish position P: there is no current sentence"</span><span class="plain">);</span>
<span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">position_P</span><span class="plain"> = </span><span class="identifier">Wordings::location</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="identifier">h</span><span class="plain"> = </span><span class="identifier">Headings::heading_of</span><span class="plain">(</span><span class="identifier">position_P</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_2"></a><b>&#167;6.2. </b>The pseudo-heading has no list of contents because all objects are created in
source files, each certainly underneath a File (0) heading, so nothing should
ever get that far.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Start the search list empty</span> <span class="cwebmacronumber">6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">pseudo_heading</span><span class="plain">.</span><span class="identifier">list_of_contents</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment"> should always be true, but just in case</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_3"></a><b>&#167;6.3. </b>The potential for disaster if this algorithm should be incorrect is high,
so we perform a quick count to see if everything made it onto the list
and produce an internal error if not.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Verify that the search list indeed contains every noun just once</span> <span class="cwebmacronumber">6.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</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">c</span><span class="plain"> != </span><span class="identifier">no_tags_attached</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Reordering failed from $H\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d tags created, %d in ordering\n"</span><span class="plain">, </span><span class="identifier">no_tags_attached</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP11">Sentences::Headings::log_all_headings</a></span><span class="plain">();</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Making fresh tree:\n"</span><span class="plain">);</span>
<span class="identifier">Headings::make_tree</span><span class="plain">();</span>
<span class="functiontext"><a href="7-hdn.html#SP11">Sentences::Headings::log_all_headings</a></span><span class="plain">();</span>
<span class="identifier">internal_error_tree_unsafe</span><span class="plain">(</span><span class="string">"reordering of nametags failed"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>The following adds all nametags under heading H to the search list, using
its own list of contents, and then recurses to add all objects under
subheadings of H other than the one which has just recursed up to H. With
that done, we recurse up to the superheading of H.
</p>
<p class="inwebparagraph">To prove that <code class="display"><span class="extract">Sentences::Headings::build_search_list_from</span></code> is called exactly once for each
heading in the tree, forget about the up/down orientation and consider it
as a graph instead. At each node we try going to every possible other node,
except the way we came (at the start of the traverse, the "way we came"
being null): clearly this ensures that all of our neighbours have been
visited. Since every heading ultimately depends from the pseudo-heading,
the graph is connected, and therefore every heading must eventually be
visited. No heading can be visited twice, because that would mean that a
cycle of nodes \(H_1, H_2, ..., H_i, H_1\) must exist: since we have a tree
structure, there are no loops, and so \(H_i = H_2\), \(H_{i-1} = H_3\), and so
on &mdash; we must be walking a path and then retracing our steps in reverse.
That being so, there is a point where we turned back: we went from \(H_j\) to
\(H_{j+1}\) to \(H_j\) again. And this violates the principle that at each node
we move outwards in every direction except the way we came, a
contradiction.
</p>
<p class="inwebparagraph">The routine looks as if it may have a large recursion depth &mdash; maybe as
deep as the number of headings &mdash; but because we go downwards and then
upwards, the maximum recursion depth of the routine is less than \(2L+1\), where
\(L\) is the number of levels in the tree other than the pseudo-heading. This
provides an upper bound of about 21, regardless of the size of the source
text. The running time is linear in both the number of headings and the
number of nametags in the source text.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::build_search_list_from<button class="popup" onclick="togglePopup('usagePopup447')">...<span class="popuptext" id="usagePopup447">Usage of <b>Sentences::Headings::build_search_list_from</b>:<br><a href="7-hdn.html#SP6">&#167;6</a></span></button></span><span class="plain">(</span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">within</span><span class="plain">, </span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">way_we_came</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">subhead</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">within</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">within</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Nouns::priority</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">) == </span><span class="identifier">p</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Add tag to the end of the search list</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="comment"> recurse downwards through subordinate headings, other than the way we came up</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">subhead</span><span class="plain"> = </span><span class="identifier">within</span><span class="plain">-&gt;</span><span class="identifier">child_heading</span><span class="plain">; </span><span class="identifier">subhead</span><span class="plain">; </span><span class="identifier">subhead</span><span class="plain"> = </span><span class="identifier">subhead</span><span class="plain">-&gt;</span><span class="identifier">next_heading</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">subhead</span><span class="plain"> != </span><span class="identifier">way_we_came</span><span class="plain">)</span>
<span class="functiontext"><a href="7-hdn.html#SP7">Sentences::Headings::build_search_list_from</a></span><span class="plain">(</span><span class="identifier">subhead</span><span class="plain">, </span><span class="identifier">within</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="comment"> recurse upwards to superior headings, unless we came here through a downward recursion</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">within</span><span class="plain">-&gt;</span><span class="identifier">parent_heading</span><span class="plain"> != </span><span class="identifier">way_we_came</span><span class="plain">)</span>
<span class="functiontext"><a href="7-hdn.html#SP7">Sentences::Headings::build_search_list_from</a></span><span class="plain">(</span><span class="identifier">within</span><span class="plain">-&gt;</span><span class="identifier">parent_heading</span><span class="plain">, </span><span class="identifier">within</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="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add tag to the end of the search list</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nt_search_finish</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">nt</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"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt_search_finish</span><span class="plain">)-&gt;</span><span class="identifier">next_to_search</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"end of tag search list has frayed somehow"</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt_search_finish</span><span class="plain">)-&gt;</span><span class="identifier">next_to_search</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">next_to_search</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The search list is used for finding best matches in a particular order, the
order being used to break tie-breaks. Note that we return <code class="display"><span class="extract">NULL</span></code> if no noun
in the search list has a positive score.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::set_noun_search_score<button class="popup" onclick="togglePopup('usagePopup448')">...<span class="popuptext" id="usagePopup448">Usage of <b>Sentences::Headings::set_noun_search_score</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">) {</span>
<span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">search_score</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::highest_scoring_noun_searched<button class="popup" onclick="togglePopup('usagePopup449')">...<span class="popuptext" id="usagePopup449">Usage of <b>Sentences::Headings::highest_scoring_noun_searched</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, *</span><span class="identifier">best_nt</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">best_score</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">x</span><span class="plain"> = </span><span class="functiontext"><a href="7-hdn.html#SP1">Sentences::Headings::name_resolution_data</a></span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-&gt;</span><span class="identifier">search_score</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> &gt; </span><span class="identifier">best_score</span><span class="plain">) { </span><span class="identifier">best_nt</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">best_score</span><span class="plain"> = </span><span class="identifier">x</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">best_nt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Handling headings during the main traverses. </b>Here's what we do when we run into a heading, as we look through the
assertions in the source text: nothing, except to wipe out any meanings of
words like "it" left over from previous sentences. Headings are for
organisation, and are not directly functional in themselves.
</p>
<pre class="display">
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">HEADING_SH_handler</span><span class="plain"> =</span>
<span class="plain">{ </span><span class="identifier">HEADING_NT</span><span class="plain">, -1, </span><span class="constant">0</span><span class="plain">, </span><span class="functiontext"><a href="7-hdn.html#SP9">Sentences::Headings::handle_heading</a></span><span class="plain"> };</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::handle_heading<button class="popup" onclick="togglePopup('usagePopup450')">...<span class="popuptext" id="usagePopup450">Usage of <b>Sentences::Headings::handle_heading</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">) {</span>
<span class="functiontext"><a href="9-tfa.html#SP13">Assertions::Traverse::new_discussion</a></span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Describing the heading structure, 1: to the debugging log. </b>Finally, three ways to describe the run of headings: to the debugging log,
to the index of the project, and to a freestanding XML file.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log<button class="popup" onclick="togglePopup('usagePopup451')">...<span class="popuptext" id="usagePopup451">Usage of <b>Sentences::Headings::log</b>:<br>Core Module - <a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a></span></button></span><span class="plain">(</span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</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">LOG</span><span class="plain">(</span><span class="string">"&lt;null heading&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">==&amp;</span><span class="identifier">pseudo_heading</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;pseudo_heading&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"H%d "</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;%f, line %d&gt;"</span><span class="plain">,</span>
<span class="identifier">TextFromFiles::get_filename</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">),</span>
<span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;nowhere&gt;"</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">" level:%d indentation:%d"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">indentation</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>And here we log the whole heading tree by recursing through it, and
surreptitiously check that it is correctly formed at the same time.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log_all_headings<button class="popup" onclick="togglePopup('usagePopup452')">...<span class="popuptext" id="usagePopup452">Usage of <b>Sentences::Headings::log_all_headings</b>:<br><a href="7-hdn.html#SP6_3">&#167;6.3</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">heading</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$H\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP11">Sentences::Headings::log_headings_recursively</a></span><span class="plain">(&amp;</span><span class="identifier">pseudo_heading</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log_headings_recursively<button class="popup" onclick="togglePopup('usagePopup453')">...<span class="popuptext" id="usagePopup453">Usage of <b>Sentences::Headings::log_headings_recursively</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">==</span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">depth</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$H\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">depth</span><span class="plain">-1 != </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">indentation</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"*** indentation should be %d ***\n"</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">-1);</span>
<span class="functiontext"><a href="7-hdn.html#SP11">Sentences::Headings::log_headings_recursively</a></span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">child_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">+1);</span>
<span class="functiontext"><a href="7-hdn.html#SP11">Sentences::Headings::log_headings_recursively</a></span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">next_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Describing the heading structure, 2: to the index. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">headings_indexed</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::index<button class="popup" onclick="togglePopup('usagePopup454')">...<span class="popuptext" id="usagePopup454">Usage of <b>Sentences::Headings::index</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;"</span><span class="plain">); </span><span class="identifier">PL::Bibliographic::contents_heading</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">"&lt;/b&gt;"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"CONTENTS"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP12_1_1">Sentences::Headings::index_heading_recursively</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pseudo_heading</span><span class="plain">.</span><span class="identifier">child_heading</span><span class="plain">);</span>
<span class="identifier">contents_entry</span><span class="plain"> *</span><span class="identifier">ce</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">min_positive_level</span><span class="plain"> = </span><span class="constant">10</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="identifier">contents_entry</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> &lt; </span><span class="identifier">min_positive_level</span><span class="plain">))</span>
<span class="identifier">min_positive_level</span><span class="plain"> = </span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="identifier">contents_entry</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Index this entry in the contents</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="identifier">contents_entry</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(This would look more like a contents page if the source text "</span>
<span class="string">"were divided up into headings."</span><span class="plain">);</span>
<span class="identifier">Index::DocReferences::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"HEADINGS"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Index this entry in the contents</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">;</span>
<span class="comment"> indent to correct tab position</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"ul"</span><span class="plain">, </span><span class="string">"class=\"leaders\""</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ind_used</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">indentation</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">ind_used</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"li"</span><span class="plain">, </span><span class="string">"class=\"leaded indent%d\""</span><span class="plain">, </span><span class="identifier">ind_used</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="identifier">contents_entry</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Source text"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Preamble"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="comment"> write the text of the heading title</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">sentence_declaring</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
<span class="identifier">contents_entry</span><span class="plain"> *</span><span class="identifier">next_ce</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="identifier">contents_entry</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> != </span><span class="constant">0</span><span class="plain">)</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">next_ce</span><span class="plain">) &amp;&amp; (</span><span class="identifier">next_ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> &gt; </span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain">))</span>
<span class="identifier">next_ce</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">next_ce</span><span class="plain">, </span><span class="identifier">contents_entry</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">start_word</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">sentence_declaring</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end_word</span><span class="plain"> = (</span><span class="identifier">next_ce</span><span class="plain">)?(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">next_ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain">-&gt;</span><span class="identifier">sentence_declaring</span><span class="plain">)))</span>
<span class="plain">: (</span><span class="identifier">TextFromFiles::last_lexed_word</span><span class="plain">(</span><span class="identifier">FIRST_OBJECT</span><span class="plain">(</span><span class="identifier">source_file</span><span class="plain">)));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="constant">0</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">i</span><span class="plain"> = </span><span class="identifier">start_word</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="identifier">end_word</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">N</span><span class="plain"> += </span><span class="identifier">TextFromFiles::word_count</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> &gt; </span><span class="identifier">min_positive_level</span><span class="plain">) </span><span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d words"</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> &gt; </span><span class="identifier">min_positive_level</span><span class="plain">) </span><span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="comment"> place a link to the relevant line of the primary source text</span>
<span class="identifier">Index::link_location</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"li"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"ul"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">List all the objects and kinds created under the given heading, one tap stop deeper</span> <span class="cwebmacronumber">12.1.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_1_1"></a><b>&#167;12.1.1. </b>We index only headings of level 1 and up &mdash; so, not the pseudo-heading or the
File (0) ones &mdash; and which are not within any extensions &mdash; so, are in the
primary source text written by the user.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::index_heading_recursively<button class="popup" onclick="togglePopup('usagePopup455')">...<span class="popuptext" id="usagePopup455">Usage of <b>Sentences::Headings::index_heading_recursively</b>:<br><a href="7-hdn.html#SP12">&#167;12</a></span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</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="reserved">return</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">child_heading</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">next</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">next_heading</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">next</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Extensions::corresponding_to</span><span class="plain">(</span><span class="identifier">next</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)))</span>
<span class="identifier">next</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">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">headings_indexed</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">next</span><span class="plain">-&gt;</span><span class="identifier">sentence_declaring</span><span class="plain">)) !=</span>
<span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">sentence_declaring</span><span class="plain">)))))</span>
<span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Extensions::corresponding_to</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">))</span>
<span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">show_heading</span><span class="plain">) {</span>
<span class="identifier">contents_entry</span><span class="plain"> *</span><span class="identifier">ce</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="identifier">contents_entry</span><span class="plain">);</span>
<span class="identifier">ce</span><span class="plain">-&gt;</span><span class="identifier">heading_entered</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
<span class="identifier">headings_indexed</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="functiontext"><a href="7-hdn.html#SP12_1_1">Sentences::Headings::index_heading_recursively</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">child_heading</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP12_1_1">Sentences::Headings::index_heading_recursively</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">next_heading</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12_1_2"></a><b>&#167;12.1.2. </b>We skip any objects or kinds without names (i.e., whose <code class="display"><span class="extract">creator</span></code> is null).
The rest appear in italic type, and without links to source text since this
in practice strews distractingly many orange berries across the page.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">List all the objects and kinds created under the given heading, one tap stop deeper</span> <span class="cwebmacronumber">12.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</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="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Nouns::get_name</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</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">c</span><span class="plain">++ == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">ind_used</span><span class="plain">+1, </span><span class="string">"hanging"</span><span class="plain">);</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;%+W&lt;/i&gt;"</span><span class="plain">, </span><span class="identifier">W</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">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) { </span><span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">); </span><span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); }</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP12_1">&#167;12.1</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Describing the heading structure, 3: to a freestanding XML file. </b>This is provided as a convenience to the application using Inform, which may want
to have a pull-down menu or similar gadget allowing the user to jump to a given
heading. This tells the interface where every heading is, thus saving it from
having to parse the source.
</p>
<p class="inwebparagraph">The property list contains a single dictionary, whose keys are the numbers
0, 1, 2, ..., \(n-1\), where there are \(n\) headings in all. (The pseudo-heading
is not included.) A special key, the only non-numerical one, called "Application
Version", contains the Inform build number in its usual form: "4Q34", for instance.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::write_as_xml<button class="popup" onclick="togglePopup('usagePopup456')">...<span class="popuptext" id="usagePopup456">Usage of <b>Sentences::Headings::write_as_xml</b>:<br>How To Compile - <a href="1-htc.html#SP2_3">&#167;2.3</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> </span><span class="identifier">xf_struct</span><span class="plain">; </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">xf</span><span class="plain"> = &amp;</span><span class="identifier">xf_struct</span><span class="plain">;</span>
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext"><a href="1-wtc.html#SP13">Task::xml_headings_file</a></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">xf</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">UTF8_ENC</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">Problems::Fatal::filename_related</span><span class="plain">(</span><span class="string">"Can't open headings file"</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="functiontext"><a href="7-hdn.html#SP13">Sentences::Headings::write_headings_as_xml_inner</a></span><span class="plain">(</span><span class="identifier">xf</span><span class="plain">);</span>
<span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">xf</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::write_headings_as_xml_inner<button class="popup" onclick="togglePopup('usagePopup457')">...<span class="popuptext" id="usagePopup457">Usage of <b>Sentences::Headings::write_headings_as_xml_inner</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Write DTD indication for XML headings file</span> <span class="cwebmacronumber">13.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;plist version=\"1.0\"&gt;&lt;dict&gt;\n"</span><span class="plain">);</span>
<span class="identifier">INDENT</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Application Version&lt;/key&gt;&lt;string&gt;%B (build %B)&lt;/string&gt;\n"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">heading</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;%d&lt;/key&gt;&lt;dict&gt;\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">INDENT</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Write the dictionary of properties for a single heading</span> <span class="cwebmacronumber">13.2</span>&gt;<span class="plain">;</span>
<span class="identifier">OUTDENT</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;/dict&gt;\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">OUTDENT</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;/dict&gt;&lt;/plist&gt;\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13_1"></a><b>&#167;13.1. </b>We use a convenient Apple DTD:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write DTD indication for XML headings file</span> <span class="cwebmacronumber">13.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n"</span>
<span class="string">"&lt;!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "</span>
<span class="string">"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"&gt;\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP13">&#167;13</a>.</p>
<p class="inwebparagraph"><a id="SP13_2"></a><b>&#167;13.2. </b>Note that a level of 0, and a title of <code class="display"><span class="extract">--</span></code>, signifies a File (0) level
heading: external tools can probably ignore such records. Similarly, it is
unlikely that they will ever see a record without a "Filename" key &mdash;
this would mean a heading arising from text created internally within Inform,
which will only happen if someone has done something funny with <code class="display"><span class="extract">.i6t</span></code> files &mdash;
but should this arise then the best recourse is to ignore the heading.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write the dictionary of properties for a single heading</span> <span class="cwebmacronumber">13.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Filename&lt;/key&gt;&lt;string&gt;%f&lt;/string&gt;\n"</span><span class="plain">,</span>
<span class="identifier">TextFromFiles::get_filename</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">));</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Line&lt;/key&gt;&lt;integer&gt;%d&lt;/integer&gt;\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">start_location</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">heading_text</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Title&lt;/key&gt;&lt;string&gt;%+W&lt;/string&gt;\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">heading_text</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Title&lt;/key&gt;&lt;string&gt;--&lt;/string&gt;\n"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Level&lt;/key&gt;&lt;integer&gt;%d&lt;/integer&gt;\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;key&gt;Indentation&lt;/key&gt;&lt;integer&gt;%d&lt;/integer&gt;\n"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">indentation</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="7-hdn.html#SP13">&#167;13</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="7-ptu.html">Back to 'Parse Tree Usage'</a></li><li><a href="7-ns.html">Continue with 'Nonstructural Sentences'</a></li></ul><hr class="tocbar">
<!--End of weave-->
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
</main>
</body>
</html>