inweb-bootstrap/docs/foundation-module/3-cf.html
2020-04-20 23:34:44 +01:00

340 lines
53 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Case-Insensitive Filenames</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Octagram.png" width=72 height=72">
</a></h1>
<ul><li><a href="../inweb/index.html">inweb</a></li>
</ul><h2>Foundation Module</h2><ul>
<li><a href="index.html"><span class="selectedlink">foundation</span></a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul><h2>Example Webs</h2><ul>
<li><a href="../goldbach/index.html">goldbach</a></li>
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
<li><a href="../eastertide/index.html">eastertide</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inform/docs/index.html">inform</a></li>
<li><a href="../../../intest/docs/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Case-Insensitive Filenames' generated by Inweb-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#3">Chapter 3: The Operating System</a></li><li><b>Case-Insensitive Filenames</b></li></ul><p class="purpose">On some of the Unix-derived file systems on which Inform runs, filenames are case-sensitive, so that FISH and fish might be different files. This makes extension files, installed by the user, prone to being missed. The code in this section provides a routine to carry out file opening as if filenames are case-insensitive, and is used only for extensions.</p>
<ul class="toc"><li><a href="3-cf.html#SP3">&#167;3. The routine</a></li><li><a href="3-cf.html#SP3_1">&#167;3.1. Looking for case-insensitive matches instead</a></li><li><a href="3-cf.html#SP3_3">&#167;3.3. Allocation and deallocation</a></li><li><a href="3-cf.html#SP3_6">&#167;3.6. Pathname hacking</a></li><li><a href="3-cf.html#SP4">&#167;4. Counting matches</a></li><li><a href="3-cf.html#SP5">&#167;5. Non-POSIX tail</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>This section contains a single utility routine, contributed by Adam
Thornton: a specialised, case-insensitive form of <code class="display"><span class="extract-syntax">fopen()</span></code>. It is specialised
in that it is designed for opening extensions, where the file path will be
case-correct up to the last two components of the path (the leafname and the
immediately containing directory), but where the casing may be wrong in those
last two components.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>If the exact filename or extension directory (case-correct) exists,
<code class="display"><span class="extract-syntax">CIFilingSystem::fopen()</span></code> will choose it to open. If not, it will
use <code class="display"><span class="extract-syntax">strcasecmp()</span></code> to find a file or directory with the same name but
differing in case and use it instead. If it finds exactly one candidate file,
it will then attempt to <code class="display"><span class="extract-syntax">fopen()</span></code> it and return the result.
</p>
<p class="inwebparagraph">If <code class="display"><span class="extract-syntax">CIFilingSystem::fopen()</span></code> succeeds, it returns a <code class="display"><span class="extract-syntax">FILE *</span></code>
(passed back to it from the underlying <code class="display"><span class="extract-syntax">fopen()</span></code>). If
<code class="display"><span class="extract-syntax">CIFilingSystem::fopen()</span></code> fails, it returns <code class="display"><span class="extract-syntax">NULL</span></code>, and
<code class="display"><span class="extract-syntax">errno</span></code> is set accordingly:
</p>
<ul class="items"><li>(a) If no suitable file was found, <code class="display"><span class="extract-syntax">errno</span></code> is set to <code class="display"><span class="extract-syntax">ENOENT</span></code>.
</li><li>(b) If more than one possibility was found, but none of them exactly match
the supplied case, <code class="display"><span class="extract-syntax">errno</span></code> is set to <code class="display"><span class="extract-syntax">EBADF</span></code>.
</li><li>(c) Note that if multiple directories which match case-insensitively are
found, but none is an exact match, <code class="display"><span class="extract-syntax">EBADF</span></code> will be set regardless of the
contents of the directories.
</li><li>(d) If <code class="display"><span class="extract-syntax">CIFilingSystem::fopen()</span></code> fails during its allocation of
space to hold its intermediate strings for comparison, or for its various
data structures, <code class="display"><span class="extract-syntax">errno</span></code> is set to <code class="display"><span class="extract-syntax">ENOMEM</span></code>.
</li><li>(e) If an unambiguous filename is found but the <code class="display"><span class="extract-syntax">fopen()</span></code> fails, <code class="display"><span class="extract-syntax">errno</span></code> is
left at whatever value the underlying <code class="display"><span class="extract-syntax">fopen()</span></code> set it to.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. The routine. </b>The routine is available only on POSIX platforms where <code class="display"><span class="extract-syntax">PLATFORM_POSIX</span></code>
is defined (see "Platform-Specific Definitions"). In practice this means
everywhere except Windows, but all Windows file systems are case-preserving
and case-insensitive in any case.
</p>
<p class="inwebparagraph">Briefly, we try to get the extension directory name right first, by looking
for the given casing, then if that fails, for a unique alternative with
different casing; and then repeat within that directory for the extension
file itself.
</p>
<pre class="display">
<span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><a href="3-cf.html#SP5" class="internal">CIFilingSystem::fopen</a><span class="plain-syntax">(</span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">cistring</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">ciextname</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">workstring</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DIR</span><span class="plain-syntax"> *</span><span class="identifier-syntax">topdir</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">extdir</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">handle</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">size_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">length</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment"> for efficiency's sake, though it's logically equivalent, we try...</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">handle</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fopen</span><span class="plain-syntax">(</span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="identifier-syntax">mode</span><span class="plain-syntax">); </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">handle</span><span class="plain-syntax">) </span>&lt;<span class="named-paragraph">Happy ending to ci-fopen</span> <span class="named-paragraph-number">3.4</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Find the length of the path, giving an error if it is empty or NULL</span> <span class="named-paragraph-number">3.6</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Allocate memory for strings large enough to hold any subpath of the path</span> <span class="named-paragraph-number">3.3</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Parse the path to break it into topdir path, extension directory and leafname</span> <span class="named-paragraph-number">3.7</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">topdir</span><span class="plain-syntax"> = </span><span class="identifier-syntax">opendir</span><span class="plain-syntax">(</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">); </span><span class="comment"> whose pathname is assumed case-correct...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">topdir</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="comment"> ...so that failure is fatal; </span><code class="display"><span class="extract-syntax">errno</span></code><span class="comment"> is set by </span><code class="display"><span class="extract-syntax">opendir</span></code>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; </span><span class="comment"> ...so that failure is fatal; </span><code class="display"><span class="extract-syntax">errno</span></code><span class="comment"> is set by </span><code class="display"><span class="extract-syntax">opendir</span></code>
<span class="plain-syntax"> </span><span class="identifier-syntax">sprintf</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">, </span><span class="string-syntax">"%s%c%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">, </span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">extdir</span><span class="plain-syntax"> = </span><span class="identifier-syntax">opendir</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">); </span><span class="comment"> try with supplied extension directory name</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">extdir</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span>&lt;<span class="named-paragraph">Try to find a unique insensitively matching directory name in topdir</span> <span class="named-paragraph-number">3.1</span>&gt;
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">strcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">cistring</span><span class="plain-syntax">, </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sprintf</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">, </span><span class="string-syntax">"%s%c%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">cistring</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">, </span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">handle</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fopen</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">, </span><span class="identifier-syntax">mode</span><span class="plain-syntax">); </span><span class="comment"> try with supplied name</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">handle</span><span class="plain-syntax">) </span>&lt;<span class="named-paragraph">Happy ending to ci-fopen</span> <span class="named-paragraph-number">3.4</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Try to find a unique insensitively matching entry in extdir</span> <span class="named-paragraph-number">3.2</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This paragraph is used only if PLATFORM_POSIX is defined.</li><li>The function CIFilingSystem::fopen is used in <a href="3-cf.html#SP5">&#167;5</a>, Filenames (<a href="3-fln.html#SP10">&#167;10</a>).</li></ul><p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. Looking for case-insensitive matches instead. </b>We emerge from the following only in the happy case where a unique matching
directory name can be found.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Try to find a unique insensitively matching directory name in topdir</span> <span class="named-paragraph-number">3.1</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> = </span><a href="3-cf.html#SP4" class="internal">CIFilingSystem::match_in_directory</a><span class="plain-syntax">(</span><span class="identifier-syntax">topdir</span><span class="plain-syntax">, </span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">, </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">rc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOENT</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sprintf</span><span class="plain-syntax">(</span><span class="identifier-syntax">cistring</span><span class="plain-syntax">, </span><span class="string-syntax">"%s%c%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">, </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">extdir</span><span class="plain-syntax"> = </span><span class="identifier-syntax">opendir</span><span class="plain-syntax">(</span><span class="identifier-syntax">cistring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">extdir</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOENT</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EBADF</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>.</li></ul><p class="inwebparagraph"><a id="SP3_2"></a><b>&#167;3.2. </b>More or less the same, but we never emerge at all: all cases of the switch
return from the function.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Try to find a unique insensitively matching entry in extdir</span> <span class="named-paragraph-number">3.2</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> = </span><a href="3-cf.html#SP4" class="internal">CIFilingSystem::match_in_directory</a><span class="plain-syntax">(</span><span class="identifier-syntax">extdir</span><span class="plain-syntax">, </span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">, </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">rc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOENT</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sprintf</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax">, </span><span class="string-syntax">"%s%c%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">cistring</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">, </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">workstring2</span><span class="plain-syntax">[</span><span class="identifier-syntax">length</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">handle</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fopen</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax">, </span><span class="identifier-syntax">mode</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">handle</span><span class="plain-syntax">) </span>&lt;<span class="named-paragraph">Happy ending to ci-fopen</span> <span class="named-paragraph-number">3.4</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOENT</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EBADF</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>.</li></ul><p class="inwebparagraph"><a id="SP3_3"></a><b>&#167;3.3. Allocation and deallocation. </b>We use six strings to hold full or partial pathnames.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Allocate memory for strings large enough to hold any subpath of the path</span> <span class="named-paragraph-number">3.3</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="identifier-syntax">workstring</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">workstring</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">workstring2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cistring</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cistring</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ciextname</span><span class="plain-syntax"> = </span><span class="identifier-syntax">calloc</span><span class="plain-syntax">(</span><span class="identifier-syntax">length</span><span class="plain-syntax">+1, </span><span class="reserved-syntax">sizeof</span><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ciextname</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOMEM</span><span class="plain-syntax">; </span>&lt;<span class="named-paragraph">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt;<span class="plain-syntax">; }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>.</li></ul><p class="inwebparagraph"><a id="SP3_4"></a><b>&#167;3.4. </b>If we are successful, we return a valid file handle...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Happy ending to ci-fopen</span> <span class="named-paragraph-number">3.4</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Prepare to exit ci-fopen cleanly</span> <span class="named-paragraph-number">3.4.1</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">handle</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a> (twice), <a href="3-cf.html#SP3_2">&#167;3.2</a>.</li></ul><p class="inwebparagraph"><a id="SP3_5"></a><b>&#167;3.5. </b>...and otherwise <code class="display"><span class="extract-syntax">NULL</span></code>, having already set <code class="display"><span class="extract-syntax">errno</span></code> with the reason why.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Sad ending to ci-fopen</span> <span class="named-paragraph-number">3.5</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span>&lt;<span class="named-paragraph">Prepare to exit ci-fopen cleanly</span> <span class="named-paragraph-number">3.4.1</span>&gt;<span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>, <a href="3-cf.html#SP3_1">&#167;3.1</a> (three times), <a href="3-cf.html#SP3_2">&#167;3.2</a> (three times), <a href="3-cf.html#SP3_3">&#167;3.3</a> (6 times).</li></ul><p class="inwebparagraph"><a id="SP3_4_1"></a><b>&#167;3.4.1. </b><code class="display">
&lt;<span class="named-paragraph-defn">Prepare to exit ci-fopen cleanly</span> <span class="named-paragraph-number">3.4.1</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cistring</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">cistring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">) </span><span class="identifier-syntax">free</span><span class="plain-syntax">(</span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">topdir</span><span class="plain-syntax">) </span><span class="identifier-syntax">closedir</span><span class="plain-syntax">(</span><span class="identifier-syntax">topdir</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">extdir</span><span class="plain-syntax">) </span><span class="identifier-syntax">closedir</span><span class="plain-syntax">(</span><span class="identifier-syntax">extdir</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3_4">&#167;3.4</a>, <a href="3-cf.html#SP3_5">&#167;3.5</a>.</li></ul><p class="inwebparagraph"><a id="SP3_6"></a><b>&#167;3.6. Pathname hacking. </b><code class="display">
&lt;<span class="named-paragraph-defn">Find the length of the path, giving an error if it is empty or NULL</span> <span class="named-paragraph-number">3.6</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="identifier-syntax">length</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">path</span><span class="plain-syntax">) </span><span class="identifier-syntax">length</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">size_t</span><span class="plain-syntax">) </span><span class="identifier-syntax">strlen</span><span class="plain-syntax">(</span><span class="identifier-syntax">path</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">length</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) { </span><span class="identifier-syntax">errno</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ENOENT</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>.</li></ul><p class="inwebparagraph"><a id="SP3_7"></a><b>&#167;3.7. </b>And here we break up a pathname like
</p>
<pre class="display">
<span class="plain-syntax"> /Users/bobama/Library/Inform/Extensions/Hillary Clinton/Health Care.i7x</span>
</pre>
<p class="inwebparagraph">into three components:
</p>
</li><li>(a) <code class="display"><span class="extract-syntax">topdirpath</span></code> is <code class="display"><span class="extract-syntax">/Users/bobama/Library/Inform/Extensions</span></code>, and its casing is correct.
</li><li>(b) <code class="display"><span class="extract-syntax">ciextdirpath</span></code> is <code class="display"><span class="extract-syntax">Hillary Clinton</span></code>, but its casing may not be correct.
</li><li>(c) <code class="display"><span class="extract-syntax">ciextname</span></code> is <code class="display"><span class="extract-syntax">Health Care.i7x</span></code>, but its casing may not be correct.
</li></ul>
<p class="inwebparagraph">The contents of <code class="display"><span class="extract-syntax">workstring</span></code> are not significant afterwards.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="named-paragraph-defn">Parse the path to break it into topdir path, extension directory and leafname</span> <span class="named-paragraph-number">3.7</span>&gt; =
</code></p>
<pre class="display">
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">size_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">extindex</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">namelen</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">dirlen</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">strrchr</span><span class="plain-syntax">(</span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">extindex</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">size_t</span><span class="plain-syntax">) (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> - </span><span class="identifier-syntax">path</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">namelen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">length</span><span class="plain-syntax"> - </span><span class="identifier-syntax">extindex</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">strncpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">, </span><span class="identifier-syntax">path</span><span class="plain-syntax"> + </span><span class="identifier-syntax">extindex</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="identifier-syntax">namelen</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ciextname</span><span class="plain-syntax">[</span><span class="identifier-syntax">namelen</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">strncpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">, </span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="identifier-syntax">extindex</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">[</span><span class="identifier-syntax">extindex</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">strrchr</span><span class="plain-syntax">(</span><span class="identifier-syntax">workstring</span><span class="plain-syntax">, </span><span class="constant-syntax">FOLDER_SEPARATOR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">size_t</span><span class="plain-syntax">) (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> - </span><span class="identifier-syntax">workstring</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">strncpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">, </span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">topdirpath</span><span class="plain-syntax">[</span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">dirlen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">extindex</span><span class="plain-syntax"> - </span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">dirlen</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">dirlen</span><span class="plain-syntax"> -= </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">strncpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">, </span><span class="identifier-syntax">path</span><span class="plain-syntax"> + </span><span class="identifier-syntax">extdirindex</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="identifier-syntax">dirlen</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ciextdirpath</span><span class="plain-syntax">[</span><span class="identifier-syntax">dirlen</span><span class="plain-syntax">] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cf.html#SP3">&#167;3</a>.</li></ul><p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Counting matches. </b>We count the number of names within the directory which case-insensitively
match against <code class="display"><span class="extract-syntax">name</span></code>, and copy the last which matches into <code class="display"><span class="extract-syntax">last_match</span></code>.
This must be at least as long as <code class="display"><span class="extract-syntax">name</span></code>. (We ought to be just a little careful
in case of improbable cases where the matched name contains a different
number of characters from <code class="display"><span class="extract-syntax">name</span></code>, for instance because on a strict reading
of Unicode "SS" is casing-equivalent to the eszet, but it's unlikely
that many contemporary implementations of <code class="display"><span class="extract-syntax">strcasecmp</span></code> are aware of this,
and in any case the code above contains much larger buffers than needed.)
</p>
<pre class="display">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">CIFilingSystem::match_in_directory</span><button class="popup" onclick="togglePopup('usagePopup1')">...<span class="popuptext" id="usagePopup1">Usage of <b>CIFilingSystem::match_in_directory</b>:<br><a href="3-cf.html#SP3_1">&#167;3.1</a>, <a href="3-cf.html#SP3_2">&#167;3.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vd</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last_match</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DIR</span><span class="plain-syntax"> *</span><span class="identifier-syntax">d</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">DIR</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vd</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">dirent</span><span class="plain-syntax"> *</span><span class="identifier-syntax">dirp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">last_match</span><span class="plain-syntax">[0] = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">dirp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">readdir</span><span class="plain-syntax">(</span><span class="identifier-syntax">d</span><span class="plain-syntax">)) != </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">strcasecmp</span><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">dirp</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">d_name</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">strcpy</span><span class="plain-syntax">(</span><span class="identifier-syntax">last_match</span><span class="plain-syntax">, </span><span class="identifier-syntax">dirp</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">d_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Non-POSIX tail. </b>On platforms without POSIX directory handling, we revert to regular <code class="display"><span class="extract-syntax">fopen</span></code>.
</p>
<pre class="display">
<span class="reserved-syntax">FILE</span><span class="plain-syntax"> *</span><span class="function-syntax">CIFilingSystem::fopen</span><button class="popup" onclick="togglePopup('usagePopup2')">...<span class="popuptext" id="usagePopup2">Usage of <b>CIFilingSystem::fopen</b>:<br><a href="3-cf.html#SP3">&#167;3</a>, Filenames - <a href="3-fln.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="reserved-syntax">const</span><span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">fopen</span><span class="plain-syntax">(</span><span class="identifier-syntax">path</span><span class="plain-syntax">, </span><span class="identifier-syntax">mode</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This paragraph is used only if PLATFORM_POSIX is undefined.</li></ul><hr class="tocbar">
<ul class="toc"><li><a href="3-fln.html">Back to 'Filenames'</a></li><li><a href="3-shl.html">Continue with 'Shell'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>