670 lines
96 KiB
HTML
670 lines
96 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>Command Line Arguments</title>
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
<nav role="navigation">
|
|
<h1><a href="../webs.html">Sources</a></h1>
|
|
<ul>
|
|
<li><a href="../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">
|
|
|
|
<!--Weave of 'Command Line Arguments' 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>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Model</a></li><li><a href="#SP2">§2. Switches</a></li><li><a href="#SP7">§7. Reading the command line</a></li><li><a href="#SP14">§14. Help text</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§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>
|
|
|
|
<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>§2. Switches. </b>Each different switch available is stored in one of these structures.
|
|
Switches come in five sorts:
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">enum</span> <span class="constant">ACTION_CLSF</span><span class="definitionkeyword"> from </span><span class="constant">1</span> <span class="comment"> does something</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">BOOLEAN_ON_CLSF</span><span class="plain"> </span><span class="comment"> sets a flag true</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">BOOLEAN_OFF_CLSF</span><span class="plain"> </span><span class="comment"> sets a flag false</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">NUMERICAL_CLSF</span><span class="plain"> </span><span class="comment"> sets an integer to the given value</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">TEXTUAL_CLSF</span><span class="plain"> </span><span class="comment"> sets text to the given value</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§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">
|
|
<span class="definitionkeyword">enum</span> <span class="constant">NO_CLSG</span><span class="definitionkeyword"> from </span><span class="constant">0</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">FOUNDATION_CLSG</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">switch_id</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">switch_name</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">no-verbose</span></code></span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">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="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">help_text</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">valency</span><span class="plain">; </span><span class="comment"> 1 for bare, 2 for one argument follows</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">form</span><span class="plain">; </span><span class="comment"> one of the <code class="display"><span class="extract">*_CLSF</span></code> values above</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">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="reserved">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>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">negates</span><span class="plain">; </span><span class="comment"> relevant only for booleans</span>
|
|
<span class="constant">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">command_line_switch</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure command_line_switch is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>In case of a prodigious number of switches (ever tried typing <code class="display"><span class="extract">clang -help</span></code>?),
|
|
we'll hash the switch names into the following:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">dictionary</span><span class="plain"> *</span><span class="identifier">cls_dictionary</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>The client must declare all the switches her program will make use of, not
|
|
counting the standard set already declared by Foundation (such as <code class="display"><span class="extract">-help</span></code>).
|
|
A new <code class="display"><span class="extract">*_CLSW</span></code> value should be enumerated to be the ID referring to this
|
|
swtich, and then the client should call:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">current_switch_group</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">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="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::begin_group</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_switch_group</span><span class="plain"> == -1)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><=</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>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::end_group</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">current_switch_group</span><span class="plain"> = </span><span class="constant">NO_CLSG</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">name_literal</span><span class="plain">), </span><span class="identifier">val</span><span class="plain">,</span>
|
|
<span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">help_literal</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_switch_group</span><span class="plain"> == -1) {</span>
|
|
<span class="identifier">current_switch_group</span><span class="plain"> = </span><span class="constant">NO_CLSG</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><=</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>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls_dictionary</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">cls_dictionary</span><span class="plain"> = </span><span class="functiontext">Dictionaries::new</span><span class="plain">(16, </span><span class="constant">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain">);</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_name</span><span class="plain"> = </span><span class="identifier">name</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Make the sorting name</span> <span class="cwebmacronumber">5.1</span>><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_id</span><span class="plain"> = </span><span class="identifier">id</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">help_text</span><span class="plain"> = </span><span class="identifier">help_literal</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> = </span><span class="constant">ACTION_CLSF</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">active_by_default</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">negates</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_group</span><span class="plain"> = </span><span class="identifier">current_switch_group</span><span class="plain">;</span>
|
|
<span class="functiontext">Dictionaries::create</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_name</span><span class="plain">);</span>
|
|
<span class="functiontext">Dictionaries::write_value</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_name</span><span class="plain">, </span><span class="identifier">cls</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::begin_group is used in 1/fnd (<a href="1-fnd.html#SP8_5">§8.5</a>).</p>
|
|
|
|
<p class="endnote">The function CommandLine::end_group is used in 1/fnd (<a href="1-fnd.html#SP8_5">§8.5</a>).</p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_switch is used in <a href="#SP6">§6</a>, 1/fnd (<a href="1-fnd.html#SP8_5">§8.5</a>).</p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_switch_p is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Make the sorting name</span> <span class="cwebmacronumber">5.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_sort_name</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">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="functiontext">Str::delete_n_characters</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">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">-></span><span class="element">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">§5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>Booleans are automatically created in pairs, e.g., <code class="display"><span class="extract">-destroy-world</span></code> and
|
|
<code class="display"><span class="extract">-no-destroy-world</span></code>:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="functiontext">CommandLine::declare_boolean_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">active</span><span class="plain">) {</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
|
|
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">neg</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">neg</span><span class="plain">, </span><span class="string">"no-%w"</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">);</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">neg_help</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">neg_help</span><span class="plain">, </span><span class="string">"don't %w"</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">negated</span><span class="plain"> =</span>
|
|
<span class="functiontext">CommandLine::declare_switch_p</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">neg</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">neg_help</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> = </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">;</span>
|
|
<span class="identifier">negated</span><span class="plain">-></span><span class="element">form</span><span class="plain"> = </span><span class="constant">BOOLEAN_OFF_CLSF</span><span class="plain">;</span>
|
|
<span class="identifier">negated</span><span class="plain">-></span><span class="element">negates</span><span class="plain"> = </span><span class="identifier">cls</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">active</span><span class="plain">) </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">active_by_default</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">negated</span><span class="plain">-></span><span class="element">active_by_default</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_numerical_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
|
|
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> = </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_textual_switch</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">,</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">name_literal</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">help_literal</span><span class="plain">) {</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> =</span>
|
|
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">name_literal</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">help_literal</span><span class="plain">);</span>
|
|
<span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> = </span><span class="constant">TEXTUAL_CLSF</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_boolean_switch is used in 1/fnd (<a href="1-fnd.html#SP8_5">§8.5</a>).</p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_numerical_switch appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_textual_switch appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. Reading the command line. </b>Once all the switches are declared, the client calls the following routine
|
|
in order to parse the usual C <code class="display"><span class="extract">argc</span></code> and <code class="display"><span class="extract">argv</span></code> pair, and take action as
|
|
appropriate. The client passes a pointer to some structure in <code class="display"><span class="extract">state</span></code>:
|
|
probably a structure holding its settings variables. When we parse a
|
|
switch, we call <code class="display"><span class="extract">f</span></code> to say so; when we parse a bareword, we call <code class="display"><span class="extract">g</span></code>. In
|
|
each case we pass back <code class="display"><span class="extract">state</span></code> so that these functions can record whatever
|
|
they would like to in the state structure.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The return value is <code class="display"><span class="extract">TRUE</span></code> if the command line appeared to contain at least
|
|
one non-trivial request, but <code class="display"><span class="extract">FALSE</span></code> if it only asked for e.g. <code class="display"><span class="extract">-help</span></code>. In
|
|
general, the client should then exit with exit code 0 if this happens.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This is all easier to demonstrate than explain. See Inweb for an example.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§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>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">BOGUS_CLSN</span><span class="plain"> -12345678 </span><span class="comment"> bogus because guaranteed not to be a genuine switch ID</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">clf_reader_state</span><span class="plain"> {</span>
|
|
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">;</span>
|
|
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *);</span>
|
|
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">g</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">subs</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nrt</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">clf_reader_state</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">argc</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> **</span><span class="identifier">argv</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
|
|
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *), </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">g</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *)) {</span>
|
|
<span class="reserved">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="element">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="element">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="element">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="element">subs</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">; </span><span class="identifier">crs</span><span class="plain">.</span><span class="element">nrt</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="functiontext">CommandLine::read_array</span><span class="plain">(&</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="functiontext">CommandLine::read_file</span><span class="plain">(&</span><span class="identifier">crs</span><span class="plain">);</span>
|
|
<span class="reserved">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>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::read_array</span><span class="plain">(</span><span class="reserved">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">argc</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> **</span><span class="identifier">argv</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">argc</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">switched</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">argv</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'-'</span><span class="plain">) { </span><span class="identifier">p</span><span class="plain">++; </span><span class="identifier">switched</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; } </span><span class="comment"> allow a doubled-dash as a single</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="functiontext">Streams::write_locale_string</span><span class="plain">(</span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">+1 < </span><span class="identifier">argc</span><span class="plain">) </span><span class="functiontext">Streams::write_locale_string</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">argv</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">switched</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">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="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"unknown command line switch: -%S"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">N</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="functiontext">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>
|
|
<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>§9. </b>We can also read the "command line" from a file. The following variable
|
|
holds the filename to read from.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">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="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::also_read_file</span><span class="plain">(</span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
|
|
<span class="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>§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">
|
|
<span class="reserved">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="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::record_log</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">) {</span>
|
|
<span class="reserved">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>
|
|
<span class="identifier">command_line_logs</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">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="reserved">text_stream</span><span class="plain">, </span><span class="identifier">command_line_logs</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::play_back_log</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">command_line_logs</span><span class="plain">) {</span>
|
|
<span class="reserved">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="reserved">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\n"</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">§11</a>.</p>
|
|
|
|
<p class="endnote">The function CommandLine::play_back_log appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§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">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::read_file</span><span class="plain">(</span><span class="reserved">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">logline</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">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>
|
|
<span class="functiontext">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">command_line_file</span><span class="plain">)</span>
|
|
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">command_line_file</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">,</span>
|
|
<span class="identifier">NULL</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="functiontext">CommandLine::read_file_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="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>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">lastline</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">lastline</span><span class="plain">, </span><span class="string">"Completed expert settings file"</span><span class="plain">);</span>
|
|
<span class="functiontext">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">lastline</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::read_file_helper</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">, </span><span class="reserved">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
|
|
<span class="reserved">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain"> = (</span><span class="reserved">clf_reader_state</span><span class="plain"> *) </span><span class="identifier">state</span><span class="plain">;</span>
|
|
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::is_whitespace</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">)) || (</span><span class="functiontext">Regexp::match</span><span class="plain">(&</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="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">logline</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">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">-></span><span class="element">line_count</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="functiontext">CommandLine::record_log</span><span class="plain">(</span><span class="identifier">logline</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&</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="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0], </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"unknown command line switch: -%S"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">)</span>
|
|
<span class="functiontext">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="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&</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="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="identifier">crs</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0], </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"unknown command line switch: -%S"</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">)</span>
|
|
<span class="functiontext">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="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="functiontext">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="constant">STDERR</span><span class="plain">, </span><span class="string">"'%S'\n"</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::read_one</span><span class="plain">(</span><span class="reserved">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">) {</span>
|
|
<span class="plain">(*(</span><span class="identifier">crs</span><span class="plain">-></span><span class="element">g</span><span class="plain">))(</span><span class="identifier">crs</span><span class="plain">-></span><span class="element">nrt</span><span class="plain">++, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">crs</span><span class="plain">-></span><span class="element">state</span><span class="plain">);</span>
|
|
<span class="identifier">crs</span><span class="plain">-></span><span class="element">subs</span><span class="plain"> = </span><span class="constant">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">§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">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§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">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read_pair</span><span class="plain">(</span><span class="reserved">clf_reader_state</span><span class="plain"> *</span><span class="identifier">crs</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">);</span>
|
|
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="constant">BOGUS_CLSN</span><span class="plain">;</span>
|
|
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(%d+)"</span><span class="plain">)) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(-%d+)"</span><span class="plain">))) {</span>
|
|
<span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Str::atoi</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1], </span><span class="constant">0</span><span class="plain">);</span>
|
|
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+)=(%c*)"</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
|
|
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">CommandLine::read_pair_p</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">, </span><span class="identifier">opt_val</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">crs</span><span class="plain">-></span><span class="element">state</span><span class="plain">, </span><span class="identifier">crs</span><span class="plain">-></span><span class="element">f</span><span class="plain">, &(</span><span class="identifier">crs</span><span class="plain">-></span><span class="element">subs</span><span class="plain">));</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">opt_p</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">opt_val</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::read_pair is used in <a href="#SP8">§8</a>, <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>So at this point we have definitely found what looks like a switch:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::read_pair_p</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">opt_val</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">,</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">,</span>
|
|
<span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">int</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *, </span><span class="reserved">void</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">substantive</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dictionaries::find</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="functiontext">Dictionaries::read_value</span><span class="plain">(</span><span class="identifier">cls_dictionary</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">BOGUS_CLSN</span><span class="plain">) && (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"no value N given for -%S=N"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> != </span><span class="constant">BOGUS_CLSN</span><span class="plain">) && (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> != </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"this is not a numerical setting: -%S"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain"> > </span><span class="constant">1</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span><span class="string">"no argument X for -%S X"</span><span class="plain">, </span><span class="identifier">opt</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Take action on what is now definitely a switch</span> <span class="cwebmacronumber">13.1</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">innocuous</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) && (</span><span class="identifier">substantive</span><span class="plain">)) *</span><span class="identifier">substantive</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::read_pair_p is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13_1"></a><b>§13.1. </b>The common set of switches declared by Foundation are all handled here;
|
|
all other switches are delegated to the client's callback function <code class="display"><span class="extract">f</span></code>.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Take action on what is now definitely a switch</span> <span class="cwebmacronumber">13.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_id</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CRASH_CLSW:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">) {</span>
|
|
<span class="functiontext">Errors::enter_debugger_mode</span><span class="plain">(); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOG_CLSW:</span><span class="plain"> </span><<span class="cwebmacro">Parse debugging log inclusion</span> <span class="cwebmacronumber">13.1.1</span>><span class="plain">; </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">VERSION_CLSW:</span><span class="plain"> {</span>
|
|
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[[Title]]"</span><span class="plain">);</span>
|
|
<span class="reserved">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="reserved">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="reserved">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="reserved">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="reserved">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="reserved">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>
|
|
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
|
|
<span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">HELP_CLSW:</span><span class="plain"> </span><span class="functiontext">CommandLine::write_help</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">); </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">FIXTIME_CLSW:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">) </span><span class="functiontext">Time::fix</span><span class="plain">();</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">AT_CLSW:</span><span class="plain"> </span><span class="functiontext">Pathnames::set_installation_path</span><span class="plain">(</span><span class="functiontext">Pathnames::from_text</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="identifier">default:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain">) {</span>
|
|
<span class="reserved">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="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">BOOLEAN_OFF_CLSF:</span><span class="plain"> </span><span class="identifier">par</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="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="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">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="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">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">-></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="reserved">else</span><span class="plain"> (*</span><span class="identifier">f</span><span class="plain">)(</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_id</span><span class="plain">, </span><span class="identifier">par</span><span class="plain">, </span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">state</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP13">§13</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13_1_1"></a><b>§13.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Parse debugging log inclusion</span> <span class="cwebmacronumber">13.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Log::get_debug_log_filename</span><span class="plain">() == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">, </span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">INTOOL_NAME</span><span class="plain">);</span>
|
|
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="functiontext">Pathnames::from_text</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">), </span><span class="identifier">I</span><span class="string">"debug-log.txt"</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">itn</span><span class="plain">);</span>
|
|
<span class="functiontext">Log::set_debug_log_filename</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Log::open</span><span class="plain">();</span>
|
|
<span class="functiontext">Log::set_aspect_from_command_line</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP13_1">§13.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§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.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">cls_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::declare_heading</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">heading_text_literal</span><span class="plain">) {</span>
|
|
<span class="identifier">cls_heading</span><span class="plain"> = </span><span class="functiontext">Str::new_from_wide_string</span><span class="plain">(</span><span class="identifier">heading_text_literal</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CommandLine::write_help</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max</span><span class="plain"> = </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>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">, </span><span class="reserved">command_line_switch</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_name</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> > </span><span class="identifier">max</span><span class="plain">) </span><span class="identifier">max</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="identifier">N</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> **</span><span class="identifier">sorted_table</span><span class="plain"> =</span>
|
|
<span class="functiontext">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">, (</span><span class="reserved">int</span><span class="plain">) </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *), </span><span class="constant">CLS_SORTING_MREASON</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">cls</span><span class="plain">, </span><span class="reserved">command_line_switch</span><span class="plain">) </span><span class="identifier">sorted_table</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">cls</span><span class="plain">;</span>
|
|
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted_table</span><span class="plain">, (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">N</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *), </span><span class="functiontext">CommandLine::compare_names</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">cls_heading</span><span class="plain">) > </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\n"</span><span class="plain">, </span><span class="identifier">cls_heading</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> = </span><span class="constant">NO_CLSG</span><span class="plain">, </span><span class="identifier">new_para_needed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">filter</span><span class="plain"> = </span><span class="constant">NO_CLSG</span><span class="plain">; </span><span class="identifier">filter</span><span class="plain"><</span><span class="identifier">NO_DEFINED_CLSG_VALUES</span><span class="plain">; </span><span class="identifier">filter</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain"> != </span><span class="constant">NO_CLSG</span><span class="plain">) && (</span><span class="identifier">filter</span><span class="plain"> != </span><span class="constant">FOUNDATION_CLSG</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>><span class="plain">;</span>
|
|
<span class="identifier">filter</span><span class="plain"> = </span><span class="constant">FOUNDATION_CLSG</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>><span class="plain">;</span>
|
|
|
|
<span class="functiontext">Memory::I7_free</span><span class="plain">(</span><span class="identifier">sorted_table</span><span class="plain">, </span><span class="constant">CLS_SORTING_MREASON</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">*((</span><span class="reserved">int</span><span class="plain">) </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">command_line_switch</span><span class="plain"> *)));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::declare_heading appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function CommandLine::write_help is used in <a href="#SP13_1">§13.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1"></a><b>§14.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Show options in alphabetical order</span> <span class="cwebmacronumber">14.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">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">"\n"</span><span class="plain">);</span>
|
|
<span class="identifier">new_para_needed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">command_line_switch</span><span class="plain"> *</span><span class="identifier">cls</span><span class="plain"> = </span><span class="identifier">sorted_table</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">switch_group</span><span class="plain"> != </span><span class="identifier">filter</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cls</span><span class="plain">-></span><span class="identifier">form</span><span class="plain"> == </span><span class="constant">BOOLEAN_OFF_CLSF</span><span class="plain">) || (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">BOOLEAN_ON_CLSF</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">active_by_default</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">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="reserved">if</span><span class="plain"> (</span><span class="identifier">new_para_needed</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">label</span><span class="plain">) > </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S:\n"</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="constant">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">label</span><span class="plain">) > </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">-></span><span class="element">switch_name</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">NUMERICAL_CLSF</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"=N"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">TEXTUAL_CLSF</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">, </span><span class="string">"=X"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">valency</span><span class="plain"> > </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="reserved">while</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">) < </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">-></span><span class="element">help_text</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">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">-></span><span class="element">switch_name</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cls</span><span class="plain">-></span><span class="element">form</span><span class="plain"> == </span><span class="constant">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">-></span><span class="element">negates</span><span class="plain">-></span><span class="element">switch_name</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\n"</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP14">§14</a> (three times).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. </b></p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CommandLine::compare_names</span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent1</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent2</span><span class="plain">) {</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tx1</span><span class="plain"> = (*((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent1</span><span class="plain">))-></span><span class="element">switch_sort_name</span><span class="plain">;</span>
|
|
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">tx2</span><span class="plain"> = (*((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">command_line_switch</span><span class="plain"> **) </span><span class="identifier">ent2</span><span class="plain">))-></span><span class="element">switch_sort_name</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">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>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function CommandLine::compare_names is used in <a href="#SP14">§14</a>.</p>
|
|
|
|
<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>
|
|
</body>
|
|
</html>
|
|
|