inweb-bootstrap/docs/foundation-module/3-cla.html

463 lines
66 KiB
HTML
Raw Normal View History

2019-02-04 22:26:45 +00:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>3/em</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>
2019-02-09 12:33:40 +00:00
<!--Weave of '3/cla' generated by 7-->
2019-02-04 22:26:45 +00:00
<ul class="crumbs"><li><a href="../webs.html">&#9733;</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>Command Line Arguments</b></li></ul><p class="purpose">To parse the command line arguments with which inweb was called, and to handle any errors it needs to issue.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Model</a></li><li><a href="#SP2">&#167;2. Switches</a></li><li><a href="#SP6">&#167;6. Reading the command line</a></li><li><a href="#SP9">&#167;9. Help text</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Model. </b>Our scheme is that the command line syntax will contain an optional
series of dashed switches. Some switches appear alone, others must be
followed by an argument. Anything not part of the switches is termed
a "bareword". For example, in
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">-log no-memory-usage -fixtime jam marmalade</span>
</pre>
<p class="inwebparagraph">there are two switches, <code class="display"><span class="extract">-log</span></code> taking an argument (it has valency 2
in the terminology below), <code class="display"><span class="extract">-fixtime</span></code> not (valency 1). There are
then two barewords, <code class="display"><span class="extract">jam</span></code> and <code class="display"><span class="extract">marmalade</span></code>.
</p>
<p class="inwebparagraph">For an example of all this in action, see Inweb, or see the basic
command-line switches created by Foundation itself in "Foundation".
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Switches. </b>Each different switch available is stored in one of these structures.
Switches come in five sorts:
</p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">ACTION_CLSF</span><span class="definitionkeyword"> from </span><span class="constant">1</span> <span class="comment">does something</span>
<span class="definitionkeyword">enum</span> <span class="constant">BOOLEAN_ON_CLSF</span><span class="plain"> </span> <span class="comment">sets a flag true</span>
<span class="definitionkeyword">enum</span> <span class="constant">BOOLEAN_OFF_CLSF</span><span class="plain"> </span> <span class="comment">sets a flag false</span>
<span class="definitionkeyword">enum</span> <span class="constant">NUMERICAL_CLSF</span><span class="plain"> </span> <span class="comment">sets an integer to the given value</span>
<span class="definitionkeyword">enum</span> <span class="constant">TEXTUAL_CLSF</span><span class="plain"> </span> <span class="comment">sets text to the given value</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">switch_id</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">switch_name</span><span class="plain">; </span> <span class="comment">e.g., <code class="display"><span class="extract">log</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">help_text</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">valency</span><span class="plain">; </span> <span class="comment">1 for bare, 2 for one argument follows</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">form</span><span class="plain">; </span> <span class="comment">one of the <code class="display"><span class="extract">*_CLSF</span></code> values above</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">foundation_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">TRUE</span></code> for the ones built in to every tool</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">negates</span><span class="plain">; </span> <span class="comment">relevant only for booleans</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">command_line_switch</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure command_line_switch is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>In case of a prodigious number of switches (ever tried typing <code class="display"><span class="extract">clang -help</span></code>?),
we'll hash the switch names into the following:
</p>
<pre class="display">
<span class="reserved">dictionary</span><span class="plain"> *</span><span class="identifier">cls_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The client must declare all the switches her program will make use of, not
counting the standard set already declared by Foundation (such as <code class="display"><span class="extract">-help</span></code>).
A new <code class="display"><span class="extract">*_CLSW</span></code> value should be enumerated to be the ID referring to this
swtich, and then the client should call:
</p>
<pre class="display">
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">,</span>
<span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">name_literal</span><span class="plain">), </span><span class="identifier">val</span><span class="plain">,</span>
<span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">help_literal</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_switch_f</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span>
<span class="identifier">id</span><span class="plain">, </span><span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">name_literal</span><span class="plain">), </span><span class="identifier">val</span><span class="plain">,</span>
<span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">help_literal</span><span class="plain">));</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;foundation_switch</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls_dictionary</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">cls_dictionary</span><span class="plain"> = </span><span class="functiontext">Dictionaries::new</span><span class="plain">(16, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain">);</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_name</span><span class="plain"> = </span><span class="identifier">name</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_id</span><span class="plain"> = </span><span class="identifier">id</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;help_text</span><span class="plain"> = </span><span class="identifier">help_literal</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> = </span><span class="constant">ACTION_CLSF</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;negates</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;foundation_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="functiontext">Dictionaries::create</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_name</span><span class="plain">);</span>
<span class="functiontext">Dictionaries::write_value</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_name</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::declare_switch is used in <a href="#SP5">&#167;5</a>.</p>
<p class="endnote">The function CommandLine::declare_switch_f is used in 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
<p class="endnote">The function CommandLine::declare_switch_p is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Booleans are automatically created in pairs, e.g., <code class="display"><span class="extract">-destroy-world</span></code> and
<code class="display"><span class="extract">-no-destroy-world</span></code>:
</p>
<pre class="display">
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_boolean_switch_p</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">fnd</span><span class="plain">) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">neg</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">neg</span><span class="plain">, </span><span class="string">"no-%w"</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">neg_help</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">neg_help</span><span class="plain">, </span><span class="string">"don't %w"</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">negated</span><span class="plain"> =</span>
<span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">neg</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">neg_help</span><span class="plain">);</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> = </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">;</span>
<span class="identifier">negated</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> = </span><span class="constant">BOOLEAN_OFF_CLSF</span><span class="plain">;</span>
<span class="identifier">negated</span><span class="plain">-</span><span class="element">&gt;negates</span><span class="plain"> = </span><span class="identifier">cls</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;foundation_switch</span><span class="plain"> = </span><span class="identifier">fnd</span><span class="plain">;</span>
<span class="identifier">negated</span><span class="plain">-</span><span class="element">&gt;foundation_switch</span><span class="plain"> = </span><span class="identifier">fnd</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_boolean_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_boolean_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_boolean_switch_f</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_boolean_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_numerical_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> = </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_textual_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
<span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> = </span><span class="constant">TEXTUAL_CLSF</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::declare_boolean_switch_p appears nowhere else.</p>
<p class="endnote">The function CommandLine::declare_boolean_switch appears nowhere else.</p>
<p class="endnote">The function CommandLine::declare_boolean_switch_f is used in 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
<p class="endnote">The function CommandLine::declare_numerical_switch appears nowhere else.</p>
<p class="endnote">The function CommandLine::declare_textual_switch appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Reading the command line. </b>Once all the switches are declared, the client calls the following routine
in order to parse the usual C <code class="display"><span class="extract">argc</span></code> and <code class="display"><span class="extract">argv</span></code> pair, and take action as
appropriate. The client passes a pointer to some structure in <code class="display"><span class="extract">state</span></code>:
probably a structure holding its settings variables. When we parse a
switch, we call <code class="display"><span class="extract">f</span></code> to say so; when we parse a bareword, we call <code class="display"><span class="extract">g</span></code>. In
each case we pass back <code class="display"><span class="extract">state</span></code> so that these functions can record whatever
they would like to in the state structure.
</p>
<p class="inwebparagraph">The return value is <code class="display"><span class="extract">TRUE</span></code> if the command line appeared to contain at least
one non-trivial request, but <code class="display"><span class="extract">FALSE</span></code> if it only asked for e.g. <code class="display"><span class="extract">-help</span></code>. In
general, the client should then exit with exit code 0 if this happens.
</p>
<p class="inwebparagraph">This is all easier to demonstrate than explain. See Inweb for an example.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BOGUS_CLSN</span><span class="plain"> -12345678 </span> <span class="comment">bogus because guaranteed not to be a genuine switch ID</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">argc</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> **</span><span class="identifier">argv</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *), </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">g</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">substantive</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=1, </span><span class="identifier">no_raw_tokens</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">argc</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">switched</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">argv</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'-'</span><span class="plain">) { </span><span class="identifier">p</span><span class="plain">++; </span><span class="identifier">switched</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; } </span> <span class="comment">allow a doubled-dash as a single</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">);</span>
<span class="functiontext">Streams::write_locale_string</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">+1 &lt; </span><span class="identifier">argc</span><span class="plain">) </span><span class="functiontext">Streams::write_locale_string</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">argv</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">switched</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">, </span><span class="identifier">f</span><span class="plain">, &amp;</span><span class="identifier">substantive</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == 0)</span>
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"unknown command line switch: -%S"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">N</span><span class="plain"> - 1;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">(*</span><span class="identifier">g</span><span class="plain">)(</span><span class="identifier">no_raw_tokens</span><span class="plain">++, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">);</span>
<span class="identifier">substantive</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">substantive</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>We also allow <code class="display"><span class="extract">-setting=X</span></code> as equivalent to <code class="display"><span class="extract">-setting X</span></code>.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">substantive</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="constant">BOGUS_CLSN</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(%d+)"</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(-%d+)"</span><span class="plain">))) {</span>
<span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Str::atoi</span><span class="plain">(</span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[1], 0);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[1]);</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">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(%c*)"</span><span class="plain">)) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[1]);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair_p</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">, </span><span class="identifier">f</span><span class="plain">, </span><span class="identifier">substantive</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read_pair is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>So at this point we have definitely found what looks like a switch:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read_pair_p</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">substantive</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dictionaries::find</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="functiontext">Dictionaries::read_value</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">BOGUS_CLSN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> == </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">)) {</span>
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"no value N given for -%S=N"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> != </span><span class="constant">BOGUS_CLSN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> != </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">)) {</span>
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"this is not a numerical setting: -%S"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain"> &gt; 1) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">) == 0) {</span>
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"no argument X for -%S X"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Take action on what is now definitely a switch</span> <span class="cwebmacronumber">8.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">innocuous</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">substantive</span><span class="plain">)) *</span><span class="identifier">substantive</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read_pair_p is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP8_1"></a><b>&#167;8.1. </b>The common set of switches declared by Foundation are all handled here;
all other switches are delegated to the client's callback function <code class="display"><span class="extract">f</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Take action on what is now definitely a switch</span> <span class="cwebmacronumber">8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_id</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CRASH_CLSW</span><span class="plain">: </span><span class="functiontext">Errors::enter_debugger_mode</span><span class="plain">(); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</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">LOG_CLSW</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse debugging log inclusion</span> <span class="cwebmacronumber">8.1.1</span>&gt;<span class="plain">; </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</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">VERSION_CLSW</span><span class="plain">:</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"%s [[Version Number]] '[[Version Name]]' (build [[Build Number]] on [[Build Date]])\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">INTOOL_NAME</span><span class="plain">);</span>
<span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</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">HELP_CLSW</span><span class="plain">: </span><span class="functiontext">CommandLine::write_help</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</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">FIXTIME_CLSW</span><span class="plain">: </span><span class="functiontext">Time::fix</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">AT_CLSW</span><span class="plain">: </span><span class="functiontext">Pathnames::set_installation_path</span><span class="plain">(</span><span class="functiontext">Pathnames::from_text</span><span class="plain">(</span><span class="identifier">arg</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="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = -1;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">: </span><span class="identifier">par</span><span class="plain"> = </span><span class="constant">TRUE</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">BOOLEAN_OFF_CLSF</span><span class="plain">: </span><span class="identifier">par</span><span class="plain"> = </span><span class="constant">FALSE</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">NUMERICAL_CLSF</span><span class="plain">: </span><span class="identifier">par</span><span class="plain"> = </span><span class="identifier">N</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">TEXTUAL_CLSF</span><span class="plain">: </span><span class="identifier">arg</span><span class="plain"> = </span><span class="identifier">opt_val</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain"> == 1) (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_id</span><span class="plain">, </span><span class="identifier">par</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_id</span><span class="plain">, </span><span class="identifier">par</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">);</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="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_1_1"></a><b>&#167;8.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse debugging log inclusion</span> <span class="cwebmacronumber">8.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Log::get_debug_log_filename</span><span class="plain">() == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">INTOOL_NAME</span><span class="plain">);</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="functiontext">Pathnames::from_text</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">), </span><span class="identifier">I</span><span class="string">"debug-log.txt"</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">);</span>
<span class="functiontext">Log::set_debug_log_filename</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Log::open</span><span class="plain">();</span>
<span class="functiontext">Log::set_aspect_from_command_line</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8_1">&#167;8.1</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Help text. </b>That just leaves the following, which implements the <code class="display"><span class="extract">-help</span></code> switch. It
alphabetically sorts the switches, and prints out a list of them, except
that switches created by Foundation are in a separate bunch at the bottom.
(Those are the dull ones.) If a header text has been declared, that appears
at the top of the list. It's usually a brief description of the tool's
name and purpose.
</p>
<pre class="display">
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">cls_heading</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">CommandLine::declare_heading</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">heading_text_literal</span><span class="plain">) {</span>
<span class="identifier">cls_heading</span><span class="plain"> = </span><span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">heading_text_literal</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::write_help</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max</span><span class="plain"> = 0, </span><span class="identifier">N</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">, </span><span class="reserved">command_line_switch</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> &gt; </span><span class="identifier">max</span><span class="plain">) </span><span class="identifier">max</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">N</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">command_line_switch</span><span class="plain"> **</span><span class="identifier">sorted_table</span><span class="plain"> =</span>
<span class="functiontext">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, (</span><span class="reserved">int</span><span class="plain">) </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *), </span><span class="constant">CLS_SORTING_MREASON</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">, </span><span class="reserved">command_line_switch</span><span class="plain">) </span><span class="identifier">sorted_table</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">cls</span><span class="plain">;</span>
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted_table</span><span class="plain">, (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">N</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *), </span><span class="functiontext">CommandLine::compare_names</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cls_heading</span><span class="plain">) &gt; 0) </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">cls_heading</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">filter</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Memory::I7_free</span><span class="plain">(</span><span class="identifier">sorted_table</span><span class="plain">, </span><span class="constant">CLS_SORTING_MREASON</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">*((</span><span class="reserved">int</span><span class="plain">) </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *)));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::declare_heading appears nowhere else.</p>
<p class="endnote">The function CommandLine::write_help is used in <a href="#SP8_1">&#167;8.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show options in alphabetical order</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="identifier">sorted_table</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;foundation_switch</span><span class="plain"> != </span><span class="identifier">filter</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"-%S"</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;switch_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> == </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"=N"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;form</span><span class="plain"> == </span><span class="constant">TEXTUAL_CLSF</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"=X"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-</span><span class="element">&gt;valency</span><span class="plain"> &gt; 1) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">" X"</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">) &lt; </span><span class="identifier">max</span><span class="plain">+5) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">" "</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</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">cls</span><span class="plain">-</span><span class="element">&gt;help_text</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">line</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a> (twice).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::compare_names</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">ent1</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">ent2</span><span class="plain">) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tx1</span><span class="plain"> = (*((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent1</span><span class="plain">))-</span><span class="element">&gt;switch_name</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tx2</span><span class="plain"> = (*((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent2</span><span class="plain">))-</span><span class="element">&gt;switch_name</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">tx1</span><span class="plain">, </span><span class="identifier">tx2</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::compare_names is used in <a href="#SP9">&#167;9</a>.</p>
2019-02-09 12:33:40 +00:00
<!--End of weave: 333 lines from a web of 9267-->
2019-02-04 22:26:45 +00:00
</body>
</html>