mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 16:44:21 +03:00
1040 lines
112 KiB
HTML
1040 lines
112 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>5/es</title>
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
<nav role="navigation">
|
|
<h1><a href="../webs.html">Sources</a></h1>
|
|
<ul>
|
|
<li><a href="../compiler.html"><b>compiler</b></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="../inbuild-module/index.html">inbuild</a></li>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../words-module/index.html">words</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
</ul>
|
|
<h2>Inform7 Modules</h2>
|
|
<ul>
|
|
<li><a href="../core-module/index.html">core</a></li>
|
|
<li><a href="../problems-module/index.html">problems</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="../index-module/index.html">index</a></li>
|
|
</ul>
|
|
<h2>Inter Modules</h2>
|
|
<ul>
|
|
<li><a href="../inter-module/index.html">inter</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul>
|
|
<h2>Foundation</h2>
|
|
<ul>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
</ul>
|
|
|
|
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of '5/ed' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">inbuild</a></li><li><a href="index.html#5">Chapter 5: Services for the Inform Compiler</a></li><li><b>Extension Dictionary</b></li></ul><p class="purpose">To maintain a database of names and constructions in all extensions so far used by this installation of Inform, and spot potential namespace clashes.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP8">§8. Erasing entries</a></li><li><a href="#SP10">§10. Making new entries</a></li><li><a href="#SP11">§11. Loading from disc</a></li><li><a href="#SP13">§13. Time stamping</a></li><li><a href="#SP14">§14. Saving to disc</a></li><li><a href="#SP15">§15. Sorting the extension dictionary</a></li><li><a href="#SP17">§17. Extension clashes</a></li><li><a href="#SP20">§20. Writing the HTML extension index</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>Not during the census, but rather when extensions are successfully
|
|
used, a dictionary is kept of the terms defined in them: this is used
|
|
to generate the dynamic documentation on installed extensions, and
|
|
is stored between runs in a cache file inside the I7 application.
|
|
This means dictionary entries are first read in from the cache; then
|
|
the entries for any extension used by Inform in its current run are
|
|
revised, which may mean deleting some entries or adding new ones;
|
|
and at last Inform writes the final state of the dictionary back to the
|
|
cache. In this way, changes in what an extension defines are reflected
|
|
in the dictionary after each successful use of that extension.
|
|
</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_dictionary_entry</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inbuild_work</span><span class="plain"> *</span><span class="identifier">ede_work</span><span class="plain">; </span> <span class="comment">author name and title, with hash code</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">entry_text</span><span class="plain">; </span> <span class="comment">text of the dictionary entry</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sorting</span><span class="plain">; </span> <span class="comment">text reprocessed for sorting purposes</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">type</span><span class="plain">; </span> <span class="comment">grammatical category, such as "kind"</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">erased</span><span class="plain">; </span> <span class="comment">marked to be erased</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">next_in_sorted_dictionary</span><span class="plain">; </span> <span class="comment">link in linked list</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">extension_dictionary_entry</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">first_in_sorted_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure extension_dictionary_entry is accessed in 3/bg and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>Clashes occur if, say, two extensions define "chopper" as a kind
|
|
of vehicle (for instance, meaning a helicopter in one and a motorcycle
|
|
in the other). This results in two dictionary entries under "chopper"
|
|
and is recorded as a clash between them. Often, more will turn up:
|
|
perhaps "chopper" might elsewhere mean a butchery tool. In the
|
|
event of 3 or more clashing entries, A, B, C, ..., a linked list of
|
|
ordered pairs (A,B), (A,C), ... is maintained where in each pair the
|
|
first term (the left one) is from an extension lexicographically earlier
|
|
than the second (the right one): see below.
|
|
</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">known_extension_clash</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">first_known</span><span class="plain">; </span> <span class="comment">heads a linked list of clashes with a given <code class="display"><span class="extract">ede1</span></code></span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span> <span class="comment">next in linked list of clashes</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">leftx</span><span class="plain">; </span> <span class="comment">clash is between this entry...</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">rightx</span><span class="plain">; </span> <span class="comment">...and this one</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">number_clashes</span><span class="plain">; </span> <span class="comment">number of entries clashing between <code class="display"><span class="extract">ede1</span></code> and <code class="display"><span class="extract">ede2</span></code></span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">known_extension_clash</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure known_extension_clash is accessed in 5/ec, 6/hdn, 6/inc and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>The extension dictionary has no natural order as such. In order to generate
|
|
the dictionary page of the documentation, we will sort it alphabetically,
|
|
but it is not alphabetically stored either in memory or in its serialised
|
|
form on disc. (It might seem advantageous, since we're going to sort it
|
|
anyway, to use the sorted ordering when saving it back to disc, as at least
|
|
the structure will then be nearly sorted most of the time: but in fact the
|
|
reverse is true, because we will sort using the C library's implementation
|
|
of quicksort, an algorithm whose worst-case performance is on nearly
|
|
sorted lists.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>The following sample is an extract of the dictionary in its serialised
|
|
form on disc. The four columns are author, title, headword and category.
|
|
The special entries with category "indexing" have two roles: they are
|
|
markers that the extension in question is indexed in the dictionary, and
|
|
they record the last date on which the extension was used.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that the stroke character is illegal in unquoted Inform source text,
|
|
and therefore also in excerpts with meanings, in extension titles and in
|
|
author names. It can therefore safely be used as a record divider.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">In December 2007, the dictionary file of a user who had employed 155 different
|
|
extensions (by 33 different authors) contained 2223 entries, the longest of
|
|
which formed a line 95 characters long: the most prolific extension made 380
|
|
definitions. The total file size was about 130K. Some typical entries:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">...</span>
|
|
<span class="plain">|Emily Short|Plurality|20110130181823:Sun 30 January 2011 18:18|indexing|</span>
|
|
<span class="plain">|Emily Short|Plurality|prior named noun|value|</span>
|
|
<span class="plain">|Emily Short|Plurality|ambiguously plural|property|</span>
|
|
<span class="plain">|Emily Short|Plurality|ordinarily enumerated|property|</span>
|
|
<span class="plain">|Emily Short|Locksmith|20110130181823:Sun 30 January 2011 18:18|indexing|</span>
|
|
<span class="plain">|Emily Short|Locksmith|passkey|kind|</span>
|
|
<span class="plain">|Emily Short|Locksmith|keychain|kind|</span>
|
|
<span class="plain">...</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>The file is encoded as ISO Latin-1 and can in principle have any of <code class="display"><span class="extract">0A</span></code>, <code class="display"><span class="extract">0D</span></code>,
|
|
<code class="display"><span class="extract">0A 0D</span></code> or <code class="display"><span class="extract">0D 0A</span></code> as line divider. Each line must be no longer than the
|
|
following number of characters minus 1:
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_ED_LINE_LENGTH</span><span class="plain"> 512</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>The following logs the dictionary as it stands in memory, in a similar
|
|
format but also recorded the erasure flag.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::log_entry</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"ede: %4d %d |%S|%S|%S|%S|\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">,</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">-</span><span class="element">>author_name</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">-</span><span class="element">>title</span><span class="plain">,</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>type</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::log_extension_dictionary</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">=0;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Extension dictionary:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">) {</span>
|
|
<span class="identifier">n</span><span class="plain">++; </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"$d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain">==0) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"no entries\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::log_entry appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::log_extension_dictionary appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Erasing entries. </b>The erasure flag is used to mark entries in the dictionary which are to
|
|
be erased, in that they will not survive when we save it back from memory
|
|
to disc. (Entries are never physically deleted from the memory structures.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">There are two reasons to erase entries. First, the following routine sets the
|
|
erased flag for dictionary entries corresponding to an extension which,
|
|
according to the census returns, is no longer installed. (This can happen
|
|
if the user has uninstalled an extension since the last time Inform successfully
|
|
ran.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::erase_entries_of_uninstalled_extensions</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Erasure of dictionary entries for uninstalled extensions\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Works::no_times_used_in_context</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="constant">INSTALLED_WDBC</span><span class="plain">) == 0)) {</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Erased $d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::erase_entries_of_uninstalled_extensions is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>The second reason arises when we are making the dictionary entries for an
|
|
extension which was used on the current run. (For instance, if it created a
|
|
kind of vehicle called "dragster", then we will make a dictionary entry
|
|
for that.) Before making its dictionary entries, we first erase all entries
|
|
for the same extension which are left in the dictionary from some previous
|
|
run of Inform, as those are now out of date.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::erase_entries</span><span class="plain">(</span><span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Erasure of dictionary entries for %X\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Works::match</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">))) {</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Erased $d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::erase_entries appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. Making new entries. </b>We provide two ways to add a new entry: from a C string or from a word range.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::new_entry</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">category</span><span class="plain">, </span><span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</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="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="comment">a safety precaution: never index the empty text</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="functiontext">Extensions::Dictionary::new_dictionary_entry_raw</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">-</span><span class="element">>raw_author_name</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">-</span><span class="element">>raw_title</span><span class="plain">, </span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">headword</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::Dictionary::new_entry_from_stream</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">category</span><span class="plain">, </span><span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">headword</span><span class="plain">) {</span>
|
|
<span class="functiontext">Extensions::Dictionary::new_dictionary_entry_raw</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">-</span><span class="element">>author_name</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">-</span><span class="element">>as_copy</span><span class="plain">-</span><span class="element">>edition</span><span class="plain">-</span><span class="element">>work</span><span class="plain">-</span><span class="element">>title</span><span class="plain">, </span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::new_dictionary_entry_raw</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">category</span><span class="plain">,</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">author</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="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">headword</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain">);</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain"> = </span><span class="functiontext">Works::new</span><span class="plain">(</span><span class="identifier">extension_genre</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">author</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"NDER %X\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">);</span>
|
|
<span class="functiontext">Works::add_to_database</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="constant">DICTIONARY_REFERRED_WDBC</span><span class="plain">);</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>type</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">);</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"indexing"</span><span class="plain">)) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">sdate</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">udate</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">mode</span><span class="plain"> = 0, </span><span class="identifier">wc</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">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">) {</span>
|
|
<span class="reserved">if</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="character">'/'</span><span class="plain">) { </span><span class="identifier">mode</span><span class="plain"> = 1; </span><span class="reserved">continue</span><span class="plain">; }</span>
|
|
<span class="reserved">if</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="character">':'</span><span class="plain">) { </span><span class="identifier">mode</span><span class="plain"> = 2; </span><span class="reserved">continue</span><span class="plain">; }</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">digital</span><span class="plain"> = </span><span class="identifier">Characters::isdigit</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">switch</span><span class="plain"> (</span><span class="identifier">mode</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">digital</span><span class="plain">) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">sdate</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">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">digital</span><span class="plain">) </span><span class="identifier">wc</span><span class="plain"> = 10*</span><span class="identifier">wc</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="reserved">int</span><span class="plain">) </span><span class="character">'0'</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2:</span>
|
|
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">udate</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">break</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">Str::len</span><span class="plain">(</span><span class="identifier">sdate</span><span class="plain">) > 0) </span><span class="functiontext">Works::set_sort_date</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">sdate</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">wc</span><span class="plain"> > 0) </span><span class="functiontext">Works::set_word_count</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">wc</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">udate</span><span class="plain">) > 0) </span><span class="functiontext">Works::set_usage_date</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">udate</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">sdate</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">udate</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Created $d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::new_entry appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::new_entry_from_stream is used in <a href="#SP13">§13</a>.</p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::new_dictionary_entry_raw is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. Loading from disc. </b>Not a surprising routine: open, convert one line at a time to dictionary
|
|
entries, close.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">filename</span><span class="plain"> *</span><span class="functiontext">Extensions::Dictionary::filename</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Inbuild::transient</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="identifier">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Documentation"</span><span class="plain">);</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="identifier">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Census"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Dictionary.txt"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::load</span><span class="plain">(</span><span class="reserved">void</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">Extensions::Dictionary::filename</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Ensure the serialised extensions dictionary file exists</span> <span class="cwebmacronumber">11.1</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Reading dictionary file %f\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="identifier">TextFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">,</span>
|
|
<span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="functiontext">Extensions::Dictionary::load_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Finished reading dictionary file\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::filename is used in <a href="#SP14">§14</a>.</p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::load is used in 5/ec (<a href="5-ec.html#SP11">§11</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_1"></a><b>§11.1. </b>The extension dictionary file is stored only transiently and may never have
|
|
been made, or may have been wiped by a zealous mobile OS. If it doesn't exist,
|
|
we try to make an empty one. Should these attempts fail, we simply return:
|
|
there might be permissions reasons, and it doesn't matter too much if the
|
|
dictionary isn't read. A fatal error results only if, having written the empty
|
|
file, we are then unable to open it again: that must mean a file I/O error of
|
|
some kind, which is bad enough news to bother the user with.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Ensure the serialised extensions dictionary file exists</span> <span class="cwebmacronumber">11.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">DICTF</span><span class="plain"> = </span><span class="identifier">Filenames::fopen</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="string">"r"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">DICTF</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Creating new empty dictionary file\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">EMPTY_DICTF</span><span class="plain"> = </span><span class="identifier">Filenames::fopen</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="string">"w"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">EMPTY_DICTF</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">fclose</span><span class="plain">(</span><span class="identifier">EMPTY_DICTF</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>We parse lines in a fairly forgiving way. Material before the initial stroke
|
|
is ignored (this helps us cope with any spare newline characters if there are
|
|
blank lines, or if the line division is multi-byte); material after the final
|
|
stroke is also ignored, and any line not containing five vertical strokes
|
|
(i.e., four stroke-divided columns) is ignored altogether. This means that
|
|
any truncated, overlong lines are ineffectual but safe.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::load_helper</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line_entry</span><span class="plain">,</span>
|
|
<span class="identifier">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">author</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">category</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">strokes</span><span class="plain"> = 0, </span><span class="identifier">pos</span><span class="plain"> = 0; </span><span class="identifier">strokes</span><span class="plain"> <= 4; </span><span class="identifier">pos</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="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">line_entry</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"> == 0) </span><span class="reserved">break</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="reserved">if</span><span class="plain"> (++</span><span class="identifier">strokes</span><span class="plain"> == 5)</span>
|
|
<span class="functiontext">Extensions::Dictionary::new_dictionary_entry_raw</span><span class="plain">(</span>
|
|
<span class="identifier">category</span><span class="plain">, </span><span class="identifier">author</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">strokes</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">author</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">author</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">headword</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">category</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::load_helper is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. Time stamping. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::time_stamp</span><span class="plain">(</span><span class="reserved">inform_extension</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">dbuff</span><span class="plain">);</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">ascday</span><span class="plain">[] = { </span><span class="string">"Sun"</span><span class="plain">, </span><span class="string">"Mon"</span><span class="plain">, </span><span class="string">"Tue"</span><span class="plain">, </span><span class="string">"Wed"</span><span class="plain">, </span><span class="string">"Thu"</span><span class="plain">, </span><span class="string">"Fri"</span><span class="plain">, </span><span class="string">"Sat"</span><span class="plain"> };</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">ascmon</span><span class="plain">[] = { </span><span class="string">"January"</span><span class="plain">, </span><span class="string">"February"</span><span class="plain">, </span><span class="string">"March"</span><span class="plain">, </span><span class="string">"April"</span><span class="plain">, </span><span class="string">"May"</span><span class="plain">, </span><span class="string">"June"</span><span class="plain">,</span>
|
|
<span class="string">"July"</span><span class="plain">, </span><span class="string">"August"</span><span class="plain">, </span><span class="string">"September"</span><span class="plain">, </span><span class="string">"October"</span><span class="plain">, </span><span class="string">"November"</span><span class="plain">, </span><span class="string">"December"</span><span class="plain"> };</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">dbuff</span><span class="plain">, </span><span class="string">"%04d%02d%02d%02d%02d%02d/%d:%s %d %s %d %02d:%02d"</span><span class="plain">,</span>
|
|
<span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_year</span><span class="plain">+1900, </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_mon</span><span class="plain"> + 1, </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_mday</span><span class="plain">,</span>
|
|
<span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_hour</span><span class="plain">, </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_min</span><span class="plain">, </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_sec</span><span class="plain">,</span>
|
|
<span class="plain">(</span><span class="identifier">E</span><span class="plain">-</span><span class="element">>read_into_file</span><span class="plain">)?(</span><span class="identifier">TextFromFiles::total_word_count</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">-</span><span class="element">>read_into_file</span><span class="plain">)):0,</span>
|
|
<span class="identifier">ascday</span><span class="plain">[</span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_wday</span><span class="plain">], </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_mday</span><span class="plain">,</span>
|
|
<span class="identifier">ascmon</span><span class="plain">[</span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_mon</span><span class="plain">], </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_year</span><span class="plain">+1900,</span>
|
|
<span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_hour</span><span class="plain">, </span><span class="identifier">the_present</span><span class="plain">-></span><span class="identifier">tm_min</span><span class="plain">);</span>
|
|
<span class="functiontext">Extensions::Dictionary::new_entry_from_stream</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"indexing"</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">dbuff</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">dbuff</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::time_stamp is used in 5/ec (<a href="5-ec.html#SP6_2">§6.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Saving to disc. </b>And inversely...
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::write_back</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> </span><span class="identifier">DICTF_struct</span><span class="plain">;</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">DICTF</span><span class="plain"> = &</span><span class="identifier">DICTF_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">Extensions::Dictionary::filename</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</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">DICTF</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="reserved">return</span><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Writing dictionary file\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Writing $d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Write line to the dictionary file from single entry</span> <span class="cwebmacronumber">14.1</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Suppressing $d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Finished writing dictionary file\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">DICTF</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::write_back is used in 5/ec (<a href="5-ec.html#SP11">§11</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1"></a><b>§14.1. </b>We needn't worry overmuch about exceeding the maximum length, since any such
|
|
lines are handled safely by the loading code above. In any case, they could
|
|
only occur if it were true that
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">4 + MAX_ED_CATEGORY_LENGTH + MAX_ED_HEADWORD_LENGTH +</span>
|
|
<span class="plain"> MAX_EXTENSION_TITLE_LENGTH + MAX_EXTENSION_AUTHOR_LENGTH >= MAX_ED_LINE_LENGTH</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">and this is not nearly the case. (<code class="display"><span class="extract">MAX_ED_LINE_LENGTH</span></code> is larger than
|
|
strictly necessary since it costs us only temporary stack space and allows
|
|
for any future increase of the above maxima without fuss.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write line to the dictionary file from single entry</span> <span class="cwebmacronumber">14.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">DICTF</span><span class="plain">, </span><span class="string">"|%S|%S|%S|%S|\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">-</span><span class="element">>author_name</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">-</span><span class="element">>title</span><span class="plain">,</span>
|
|
<span class="identifier">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>type</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP14">§14</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Sorting the extension dictionary. </b>We pass this job on to the standard C library <code class="display"><span class="extract">qsort</span></code>, in hopes that it is
|
|
reasonably efficiently implemented. We need to bear in mind that the
|
|
extensions database can be expected to have some thousands of entries,
|
|
and that the O(n^2) insertion sorts used so casually elsewhere in Inform —
|
|
where lists are certainly much smaller — could cause misery here.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This routine returns the number of (unerased) entries in the dictionary,
|
|
and on its exit the (unerased) entries each occur once in alphabetical
|
|
order in the linked list beginning at <code class="display"><span class="extract">first_in_sorted_dictionary</span></code>.
|
|
If two entries have identical headwords, the earliest created is the
|
|
one which appears earlier in the sorted dictionary.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::sort_extension_dictionary</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> **</span><span class="identifier">sorted_extension_dictionary</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">no_entries</span><span class="plain"> = 0;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Beginning dictionary sort\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">sorted_extension_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Count headwords and reprocess their texts for dictionary sorting</span> <span class="cwebmacronumber">15.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_entries</span><span class="plain"> == 0) {</span>
|
|
<span class="identifier">first_in_sorted_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<<span class="cwebmacro">Allocate memory for, and fill, an array of pointers to the EDEs</span> <span class="cwebmacronumber">15.2</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted_extension_dictionary</span><span class="plain">, (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">no_entries</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *),</span>
|
|
<span class="functiontext">Extensions::Dictionary::compare_ed_entries</span><span class="plain">);</span>
|
|
|
|
<<span class="cwebmacro">String the sorted array together into a sorted linked list of EDEs</span> <span class="cwebmacronumber">15.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deallocate memory for the array again</span> <span class="cwebmacronumber">15.4</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Sorted dictionary: %d entries\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">no_entries</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">no_entries</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::sort_extension_dictionary is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_1"></a><b>§15.1. </b>Dictionary entries must be in mixed case: we might have both "green" the
|
|
colour and "Green" the kind of person (an environmental activist), say.
|
|
But we want to compare them with <code class="display"><span class="extract">strcmp</span></code>, which is much faster than its
|
|
case-insensitive analogue. So we trade memory for speed and store a modified
|
|
form of the headword in which spaces are removed and letters are reduced
|
|
to lower case; note that this is no larger than the original, so there is
|
|
no risk of the <code class="display"><span class="extract">sorting</span></code> string (which is 10 characters longer than the
|
|
unprocessed version) overflowing. Note: later we shall rely on the first
|
|
character of the sorting text being the lower-case form of the first
|
|
character of the original word.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We then append the allocation ID number, padded with initial zeros. We do
|
|
this so that (i) all sorting texts will be distinct, and (ii) alphabetical
|
|
order for sorting texts derived from two identical headword texts will
|
|
correspond to creation order. This means that <code class="display"><span class="extract">qsort</span></code>'s output will be
|
|
predictable (whereas different implementations of Quicksort might use the
|
|
freedom to sort unstably in different ways), and this seems a good idea
|
|
for better testing.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Count headwords and reprocess their texts for dictionary sorting</span> <span class="cwebmacronumber">15.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<span class="identifier">no_entries</span><span class="plain">++;</span>
|
|
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>sorting</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">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">)</span>
|
|
<span class="reserved">if</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="character">' '</span><span class="plain">)</span>
|
|
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain">,</span>
|
|
<span class="identifier">Characters::tolower</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">WRITE_TO</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain">, </span><span class="string">"-%09d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">EXTENSIONS_CENSUS</span><span class="plain">, </span><span class="string">"Sorted under '%S': $d"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2"></a><b>§15.2. </b>We unbundle the linked list of EDEs in creation order into an array
|
|
temporarily allocated in memory:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Allocate memory for, and fill, an array of pointers to the EDEs</span> <span class="cwebmacronumber">15.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</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">sorted_extension_dictionary</span><span class="plain"> = </span><span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">no_entries</span><span class="plain">,</span>
|
|
<span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *), </span><span class="constant">EXTENSION_DICTIONARY_MREASON</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>erased</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">sorted_extension_dictionary</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_3"></a><b>§15.3. </b>We then use the sorted version of the same array to reorder the EDEs:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">String the sorted array together into a sorted linked list of EDEs</span> <span class="cwebmacronumber">15.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">first_in_sorted_dictionary</span><span class="plain"> = </span><span class="identifier">sorted_extension_dictionary</span><span class="plain">[0];</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"><</span><span class="identifier">no_entries</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="identifier">sorted_extension_dictionary</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain"> =</span>
|
|
<span class="identifier">sorted_extension_dictionary</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1];</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_entries</span><span class="plain"> > 0)</span>
|
|
<span class="identifier">sorted_extension_dictionary</span><span class="plain">[</span><span class="identifier">no_entries</span><span class="plain">-1]-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_4"></a><b>§15.4. </b>And for the sake of tidiness:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deallocate memory for the array again</span> <span class="cwebmacronumber">15.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Memory::I7_array_free</span><span class="plain">(</span><span class="identifier">sorted_extension_dictionary</span><span class="plain">, </span><span class="constant">EXTENSION_DICTIONARY_MREASON</span><span class="plain">,</span>
|
|
<span class="identifier">no_entries</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>As always with <code class="display"><span class="extract">qsort</span></code>, there's a palaver about the types used for the
|
|
comparison function so that the result will compile without errors. The
|
|
comparison of two EDEs is in fact delegated to a <code class="display"><span class="extract">strcmp</span></code> comparison
|
|
of their sorting texts:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::compare_ed_entries</span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">elem1</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">elem2</span><span class="plain">) {</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> **</span><span class="identifier">e1</span><span class="plain"> = (</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> **) </span><span class="identifier">elem1</span><span class="plain">;</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> **</span><span class="identifier">e2</span><span class="plain"> = (</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> **) </span><span class="identifier">elem2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((*</span><span class="identifier">e1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">e2</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">"Disaster while sorting extension dictionary"</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">e1</span><span class="plain">)-</span><span class="element">>sorting</span><span class="plain">, (*</span><span class="identifier">e2</span><span class="plain">)-</span><span class="element">>sorting</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::compare_ed_entries is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Extension clashes. </b>All Inform extensions included share the main name-space of the source
|
|
text, and this causes potential problems with name clashes between two
|
|
different extensions if ever an author wants to include both at once. To
|
|
try to detect these clashes, we automatically scan the dictionary for them,
|
|
and provide warnings on the dynamic extension index.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="functiontext">Extensions::Dictionary::kec_new</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">first_known_flag</span><span class="plain">) {</span>
|
|
<span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="identifier">kec</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">known_extension_clash</span><span class="plain">);</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>leftx</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>rightx</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>number_clashes</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>first_known</span><span class="plain"> = </span><span class="identifier">first_known_flag</span><span class="plain">;</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>next</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">kec</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::kec_new is used in <a href="#SP18">§18</a>, <a href="#SP18_2">§18.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. </b>Every clash of names arises from definitions made in a pair of EDEs,
|
|
which we shall call left and right. Each distinct KEC ("known extension
|
|
clash") represents a different pair of extensions which clash, one
|
|
example of a name clashing between them, and a count of the number of
|
|
such names.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) Given a pair of extensions, the left one is the one whose author name
|
|
followed by title is lexicographically earlier. Since we are only concerned
|
|
with clashes between different extensions, this unambiguously decides which
|
|
is leftmost, as title and author suffice to identify extensions.
|
|
</li></ul>
|
|
<ul class="items"><li>(b) Similarly, given a pair of EDEs, the left one is the one whose definition
|
|
arises from the lefthand extension. (So, for instance, any definition made
|
|
in one of Eric Eve's extensions is always to the left of any definition in
|
|
one of John Clemens's.) Different EDEs deriving from the same extension do
|
|
not exemplify a clash.
|
|
</li></ul>
|
|
<ul class="items"><li>(c) For each extension L, there is at most one KEC whose left EDE derives
|
|
from L and which has the "first known" flag set.
|
|
</li></ul>
|
|
<p class="inwebparagraph">(-c.1) If such a KEC does not exist, then L does not clash with any other
|
|
extension.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">(-c.2) If such a KEC does exist, then it is the head of a linked list of
|
|
KECs all of which have lefthand EDE deriving from L, and in which no two
|
|
entries have righthand EDEs deriving from the same extension as each other.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It follows that we can determine if extensions X and Y clash by arranging
|
|
them as L and R (rule (a)), looking for L among the left EDEs of all KECs
|
|
with the "first known" flag set (rule (c)), and then looking for Y among
|
|
the right EDEs of all KECs in the list which hangs from that (rule (c.2)).
|
|
Should either of these searches fail, there is no clash between X and Y.
|
|
Should both succeed, then the KEC found provides a single example of the
|
|
clash (in its left and right EDEs), together with the number of clashes.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">If there are n extensions then there could in theory be n(n-1)/2 KECs,
|
|
which might amount to a lot of storage. In practice, though, Inform source
|
|
text tends to be dispersed around the cloud of English nouns and adjectives
|
|
fairly well, and since extension authors use each other's extensions, there
|
|
is also some social pressure to reduce the number of clashes. The user
|
|
mentioned above who had installed 155 different extensions — for a possible
|
|
11,935 distinct clashing pairs — in fact observed 15 such pairs, mostly arising
|
|
from part-finished drafts which had borrowed source text from pieces of other
|
|
extensions. Of the few remaining, several were cases where the same name
|
|
occurred in rival extensions aspiring to do much the same thing as each
|
|
other: for instance, "current quip" was defined by two different conversation
|
|
extensions. The only clashes of different meanings which might both be needed,
|
|
and which seem to have arisen spontaneously, were from definitions of the
|
|
words "seen" and "implicit", both treacherously ambiguous. Clashes did
|
|
not seem to have arisen from homonyms like "lead" (the substance) versus
|
|
"lead" (the attachment to a collar).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::extension_clash</span><span class="plain">(</span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede1</span><span class="plain">, </span><span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede2</span><span class="plain">) {</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">right</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">inbuild_work</span><span class="plain"> *</span><span class="identifier">leftx</span><span class="plain">, *</span><span class="identifier">rightx</span><span class="plain">;</span>
|
|
<span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="identifier">kec</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ede1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">ede2</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 extension clash"</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="functiontext">Works::compare</span><span class="plain">(</span><span class="identifier">ede1</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">ede2</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">); </span> <span class="comment">compare source extensions</span>
|
|
|
|
<<span class="cwebmacro">Ignore apparent clashes which are in fact not troublesome</span> <span class="cwebmacronumber">18.1</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="identifier">left</span><span class="plain"> = </span><span class="identifier">ede1</span><span class="plain">; </span><span class="identifier">right</span><span class="plain"> = </span><span class="identifier">ede2</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="identifier">left</span><span class="plain"> = </span><span class="identifier">ede2</span><span class="plain">; </span><span class="identifier">right</span><span class="plain"> = </span><span class="identifier">ede1</span><span class="plain">; }</span>
|
|
<span class="identifier">leftx</span><span class="plain"> = </span><span class="identifier">left</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">; </span><span class="identifier">rightx</span><span class="plain"> = </span><span class="identifier">right</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">kec</span><span class="plain">, </span><span class="reserved">known_extension_clash</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>first_known</span><span class="plain">) && (</span><span class="functiontext">Works::match</span><span class="plain">(</span><span class="identifier">leftx</span><span class="plain">, </span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>leftx</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">))) {</span>
|
|
<<span class="cwebmacro">Search list of KECs deriving from the same left extension as this clash</span> <span class="cwebmacronumber">18.2</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">kec</span><span class="plain"> = </span><span class="functiontext">Extensions::Dictionary::kec_new</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">right</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::Dictionary::extension_clash is used in <a href="#SP20_1">§20.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_1"></a><b>§18.1. </b>If two name clashes occur in the same extension then, since we can presume
|
|
that this extension does actually work, the clash cannot cause problems.
|
|
We also ignore a clash of a property name against some other form of name,
|
|
because these occur quite often and cause little difficulty in practice: so
|
|
they would only clutter up the dictionary with spurious warnings.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Ignore apparent clashes which are in fact not troublesome</span> <span class="cwebmacronumber">18.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<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="comment">both definitions come from the same extension</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">ede1</span><span class="plain">-</span><span class="element">>type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"property"</span><span class="plain">)) && (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">ede2</span><span class="plain">-</span><span class="element">>type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"property"</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">ede1</span><span class="plain">-</span><span class="element">>type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"property"</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) && (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">ede2</span><span class="plain">-</span><span class="element">>type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"property"</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_2"></a><b>§18.2. </b>If we can find the righthand extension on the righthand side of any KEC
|
|
in the list, then the clash is not a new one: we simply increment the number
|
|
of definition pairs clashing between the left and right extensions, and
|
|
return. (Thus forgetting what the actual definitions causing the present
|
|
clash were: we don't need them, as we already have an example of the
|
|
definitions clashing between the two.) But if we can't find righthand
|
|
extension anywhere in the list, we must add the new pair of definitions:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Search list of KECs deriving from the same left extension as this clash</span> <span class="cwebmacronumber">18.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">kec</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Works::match</span><span class="plain">(</span><span class="identifier">rightx</span><span class="plain">, </span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>rightx</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">)) {</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>number_clashes</span><span class="plain">++; </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">kec</span><span class="plain">-</span><span class="element">>next</span><span class="plain"> = </span><span class="functiontext">Extensions::Dictionary::kec_new</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">right</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="plain">}</span>
|
|
<span class="identifier">kec</span><span class="plain"> = </span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>next</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. </b>The above arrangement was designed to make it easy to print out the
|
|
clashes in a concise, human-readable way, which is what we now do.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::list_known_extension_clashes</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="identifier">kec</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="reserved">known_extension_clash</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Write the headnote about what extension clashes mean</span> <span class="cwebmacronumber">19.1</span>><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">kec</span><span class="plain">, </span><span class="reserved">known_extension_clash</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>first_known</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Write a paragraph about extensions clashing with the lefthand one here</span> <span class="cwebmacronumber">19.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::list_known_extension_clashes is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_1"></a><b>§19.1. </b>Not the end of the world! Extension clashes are not an error condition: they
|
|
are, if anything, a sign of life and activity.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write the headnote about what extension clashes mean</span> <span class="cwebmacronumber">19.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<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">"<b>Clashes found.</b> The dictionary above shows that some "</span>
|
|
<span class="string">"extensions make incompatible definitions of the same words or phrases. "</span>
|
|
<span class="string">"When two extensions disagree like this, it is not necessarily a bad "</span>
|
|
<span class="string">"sign (they might simply be two ways to approach the same problem), "</span>
|
|
<span class="string">"but in general it means that it may not be safe to use both "</span>
|
|
<span class="string">"extensions at the same time. The following list shows some potential "</span>
|
|
<span class="string">"clashes."</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="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2"></a><b>§19.2. </b>As always, we need to be careful about writing the ISO text of clashing
|
|
matter to the UTF-8 HTML file:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write a paragraph about extensions clashing with the lefthand one here</span> <span class="cwebmacronumber">19.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">known_extension_clash</span><span class="plain"> *</span><span class="identifier">example</span><span class="plain">;</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"b"</span><span class="plain">);</span>
|
|
<span class="functiontext">Works::write_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">kec</span><span class="plain">-</span><span class="element">>leftx</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"b"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">": "</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">example</span><span class="plain"> = </span><span class="identifier">kec</span><span class="plain">; </span><span class="identifier">example</span><span class="plain">; </span><span class="identifier">example</span><span class="plain"> = </span><span class="identifier">example</span><span class="plain">-</span><span class="element">>next</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"clash with "</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"b"</span><span class="plain">);</span>
|
|
<span class="functiontext">Works::write_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">-</span><span class="element">>rightx</span><span class="plain">-</span><span class="element">>ede_work</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"b"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (on "</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">example</span><span class="plain">-</span><span class="element">>number_clashes</span><span class="plain"> > 1)</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d names, for instance "</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">-</span><span class="element">>number_clashes</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">example</span><span class="plain">-</span><span class="element">>leftx</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">example</span><span class="plain">-</span><span class="element">>next</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"; "</span><span class="plain">);</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">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Writing the HTML extension index. </b>This is the index of terms, not the directory of extensions: it is, in
|
|
fact, the HTML rendering of the dictionary constructed above.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Dictionary::write_to_HTML</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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">"Whenever an extension is used, its definitions are entered into the "</span>
|
|
<span class="string">"following index. (Thus, a newly installed but never-used extension "</span>
|
|
<span class="string">"is not indexed yet.)."</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">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</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="reserved">int</span><span class="plain"> </span><span class="identifier">first_letter</span><span class="plain"> = </span><span class="character">'a'</span><span class="plain">;</span>
|
|
<span class="reserved">extension_dictionary_entry</span><span class="plain"> *</span><span class="identifier">ede</span><span class="plain">, *</span><span class="identifier">previous_ede</span><span class="plain">, *</span><span class="identifier">next_ede</span><span class="plain">;</span>
|
|
<span class="functiontext">Extensions::Dictionary::erase_entries_of_uninstalled_extensions</span><span class="plain">();</span>
|
|
<span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">Extensions::Dictionary::sort_extension_dictionary</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> <= 0) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">previous_ede</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain"> = </span><span class="identifier">first_in_sorted_dictionary</span><span class="plain">; </span><span class="identifier">ede</span><span class="plain">;</span>
|
|
<span class="identifier">previous_ede</span><span class="plain"> = </span><span class="identifier">ede</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain"> = </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>type</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"indexing"</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">next_ede</span><span class="plain"> = </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_first</span><span class="plain"> = </span><span class="identifier">Characters::tolower</span><span class="plain">(</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_letter</span><span class="plain"> != </span><span class="identifier">this_first</span><span class="plain">) {</span>
|
|
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">); </span><span class="identifier">first_letter</span><span class="plain"> = </span><span class="identifier">this_first</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<<span class="cwebmacro">Write extension dictionary entry for this headword</span> <span class="cwebmacronumber">20.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Extensions::Dictionary::list_known_extension_clashes</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Extensions::Dictionary::write_to_HTML is used in 5/ec (<a href="5-ec.html#SP15">§15</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_1"></a><b>§20.1. </b>A run of N words which are all the same should appear in tinted type
|
|
throughout, while N(N-1)/2 clashes should be reported to the machinery above:
|
|
if we find definitions A, B, C, for instance, the clashes are reported as
|
|
A vs B, A vs C, then B vs C. This has O(N^2) running time, so if there are
|
|
1000 extensions, each of which gives 1000 different meanings to the word
|
|
"frog", we would be in some trouble here. Let's take the risk.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">EDES_DEFINE_SAME_WORD</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) ((</span><span class="identifier">X</span><span class="plain">) && (</span><span class="identifier">Y</span><span class="plain">) && (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">-</span><span class="element">>sorting</span><span class="plain">)))</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write extension dictionary entry for this headword</span> <span class="cwebmacronumber">20.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tint</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">EDES_DEFINE_SAME_WORD</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="identifier">previous_ede</span><span class="plain">)) </span><span class="identifier">tint</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">EDES_DEFINE_SAME_WORD</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="identifier">next_ede</span><span class="plain">)) {</span>
|
|
<span class="identifier">tint</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="functiontext">Extensions::Dictionary::extension_clash</span><span class="plain">(</span><span class="identifier">ede</span><span class="plain">, </span><span class="identifier">next_ede</span><span class="plain">);</span>
|
|
<span class="identifier">next_ede</span><span class="plain"> = </span><span class="identifier">next_ede</span><span class="plain">-</span><span class="element">>next_in_sorted_dictionary</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">, </span><span class="string">"style='margin:0px; padding:0px;'"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tint</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">"FF8080"</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">ede</span><span class="plain">-</span><span class="element">>entry_text</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tint</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">" - <i>%S</i>&nbsp;&nbsp;&nbsp;"</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>type</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">smaller\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="functiontext">Works::write_link_to_HTML_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">ede</span><span class="plain">-</span><span class="element">>ede_work</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">"p"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="5-es.html">Back to 'Extension Services'</a></li><li><a href="5-ed2.html">Continue with 'Extension Documentation'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|