1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/8-ec.html
2019-08-24 11:21:48 +01:00

1592 lines
179 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>8/ei</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '8/ec' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#8">Chapter 8: Extensions</a></li><li><b>Extension Census</b></li></ul><p class="purpose">To conduct a census of all the extensions installed (whether used on this run or not), and keep the documentation index for them up to date.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Conducting the census</a></li><li><a href="#SP5_2_2">&#167;5.2.2. Handling the extension file</a></li><li><a href="#SP5_2_3">&#167;5.2.3. Parsing the titling line</a></li><li><a href="#SP5_2_4">&#167;5.2.4. Making sure this is the extension we expected to find</a></li><li><a href="#SP5_2_5">&#167;5.2.5. Adding the extension to the census, or not</a></li><li><a href="#SP6">&#167;6. Census errors</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>In addition to the extensions read in, there are the roads not taken: the
ones which I7 has at its disposal, but which the source text never asks to
include. Inform performs a "census" of installed extensions on every run,
essentially by scanning the directories which hold them to see what the
user has installed there.
</p>
<p class="inwebparagraph">Each extension discovered will produce a single "extension census datum",
or ECD.
</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_census_datum</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_identifier</span><span class="plain"> </span><span class="identifier">ecd_id</span><span class="plain">; </span> <span class="comment">title, author, 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">version_text</span><span class="plain">; </span> <span class="comment">such as <code class="display"><span class="extract">23</span></code> or <code class="display"><span class="extract">14/060527</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">VM_requirement</span><span class="plain">; </span> <span class="comment">such as "(for Z-machine only)"</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">built_in</span><span class="plain">; </span> <span class="comment">found in the Inform 7 application's private stock</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">project_specific</span><span class="plain">; </span> <span class="comment">found in the Materials folder for the current project</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">overriding_a_built_in_extension</span><span class="plain">; </span> <span class="comment">not built in, but overriding one which is</span>
<span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">domain</span><span class="plain">; </span> <span class="comment">pathname of the stock in which this was found</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">rubric</span><span class="plain">; </span> <span class="comment">brief description found in opening lines</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span> <span class="comment">next one in lexicographic order</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">extension_census_datum</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure extension_census_datum is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ss, 7/hdn, 7/ns, 7/oaf, 7/rs, 8/ie, 8/ed, 8/ed2, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/ass, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 16/in, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>This is a narrative section and describes the story of the census. Just as
Caesar Augustus decreed that all the world should be taxed, and that each
should return to his place of birth, so we will open and inspect every
extension we can find, checking that each is in the right place.
</p>
<p class="inwebparagraph">Note that if the same extension is found in more than one domain, the first
to be found is considered the definitive version: this is why the external
area is searched first, so that the user can override built-in extensions
by placing his own versions in the external area. (Should this convention
ever be reversed, a matching change would need to be made in the code which
opens extension files in Read Source Text.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::perform</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Extensions::Census::begin_recording_census_errors</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">area</span><span class="plain">=0; </span><span class="identifier">area</span><span class="plain">&lt;</span><span class="constant">NO_FS_AREAS</span><span class="plain">; </span><span class="identifier">area</span><span class="plain">++)</span>
<span class="functiontext">Extensions::Census::take_census_of_domain</span><span class="plain">(</span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="identifier">area</span><span class="plain">], </span><span class="identifier">area</span><span class="plain">+1);</span>
<span class="functiontext">Extensions::Census::end_recording_census_errors</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::perform is used in 8/ef (<a href="8-ef.html#SP22">&#167;22</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Conducting the census. </b>An "extension domain", for these purposes, is a directory in the filing
system which can contain extensions (providing these are themselves placed
in subdirectories identifying their authorship). The built-in domain is
special (it is read-only, for one thing), but in principle we could have
any number of other domains. The following code scans one.
</p>
<pre class="display">
<span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">current_extension_domain</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::take_census_of_domain</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="reserved">int</span><span class="plain"> </span><span class="identifier">origin</span><span class="plain">) {</span>
<span class="identifier">current_extension_domain</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">;</span>
<span class="functiontext">Extensions::Census::census_from</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">origin</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::take_census_of_domain is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The following routine is not as recursive as it looks, since it runs at
only two levels: a top level, when it is scanning the domain, and an inner
level, when it is scanning the subfolder of the domain for a given author.
</p>
<p class="inwebparagraph">The reader may wince at the way we scan a directory &mdash; we essentially dump
a catalogue listing to a temporary text file and then read it back in,
one line at a time &mdash; but it works properly on all platforms, which is
important given how poorly directory handling is standardised in C.
</p>
<p class="inwebparagraph">Because of the two-level recursion, there are two such temporary files,
<code class="display"><span class="extract">Temporary1.txt</span></code> at the upper level and <code class="display"><span class="extract">Temporary0.txt</span></code> below. These are
stored in the external Extensions area. In principle that could be
problematic since two processes running Inform on the same machine may be
simultaneously taking an extension census, so could lock each other out:
probably we ought to include a process ID in the filenames. But then we
would have further platform hassles, and we would need to delete the files
when done, and worry about what happens if Inform is aborted half-way.
(When <code class="display"><span class="extract">intest</span></code> does large multiprocessing test runs of Inform, indexing
is turned off, so extension censuses are not being taken.)
</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">census_state</span><span class="plain"> {</span>
<span class="reserved">struct</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="reserved">int</span><span class="plain"> </span><span class="identifier">top_level</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">origin</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">parent</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">census_state</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::census_from</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="reserved">int</span><span class="plain"> </span><span class="identifier">top_level</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">origin</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">parent</span><span class="plain">) {</span>
<span class="identifier">scan_directory</span><span class="plain"> *</span><span class="identifier">dir</span><span class="plain"> = </span><span class="identifier">Directories::open</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dir</span><span class="plain">) {</span>
<span class="reserved">census_state</span><span class="plain"> </span><span class="identifier">cs</span><span class="plain">;</span>
<span class="identifier">cs</span><span class="element">.P</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">; </span><span class="identifier">cs</span><span class="element">.top_level</span><span class="plain"> = </span><span class="identifier">top_level</span><span class="plain">; </span><span class="identifier">cs</span><span class="element">.origin</span><span class="plain"> = </span><span class="identifier">origin</span><span class="plain">; </span><span class="identifier">cs</span><span class="element">.parent</span><span class="plain"> = </span><span class="identifier">parent</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain"> = 0;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Directories::next</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">))</span>
<span class="functiontext">Extensions::Census::census_from_helper</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">, &amp;</span><span class="identifier">cs</span><span class="plain">, ++</span><span class="identifier">count</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="identifier">Directories::close</span><span class="plain">(</span><span class="identifier">dir</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::Census::census_from_helper</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">item_name</span><span class="plain">, </span><span class="reserved">census_state</span><span class="plain"> *</span><span class="identifier">cs</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</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">item_name</span><span class="plain">) == 0) </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">"%d: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">count</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;top_level</span><span class="plain">) </span>&lt;<span class="cwebmacro">Take census from a possible author folder</span> <span class="cwebmacronumber">5.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Take census from a possible extension</span> <span class="cwebmacronumber">5.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::census_from is used in <a href="#SP4">&#167;4</a>, <a href="#SP5_1">&#167;5.1</a>.</p>
<p class="endnote">The function Extensions::Census::census_from_helper appears nowhere else.</p>
<p class="endnote">The structure census_state is private to this section.</p>
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b>At the upper level, we expect every item to be a subfolder whose name is that
of a given author. We can identify folder names because of the terminating
slash <code class="display"><span class="extract">/</span></code>: note that this character is used regardless of whether or not it
is the platform's file separator, and that it is illegal in extension titles
or author names.
</p>
<p class="inwebparagraph">It is a "census error" &mdash; meaning, we have detected a misinstallation of
extensions &mdash; if any file is present, or any folder too long for its name to
be an author name, except that items with names beginning with a <code class="display"><span class="extract">.</span></code> are
ignored. (In particular, the folders <code class="display"><span class="extract">./</span></code> and <code class="display"><span class="extract">../</span></code> are ignored, but so too
are OS X Finder files like <code class="display"><span class="extract">.DS_Store</span></code>, and other such junk. No author name
or title is allowed to contain a <code class="display"><span class="extract">.</span></code> character, so this cannot throw away
valid census entries.)
</p>
<p class="inwebparagraph">Once we have a valid, non-reserved author subfolder, we recurse down to lower
level to scan it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Take census from a possible author folder</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">) == </span><span class="character">'.'</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::get_last_char</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">) == </span><span class="identifier">FOLDER_SEPARATOR</span><span class="plain">) {</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">); </span> <span class="comment">remove the terminal slash: it has served its purpose</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Reserved"</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::len</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">) &gt; </span><span class="constant">MAX_EXTENSION_TITLE_LENGTH</span><span class="plain">-1) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"author name exceeds the maximum permitted length"</span><span class="plain">,</span>
<span class="identifier">item_name</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">NULL</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">Str::includes_character</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">, </span><span class="character">'.'</span><span class="plain">)) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"author name contains a full stop"</span><span class="plain">,</span>
<span class="identifier">item_name</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">NULL</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Extensions::Census::census_from</span><span class="plain">(</span>
<span class="identifier">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;P</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">),</span>
<span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;origin</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"non-folder found where author folders should be"</span><span class="plain">,</span>
<span class="identifier">item_name</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">NULL</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="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_2"></a><b>&#167;5.2. </b>At the lower level, <code class="display"><span class="extract">.</span></code> files or folders are again skipped; any other
folders are a census error, since there should only be extension files
present; and once again, we enforce the title length restriction.
</p>
<p class="inwebparagraph">As will be seen from the logic below, an extension is only given a census
entry (and therefore included in the HTML documentation of installed
extensions) if no census errors arise from it. An Inform user can therefore
know that if an extension shows up on his documentation page, it is properly
installed and identifies itself correctly, and moreover that it can be
installed correctly on other Informs elsewhere (perhaps on other platforms).
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_TITLING_LINE_LENGTH</span><span class="plain"> 501 </span> <span class="comment">lots, allowing for an improbably large number of virtual machine restrictions</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Take census from a possible extension</span> <span class="cwebmacronumber">5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">overridden_by_an_extension_already_found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">raw_title</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">candidate_author_name</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">raw_author_name</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">rubric_text</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">version_text</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">requirement_text</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">claimed_author_name</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">claimed_title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">) == </span><span class="character">'.'</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::get_last_char</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">) == </span><span class="identifier">FOLDER_SEPARATOR</span><span class="plain">) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"folder or application in author folder"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</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="reserved">return</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">item_name</span><span class="plain">) &gt; </span><span class="constant">MAX_EXTENSION_TITLE_LENGTH</span><span class="plain">-1) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"title exceeds the maximum permitted length"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</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="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Make candidate title and author name from normalised casing versions of filename and parent folder name</span> <span class="cwebmacronumber">5.2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Extract the titling line and rubric, if any, from the extension file</span> <span class="cwebmacronumber">5.2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Parse the version, title, author and VM requirements from the titling line</span> <span class="cwebmacronumber">5.2.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Check that the candidate name and title match those claimed in the titling line</span> <span class="cwebmacronumber">5.2.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">See if we duplicate the title and author name of an extension already found in another domain</span> <span class="cwebmacronumber">5.2.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">overridden_by_an_extension_already_found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Create a new census datum for this extension, which has passed all tests</span> <span class="cwebmacronumber">5.2.6</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">raw_title</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">candidate_author_name</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">raw_author_name</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">rubric_text</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">version_text</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">requirement_text</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">claimed_author_name</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">claimed_title</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_1"></a><b>&#167;5.2.1. </b>If we find an extension at the relative pathname <code class="display"><span class="extract">Emily Short/Locksmith</span></code> then
we expect it to be Locksmith by Emily Short: these are the candidate author name
and title respectively. (What the file actually contains is another matter, as
we shall see.)
</p>
<p class="inwebparagraph">All titles and author names have to be stored carefully in case-normalised
form at all times, and this extends to the filename and folder name. Enforcing
this rule may seem needlessly bureaucratic, since for the majority of users
(using typical Mac OS X and Windows installations) the filing system preserves
the case of filenames but is not sensitive to case when searching for files:
thus the folders <code class="display"><span class="extract">jimmy stewart</span></code> and <code class="display"><span class="extract">Jimmy Stewart</span></code> behave identically in
practice. But we want to use <code class="display"><span class="extract">strcmp</span></code> for case-sensitive comparisons, for
instance.
</p>
<p class="inwebparagraph">There are active Inform users who do have a case-sensitive filing system
(on some of the Linux and Solaris ports), and we want extension files to
continue to work perfectly if taken from one Inform installation and added
to another. So the previously strict rules on casing of the filenames as
stored have been waived.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make candidate title and author name from normalised casing versions of filename and parent folder name</span> <span class="cwebmacronumber">5.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">candidate_author_name</span><span class="plain">, </span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Remove filename extension for extensions, if any</span> <span class="cwebmacronumber">5.2.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">raw_title</span><span class="plain">, </span><span class="identifier">candidate_title</span><span class="plain">);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">raw_author_name</span><span class="plain">, </span><span class="identifier">candidate_author_name</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">candidate_author_name</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::includes_character</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="character">'.'</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Title is &lt;%S&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">candidate_title</span><span class="plain">);</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"title contains a full stop"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">candidate_title</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="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_1_1"></a><b>&#167;5.2.1.1. </b>We permit (encourage, actually) the filename extension ".i7x" for extensions,
in any of its possible casings, and that of course isn't part of the title:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Remove filename extension for extensions, if any</span> <span class="cwebmacronumber">5.2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::ends_with_wide_string</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="identifier">L</span><span class="string">".i7x"</span><span class="plain">))</span>
<span class="identifier">Str::truncate</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">) - 4);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_1">&#167;5.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_2"></a><b>&#167;5.2.2. Handling the extension file. </b>This and the next three paragraphs do the file-handling necessary to open the extension,
extract its titling line and rubric, then close it again.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Extract the titling line and rubric, if any, from the extension file</span> <span class="cwebmacronumber">5.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">FILE</span><span class="plain"> *</span><span class="identifier">EXTF</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Open the extension file for reading</span> <span class="cwebmacronumber">5.2.2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Read the titling line of the extension and normalise its casing</span> <span class="cwebmacronumber">5.2.2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Read the rubric text, if any is present</span> <span class="cwebmacronumber">5.2.2.3</span>&gt;<span class="plain">;</span>
<span class="identifier">fclose</span><span class="plain">(</span><span class="identifier">EXTF</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_2_1"></a><b>&#167;5.2.2.1. </b>The following should only fail in the event of some peculiar filing system
failure (or of some other process having moved or deleted the file since
we scanned the folder only moments ago).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Open the extension file for reading</span> <span class="cwebmacronumber">5.2.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> =</span>
<span class="functiontext">Locations::of_extension</span><span class="plain">(</span><span class="identifier">current_extension_domain</span><span class="plain">,</span>
<span class="identifier">item_name</span><span class="plain">, </span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">EXTF</span><span class="plain"> = </span><span class="identifier">Filenames::fopen_caseless</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">EXTF</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"file cannot be read"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</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="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_2">&#167;5.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_2_2"></a><b>&#167;5.2.2.2. </b>The actual maximum number of characters in the titling line is one less
than <code class="display"><span class="extract">MAX_TITLING_LINE_LENGTH</span></code>, to allow for the null terminator. The titling
line is terminated by 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>, or by the local
<code class="display"><span class="extract">\n</span></code> for good measure.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read the titling line of the extension and normalise its casing</span> <span class="cwebmacronumber">5.2.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">titling_chars_read</span><span class="plain"> = 0, </span><span class="identifier">c</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">TextFiles::utf8_fgetc</span><span class="plain">(</span><span class="identifier">EXTF</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="identifier">NULL</span><span class="plain">)) != </span><span class="identifier">EOF</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="identifier">xFEFF</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">skip the optional Unicode BOM pseudo-character</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">x</span><span class="character">0a'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">titling_chars_read</span><span class="plain"> &lt; </span><span class="constant">MAX_TITLING_LINE_LENGTH</span><span class="plain"> - 1) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Extensions::IDs::normalise_casing</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_2">&#167;5.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_2_3"></a><b>&#167;5.2.2.3. </b>In the following, all possible newlines are converted to white space, and
all white space before a quoted rubric text is ignored. We need to do this
partly because users have probably keyed a double line break before the
rubric, but also because we might have stopped reading the titling line
halfway through a line division combination like <code class="display"><span class="extract">0A 0D</span></code>, so that the first
thing we read here is a meaningless <code class="display"><span class="extract">0D</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read the rubric text, if any is present</span> <span class="cwebmacronumber">5.2.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">, </span><span class="identifier">found_start</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">TextFiles::utf8_fgetc</span><span class="plain">(</span><span class="identifier">EXTF</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="identifier">NULL</span><span class="plain">)) != </span><span class="identifier">EOF</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">x</span><span class="character">0a'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">)) </span><span class="identifier">c</span><span class="plain"> = </span><span class="character">' '</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> != </span><span class="character">' '</span><span class="plain">) &amp;&amp; (</span><span class="identifier">found_start</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'"'</span><span class="plain">) </span><span class="identifier">found_start</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'"'</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">found_start</span><span class="plain">) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">rubric_text</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_2">&#167;5.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_3"></a><b>&#167;5.2.3. Parsing the titling line. </b>In general, once case-normalised, a titling line looks like this:
</p>
<blockquote>
<p>Version 2/070423 Of Going To The Zoo (For Glulx Only) By Cary Grant Begins Here.</p>
</blockquote>
<p class="inwebparagraph">and the version information, the VM restriction and the full stop are all
optional, but the division word "of" and the concluding "begin[s] here"
are not. We break it up into pieces, so that
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">version_text = "2/070423"</span>
<span class="plain">claimed_title = "Going To The Zoo"</span>
<span class="plain">claimed_author_name = "Cary Grant"</span>
<span class="plain">requirement_text = "(For Glulx Only)"</span>
</pre>
<p class="inwebparagraph">It's tempting to do this by feeding it into the lexer and then reusing some
of the code which parses these lines during sentence-breaking, but in fact
we want to use the information rather differently, and besides: it seems
useful to record some C code here which correctly parses a titling line,
since this can easily be extracted and used in other utilities handling
Inform extensions.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse the version, title, author and VM requirements from the titling line</span> <span class="cwebmacronumber">5.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">) == </span><span class="character">'.'</span><span class="plain">) </span><span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*) Begin Here"</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*) Begins Here"</span><span class="plain">))) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Titling: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">);</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"appears not to be an extension (its first line does "</span>
<span class="string">"not end 'begin(s) here', as extension titling lines must)"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</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="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Scan the version text, if any, and advance to the position past Version... Of</span> <span class="cwebmacronumber">5.2.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"The (%c*)"</span><span class="plain">)) </span><span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
&lt;<span class="cwebmacro">Divide the remaining text into a claimed author name and title, divided by By</span> <span class="cwebmacronumber">5.2.3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Extract the VM requirements text, if any, from the claimed title</span> <span class="cwebmacronumber">5.2.3.3</span>&gt;<span class="plain">;</span>
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_3_1"></a><b>&#167;5.2.3.1. </b>We make no attempt to check the version number for validity: the purpose
of the census is to identify extensions and reject accidentally included
other files, not to syntax-check all extensions to see if they would work
if used.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Scan the version text, if any, and advance to the position past Version... Of</span> <span class="cwebmacronumber">5.2.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Version (%c*?) Of (%c*)"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">version_text</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_3">&#167;5.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_3_2"></a><b>&#167;5.2.3.2. </b>The earliest "by" is the divider: note that extension titles are not
allowed to contain this word, so "North By Northwest By Cary Grant" is
not a situation we need to contend with.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Divide the remaining text into a claimed author name and title, divided by By</span> <span class="cwebmacronumber">5.2.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">titling_line</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*?) By (%c*)"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">claimed_title</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">claimed_author_name</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"appears not to be an extension (the titling line does "</span>
<span class="string">"not give both author and title)"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</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="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_3">&#167;5.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_3_3"></a><b>&#167;5.2.3.3. </b>Similarly, extension titles are not allowed to contain parentheses, so
this is unambiguous.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Extract the VM requirements text, if any, from the claimed title</span> <span class="cwebmacronumber">5.2.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">claimed_title</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*?) *(%(%c*%))"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">claimed_title</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">requirement_text</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2_3">&#167;5.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_4"></a><b>&#167;5.2.4. Making sure this is the extension we expected to find. </b>It's easier for these confusions to arise than might be thought. For instance,
if two different authors independently write extensions called "Followers",
it would be easy to put a file of this name in the wrong author folder by
mistake. Since extension installation is usually handled mechanically (and,
we hope, correctly) by the Inform application, such problems are only likely
to arise when users install extensions by hand. Still, it's prudent to check.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that the candidate name and title match those claimed in the titling line</span> <span class="cwebmacronumber">5.2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">right_leafname</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">right_folder</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">claimed_title</span><span class="plain">, </span><span class="identifier">candidate_title</span><span class="plain">)) </span><span class="identifier">right_leafname</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">claimed_author_name</span><span class="plain">, </span><span class="identifier">candidate_author_name</span><span class="plain">)) </span><span class="identifier">right_folder</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">right_leafname</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">right_folder</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"an extension with the right filename but in the wrong "</span>
<span class="string">"author's folder"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">, </span><span class="identifier">claimed_author_name</span><span class="plain">, </span><span class="identifier">claimed_title</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">right_leafname</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">right_folder</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">)) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"an extension stored in the correct author's folder, but "</span>
<span class="string">"with the wrong filename"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">, </span><span class="identifier">claimed_author_name</span><span class="plain">, </span><span class="identifier">claimed_title</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">right_leafname</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">right_folder</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="string">"an extension but with the wrong filename and put in the "</span>
<span class="string">"wrong author's folder"</span><span class="plain">,</span>
<span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;parent</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">, </span><span class="identifier">claimed_author_name</span><span class="plain">, </span><span class="identifier">claimed_title</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_5"></a><b>&#167;5.2.5. Adding the extension to the census, or not. </b>Recall that the higher-priority external domain is scanned first; the
built-in domain is scanned second. So if we find that our new extension has
the same title and author as one already known, it must be the case that we
are now scanning the built-in area and that the previous one was an extension
which the user had installed to override this built-in extension.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">See if we duplicate the title and author name of an extension already found in another domain</span> <span class="cwebmacronumber">5.2.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">other</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">other</span><span class="plain">, </span><span class="reserved">extension_census_datum</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">candidate_author_name</span><span class="plain">, </span><span class="identifier">other</span><span class="plain">-</span><span class="element">&gt;ecd_id.author_name</span><span class="plain">))</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="identifier">other</span><span class="plain">-</span><span class="element">&gt;ecd_id.title</span><span class="plain">))</span>
<span class="plain">&amp;&amp; ((</span><span class="identifier">other</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain">) || (</span><span class="identifier">cs</span><span class="plain">-</span><span class="element">&gt;origin</span><span class="plain"> == </span><span class="constant">ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA</span><span class="plain">))) {</span>
<span class="identifier">other</span><span class="plain">-</span><span class="element">&gt;overriding_a_built_in_extension</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">overridden_by_an_extension_already_found</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">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP5_2_6"></a><b>&#167;5.2.6. </b>Assuming the new extension was not overridden in this way, we come here.
Because we didn't check the version number text for validity, it might
through being invalid be longer than we expect: in case this is so, we
truncate it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Create a new census datum for this extension, which has passed all tests</span> <span class="cwebmacronumber">5.2.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">ecd</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">extension_census_datum</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::new</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), </span><span class="identifier">candidate_author_name</span><span class="plain">, </span><span class="identifier">candidate_title</span><span class="plain">, </span><span class="constant">INSTALLED_EIDBC</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::set_raw</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), </span><span class="identifier">raw_author_name</span><span class="plain">, </span><span class="identifier">raw_title</span><span class="plain">);</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;VM_requirement</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">requirement_text</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">version_text</span><span class="plain">) &gt; </span><span class="constant">MAX_VERSION_NUMBER_LENGTH</span><span class="plain">)</span>
<span class="identifier">Str::truncate</span><span class="plain">(</span><span class="identifier">version_text</span><span class="plain">, </span><span class="constant">MAX_VERSION_NUMBER_LENGTH</span><span class="plain">); </span> <span class="comment">truncate to maximum legal length</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;version_text</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">version_text</span><span class="plain">);</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;domain</span><span class="plain"> = </span><span class="identifier">current_extension_domain</span><span class="plain">;</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</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">cs</span><span class="plain">-</span><span class="element">&gt;origin</span><span class="plain"> == </span><span class="constant">ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA</span><span class="plain">) </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;project_specific</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">cs</span><span class="plain">-</span><span class="element">&gt;origin</span><span class="plain"> == </span><span class="constant">ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA</span><span class="plain">) </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;project_specific</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;overriding_a_built_in_extension</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;rubric</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">rubric_text</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5_2">&#167;5.2</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Census errors. </b>To recap, the extension census process involves looking for all the
extensions Inform can find, but also checking them: are the files genuine, that
is, do they appear to be suitable text files with the correct identifying
first lines? Or have binary files crept in, or genuine extension but which
have been given the wrong location or filename? When any of these checks
fails, a census error is generated: there are about a dozen different
kinds.
</p>
<p class="inwebparagraph">These are dumped to a text stream during the census process. Once again, this
is not thread-safe: two simultaneous attempts by different Inform processes
to take a census might collide.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_census_errors</span><span class="plain"> = 0, </span><span class="identifier">recording_census_errors</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">CENERR</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::begin_recording_census_errors</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">no_census_errors</span><span class="plain"> = 0; </span><span class="identifier">recording_census_errors</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">CENERR</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::currently_recording_errors</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">recording_census_errors</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::end_recording_census_errors</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">recording_census_errors</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::begin_recording_census_errors is used in <a href="#SP3">&#167;3</a>.</p>
<p class="endnote">The function Extensions::Census::currently_recording_errors is used in 8/ef (<a href="8-ef.html#SP8_1">&#167;8.1</a>).</p>
<p class="endnote">The function Extensions::Census::end_recording_census_errors is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>When a census error arises, then, we write it as a line to the errors stream.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::census_error</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">auth</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">claimed_author</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">claimed_title</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = </span><span class="identifier">CENERR</span><span class="plain">;</span>
<span class="identifier">no_census_errors</span><span class="plain">++;</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 2, </span><span class="string">"hanging"</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">claimed_author</span><span class="plain">) &gt; 0)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;%S by %S&lt;/b&gt; - %s (the extension says it is '%S by %S')"</span><span class="plain">,</span>
<span class="identifier">title</span><span class="plain">, </span><span class="identifier">auth</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">, </span><span class="identifier">claimed_title</span><span class="plain">, </span><span class="identifier">claimed_author</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">auth</span><span class="plain">) &gt; 0) &amp;&amp; (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">title</span><span class="plain">) &gt; 0))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;%S by %S&lt;/b&gt; - %s"</span><span class="plain">, </span><span class="identifier">title</span><span class="plain">, </span><span class="identifier">auth</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;%S&lt;/b&gt; - %s"</span><span class="plain">, </span><span class="identifier">auth</span><span class="plain">, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::census_error is used in <a href="#SP5_1">&#167;5.1</a>, <a href="#SP5_2">&#167;5.2</a>, <a href="#SP5_2_1">&#167;5.2.1</a>, <a href="#SP5_2_2_1">&#167;5.2.2.1</a>, <a href="#SP5_2_3">&#167;5.2.3</a>, <a href="#SP5_2_3_2">&#167;5.2.3.2</a>, <a href="#SP5_2_4">&#167;5.2.4</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And this is where the inclusion of that material into the catalogue is
taken care of. First, we sometimes position a warning prominently at the
top of the listing, because otherwise its position at the bottom will be
invisible unless the user scrolls a long way:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::warn_about_census_errors</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_census_errors</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">no need for a warning</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">extension_census_datum</span><span class="plain">) &lt; 20) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">it's a short page anyway</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 src=inform:/doc_images/misinstalled.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span>
<span class="string">"&lt;b&gt;Warning&lt;/b&gt;. One or more extensions are installed incorrectly: "</span>
<span class="string">"see details below."</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::warn_about_census_errors is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::transcribe_census_errors</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_census_errors</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">nothing to include, then</span>
&lt;<span class="cwebmacro">Include the headnote explaining what census errors are</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">CENERR</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::transcribe_census_errors is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b>We only want to warn people here: not to stop them from using Inform
until they put matters right. (Suppose, for instance, they are using an
account not giving them sufficient privileges to modify files in the external
extensions area: they'd then be locked out if anything was amiss there.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Include the headnote explaining what census errors are</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"hr"</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">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 align=\</span><span class="plain">"</span><span class="string">left\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/census_problem.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;Warning&lt;/b&gt;. Inform checks the folder of user-installed extensions "</span>
<span class="string">"each time it translates the source text, in order to keep this directory "</span>
<span class="string">"page up to date. Each file must be a properly labelled extension (with "</span>
<span class="string">"its titling line correctly identifying itself), and must be in the right "</span>
<span class="string">"place - e.g. 'Marbles by Daphne Quilt' must have the filename 'Marbles.i7x' "</span>
<span class="string">"(or just 'Marbles' with no file extension) and be stored in the folder "</span>
<span class="string">"'Daphne Quilt'. The title should be at most %d characters long; the "</span>
<span class="string">"author name, %d. At the last check, these rules were not being followed:"</span><span class="plain">,</span>
<span class="constant">MAX_EXTENSION_TITLE_LENGTH</span><span class="plain">, </span><span class="constant">MAX_EXTENSION_AUTHOR_LENGTH</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="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Here we write the copy for the directory page of the extensions
documentation: the one which the user currently sees by clicking on the
"Installed Extensions" link from the contents page of the documentation.
It contains an alphabetised catalogue of extensions by author and then
title, along with some useful information about them, and then a list of
any oddities found in the external extensions area.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CE_BY_TITLE</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">CE_BY_AUTHOR</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">CE_BY_INSTALL</span><span class="plain"> 3</span>
<span class="definitionkeyword">define</span> <span class="constant">CE_BY_DATE</span><span class="plain"> 4</span>
<span class="definitionkeyword">define</span> <span class="constant">CE_BY_LENGTH</span><span class="plain"> 5</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Extensions::Census::write_results</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Display the location of installed extensions</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Extensions::Census::warn_about_census_errors</span><span class="plain">(</span><span class="identifier">OUT</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="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"hr"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Time stamp the extensions used on this run</span> <span class="cwebmacronumber">10.2</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">key_vms</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">key_override</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">key_builtin</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">,</span>
<span class="identifier">key_pspec</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">key_bullet</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Display the census radio buttons</span> <span class="cwebmacronumber">10.3</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_entries</span><span class="plain"> = </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">extension_census_datum</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> **</span><span class="identifier">sorted_census_results</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_census_datum</span><span class="plain"> *), </span><span class="constant">EXTENSION_DICTIONARY_MREASON</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="reserved">for</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain">=1; </span><span class="identifier">d</span><span class="plain">&lt;=5; </span><span class="identifier">d</span><span class="plain">++) {</span>
&lt;<span class="cwebmacro">Start an HTML division for this sorted version of the census</span> <span class="cwebmacronumber">10.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Sort the census into the appropriate order</span> <span class="cwebmacronumber">10.6</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Display the sorted version of the census</span> <span class="cwebmacronumber">10.7</span>&gt;<span class="plain">;</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">);</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Print the key to any symbols used in the census lines</span> <span class="cwebmacronumber">10.5</span>&gt;<span class="plain">;</span>
<span class="functiontext">Extensions::Census::transcribe_census_errors</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">Memory::I7_array_free</span><span class="plain">(</span><span class="identifier">sorted_census_results</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_census_datum</span><span class="plain"> *));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::write_results is used in 8/ef (<a href="8-ef.html#SP26">&#167;26</a>).</p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Display the location of installed extensions</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nps</span><span class="plain"> = 0, </span><span class="identifier">nbi</span><span class="plain"> = 0, </span><span class="identifier">ni</span><span class="plain"> = 0;</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">, </span><span class="reserved">extension_census_datum</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;project_specific</span><span class="plain">) </span><span class="identifier">nps</span><span class="plain">++;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain">) </span><span class="identifier">nbi</span><span class="plain">++;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">ni</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">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"src='inform:/doc_images/builtin_ext.png' border=0"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;You have "</span>
<span class="string">"%d extensions built-in to this copy of Inform, marked with a grey folder "</span>
<span class="string">"icon in the catalogue below."</span><span class="plain">,</span>
<span class="identifier">nbi</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_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ni</span><span class="plain"> == 0) {</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"src='inform:/doc_images/folder4.png' border=0"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;You have no other extensions installed at present."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">HTML::Javascript::open_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">EXTERNAL_FS_AREA</span><span class="plain">], </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="string">"src='inform:/doc_images/folder4.png' border=0"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;You have %d further extension%s installed. These are marked "</span>
<span class="string">"with a blue folder icon in the catalogue below. (Click it to see "</span>
<span class="string">"where the file is stored on your computer.) "</span>
<span class="string">"For more extensions, visit &lt;b&gt;www.inform7.com&lt;/b&gt;."</span><span class="plain">,</span>
<span class="identifier">ni</span><span class="plain">, (</span><span class="identifier">ni</span><span class="plain">==1)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">);</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="reserved">if</span><span class="plain"> (</span><span class="identifier">nps</span><span class="plain"> &gt; 0) {</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">HTML::Javascript::open_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">INTERNAL_FS_AREA</span><span class="plain">], </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">PROJECT_SPECIFIC_SYMBOL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;You have %d extension%s in the .materials folder for the "</span>
<span class="string">"current project. (Click the purple folder icon to show the "</span>
<span class="string">"location.) %s not available to other projects."</span><span class="plain">,</span>
<span class="identifier">nps</span><span class="plain">, (</span><span class="identifier">nps</span><span class="plain">==1)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">, (</span><span class="identifier">nps</span><span class="plain">==1)?</span><span class="string">"This is"</span><span class="plain">:</span><span class="string">"These are"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_2"></a><b>&#167;10.2. </b>This simply ensures that dates used are updated to today's date for
extensions used in the current run; otherwise they wouldn't show in the
documentation as used today until the next run, for obscure timing reasons.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Time stamp the extensions used on this run</span> <span class="cwebmacronumber">10.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">ef</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">, </span><span class="reserved">extension_file</span><span class="plain">)</span>
<span class="functiontext">Extensions::Dictionary::time_stamp</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_3"></a><b>&#167;10.3. </b>I am the first to admit that this implementation is not inspired. There
are five radio buttons, and number 2 is selected by default.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Display the census radio buttons</span> <span class="cwebmacronumber">10.3</span>&gt; =
</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">"Sort catalogue: "</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">,</span>
<span class="string">"href=\</span><span class="plain">"</span><span class="string">#\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"onclick=\</span><span class="plain">"</span><span class="string">openExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "</span>
<span class="string">"closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "</span>
<span class="string">"closeExtra('disp5', 'plus5'); return false;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 id=\</span><span class="plain">"</span><span class="string">plus1\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/extrarboff.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;By title"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" | "</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">,</span>
<span class="string">"href=\</span><span class="plain">"</span><span class="string">#\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"onclick=\</span><span class="plain">"</span><span class="string">closeExtra('disp1', 'plus1'); openExtra('disp2', 'plus2'); "</span>
<span class="string">"closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "</span>
<span class="string">"closeExtra('disp5', 'plus5'); return false;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 id=\</span><span class="plain">"</span><span class="string">plus2\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/extrarbon.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;By author"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" | "</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">,</span>
<span class="string">"href=\</span><span class="plain">"</span><span class="string">#\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"onclick=\</span><span class="plain">"</span><span class="string">closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "</span>
<span class="string">"openExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "</span>
<span class="string">"closeExtra('disp5', 'plus5'); return false;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 id=\</span><span class="plain">"</span><span class="string">plus3\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/extrarboff.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;By installation"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" | "</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">,</span>
<span class="string">"href=\</span><span class="plain">"</span><span class="string">#\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"onclick=\</span><span class="plain">"</span><span class="string">closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "</span>
<span class="string">"closeExtra('disp3', 'plus3'); openExtra('disp4', 'plus4'); "</span>
<span class="string">"closeExtra('disp5', 'plus5'); return false;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 id=\</span><span class="plain">"</span><span class="string">plus4\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/extrarboff.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;By date used"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" | "</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">,</span>
<span class="string">"href=\</span><span class="plain">"</span><span class="string">#\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">text-decoration: none\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"onclick=\</span><span class="plain">"</span><span class="string">closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "</span>
<span class="string">"closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "</span>
<span class="string">"openExtra('disp5', 'plus5'); return false;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 id=\</span><span class="plain">"</span><span class="string">plus5\</span><span class="plain">"</span><span class="string"> src=inform:/doc_images/extrarboff.png"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;By word count"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="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="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_4"></a><b>&#167;10.4. </b>Consequently, of the five divisions, number 2 is shown and the others
hidden, by default.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Start an HTML division for this sorted version of the census</span> <span class="cwebmacronumber">10.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">display</span><span class="plain"> = </span><span class="string">"none"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_AUTHOR</span><span class="plain">) </span><span class="identifier">display</span><span class="plain"> = </span><span class="string">"block"</span><span class="plain">;</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"div"</span><span class="plain">, </span><span class="string">"id=\</span><span class="plain">"</span><span class="string">disp%d\</span><span class="plain">"</span><span class="string"> style=\</span><span class="plain">"</span><span class="string">display: %s;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">, </span><span class="identifier">display</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_5"></a><b>&#167;10.5. </b>The key at the foot only explicates those symbols actually used, and
doesn't explicate the "unindexed" symbol at all, since that's actually
just a blank image used for horizontal spacing to keep margins straight.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print the key to any symbols used in the census lines</span> <span class="cwebmacronumber">10.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">key_builtin</span><span class="plain">) || (</span><span class="identifier">key_override</span><span class="plain">) || (</span><span class="identifier">key_bullet</span><span class="plain">) || (</span><span class="identifier">key_vms</span><span class="plain">) || (</span><span class="identifier">key_pspec</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">"Key: "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">key_bullet</span><span class="plain">) {</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="constant">INDEXED_SYMBOL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" Used&amp;nbsp;"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">key_builtin</span><span class="plain">) {</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="constant">BUILT_IN_SYMBOL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" Built in&amp;nbsp;"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">key_pspec</span><span class="plain">) {</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="constant">PROJECT_SPECIFIC_SYMBOL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" Project specific&amp;nbsp;"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">key_override</span><span class="plain">) {</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="constant">OVERRIDING_SYMBOL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" Your version overrides the one built in&amp;nbsp;"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">key_vms</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="functiontext">VirtualMachines::write_key</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_6"></a><b>&#167;10.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Sort the census into the appropriate order</span> <span class="cwebmacronumber">10.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0;</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">, </span><span class="reserved">extension_census_datum</span><span class="plain">)</span>
<span class="identifier">sorted_census_results</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">ecd</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> (*</span><span class="identifier">criterion</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="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *) = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_TITLE</span><span class="plain">: </span><span class="identifier">criterion</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::compare_ecd_by_title</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_AUTHOR</span><span class="plain">: </span><span class="identifier">criterion</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::compare_ecd_by_author</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_INSTALL</span><span class="plain">: </span><span class="identifier">criterion</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::compare_ecd_by_installation</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_DATE</span><span class="plain">: </span><span class="identifier">criterion</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::compare_ecd_by_date</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_LENGTH</span><span class="plain">: </span><span class="identifier">criterion</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::compare_ecd_by_length</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no such sorting criterion"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted_census_results</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_census_datum</span><span class="plain"> *),</span>
<span class="identifier">criterion</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_7"></a><b>&#167;10.7. </b>Standard rows have black text on striped background colours, these being
the usual ones seen in Mac OS X applications such as iTunes.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">FIRST_STRIPE_COLOUR</span><span class="plain"> </span><span class="string">"#ffffff"</span>
<span class="definitionkeyword">define</span> <span class="constant">SECOND_STRIPE_COLOUR</span><span class="plain"> </span><span class="string">"#f3f6fa"</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Display the sorted version of the census</span> <span class="cwebmacronumber">10.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">HTML::begin_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="constant">FIRST_STRIPE_COLOUR</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, 0, 0, 2, 0, 0);</span>
&lt;<span class="cwebmacro">Show a titling row explaining the census sorting, if necessary</span> <span class="cwebmacronumber">10.7.1</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">stripe</span><span class="plain"> = 0;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">current_author_name</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">current_installation</span><span class="plain"> = -1;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">no_entries</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain"> = </span><span class="identifier">sorted_census_results</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
&lt;<span class="cwebmacro">Insert a subtitling row in the census sorting, if necessary</span> <span class="cwebmacronumber">10.7.2</span>&gt;<span class="plain">;</span>
<span class="identifier">stripe</span><span class="plain"> = 1 - </span><span class="identifier">stripe</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stripe</span><span class="plain"> == 0)</span>
<span class="identifier">HTML::first_html_column_coloured</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0, </span><span class="constant">SECOND_STRIPE_COLOUR</span><span class="plain">, 0);</span>
<span class="reserved">else</span>
<span class="identifier">HTML::first_html_column_coloured</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0, </span><span class="constant">FIRST_STRIPE_COLOUR</span><span class="plain">, 0);</span>
&lt;<span class="cwebmacro">Print the census line for this extension</span> <span class="cwebmacronumber">10.7.4</span>&gt;<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="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">current_author_name</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Show a final titling row closing the census sorting</span> <span class="cwebmacronumber">10.7.3</span>&gt;<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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_1"></a><b>&#167;10.7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show a titling row explaining the census sorting, if necessary</span> <span class="cwebmacronumber">10.7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_TITLE</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Extensions in alphabetical order"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_DATE</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Extensions in order of date used (most recent first)"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CE_BY_LENGTH</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Extensions in order of word count (longest first)"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7">&#167;10.7</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_2"></a><b>&#167;10.7.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insert a subtitling row in the census sorting, if necessary</span> <span class="cwebmacronumber">10.7.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_AUTHOR</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::ne</span><span class="plain">(</span><span class="identifier">current_author_name</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.author_name</span><span class="plain">))) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">current_author_name</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.author_name</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Print the author's line in the extension census table</span> <span class="cwebmacronumber">10.7.2.1</span>&gt;<span class="character">;</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">stripe</span><span class="plain"> = 0;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_INSTALL</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Extensions::Census::installation_region</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">) != </span><span class="identifier">current_installation</span><span class="plain">)) {</span>
<span class="identifier">current_installation</span><span class="plain"> = </span><span class="functiontext">Extensions::Census::installation_region</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Print the installation region in the extension census table</span> <span class="cwebmacronumber">10.7.2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">stripe</span><span class="plain"> = 0;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7">&#167;10.7</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_3"></a><b>&#167;10.7.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show a final titling row closing the census sorting</span> <span class="cwebmacronumber">10.7.3</span>&gt; =
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt;<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="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d extensions installed"</span><span class="plain">, </span><span class="identifier">no_entries</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7">&#167;10.7</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_1_1"></a><b>&#167;10.7.1.1. </b>Black text on a grey background.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CENSUS_TITLING_BG</span><span class="plain"> </span><span class="string">"#808080"</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Begin a tinted census line</span> <span class="cwebmacronumber">10.7.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">span</span><span class="plain"> = 4;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_TITLE</span><span class="plain">) </span><span class="identifier">span</span><span class="plain"> = 3;</span>
<span class="identifier">HTML::first_html_column_coloured</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0, </span><span class="constant">CENSUS_TITLING_BG</span><span class="plain">, </span><span class="identifier">span</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">"ffffff"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_1">&#167;10.7.1</a> (three times), <a href="#SP10_7_2">&#167;10.7.2</a> (twice), <a href="#SP10_7_3">&#167;10.7.3</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_1_2"></a><b>&#167;10.7.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">End a tinted census line</span> <span class="cwebmacronumber">10.7.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_1">&#167;10.7.1</a> (three times), <a href="#SP10_7_2">&#167;10.7.2</a> (twice), <a href="#SP10_7_3">&#167;10.7.3</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_2_1"></a><b>&#167;10.7.2.1. </b>Used only in "by author".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print the author's line in the extension census table</span> <span class="cwebmacronumber">10.7.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_author_name</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd2</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cu</span><span class="plain"> = 0, </span><span class="identifier">cn</span><span class="plain"> = 0, </span><span class="identifier">j</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; </span><span class="identifier">j</span><span class="plain"> &lt; </span><span class="identifier">no_entries</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="identifier">ecd2</span><span class="plain"> = </span><span class="identifier">sorted_census_results</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::ne</span><span class="plain">(</span><span class="identifier">current_author_name</span><span class="plain">, </span><span class="identifier">ecd2</span><span class="plain">-</span><span class="element">&gt;ecd_id.author_name</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::Census::ecd_used</span><span class="plain">(</span><span class="identifier">ecd2</span><span class="plain">)) </span><span class="identifier">cu</span><span class="plain">++;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">cn</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;&amp;nbsp;"</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d extension%s"</span><span class="plain">, </span><span class="identifier">cu</span><span class="plain">+</span><span class="identifier">cn</span><span class="plain">, (</span><span class="identifier">cu</span><span class="plain">+</span><span class="identifier">cn</span><span class="plain">==1)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cu</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cn</span><span class="plain"> == 1)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", unused"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cu</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cn</span><span class="plain"> == 2)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", both unused"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cu</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cn</span><span class="plain"> &gt; 2)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", all unused"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cn</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cu</span><span class="plain"> == 1)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", used"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cn</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cu</span><span class="plain"> == 2)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", both used"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cn</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">cu</span><span class="plain"> &gt; 2)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", all used"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cn</span><span class="plain">+</span><span class="identifier">cu</span><span class="plain"> &gt; 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", %d used, %d unused"</span><span class="plain">, </span><span class="identifier">cu</span><span class="plain">, </span><span class="identifier">cn</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_2">&#167;10.7.2</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_2_2"></a><b>&#167;10.7.2.2. </b>Used only in "by installation".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print the installation region in the extension census table</span> <span class="cwebmacronumber">10.7.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">current_installation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> 0:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Supplied in the .materials folder&amp;nbsp;&amp;nbsp;"</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"%p"</span><span class="plain">, </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">INTERNAL_FS_AREA</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="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Built in to Inform"</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">WRITE</span><span class="plain">(</span><span class="string">"User installed but overriding a built-in extension"</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">WRITE</span><span class="plain">(</span><span class="string">"User installed&amp;nbsp;&amp;nbsp;"</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"%p"</span><span class="plain">, </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">EXTERNAL_FS_AREA</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="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_2">&#167;10.7.2</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4"></a><b>&#167;10.7.4. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">UNINDEXED_SYMBOL</span><span class="plain"> </span><span class="string">"border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> src=\</span><span class="plain">"</span><span class="string">inform:/doc_images/unindexed_bullet.png\</span><span class="plain">"</span><span class="string">"</span>
<span class="definitionkeyword">define</span> <span class="constant">INDEXED_SYMBOL</span><span class="plain"> </span><span class="string">"border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> src=\</span><span class="plain">"</span><span class="string">inform:/doc_images/indexed_bullet.png\</span><span class="plain">"</span><span class="string">"</span>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print the census line for this extension</span> <span class="cwebmacronumber">10.7.4</span>&gt; =
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Print column 1 of the census line</span> <span class="cwebmacronumber">10.7.4.1</span>&gt;<span class="plain">;</span>
<span class="identifier">HTML::next_html_column_nw</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != </span><span class="constant">CE_BY_TITLE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Print column 2 of the census line</span> <span class="cwebmacronumber">10.7.4.2</span>&gt;<span class="plain">;</span>
<span class="identifier">HTML::next_html_column_nw</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Print column 3 of the census line</span> <span class="cwebmacronumber">10.7.4.3</span>&gt;<span class="plain">;</span>
<span class="identifier">HTML::next_html_column_w</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
&lt;<span class="cwebmacro">Print column 4 of the census line</span> <span class="cwebmacronumber">10.7.4.4</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7">&#167;10.7</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4_1"></a><b>&#167;10.7.4.1. </b>The appearance of the line is
</p>
<blockquote>
<p>(bullet) The Title (by The Author) (VM requirement icons)</p>
</blockquote>
<p class="inwebparagraph">where all is optional except the title part.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print column 1 of the census line</span> <span class="cwebmacronumber">10.7.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">bulletornot</span><span class="plain"> = </span><span class="constant">UNINDEXED_SYMBOL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::Census::ecd_used</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">)) { </span><span class="identifier">bulletornot</span><span class="plain"> = </span><span class="constant">INDEXED_SYMBOL</span><span class="plain">; </span><span class="identifier">key_bullet</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; }</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">bulletornot</span><span class="plain">);</span>
<span class="functiontext">Extensions::IDs::begin_extension_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, &amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;rubric</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != </span><span class="constant">CE_BY_AUTHOR</span><span class="plain">) {</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"404040"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_title</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">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_title</span><span class="plain">) + </span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_author_name</span><span class="plain">) &gt; 45) {</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"by %S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_author_name</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="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"404040"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_title</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="plain">}</span>
<span class="functiontext">Extensions::IDs::end_extension_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, &amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;VM_requirement</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Append icons which signify the VM requirements of the extension</span> <span class="cwebmacronumber">10.7.4.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">key_vms</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">This code is used in <a href="#SP10_7_4">&#167;10.7.4</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4_1_1"></a><b>&#167;10.7.4.1.1. </b>VM requirements are parsed by feeding them into the lexer and calling the
same routines as would be used when parsing headings about VM requirements
in a normal run of Inform. Note that because the requirements are in round
brackets, which the lexer will split off as distinct words, we can ignore
the first and last word and just look at what is in between:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Append icons which signify the VM requirements of the extension</span> <span class="cwebmacronumber">10.7.4.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;VM_requirement</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">);</span>
<span class="functiontext">VirtualMachines::write_icons</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_4_1">&#167;10.7.4.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4_2"></a><b>&#167;10.7.4.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Print column 2 of the census line</span> <span class="cwebmacronumber">10.7.4.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<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="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;version_text</span><span class="plain">) &gt; 0)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"v&amp;nbsp;%S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;version_text</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"--"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_4">&#167;10.7.4</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4_3"></a><b>&#167;10.7.4.3. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BUILT_IN_SYMBOL</span><span class="plain"> </span><span class="string">"border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> src=\</span><span class="plain">"</span><span class="string">inform:/doc_images/builtin_ext.png\</span><span class="plain">"</span><span class="string">"</span>
<span class="definitionkeyword">define</span> <span class="constant">OVERRIDING_SYMBOL</span><span class="plain"> </span><span class="string">"border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> src=\</span><span class="plain">"</span><span class="string">inform:/doc_images/override_ext.png\</span><span class="plain">"</span><span class="string">"</span>
<span class="definitionkeyword">define</span> <span class="constant">PROJECT_SPECIFIC_SYMBOL</span><span class="plain"> </span><span class="string">"border=\</span><span class="plain">"</span><span class="string">0\</span><span class="plain">"</span><span class="string"> src=\</span><span class="plain">"</span><span class="string">inform:/doc_images/pspec_ext.png\</span><span class="plain">"</span><span class="string">"</span>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Print column 3 of the census line</span> <span class="cwebmacronumber">10.7.4.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">opener</span><span class="plain"> = </span><span class="string">"src='inform:/doc_images/folder4.png' border=0"</span><span class="plain">;</span>
<span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">area</span><span class="plain"> = </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">EXTERNAL_FS_AREA</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain">) { </span><span class="identifier">opener</span><span class="plain"> = </span><span class="constant">BUILT_IN_SYMBOL</span><span class="plain">; </span><span class="identifier">key_builtin</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;overriding_a_built_in_extension</span><span class="plain">) {</span>
<span class="identifier">opener</span><span class="plain"> = </span><span class="constant">OVERRIDING_SYMBOL</span><span class="plain">; </span><span class="identifier">key_override</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;project_specific</span><span class="plain">) {</span>
<span class="identifier">opener</span><span class="plain"> = </span><span class="constant">PROJECT_SPECIFIC_SYMBOL</span><span class="plain">; </span><span class="identifier">key_pspec</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">area</span><span class="plain"> = </span><span class="identifier">pathname_of_extensions</span><span class="plain">[</span><span class="constant">MATERIALS_FS_AREA</span><span class="plain">];</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain">) </span><span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">opener</span><span class="plain">)</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">HTML::Javascript::open_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">area</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id.raw_author_name</span><span class="plain">, </span><span class="identifier">opener</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_4">&#167;10.7.4</a>.</p>
<p class="inwebparagraph"><a id="SP10_7_4_4"></a><b>&#167;10.7.4.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Print column 4 of the census line</span> <span class="cwebmacronumber">10.7.4.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<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="reserved">if</span><span class="plain"> ((</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_DATE</span><span class="plain">) || (</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_INSTALL</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="functiontext">Extensions::IDs::get_usage_date</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">)));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CE_BY_LENGTH</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::forgot</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"I did read this, but forgot"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::never</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"I've never read this"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d words"</span><span class="plain">, </span><span class="functiontext">Extensions::IDs::get_word_count</span><span class="plain">(&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">)));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;rubric</span><span class="plain">) &gt; 0)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;rubric</span><span class="plain">);</span>
<span class="reserved">else</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_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_7_4">&#167;10.7.4</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Two useful measurements:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::installation_region</span><span class="plain">(</span><span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;project_specific</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;built_in</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;overriding_a_built_in_extension</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 2;</span>
<span class="reserved">return</span><span class="plain"> 3;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::ecd_used</span><span class="plain">(</span><span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">ecd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Extensions::IDs::no_times_used_in_context</span><span class="plain">(</span>
<span class="plain">&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), </span><span class="constant">LOADED_EIDBC</span><span class="plain">) &gt; 0) ||</span>
<span class="plain">(</span><span class="functiontext">Extensions::IDs::no_times_used_in_context</span><span class="plain">(</span>
<span class="plain">&amp;(</span><span class="identifier">ecd</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), </span><span class="constant">DICTIONARY_REFERRED_EIDBC</span><span class="plain">) &gt; 0))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::installation_region is used in <a href="#SP10_7_2">&#167;10.7.2</a>, <a href="#SP12">&#167;12</a>.</p>
<p class="endnote">The function Extensions::Census::ecd_used is used in <a href="#SP10_7_2_1">&#167;10.7.2.1</a>, <a href="#SP10_7_4_1">&#167;10.7.4.1</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>The following give the sorting criteria:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::compare_ecd_by_title</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">ecd1</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">ecd2</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e1</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd1</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e2</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd2</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_title</span><span class="plain">(&amp;(</span><span class="identifier">e1</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), &amp;(</span><span class="identifier">e2</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::compare_ecd_by_author</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">ecd1</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">ecd2</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e1</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd1</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e2</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd2</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare</span><span class="plain">(&amp;(</span><span class="identifier">e1</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), &amp;(</span><span class="identifier">e2</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::compare_ecd_by_installation</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">ecd1</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">ecd2</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e1</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd1</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e2</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd2</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">Extensions::Census::installation_region</span><span class="plain">(</span><span class="identifier">e1</span><span class="plain">) - </span><span class="functiontext">Extensions::Census::installation_region</span><span class="plain">(</span><span class="identifier">e2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_title</span><span class="plain">(&amp;(</span><span class="identifier">e1</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), &amp;(</span><span class="identifier">e2</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::compare_ecd_by_date</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">ecd1</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">ecd2</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e1</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd1</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e2</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd2</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_date</span><span class="plain">(&amp;(</span><span class="identifier">e1</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), &amp;(</span><span class="identifier">e2</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Extensions::Census::compare_ecd_by_length</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">ecd1</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">ecd2</span><span class="plain">) {</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e1</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd1</span><span class="plain">);</span>
<span class="reserved">extension_census_datum</span><span class="plain"> *</span><span class="identifier">e2</span><span class="plain"> = *((</span><span class="reserved">extension_census_datum</span><span class="plain"> **) </span><span class="identifier">ecd2</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Extensions::IDs::compare_by_length</span><span class="plain">(&amp;(</span><span class="identifier">e1</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">), &amp;(</span><span class="identifier">e2</span><span class="plain">-</span><span class="element">&gt;ecd_id</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Extensions::Census::compare_ecd_by_title is used in <a href="#SP10_6">&#167;10.6</a>.</p>
<p class="endnote">The function Extensions::Census::compare_ecd_by_author is used in <a href="#SP10_6">&#167;10.6</a>.</p>
<p class="endnote">The function Extensions::Census::compare_ecd_by_installation is used in <a href="#SP10_6">&#167;10.6</a>.</p>
<p class="endnote">The function Extensions::Census::compare_ecd_by_date is used in <a href="#SP10_6">&#167;10.6</a>.</p>
<p class="endnote">The function Extensions::Census::compare_ecd_by_length is used in <a href="#SP10_6">&#167;10.6</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="8-ei.html">Back to 'Extension Identifiers'</a></li><li><a href="8-ed.html">Continue with 'Extension Dictionary'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>