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

684 lines
97 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 name="viewport" content="width=device-width initial-scale=1">
2019-02-04 22:26:45 +00:00
<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">
2019-02-04 22:26:45 +00:00
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
2019-02-09 12:33:40 +00:00
<!--Weave of '3/cla' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</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>
2019-02-04 22:26:45 +00:00
<ul class="toc"><li><a href="#SP1">&#167;1. Model</a></li><li><a href="#SP2">&#167;2. Switches</a></li><li><a href="#SP7">&#167;7. Reading the command line</a></li><li><a href="#SP14">&#167;14. Help text</a></li></ul><hr class="tocbar">
2019-02-04 22:26:45 +00:00
<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">
2020-04-05 17:37:43 +00:00
<span class="definitionkeyword">enum</span> <span class="identifier">ACTION_CLSF</span><span class="definitionkeyword"> from </span><span class="identifier">1</span> <span class="comment">does something</span>
<span class="definitionkeyword">enum</span> <span class="identifier">BOOLEAN_ON_CLSF</span><span class="plain"> </span><span class="comment">sets a flag true</span>
<span class="definitionkeyword">enum</span> <span class="identifier">BOOLEAN_OFF_CLSF</span><span class="plain"> </span><span class="comment">sets a flag false</span>
<span class="definitionkeyword">enum</span> <span class="identifier">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="identifier">TEXTUAL_CLSF</span><span class="plain"> </span><span class="comment">sets text to the given value</span>
2019-02-04 22:26:45 +00:00
</pre>
<pre class="display">
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Switches are also grouped, though this affects only the printout of them
in <code class="display"><span class="extract">-help</span></code>. Groups are enumerated thus:
</p>
<pre class="definitions">
2020-04-05 17:37:43 +00:00
<span class="definitionkeyword">enum</span> <span class="identifier">NO_CLSG</span><span class="definitionkeyword"> from </span><span class="identifier">0</span>
<span class="definitionkeyword">enum</span> <span class="identifier">FOUNDATION_CLSG</span>
</pre>
2019-02-04 22:26:45 +00:00
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">typedef</span><span class="plain"> </span><span class="identifier">struct</span><span class="plain"> </span><span class="identifier">command_line_switch</span><span class="plain"> {</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">switch_id</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">struct</span><span class="plain"> </span><span class="identifier">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">no-verbose</span></code></span>
<span class="identifier">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">switch_sort_name</span><span class="plain">; </span><span class="comment">e.g., <code class="display"><span class="extract">verbose</span></code></span>
<span class="identifier">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">help_text</span><span class="plain">;</span>
<span class="identifier">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="identifier">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="identifier">int</span><span class="plain"> </span><span class="identifier">switch_group</span><span class="plain">; </span><span class="comment">one of the <code class="display"><span class="extract">*_CLSG</span></code> valyes above</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">active_by_default</span><span class="plain">; </span><span class="comment">relevant only for booleans</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">struct</span><span class="plain"> </span><span class="identifier">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="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="identifier">command_line_switch</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure command_line_switch is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>In case of a prodigious number of switches (ever tried typing <code class="display"><span class="extract">clang -help</span></code>?),
2019-02-04 22:26:45 +00:00
we'll hash the switch names into the following:
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">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>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The client must declare all the switches her program will make use of, not
2019-02-04 22:26:45 +00:00
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="identifier">int</span><span class="plain"> </span><span class="identifier">current_switch_group</span><span class="plain"> = -1;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">switch_group_names</span><span class="plain">[</span><span class="identifier">NO_DEFINED_CLSG_VALUES</span><span class="plain">+1];</span>
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::begin_group</span><span class="plain">(</span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">current_switch_group</span><span class="plain"> == -1)</span>
<span class="identifier">for</span><span class="plain"> (</span><span class="identifier">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">NO_DEFINED_CLSG_VALUES</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">switch_group_names</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">current_switch_group</span><span class="plain"> = </span><span class="identifier">id</span><span class="plain">;</span>
<span class="identifier">switch_group_names</span><span class="plain">[</span><span class="identifier">id</span><span class="plain">] = </span><span class="identifier">name</span><span class="plain">;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::end_group</span><span class="plain">(</span><span class="identifier">void</span><span class="plain">) {</span>
<span class="identifier">current_switch_group</span><span class="plain"> = </span><span class="identifier">NO_CLSG</span><span class="plain">;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">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="identifier">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>
2020-04-05 17:37:43 +00:00
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">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="identifier">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">help_literal</span><span class="plain">));</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">current_switch_group</span><span class="plain"> == -1) {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">current_switch_group</span><span class="plain"> = </span><span class="identifier">NO_CLSG</span><span class="plain">;</span>
<span class="identifier">for</span><span class="plain"> (</span><span class="identifier">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">NO_DEFINED_CLSG_VALUES</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">switch_group_names</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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="identifier">Dictionaries::new</span><span class="plain">(16, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">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="identifier">command_line_switch</span><span class="plain">);</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_name</span><span class="plain"> = </span><span class="identifier">name</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Make the sorting name</span> <span class="cwebmacronumber">5.1</span>&gt;<span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_id</span><span class="plain"> = </span><span class="identifier">id</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">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">-&gt;</span><span class="identifier">form</span><span class="plain"> = </span><span class="identifier">ACTION_CLSF</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">active_by_default</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">negates</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_group</span><span class="plain"> = </span><span class="identifier">current_switch_group</span><span class="plain">;</span>
<span class="identifier">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">-&gt;</span><span class="identifier">switch_name</span><span class="plain">);</span>
<span class="identifier">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">-&gt;</span><span class="identifier">switch_name</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">);</span>
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::begin_group is used in 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
<p class="endnote">The function CommandLine::end_group is used in 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
2019-02-04 22:26:45 +00:00
<p class="endnote">The function CommandLine::declare_switch is used in <a href="#SP6">&#167;6</a>, 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
2019-02-04 22:26:45 +00:00
<p class="endnote">The function CommandLine::declare_switch_p is used in <a href="#SP6">&#167;6</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP5_1"></a><b>&#167;5.1. </b>When we alphabetically sort switches for the <code class="display"><span class="extract">-help</span></code> output, we want to
file, say, <code class="display"><span class="extract">-no-verbose</span></code> immediately after <code class="display"><span class="extract">-verbose</span></code>, not back in the N
section. So the sorting version of <code class="display"><span class="extract">no-verbose</span></code> is <code class="display"><span class="extract">verbose_</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make the sorting name</span> <span class="cwebmacronumber">5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
2020-04-05 17:37:43 +00:00
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_sort_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Str::begins_with_wide_string</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"no-"</span><span class="plain">)) {</span>
<span class="identifier">Str::delete_n_characters</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_sort_name</span><span class="plain">, </span><span class="constant">3</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_sort_name</span><span class="plain">, </span><span class="string">"_"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Booleans are automatically created in pairs, e.g., <code class="display"><span class="extract">-destroy-world</span></code> and
2019-02-04 22:26:45 +00:00
<code class="display"><span class="extract">-no-destroy-world</span></code>:
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">CommandLine::declare_boolean_switch</span><span class="plain">(</span><span class="identifier">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="identifier">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="identifier">int</span><span class="plain"> </span><span class="identifier">active</span><span class="plain">) {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="identifier">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">text_stream</span><span class="plain"> *</span><span class="identifier">neg</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
2019-02-04 22:26:45 +00:00
<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>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">neg_help</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
2019-02-04 22:26:45 +00:00
<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>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">negated</span><span class="plain"> =</span>
<span class="identifier">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>
2019-02-04 22:26:45 +00:00
2020-04-05 17:37:43 +00:00
<span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> = </span><span class="identifier">BOOLEAN_ON_CLSF</span><span class="plain">;</span>
<span class="identifier">negated</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> = </span><span class="identifier">BOOLEAN_OFF_CLSF</span><span class="plain">;</span>
<span class="identifier">negated</span><span class="plain">-&gt;</span><span class="identifier">negates</span><span class="plain"> = </span><span class="identifier">cls</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">active</span><span class="plain">) </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">active_by_default</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">else</span><span class="plain"> </span><span class="identifier">negated</span><span class="plain">-&gt;</span><span class="identifier">active_by_default</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::declare_numerical_switch</span><span class="plain">(</span><span class="identifier">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="identifier">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>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="identifier">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">-&gt;</span><span class="identifier">form</span><span class="plain"> = </span><span class="identifier">NUMERICAL_CLSF</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::declare_textual_switch</span><span class="plain">(</span><span class="identifier">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="identifier">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>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
<span class="identifier">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">-&gt;</span><span class="identifier">form</span><span class="plain"> = </span><span class="identifier">TEXTUAL_CLSF</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::declare_boolean_switch is used in 1/fnd (<a href="1-fnd.html#SP8_5">&#167;8.5</a>).</p>
2019-02-04 22:26:45 +00:00
<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="SP7"></a><b>&#167;7. Reading the command line. </b>Once all the switches are declared, the client calls the following routine
2019-02-04 22:26:45 +00:00
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>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>Here goes the reader. It works through the command line arguments, then
through the file if one has by that point been provided.
</p>
2019-02-04 22:26:45 +00:00
<pre class="definitions">
2020-04-05 17:37:43 +00:00
<span class="definitionkeyword">define</span> <span class="identifier">BOGUS_CLSN</span><span class="plain"> -12345678 </span><span class="comment">bogus because guaranteed not to be a genuine switch ID</span>
2019-02-04 22:26:45 +00:00
</pre>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">typedef</span><span class="plain"> </span><span class="identifier">struct</span><span class="plain"> </span><span class="identifier">clf_reader_state</span><span class="plain"> {</span>
<span class="identifier">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="identifier">void</span><span class="plain"> *);</span>
<span class="identifier">void</span><span class="plain"> (*</span><span class="identifier">g</span><span class="plain">)(</span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="identifier">void</span><span class="plain"> *);</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">subs</span><span class="plain">;</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">nrt</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="plain">} </span><span class="identifier">clf_reader_state</span><span class="plain">;</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">CommandLine::read</span><span class="plain">(</span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">argc</span><span class="plain">, </span><span class="identifier">char</span><span class="plain"> **</span><span class="identifier">argv</span><span class="plain">, </span><span class="identifier">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
<span class="identifier">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="identifier">void</span><span class="plain"> *), </span><span class="identifier">void</span><span class="plain"> (*</span><span class="identifier">g</span><span class="plain">)(</span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="identifier">void</span><span class="plain"> *)) {</span>
<span class="identifier">clf_reader_state</span><span class="plain"> </span><span class="identifier">crs</span><span class="plain">;</span>
<span class="identifier">crs</span><span class="plain">.</span><span class="identifier">state</span><span class="plain"> = </span><span class="identifier">state</span><span class="plain">; </span><span class="identifier">crs</span><span class="plain">.</span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">f</span><span class="plain">; </span><span class="identifier">crs</span><span class="plain">.</span><span class="identifier">g</span><span class="plain"> = </span><span class="identifier">g</span><span class="plain">;</span>
<span class="identifier">crs</span><span class="plain">.</span><span class="identifier">subs</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">crs</span><span class="plain">.</span><span class="identifier">nrt</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">CommandLine::read_array</span><span class="plain">(&amp;</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">argc</span><span class="plain">, </span><span class="identifier">argv</span><span class="plain">);</span>
<span class="identifier">CommandLine::read_file</span><span class="plain">(&amp;</span><span class="identifier">crs</span><span class="plain">);</span>
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">crs</span><span class="plain">.</span><span class="identifier">subs</span><span class="plain">;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::read_array</span><span class="plain">(</span><span class="identifier">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">argc</span><span class="plain">, </span><span class="identifier">char</span><span class="plain"> **</span><span class="identifier">argv</span><span class="plain">) {</span>
<span class="identifier">for</span><span class="plain"> (</span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=1; </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>
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">switched</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">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>
2020-04-05 17:37:43 +00:00
<span class="identifier">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="identifier">TRUE</span><span class="plain">; } </span><span class="comment">allow a doubled-dash as a single</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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>
2019-02-04 22:26:45 +00:00
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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="identifier">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="identifier">if</span><span class="plain"> (</span><span class="identifier">switched</span><span class="plain">) {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">crs</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">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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>
2020-04-04 19:46:43 +00:00
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">N</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">} </span><span class="identifier">else</span><span class="plain"> {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">CommandLine::read_one</span><span class="plain">(</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read appears nowhere else.</p>
<p class="endnote">The function CommandLine::read_array appears nowhere else.</p>
<p class="endnote">The structure clf_reader_state is accessed in 2/dl, 2/mmr, 6/id, 6/sd, 8/ws and here.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>We can also read the "command line" from a file. The following variable
holds the filename to read from.
2019-02-04 22:26:45 +00:00
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">command_line_file</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::also_read_file</span><span class="plain">(</span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="identifier">command_line_file</span><span class="plain"> = </span><span class="identifier">F</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::also_read_file appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>It's useful to log some of what we're reading here, so that people can tell
from the debugging log what switches were actually used. But since the log
might not exist as early as now, we have to record any log entries, and play
them back later (i.e., when the debugging log does exist).
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">linked_list</span><span class="plain"> *</span><span class="identifier">command_line_logs</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">command_line_logs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_logs</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain">);</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain">, </span><span class="identifier">command_line_logs</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::play_back_log</span><span class="plain">(</span><span class="identifier">void</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">command_line_logs</span><span class="plain">) {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain">, </span><span class="identifier">command_line_logs</span><span class="plain">)</span>
<span class="identifier">LOG</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">line</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::record_log is used in <a href="#SP11">&#167;11</a>.</p>
<p class="endnote">The function CommandLine::play_back_log appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>White space at start and end of lines is ignored; blank lines and those
beginning with a <code class="display"><span class="extract">#</span></code> are ignored (but a # following other content does not
mean a comment, so don't use trailing comments on lines); each line must
either be a single switch like <code class="display"><span class="extract">-no-service</span></code> or a pair like <code class="display"><span class="extract">-connect tower11</span></code>.
Shell conventions on quoting are not used, but the line <code class="display"><span class="extract">-greet Fred Smith</span></code>
is equivalent to <code class="display"><span class="extract">-greet 'Fred Smith'</span></code> on the command line, so there's no
problem with internal space characters in arguments.
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::read_file</span><span class="plain">(</span><span class="identifier">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">logline</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">, </span><span class="string">"Reading further switches from file: %f"</span><span class="plain">, </span><span class="identifier">command_line_file</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">command_line_file</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">TextFiles::read</span><span class="plain">(</span><span class="identifier">command_line_file</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">,</span>
<span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">CommandLine::read_file_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, (</span><span class="identifier">void</span><span class="plain"> *) </span><span class="identifier">crs</span><span class="plain">);</span>
<span class="identifier">command_line_file</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">lastline</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">lastline</span><span class="plain">, </span><span class="string">"Completed expert settings file"</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">lastline</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::read_file_helper</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="identifier">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
<span class="identifier">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain"> = (</span><span class="identifier">clf_reader_state</span><span class="plain"> *) </span><span class="identifier">state</span><span class="plain">;</span>
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">Str::is_whitespace</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">)) || (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *#%c*"</span><span class="plain">))) {</span>
<span class="plain">;</span>
<span class="plain">} </span><span class="identifier">else</span><span class="plain"> {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">logline</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">, </span><span class="string">"line %d: %S"</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">-&gt;</span><span class="identifier">line_count</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
<span class="identifier">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *-*(%C+) (%c+?) *"</span><span class="plain">)) {</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0], </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"command line switch does not take value: -%S"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="identifier">else</span><span class="plain"> </span><span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *-*(%C+) *"</span><span class="plain">)) {</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0], </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">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">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">)</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"command line switch requires value: -%S"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="identifier">else</span><span class="plain"> {</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Errors::in_text_file</span><span class="plain">(</span><span class="string">"illegible line in expert settings file"</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">STDERR</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">text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::read_one</span><span class="plain">(</span><span class="identifier">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">) {</span>
<span class="plain">(*(</span><span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">g</span><span class="plain">))(</span><span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">nrt</span><span class="plain">++, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">state</span><span class="plain">);</span>
<span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">subs</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read_file is used in <a href="#SP8">&#167;8</a>.</p>
<p class="endnote">The function CommandLine::read_file_helper appears nowhere else.</p>
<p class="endnote">The function CommandLine::read_one is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </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">
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">) {</span>
2019-02-04 22:26:45 +00:00
<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>
2020-04-05 17:37:43 +00:00
<span class="identifier">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="identifier">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">BOGUS_CLSN</span><span class="plain">;</span>
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">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="identifier">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="identifier">Str::atoi</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1], </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="plain">} </span><span class="identifier">else</span><span class="plain"> </span><span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(%c*)"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">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">crs</span><span class="plain">-&gt;</span><span class="identifier">state</span><span class="plain">, </span><span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">f</span><span class="plain">, &amp;(</span><span class="identifier">crs</span><span class="plain">-&gt;</span><span class="identifier">subs</span><span class="plain">));</span>
2019-02-04 22:26:45 +00:00
<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="identifier">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read_pair is used in <a href="#SP8">&#167;8</a>, <a href="#SP11">&#167;11</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>So at this point we have definitely found what looks like a switch:
2019-02-04 22:26:45 +00:00
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">CommandLine::read_pair_p</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">,</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
<span class="identifier">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">int</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="identifier">void</span><span class="plain"> *), </span><span class="identifier">int</span><span class="plain"> *</span><span class="identifier">substantive</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">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="identifier">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="identifier">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="identifier">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="identifier">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> == </span><span class="identifier">BOGUS_CLSN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">NUMERICAL_CLSF</span><span class="plain">)) {</span>
<span class="identifier">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="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> != </span><span class="identifier">BOGUS_CLSN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> != </span><span class="identifier">NUMERICAL_CLSF</span><span class="plain">)) {</span>
<span class="identifier">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="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">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="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Take action on what is now definitely a switch</span> <span class="cwebmacronumber">13.1</span>&gt;<span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">innocuous</span><span class="plain"> == </span><span class="identifier">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="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::read_pair_p is used in <a href="#SP12">&#167;12</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP13_1"></a><b>&#167;13.1. </b>The common set of switches declared by Foundation are all handled here;
2019-02-04 22:26:45 +00:00
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">13.1</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-05 17:37:43 +00:00
<span class="identifier">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_id</span><span class="plain">) {</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">CRASH_CLSW:</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_ON_CLSF</span><span class="plain">) {</span>
<span class="identifier">Errors::enter_debugger_mode</span><span class="plain">(); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">break</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">LOG_CLSW:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Parse debugging log inclusion</span> <span class="cwebmacronumber">13.1.1</span>&gt;<span class="plain">; </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">break</span><span class="plain">;</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">VERSION_CLSW:</span><span class="plain"> {</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[[Title]]"</span><span class="plain">);</span>
<span class="identifier">char</span><span class="plain"> *</span><span class="identifier">svn</span><span class="plain"> = </span><span class="string">"[[Semantic Version Number]]"</span><span class="plain">;</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">svn</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" version %s"</span><span class="plain">, </span><span class="identifier">svn</span><span class="plain">);</span>
<span class="identifier">char</span><span class="plain"> *</span><span class="identifier">vname</span><span class="plain"> = </span><span class="string">"[[Version Name]]"</span><span class="plain">;</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">vname</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" '%s'"</span><span class="plain">, </span><span class="identifier">vname</span><span class="plain">);</span>
<span class="identifier">char</span><span class="plain"> *</span><span class="identifier">d</span><span class="plain"> = </span><span class="string">"[[Build Date]]"</span><span class="plain">;</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" (%s)"</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">);</span>
2019-03-12 23:32:12 +00:00
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">innocuous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">break</span><span class="plain">;</span>
2019-03-12 23:32:12 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">HELP_CLSW:</span><span class="plain"> </span><span class="identifier">CommandLine::write_help</span><span class="plain">(</span><span class="identifier">STDOUT</span><span class="plain">); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">break</span><span class="plain">;</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">FIXTIME_CLSW:</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_ON_CLSF</span><span class="plain">) </span><span class="identifier">Time::fix</span><span class="plain">();</span>
<span class="identifier">break</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">AT_CLSW:</span><span class="plain"> </span><span class="identifier">Pathnames::set_installation_path</span><span class="plain">(</span><span class="identifier">Pathnames::from_text</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">)); </span><span class="identifier">break</span><span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">default:</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">) {</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = -1;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain">) {</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">BOOLEAN_ON_CLSF:</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">break</span><span class="plain">;</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">BOOLEAN_OFF_CLSF:</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">break</span><span class="plain">;</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">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="identifier">break</span><span class="plain">;</span>
<span class="identifier">case</span><span class="plain"> </span><span class="identifier">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="identifier">break</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">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="identifier">else</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">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>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
<span class="identifier">break</span><span class="plain">;</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP13">&#167;13</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP13_1_1"></a><b>&#167;13.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse debugging log inclusion</span> <span class="cwebmacronumber">13.1.1</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Log::get_debug_log_filename</span><span class="plain">() == </span><span class="identifier">NULL</span><span class="plain">) {</span>
2019-02-04 22:26:45 +00:00
<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>
2020-04-05 17:37:43 +00:00
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">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>
2019-02-04 22:26:45 +00:00
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Log::set_debug_log_filename</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Log::open</span><span class="plain">();</span>
<span class="identifier">Log::set_aspect_from_command_line</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP13_1">&#167;13.1</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. 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 as grouped,
with ungrouped switches as the top paragraph and Foundation switches as the
bottom one. (Those are the dull ones.)
</p>
<p class="inwebparagraph">If a header text has been declared, that appears above the list. It's usually
a brief description of the tool's name and purpose.
2019-02-04 22:26:45 +00:00
</p>
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">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>
2019-02-04 22:26:45 +00:00
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">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="identifier">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">heading_text_literal</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">void</span><span class="plain"> </span><span class="identifier">CommandLine::write_help</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="identifier">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain">;</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">max</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">N</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">, </span><span class="identifier">command_line_switch</span><span class="plain">) {</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_name</span><span class="plain">);</span>
<span class="identifier">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>
2019-02-04 22:26:45 +00:00
<span class="identifier">N</span><span class="plain">++;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">command_line_switch</span><span class="plain"> **</span><span class="identifier">sorted_table</span><span class="plain"> =</span>
<span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, (</span><span class="identifier">int</span><span class="plain">) </span><span class="identifier">sizeof</span><span class="plain">(</span><span class="identifier">command_line_switch</span><span class="plain"> *), </span><span class="identifier">CLS_SORTING_MREASON</span><span class="plain">);</span>
<span class="identifier">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="identifier">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="identifier">sizeof</span><span class="plain">(</span><span class="identifier">command_line_switch</span><span class="plain"> *), </span><span class="identifier">CommandLine::compare_names</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">cls_heading</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">cls_heading</span><span class="plain">);</span>
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> = </span><span class="identifier">NO_CLSG</span><span class="plain">, </span><span class="identifier">new_para_needed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">for</span><span class="plain"> (</span><span class="identifier">filter</span><span class="plain"> = </span><span class="identifier">NO_CLSG</span><span class="plain">; </span><span class="identifier">filter</span><span class="plain">&lt;</span><span class="identifier">NO_DEFINED_CLSG_VALUES</span><span class="plain">; </span><span class="identifier">filter</span><span class="plain">++)</span>
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain"> != </span><span class="identifier">NO_CLSG</span><span class="plain">) &amp;&amp; (</span><span class="identifier">filter</span><span class="plain"> != </span><span class="identifier">FOUNDATION_CLSG</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">filter</span><span class="plain"> = </span><span class="identifier">FOUNDATION_CLSG</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">Memory::I7_free</span><span class="plain">(</span><span class="identifier">sorted_table</span><span class="plain">, </span><span class="identifier">CLS_SORTING_MREASON</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">*((</span><span class="identifier">int</span><span class="plain">) </span><span class="identifier">sizeof</span><span class="plain">(</span><span class="identifier">command_line_switch</span><span class="plain"> *)));</span>
2019-02-04 22:26:45 +00:00
<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="#SP13_1">&#167;13.1</a>.</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>&gt; =
2019-02-04 22:26:45 +00:00
</code></p>
<pre class="displaydefn">
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">new_para_needed</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">new_para_needed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">for</span><span class="plain"> (</span><span class="identifier">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>
2020-04-05 17:37:43 +00:00
<span class="identifier">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="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_group</span><span class="plain"> != </span><span class="identifier">filter</span><span class="plain">) </span><span class="identifier">continue</span><span class="plain">;</span>
<span class="identifier">if</span><span class="plain"> ((</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_OFF_CLSF</span><span class="plain">) || (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_ON_CLSF</span><span class="plain">)) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">active_by_default</span><span class="plain">) </span><span class="identifier">continue</span><span class="plain">;</span>
<span class="plain">}</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">label</span><span class="plain"> = </span><span class="identifier">switch_group_names</span><span class="plain">[</span><span class="identifier">filter</span><span class="plain">];</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">new_para_needed</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">label</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">label</span><span class="plain">);</span>
<span class="identifier">new_para_needed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
2019-02-04 22:26:45 +00:00
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
2020-04-05 17:37:43 +00:00
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">label</span><span class="plain">) &gt; </span><span class="constant">0</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">" "</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">-&gt;</span><span class="identifier">switch_name</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">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="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">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="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">valency</span><span class="plain"> &gt; </span><span class="constant">1</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="identifier">while</span><span class="plain"> (</span><span class="identifier">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">+7) </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">, </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">help_text</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_ON_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">" (default is -no-%S)"</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">switch_name</span><span class="plain">);</span>
<span class="identifier">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">form</span><span class="plain"> == </span><span class="identifier">BOOLEAN_OFF_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">" (default is -%S)"</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-&gt;</span><span class="identifier">negates</span><span class="plain">-&gt;</span><span class="identifier">switch_name</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<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="#SP14">&#167;14</a> (three times).</p>
2019-02-04 22:26:45 +00:00
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b></p>
2019-02-04 22:26:45 +00:00
<pre class="display">
2020-04-05 17:37:43 +00:00
<span class="identifier">int</span><span class="plain"> </span><span class="identifier">CommandLine::compare_names</span><span class="plain">(</span><span class="identifier">const</span><span class="plain"> </span><span class="identifier">void</span><span class="plain"> *</span><span class="identifier">ent1</span><span class="plain">, </span><span class="identifier">const</span><span class="plain"> </span><span class="identifier">void</span><span class="plain"> *</span><span class="identifier">ent2</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">tx1</span><span class="plain"> = (*((</span><span class="identifier">const</span><span class="plain"> </span><span class="identifier">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent1</span><span class="plain">))-&gt;</span><span class="identifier">switch_sort_name</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">tx2</span><span class="plain"> = (*((</span><span class="identifier">const</span><span class="plain"> </span><span class="identifier">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent2</span><span class="plain">))-&gt;</span><span class="identifier">switch_sort_name</span><span class="plain">;</span>
<span class="identifier">return</span><span class="plain"> </span><span class="identifier">Str::cmp_insensitive</span><span class="plain">(</span><span class="identifier">tx1</span><span class="plain">, </span><span class="identifier">tx2</span><span class="plain">);</span>
2019-02-04 22:26:45 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CommandLine::compare_names is used in <a href="#SP14">&#167;14</a>.</p>
2019-02-04 22:26:45 +00:00
2019-03-12 23:32:12 +00:00
<hr class="tocbar">
<ul class="toc"><li><a href="3-em.html">Back to 'Error Messages'</a></li><li><a href="3-pth.html">Continue with 'Pathnames'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
2019-02-04 22:26:45 +00:00
</body>
</html>