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/8-ei.html
2019-10-02 23:04:15 +01:00

599 lines
90 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>8/ie</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '8/ei' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#8">Chapter 8: Extensions</a></li><li><b>Extension Identifiers</b></li></ul><p class="purpose">To store, hash code and compare title/author pairs used to identify extensions which, though installed, are not necessarily used in the present source text.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP10">&#167;10. The database of known EIDs</a></li><li><a href="#SP14">&#167;14. How casing is normalised</a></li><li><a href="#SP15">&#167;15. Documentation links</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Extensions are identified by the pair of title and author name, each of
which is an ISO Latin-1 string limited in length, with certain bad-news
characters excluded (such as <code class="display"><span class="extract">/</span></code> and <code class="display"><span class="extract">:</span></code>) so that they can be used
directly in filenames. However, we will not want to compare these by
string comparison: so we hash-code the combination for speed. The
following structure holds a combination of the textual names and the
hash code:
</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">extension_identifier</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">author_name</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">raw_author_name</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">title</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">raw_title</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">extension_id_hash_code</span><span class="plain">; </span> <span class="comment">hash code derived from the above</span>
<span class="plain">} </span><span class="reserved">extension_identifier</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure extension_identifier is accessed in 8/ef, 8/ec, 8/ed, 8/ed2, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Each EID is given a hash code &mdash; an integer between 0 and the following
constant minus 1, derived from its title and author name.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">EI_HASH_CODING_BASE</span><span class="plain"> 499</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>EIDs are created with one of the following contexts:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NO_EIDB_CONTEXTS</span><span class="plain"> 5</span>
<span class="definitionkeyword">define</span> <span class="constant">LOADED_EIDBC</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">INSTALLED_EIDBC</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">HYPOTHETICAL_EIDBC</span><span class="plain"> 3</span>
<span class="definitionkeyword">define</span> <span class="constant">USEWITH_EIDBC</span><span class="plain"> 4</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_identifier_database_entry</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eide_id</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">hash_next</span><span class="plain">; </span> <span class="comment">next one in hashed EID database</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">incidence_count</span><span class="plain">[</span><span class="constant">NO_EIDB_CONTEXTS</span><span class="plain">];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">last_usage_date</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sort_usage_date</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">word_count_text</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">word_count_number</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">extension_identifier_database_entry</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure extension_identifier_database_entry is private to this section.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">EXTENSIONS_PRESENT</span>
</pre>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Each EID structure is written only once, and its title and author name are
not subsequently altered. We therefore hash-code on arrival. As when
hashing vocabulary, we apply the X 30011 algorithm, this time with 499
(coprime to 30011) as base, to the text of the Unix-style pathname
<code class="display"><span class="extract">Author/Title</span></code>.
</p>
<p class="inwebparagraph">It is important that no EID structure ever be modified or destroyed once
created, so it must not be stored inside a transient data structure like a
<code class="display"><span class="extract">specification</span></code>.
</p>
<p class="inwebparagraph">Though it is probably the case that the author name and title supplied are
already of normalised casing, we do not want to rely on that. EIDs of the
same extension but named with different casing conventions would fail to
match: and this could happen if a new build of Inform were published which
made a subtle change to the casing conventions, but which continued to use
an extension dictionary file first written by previous builds under the
previous conventions.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::new</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">an</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">ti</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">context</span><span class="plain">) {</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_author_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">an</span><span class="plain">);</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">an</span><span class="plain">);</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_title</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">ti</span><span class="plain">);</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">ti</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">)</span>
<span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">hc</span><span class="plain">*30011 + (</span><span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">hc</span><span class="plain">*30011 + (</span><span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain">) </span><span class="character">'/'</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">)</span>
<span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">hc</span><span class="plain">*30011 + (</span><span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">hc</span><span class="plain"> % </span><span class="constant">EI_HASH_CODING_BASE</span><span class="plain">;</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain"> = (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">hc</span><span class="plain">;</span>
<span class="functiontext">Extensions::IDs::add_EID_to_database</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::set_raw</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">raw_an</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">raw_ti</span><span class="plain">) {</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_author_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">raw_an</span><span class="plain">);</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_title</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">raw_ti</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::write_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">fancy</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fancy</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">"404040"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" by "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fancy</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">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_author_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::write_link_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"href='Extensions/%S/%S.html' style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</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">"404040"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::is_standard_rules</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::write_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">FALSE</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">"a"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::writer</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">format_string</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vE</span><span class="plain">) {</span>
<span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain"> = (</span><span class="reserved">extension_identifier</span><span class="plain"> *) </span><span class="identifier">vE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">format_string</span><span class="plain">[0]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&lt;'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eid</span><span class="plain"> == </span><span class="identifier">NULL</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="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::is_standard_rules</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" by %S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_author_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'X'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eid</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;no extension&gt;"</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">"%S by %S"</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_title</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;raw_author_name</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad %X extension"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::new is used in <a href="#SP9">&#167;9</a>, 7/hdn (<a href="7-hdn.html#SP11_3">&#167;11.3</a>), 8/ef (<a href="8-ef.html#SP8_1">&#167;8.1</a>), 8/ec (<a href="8-ec.html#SP5_2_6">&#167;5.2.6</a>), 8/ed (<a href="8-ed.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Extensions::IDs::set_raw is used in 8/ec (<a href="8-ec.html#SP5_2_6">&#167;5.2.6</a>).</p>
<p class="endnote">The function Extensions::IDs::write_to_HTML_file is used in 2/sq (<a href="2-sq.html#SP2">&#167;2</a>), 8/ed (<a href="8-ed.html#SP19_2">&#167;19.2</a>), 8/ed2 (<a href="8-ed2.html#SP3_2_1">&#167;3.2.1</a>), 21/rl2 (<a href="21-rl2.html#SP23_11">&#167;23.11</a>).</p>
<p class="endnote">The function Extensions::IDs::write_link_to_HTML_file is used in 8/ed (<a href="8-ed.html#SP20_1">&#167;20.1</a>).</p>
<p class="endnote">The function Extensions::IDs::writer is used in 1/cm (<a href="1-cm.html#SP6_3">&#167;6.3</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Two EIDs with different hash codes definitely identify different extensions;
if the code is the same, we must use <code class="display"><span class="extract">strcmp</span></code> on the actual title and author
name. This is in effect case insensitive, since we normalised casing when
the EIDs were created.
</p>
<p class="inwebparagraph">(Note that this is not a lexicographic function suitable for sorting
EIDs into alphabetical order: it cannot be, since the hash code is not
order-preserving. To emphasise this we return true or false rather than a
<code class="display"><span class="extract">strcmp</span></code>-style delta value. For <code class="display"><span class="extract">Extensions::IDs::compare</span></code>, see below...)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid1</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">eid1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">eid2</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">"bad eid match"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain"> != </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::match is used in <a href="#SP9">&#167;9</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, 7/hdn (<a href="7-hdn.html#SP20">&#167;20</a>, <a href="7-hdn.html#SP20_2">&#167;20.2</a>), 8/ed (<a href="8-ed.html#SP9">&#167;9</a>, <a href="8-ed.html#SP18">&#167;18</a>, <a href="8-ed.html#SP18_2">&#167;18.2</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>These are quite a deal slower, but trichotomous.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid1</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">eid1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">eid2</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">"bad eid match"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_title</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid1</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">eid1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">eid2</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">"bad eid match"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_date</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid1</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">eid1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">eid2</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">"bad eid match"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="functiontext">Extensions::IDs::get_sort_date</span><span class="plain">(</span><span class="identifier">eid2</span><span class="plain">), </span><span class="functiontext">Extensions::IDs::get_sort_date</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_length</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid1</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">eid1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">eid2</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">"bad eid match"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="functiontext">Extensions::IDs::get_sort_word_count</span><span class="plain">(</span><span class="identifier">eid2</span><span class="plain">), </span><span class="functiontext">Extensions::IDs::get_sort_word_count</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="identifier">d</span><span class="plain"> = </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Str::cmp</span><span class="plain">(</span><span class="identifier">eid1</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">, </span><span class="identifier">eid2</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::compare is used in 8/ec (<a href="8-ec.html#SP12">&#167;12</a>), 8/ed (<a href="8-ed.html#SP18">&#167;18</a>).</p>
<p class="endnote">The function Extensions::IDs::compare_by_title is used in 8/ec (<a href="8-ec.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function Extensions::IDs::compare_by_date is used in 8/ec (<a href="8-ec.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function Extensions::IDs::compare_by_length is used in 8/ec (<a href="8-ec.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Because the Standard Rules are treated slightly differently by the
documentation, and so forth, it's convenient to provide a single function
which asks if a given EID is talking about them.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">an_eid_for_standard_rules_created</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">extension_identifier</span><span class="plain"> </span><span class="identifier">an_eid_for_standard_rules</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">an_eid_for_basic_inform_created</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">extension_identifier</span><span class="plain"> </span><span class="identifier">an_eid_for_basic_inform</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::is_standard_rules</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">an_eid_for_standard_rules_created</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">an_eid_for_standard_rules_created</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Extensions::IDs::new</span><span class="plain">(&amp;</span><span class="identifier">an_eid_for_standard_rules</span><span class="plain">,</span>
<span class="identifier">I</span><span class="string">"Graham Nelson"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Standard Rules"</span><span class="plain">, </span><span class="constant">HYPOTHETICAL_EIDBC</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, &amp;</span><span class="identifier">an_eid_for_standard_rules</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::is_basic_inform</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">an_eid_for_basic_inform_created</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">an_eid_for_basic_inform_created</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Extensions::IDs::new</span><span class="plain">(&amp;</span><span class="identifier">an_eid_for_basic_inform</span><span class="plain">,</span>
<span class="identifier">I</span><span class="string">"Graham Nelson"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Basic Inform"</span><span class="plain">, </span><span class="constant">HYPOTHETICAL_EIDBC</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, &amp;</span><span class="identifier">an_eid_for_basic_inform</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::is_standard_rules is used in <a href="#SP6">&#167;6</a>, 8/ef (<a href="8-ef.html#SP8_1">&#167;8.1</a>), 8/ed2 (<a href="8-ed2.html#SP3_2_1">&#167;3.2.1</a>).</p>
<p class="endnote">The function Extensions::IDs::is_basic_inform appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. The database of known EIDs. </b>We will need to be able to give rapid answers to questions like "is there
an installed extension with this EID?" and "does any entry in the dictionary
relate to this EID?": there may be many extensions and very many dictionary
entries, so we keep an incidence count of each EID and in what context it
has been used, and store that in a hash table. Note that each distinct EID
is recorded only once in the table: this is important, as although an
individual extension can only be loaded or installed once, it could be
referred to in the dictionary dozens or even hundreds of times.
</p>
<p class="inwebparagraph">The table is unsorted and is intended for rapid searching. Typically there
will be only a handful of EIDs in the list of those with a given hash code:
indeed, the typical number will be 0 or 1.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">EID_database_created</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="constant">EI_HASH_CODING_BASE</span><span class="plain">];</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::add_EID_to_database</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">context</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">EID_database_created</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">EID_database_created</span><span class="plain"> = </span><span class="identifier">TRUE</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">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">EI_HASH_CODING_BASE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="identifier">context</span><span class="plain">]++;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">extension_identifier_database_entry</span><span class="plain">);</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">] = </span><span class="identifier">eide</span><span class="plain">;</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain"> = </span><span class="identifier">eid</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">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">NO_EIDB_CONTEXTS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 0;</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="identifier">context</span><span class="plain">] = 1;</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;last_usage_date</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;sort_usage_date</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::add_EID_to_database is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>This gives us reasonably rapid access to a shared date:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::set_usage_date</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">date</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;last_usage_date</span><span class="plain">, </span><span class="identifier">date</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::set_sort_date</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">date</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;sort_usage_date</span><span class="plain">, </span><span class="identifier">date</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Extensions::IDs::get_usage_date</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;last_usage_date</span><span class="plain">) &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;last_usage_date</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">] &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"Once upon a time"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"Never"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"---"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Extensions::IDs::get_sort_date</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;sort_usage_date</span><span class="plain">) &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;sort_usage_date</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">] &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"00000000000000Once upon a time"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"00000000000000Never"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"000000000000000"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::set_word_count</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">wc</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain">, </span><span class="string">"%08d words"</span><span class="plain">, </span><span class="identifier">wc</span><span class="plain">);</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_number</span><span class="plain"> = </span><span class="identifier">wc</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Extensions::IDs::get_sort_word_count</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain">) &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">] &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"00000000I did read this, but forgot"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"00000000I've never read this"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="string">"---"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::forgot</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain">) &gt; 0)</span>
<span class="reserved">return</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">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">] &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::never</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_text</span><span class="plain">) &gt; 0)</span>
<span class="reserved">return</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">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">] &gt; 0)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::get_word_count</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain"> = </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;word_count_number</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> 0;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::set_usage_date is used in 8/ed (<a href="8-ed.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Extensions::IDs::set_sort_date is used in 8/ed (<a href="8-ed.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Extensions::IDs::get_usage_date is used in 8/ec (<a href="8-ec.html#SP10_7_4_4">&#167;10.7.4.4</a>).</p>
<p class="endnote">The function Extensions::IDs::get_sort_date is used in <a href="#SP8">&#167;8</a>.</p>
<p class="endnote">The function Extensions::IDs::set_word_count is used in 8/ed (<a href="8-ed.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Extensions::IDs::get_sort_word_count is used in <a href="#SP8">&#167;8</a>.</p>
<p class="endnote">The function Extensions::IDs::forgot is used in 8/ec (<a href="8-ec.html#SP10_7_4_4">&#167;10.7.4.4</a>).</p>
<p class="endnote">The function Extensions::IDs::never is used in 8/ec (<a href="8-ec.html#SP10_7_4_4">&#167;10.7.4.4</a>).</p>
<p class="endnote">The function Extensions::IDs::get_word_count is used in 8/ec (<a href="8-ec.html#SP10_7_4_4">&#167;10.7.4.4</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>The purpose of the hash table is to enable us to reply quickly when asked
for one of the following usage counts:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::no_times_used_in_context</span><span class="plain">(</span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">context</span><span class="plain">) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;extension_id_hash_code</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[</span><span class="identifier">context</span><span class="plain">];</span>
<span class="reserved">return</span><span class="plain"> 0;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::no_times_used_in_context is used in 7/hdn (<a href="7-hdn.html#SP20">&#167;20</a>), 8/ec (<a href="8-ec.html#SP11">&#167;11</a>), 8/ed (<a href="8-ed.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>The EID hash table makes quite interesting reading, so:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::log_EID_hash_table</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">hc</span><span class="plain">, </span><span class="identifier">total</span><span class="plain"> = 0;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Extension identifier hash table:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">hc</span><span class="plain">=0; </span><span class="identifier">hc</span><span class="plain">&lt;</span><span class="constant">EI_HASH_CODING_BASE</span><span class="plain">; </span><span class="identifier">hc</span><span class="plain">++) {</span>
<span class="reserved">extension_identifier_database_entry</span><span class="plain"> *</span><span class="identifier">eide</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">hash_of_EIDEs</span><span class="plain">[</span><span class="identifier">hc</span><span class="plain">]; </span><span class="identifier">eide</span><span class="plain">; </span><span class="identifier">eide</span><span class="plain"> = </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;hash_next</span><span class="plain">) {</span>
<span class="identifier">total</span><span class="plain">++;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%03d %3d %3d %3d %3d %X\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">hc</span><span class="plain">, </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[0], </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[1],</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[2], </span><span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;incidence_count</span><span class="plain">[3],</span>
<span class="identifier">eide</span><span class="plain">-</span><span class="element">&gt;eide_id</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d entries in all\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">total</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::log_EID_hash_table is used in 8/ef (<a href="8-ef.html#SP22">&#167;22</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. How casing is normalised. </b>Every word is capitalised, where a word begins at the start of the text,
after a hyphen, or after a bracket. Thus "Every Word Counts", "Even
Double-Barrelled Ones (And Even Parenthetically)".
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">boundary</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">boundary</span><span class="plain">) </span><span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">Characters::tolower</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">));</span>
<span class="identifier">boundary</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">c</span><span class="plain"> == </span><span class="character">' '</span><span class="plain">) </span><span class="identifier">boundary</span><span class="plain"> = </span><span class="identifier">TRUE</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="character">'-'</span><span class="plain">) </span><span class="identifier">boundary</span><span class="plain"> = </span><span class="identifier">TRUE</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="character">'('</span><span class="plain">) </span><span class="identifier">boundary</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::normalise_casing is used in <a href="#SP6">&#167;6</a>, 8/ec (<a href="8-ec.html#SP5_2_1">&#167;5.2.1</a>, <a href="8-ec.html#SP5_2_2_2">&#167;5.2.2.2</a>).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Documentation links. </b>This is where HTML links to extension documentation are created; the URL for
each extension's page is generated from its ID.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::begin_extension_link</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">rubric</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">"href='inform://Extensions/Extensions/"</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::escape_apostrophes</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;author_name</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">"/"</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::escape_apostrophes</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">-</span><span class="element">&gt;title</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">".html' "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">rubric</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">"title=\</span><span class="plain">"</span><span class="string">%S\</span><span class="plain">"</span><span class="string"> "</span><span class="plain">, </span><span class="identifier">rubric</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">"title=\</span><span class="plain">"</span><span class="string">%X\</span><span class="plain">"</span><span class="string"> "</span><span class="plain">, </span><span class="identifier">eid</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">, </span><span class="string">"style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">link</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">link</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::escape_apostrophes</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">) {</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">"</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">' '</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'&amp;'</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'&lt;'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'&gt;'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'%'</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%%%x"</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="reserved">else</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::end_extension_link</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain">) {</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::IDs::begin_extension_link is used in 8/ef (<a href="8-ef.html#SP21">&#167;21</a>), 8/ec (<a href="8-ec.html#SP10_7_4_1">&#167;10.7.4.1</a>).</p>
<p class="endnote">The function Extensions::IDs::escape_apostrophes appears nowhere else.</p>
<p class="endnote">The function Extensions::IDs::end_extension_link is used in 8/ef (<a href="8-ef.html#SP21">&#167;21</a>), 8/ec (<a href="8-ec.html#SP10_7_4_1">&#167;10.7.4.1</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="8-ie.html">Back to 'Including Extensions'</a></li><li><a href="8-ec.html">Continue with 'Extension Census'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>