    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Building C &amp; C++ CLI Programs with the libCLImate Mini-framework</title>
        <link>https://members.accu.org/index.php/articles/2165</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 27, #5 - November 2015</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c355/">275</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-355/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+355/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Building C &amp; C++ CLI Programs with the libCLImate Mini-framework</h1>
<p><strong>Author:</strong>&nbsp;Martin Moene</p>
<p>
<strong>Date:</strong> 08 November 2015 08:55:43 +00:00 or Sun, 08 November 2015 08:55:43 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Matthew Wilson presents a framework for simplifying CLI programs.</p>
<p><strong>Body:</strong>&nbsp;<p>This article, the third in a series looking at software anatomy, builds on the material discussed in the first two instalments by discussing <strong>libCLImate</strong>, a mini-framework for command line interface (CLI) programming that encapsulates as much of the boilerplate as possible, and how it may be used in combination with program suite-specific libraries that encapsulate the rest, leaving the CLI application programmer to concentrate only on the interesting parts of the application development.</p>

<h2>Introduction</h2>

<p>In the first instalment of this series, â€˜Anatomy of a CLI Program written in Câ€™ <a href="#[1]">[1]</a>, I considered in some depth the different aspects of CLI program construction, and expressed my desire to find a way to stop spending so much time thinking about and working on the fundamental aspects of program construction and focus instead on the interesting parts of the different problems programs need to solve. In the second instalment, â€˜Anatomy of a CLI Program written in C++â€™ <a href="#[2]">[2]</a>, I considered how to apply disparate utility libraries in the design and implementation of CLI programs, with the intention of separating out the boring boilerplate from the program-specific code, to promote flexibility, reuse, and testability.</p>

<p>In this, the third instalment, I discuss the reification of these previous intentions and considerations in the form of the <strong>libCLImate</strong> mini-framework, and its use in combination with program suite-specific libraries to drastically simplify the effort in creating CLI programs in C and C++.</p>

<h2>libCLImate requirements</h2>

<p>The requirements for the framework included:</p>

<ul>
	<li>Require of the application programmer only a single entry-point function and declarative specification of command-line arguments;</li>
	
	<li>Support C and C++ without compromise to either;</li>
	
	<li>Handle (un)initialisation of all dependency libraries;</li>
	
	<li>Hide away as much boring boilerplate as possible (without detracting too much from discoverability);</li>
	
	<li>Make as much of the non-hideable boring boilerplate as possible be declarative;</li>
	
	<li>Facilitate strict separation of the <em>action logic</em> from the <em>decision logic</em>, <em>support logic</em>, and <em>declarative logic</em> to support the principle of <strong>program design is library design</strong> <a href="#[1]">[1]</a>.</li>
</ul>

<p>In essence: make the job of the CLI programmer less boring, so they can do it faster and better.</p>

<h2>Tour of the code</h2>

<p>Because the <strong>libCLImate</strong> library comprises just a few small source files, it might be most illuminating to learn about the library by walking through the code.</p>

<h3>Interface</h3>

<p>There are six header files of interest to a user of the library (under the <span class="filename">include</span> directory):</p>

<ul>
	<li><span class="filename">libclimate/main.h</span></li>
	
	<li><span class="filename">libclimate/main.hpp</span></li>
	
	<li><span class="filename">libclimate/main/api.h</span></li>
	
	<li><span class="filename">libclimate/main/api.hpp</span></li>
	
	<li><span class="filename">libclimate/implicit_link/common_implicit_link.i</span></li>
	
	<li><span class="filename">libclimate/implicit_link/core.h</span></li>
</ul>

<h4>libclimate/main.h</h4>

<p>If youâ€™re writing a C program you would probably include <span class="filename">libclimate/main.h</span> (an elided form of which is shown in Listing 1).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;libclimate/main/api.h&gt;
int
main(
  int     argc
, char**  argv
)
{
  void* reserved = NULL;
  int (*pfn)(int, char**, void*);
#ifdef __cplusplus
  pfn = libCLImate_main_entry_point_Cpp;
#else /* ? __cplusplus */
  pfn = libCLImate_main_entry_point_C;
#endif /* __cplusplus */
  return (*pfn)(argc, argv, reserved);
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>As is strikingly obvious, including this file defines for you the <code>main()</code> entry point for the program, in terms of</p>

<ul>
	<li><code>libCLImate_main_entry_point_Cpp</code> (if C++), or</li>
	
	<li><code>libCLImate_main_entry_point_C</code> (if C)</li>
</ul>

<p>both of which weâ€™ll discuss shortly. Naturally, you can only include this file into one compilation unit of your program.</p>

<h4>libclimate/main.hpp</h4>

<p>If youâ€™re writing a C++ program you would probably include <span class="filename">libclimate/main.hpp</span>:</p>

&lt;CodeListing&gt;
  #include &lt;libclimate/main.h&gt;&lt;/CodeListing&gt;
&lt;CodeListing&gt;
  #include &lt;libclimate/main/api.hpp&gt;&lt;/CodeListing&gt;
  
<p>Note that Iâ€™ve said â€˜probablyâ€™ in both cases. If youâ€™re using a framework that itself provides <code>main()</code> â€“ I recall that ACE <a href="#[3]">[3]</a> does that, and there are doubtless others â€“ then you would instead eschew these two files and go to the underlying API files <span class="filename">libclimate/main/api.h</span> and <span class="filename">libclimate/main/api.hpp</span>.</p>

<h4>libclimate/main/api.h</h4>

<p>The first of these, <span class="filename">libclimate/main/api.h</span>, is the primary header file for the library. The abridged contents are shown in Listing 2.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;libclimate/common.h&gt;
#include &lt;libclimate/internal/clasp.clasp.h&gt;
#include &lt;stdio.h&gt;

/* API globals */
/* The application-defined CLASP aliases array */
#ifdef __cplusplus
extern &quot;C&quot;
#else /* ? __cplusplus */
extern
#endif /* __cplusplus */
clasp_alias_t const libCLImate_aliases[];

/* API callbacks */
/* Application-defined program entry point 
   (for C) */
#ifdef __cplusplus
extern &quot;C&quot;
#else /* ? __cplusplus */
extern
#endif /* __cplusplus */
int
libCLImate_program_main_C(
  clasp_arguments_t const* args
);

/* Application-defined program entry point 
   (for C++) */
#ifdef __cplusplus
extern &quot;C++&quot;
int
libCLImate_program_main_Cpp(
  clasp_arguments_t const* args
);
# define libCLImate_program_main libCLImate_program_main_Cpp
#else /* ? __cplusplus */
# define libCLImate_program_main libCLImate_program_main_C
#endif /* __cplusplus */

/* API functions */
#ifdef __cplusplus
extern &quot;C&quot;
{
#endif

/* main */
#ifdef __cplusplus
int
libCLImate_main_entry_point_Cpp(
  int     argc
, char**  argv
, void*   reserved
);
#endif /* __cplusplus */

#ifndef __cplusplus
int
libCLImate_main_entry_point_C(
  int     argc
, char**  argv
, void*   reserved
);
#endif /* !__cplusplus */

/* exit */
void
libCLImate_exit_immediately(
  int   exitCode
, void (*pfn)(int exitCode, void* param)
, void* param
) /* noexcept */
;
#ifdef __cplusplus
extern &quot;C++&quot;
void
libCLImate_unwind_and_exit(
  int   exitCode
);
#endif /* __cplusplus */
/* usage */
int
libCLImate_show_usage(
  clasp_arguments_t const*  args
, clasp_alias_t const*      aliases
, FILE*                     stm
, int                       verMajor
, int                       verMinor
, int                       verRevision
, int                       buildNumber
, char const*               programName
, char const*               summary
, char const*               copyright
, char const*               description
, char const*               usage
, int                       showBlanksBetweenItems
);
int
libCLImate_show_usage_header(
  clasp_arguments_t const*  args
. . . // as libCLImate_show_usage()
);
int
libCLImate_show_usage_body(
  clasp_arguments_t const*  args
. . . // as libCLImate_show_usage()
);
int
libCLImate_show_version(
  clasp_arguments_t const*  args
, clasp_alias_t const*      aliases
, FILE*                     stm
, int                       verMajor
, int                       verMinor
, int                       verRevision
, int                       buildNumber
, char const*               programName
);

#ifdef __cplusplus
} /* extern &quot;C&quot; */
#endif
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>This breaks down as follows:</p>

<ul>
	<li>application-defined constructs; and</li>
	
	<li>API functions:
		<ul>
			<li>the framework entry point(s);</li>
			<li>early exit functions; and</li>
			<li>usage helpers.</li>
		</ul>
	</li>
</ul>

<p>A bit grandiose, perhaps, but the <strong>libCLImate</strong> (mini-)framework can be considered a powerful and semi-intelligent <code>ExecuteAroundMethod</code> <a href="#[4]">[4]</a>. As such, the application programmer is required to provide the effective entry point and, so that command-line arguments can be processed on the application programmerâ€™s behalf (by the CLASP library <a href="#[5]">[5]</a>), the CLASP aliases array. Hence, there are three application-defined constructs, two of which must be defined (depending on whether you're writing a C or C++ program). The aliases array is familiar from both previous instalments in this series ([1, 2]) and for <strong>libCLImate</strong> it must have the name <code>libCLImate_aliases</code>. The effective entry point must be called <code>libCLImate_program_main_C()</code> (for C) or <code>libCLImate_program_main_Cpp()</code> (for C++), as in Listing 3.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
/* example.c */
#include &lt;libclimate/main.h&gt;
#include &lt;stdlib.h&gt;
clasp_alias_t const libCLImate_aliases[] =
{
  CLASP_ALIAS_ARRAY_TERMINATOR
};
int
libCLImate_program_main_C(
  clasp_arguments_t const* args
)
{
  return EXIT_SUCCESS;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<p>There is a preprocessor macro <code>libCLImate_program_main</code> that resolves to <code>libCLImate_program_main_Cpp</code> or <code>libCLImate_program_main_C</code> as appropriate. You may wonder why not simply declare a single function of that name; this is explained later in this article.</p>

<p>The remainder of the contents of the main header file are API functions. The first pair are the framework entry points, as discussed earlier. If you are handling the definition of <code>main()</code> separate to <strong>libCLImate</strong> and so are not including <span class="filename">libclimate/main.h</span> or <span class="filename">libclimate/main.hpp</span>, then you will invoke one of these (<code>libCLImate_main_entry_point_C()</code> for C; <code>libCLImate_main_entry_point_Cpp()</code> for C++) once in your programâ€™s execution.</p>

<p>The early exit functions are next, and are discussed separately shortly.</p>

<p>The usage helpers are thin wrappers over the CLASP <a href="#[5]">[5]</a> facilities that have been discussed in previous instalments <a href="#[1]">[1</a>, <a href="#[2]">2]</a>, so I wonâ€™t discuss them further here. Note, however, that they still involve many parameters â€“ this will be addressed satisfactorily when I show how <strong>libCLImate</strong> may be used with CLI program suites.</p>

<h4>libclimate/main/api.hpp</h4>

<p>As you may have guessed from the earlier definition of <span class="filename">libclimate/main.hpp</span>, the contents of <span class="filename">libclimate/main/api.hpp</span> are defined largely in terms of <span class="filename">libclimate/main/api.h</span>:</p>

&lt;CodeListing&gt;
  #include &lt;libclimate/main.h&gt;&lt;/CodeListing&gt;
&lt;CodeListing&gt;
  #include &lt;libclimate/main/api.hpp&gt;&lt;/CodeListing&gt;

<h4>libclimate/implicit_link/core.h</h4>

<p>This is a standard-fare implicit link header file, for use with those compiler suites (such as Visual C++) that support that technique, to link implicitly to the requisite (to the compilation conditions, e.g. release, multithreaded, multibyte-string, ...) <strong>libCLImate</strong> static library.</p>

<h4>libclimate/implicit_link/common_implicit_link.i</h4>

<p>Since <strong>libCLImate</strong> is implemented in terms of several other libraries â€“ <strong>CLASP</strong>, <strong>Pantheios</strong> <a href="#[6]">[6]</a>, <strong>recls</strong> <a href="#[7]">[7]</a> (Windows-only), this file includes some common, always-used librariesâ€™ implicit-link headers (see Listing 4).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;libclimate/implicit_link/core.h&gt;

#include &lt;systemtools/clasp/implicit_link.h&gt;

#include &lt;pantheios/implicit_link/util.h&gt;
#include &lt;pantheios/implicit_link/core.h&gt;

#ifdef _WIN32
# include &lt;recls/implicit_link.h&gt;
#endif
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 4</td>
	</tr>
</table>

<p><strong>Pantheios</strong> aficionados will likely pick up that only the core and util libraries are specified, and why: front-end and back-end libraries are not specified, precisely because it is not the business of a general purpose mini-framework such as <strong>libCLImate</strong> to prescribe the specifics of the diagnostic logging control and output used by its users. Thus, if youâ€™re using implicit-linking with <strong>libCLImate</strong> you will need to specify additionally which front/back-end libraries you require; specifying linking of core and util will not be necessary (but is harmless if you do).</p>

<h3>Implementation</h3>

<p>Iâ€™m not going to show much of the implementation, as a lot of it is simply a gathering together of notions previously espoused (in this forum), and youâ€™re all welcome to simply browse it in (and fork it from!) the GitHub repo (http://github.com/synesissoftware/libCLImate).</p>

<p>There are five implementation files and one internal header file (in the <span class="filename">src</span> directory):</p>

<ul>
	<li><span class="filename">main_entry_point.c</span></li>
	
	<li><span class="filename">main_entry_point.cpp</span></li>
	
	<li><span class="filename">exit_immediately.c</span></li>
	
	<li><span class="filename">unwind_and_exit.cpp</span></li>
	
	<li><span class="filename">quiet_program_termination_exception.hpp</span></li>
	
	<li><span class="filename">usage_etc.c</span></li>
</ul>

<p>The first five of these are discussed in the next two sections. <span class="filename">usage_etc.c</span> does little more than provide the implementations for the helper functions mentioned earlier, including invoking the requisite CLASP API functions (using C Streams, aka <code>FILE*</code>) and determining the console width (if not piped).</p>

<h2>Supporting C and C++</h2>

<p>We all know that there can be only a single definition of <code>main()</code> in a link-unit. You are likely to know also that calling a C++ function that may throw exceptions from a C function yields undefined behaviour.</p>

<p>So, in order to support both C and C++ from the same library, we have to make sure that <code>main()</code> is not defined in the library. As youâ€™ve already seen, <code>main()</code> is defined <em>within the programâ€™s object code</em> by including <span class="filename">libclimate/main.h(pp)</span> in one compilation unit in the project. It is then implemented in terms of either:</p>

<ul>
	<li><code>libCLImate_main_entry_point_C()</code> for C, which is defined in <span class="filename">main_entry_point.c</span>; or</li>
	
	<li><code>libCLImate_main_entry_point_Cpp()</code> for C++, which is defined in <span class="filename">main_entry_point.cpp</span>.</li>
</ul>

<p>These two files have the same logical structure:</p>

<ul>
	<li>(un)initialise <strong>Pantheios</strong> with <strong>Pantheios.Extras.Main</strong> <a href="#[8]">[8]</a>;</li>
	
	<li>trace outer-scope memory leaks with <strong>Pantheios.Extras.DiagUtil</strong> <a href="#[9]">[9]</a>;</li>
	
	<li>(un)initialise CLASP.</li>
</ul>

<p>However, the libraries used â€“ <strong>Pantheios.Extras.*</strong>, <strong>CLASP</strong> â€“ have very different behaviours depending on whether they are compiled in C or C++. Most importantly, in C++: <strong>Pantheios.Extras.Main</strong> performs outermost-scope exception handling, issuing contingent reports (to standard error stream) and diagnostic log statements; and <strong>CLASP</strong> handles command line-related exceptions along the lines of â€œ<em>MyProgram: unrecognised flag '--stranger'; use --help for usage</em>â€.</p>

<p>Thus, the separation is necessitated by the rules of the language as they pertain to <code>main()</code>â€™s uniqueness, by the need to support exceptions in order to provide rich handling of common non-normative conditions (such as a user specifying an unrecognised flag/option). That it also facilitates the ability of the user to provide his/her own <code>main()</code> and call into <strong>libCLImate</strong> explicitly may be thought a bonus.</p>

<h2>Exceptions and early exit</h2>

<p>The necessary handling of exceptions just mentioned also affords us the ability to take away another common (at least to me) but non-standard bit of repetitive work.</p>

<p>As you may know, gentle reader, when (<code>std::</code>)<code>exit()</code> is invoked, the implementation does not cause the destruction of any automatic variables. Hence, the output of Listing 5 is â€˜in and outâ€™ when run without arguments, but only â€˜inâ€™ when given one or more arguments.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
class inout
{
public:
  inout() { fputs(&quot;in&quot;, stdout); }
  ~inout() { fputs(&quot; &amp; out\n&quot;, stdout); }
};
int main(int argc, char* argv[])
{
  inout io;
  if(1 != argc)
  {
    exit(1);
  }
  return 0;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 5</td>
	</tr>
</table>

<p>What this means for sophisticated CLI programs is that calling (<code>std::</code>)<code>exit()</code> can be a bad idea, because things wonâ€™t get cleaned up by the C++ runtime. For sure, many things, such as file handles, will be cleaned up by the operating system (and some things by the C runtime), but it may be unwise to rely on that, because none of it will be done with an understanding of what those objects were doing from a â€˜C++ point of viewâ€™. (I know thatâ€™s a horribly woolly description, but I canâ€™t think of a good example right now, and I trust, gentle readers, that you can go with me regardless...)</p>

<p>Anyway, we do want to be able to perform an early exit to the program, and we donâ€™t (always) want to achieve this by <em>N</em> <code>return</code>s (where <em>N</em> can be a very large number). Well, in C++, thereâ€™s a well-known control-transfer mechanism <a href="#[10]">[10]</a>: exceptions. Why not throw an exception?</p>

<p>Two problems. First, which exception do we throw? Thereâ€™s no standard exception to indicate a request to exit a program (or thread). Iâ€™ve written many such things over the years: some within general-purpose C++ libraries; others within program suites. The problem with the former is that itâ€™s more coupling for something totally fundamental and uninteresting. The problem with the latter is that one ends up in copy-paste hell. Coupling or copying â€“ yuck!</p>

<p>The second problem is more subtle, but much more significant. It is received wisdom (which I too espouse <a href="#[11]">[11]</a>) that <em>all exception types should be derived from</em> <code>std::exception</code>. But really this rubric is too simplistic. What I think it should actually mean is that <em>all exceptions types </em><strong>whose instances we may interact with</strong><em> should be derived from </em><code>std::exception</code>. The reason is that one should only catch what is oneâ€™s business to catch. Or, put more powerfully, one should not catch what it is not oneâ€™s business to catch.</p>

<p>If we define our putative <em>end-program-exception</em> to derive (by whatever depth) from <code>std::exception</code>, then it is possible that application code (or library code that is at a higher level of abstraction and dependency than our <em>end-program-exception</em>) may intercept and quench it. Of course, any code that does such a thing is (overwhelmingly likely) in error, but practical experience (in C++, and in many other languages â€“ C# being the standout worst) tells me that this will happen.</p>

<p>So, thereâ€™s a strong argument to be made to have an <em>end-program-exception</em> that is not part of the <code>std::exception</code> hierarchy. (Note: there are some arguments against, such as subversion of a <code>std::exception</code>-derivation assumption in the implementation of a C-API boundary, but Iâ€™m running out of space to discuss here. Pepper me with email on the accu-general mailing list if you wish.)</p>

<p>Going with this argument, however, means we risk exposing our exception to good practice â€“ pun intended! â€“ to the wider world, giving a bad example. Thatâ€™s where <span class="filename">quiet_program_termination_exception</span>comes in: it carries an exit code from the throw point, which is in  <code>libCLImate_unwind_and_exit()</code> (in <span class="filename">unwind_and_exit.cpp</span>) to a handler in the <code>ExecuteAroundMethod</code> layered function stack in <span class="filename">main_entry_point_Cpp.cpp</span>. No user of <strong>libCLImate</strong> is exposed to this class, not even polymorphically.</p>

<p>Being practical, however, we must recognise that there may be some circumstances in which this isolation from <code>
std::exception</code> is not desired. So, there are a bunch of pre-processor symbols that may be defined during the building of <strong>libCLImate</strong> that allow the exception to:</p>

<ul>
	<li>have no inheritance (the default);</li>
	
	<li>inherit from <code>std::exception</code>;</li>
	
	<li>inherit from <code>std::runtime_error</code>; or</li>
	
	<li>inherit from <code>stlsoft::unrecoverable</code>, an STLSoft <a href="#[12]">[12]</a> exception type that may not be quenched, and if it is causes the program to exit.</li>
</ul>

<h3>The name</h3>

<p>I asked the friendly fellows at ACCU-general for assistance in naming the library. There were several apposite suggestions (along with the odd inevitable â€˜wheel already inventedâ€™ carp), but one stood out. Jonathan Wakeley offered <strong>libCLImate</strong>, ostensibly because itâ€™s a supporting (mate) library for CLI, but really so that Phil Nash could pun that â€˜every pull request will result in CLI-mate changeâ€™. In the face of such wit I was powerless to resist. ïŠ</p>

<h2>Program suites</h2>

<p>Applying <strong>libCLImate</strong> results in a substantial reduction in size and simplification of the implementation of standalone CLI programs. However, there are still some aspects that involve too much work:</p>

<ul>
	<li>Since (almost) all CLI programs support the UNIX-standard flags <code>--help</code> and <code>--version</code>, having to detect and act on these flags, and in the same way, in every program is tiresome;</li>
	
	<li>Defining (and using) all 13 program identity attributes â€“ version (major, minor, revision, build); strings (name, copyright, summary, description, usage) â€“ is a drag, and leads to cluttered code (reducing transparency and increasing the likelihood of mistakes);</li>
	
	<li><strong>libCLImate</strong>â€™s usage helpers are necessarily verbose, taking between 8 and 13 parameters;</li>
	
	<li><strong>libCLImate</strong> does not select diagnostics transport (in the form of Pantheios back-ends) or control (in the form of Pantheios front-end), because it canâ€™t know whatâ€™s appropriate for arbitrary CLI programs. Since (in my experience) program suites use the same diagnostics facilities in each program, having to do the same specifications and customisations of such facilities repeatedly is tiresome and duplicative, and may lead to copy-paste errors and/or divergence;</li>
	
	<li>Some program suites have common, but suite-specific, exceptions that may be caught and handled in a suite-common manner. Having to write this same code in each program is tiresome and duplicative, and may lead to copy-paste errors and/or divergence.</li>
</ul>

<p>By combining <strong>libCLImate</strong> with a program suite-specific library, the implementation of each program in the suite can be distilled down so much as to achieve the primary expressed aim of the library: Require of the application programmer only a single entry-point function and declarative specification of command-line arguments. In the remainder of this instalment I will demonstrate how thatâ€™s been achieved for the Synesis Software Source Tools program suite via the proprietary library <strong>libSrcToolMain</strong>.</p>

<p><strong>libSrcToolMain</strong> consists of three groups of source files:</p>

<ul>
	<li>CLI framework files;</li>
	
	<li>CRT extension files; and</li>
	
	<li>Common utilities files.</li>
</ul>

<p>Weâ€™re interested in the CLI framework files, of which there are nine worth exploring:</p>

<ul>
	<li><span class="filename">include/SynesisSoftware/SourceTools/implicit_link/core.h</span></li>
	
	<li><span class="filename">src/common/common_implicit_link.i</span></li>
	
	<li><span class="filename">src/CLI/diagnostics.c</span></li>
	
	<li><span class="filename">include/SynesisSoftware/SourceTools/program_identity_globals.h</span></li>
	
	<li><span class="filename">include/SynesisSoftware/SourceTools/standard_argument_helpers.h</span></li>
	
	<li><span class="filename">src/CLI/show_usage.c</span></li>
	
	<li><span class="filename">src/CLI/standard_argument_helpers.cpp</span></li>
	
	<li><span class="filename">src/CLI/main.cpp</span></li>
	
	<li><span class="filename">src/CLI/tool_main_outer.cpp</span></li>
</ul>

<p>The files <span class="filename">core.h</span> and <span class="filename">common_implicit_link.i</span> serve the same functions as their <strong>libCLImate</strong>  analogues. But because all programs in the program suite have common diagnostics, the latter file also includes implicit link inclusions for Pantheiosâ€™ <code>fe.simple</code> front-end and <code>be.N</code> multiplexing back-end (in conjunction with the <code>console</code>, <code>file</code> and <code>WindowsDebugger</code> concrete back-ends).</p>

<p>The file <span class="filename">diagnostics.c</span> contains the program suite-specific back-end customisations, a small part of which is shown in Listing 6.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
/* application-defined callbacks */
PANTHEIOS_CALL(void)
pantheios_be_WindowsDebugger_getAppInit(
  int                             backEndId
, pan_be_WindowsDebugger_init_t*  init
) /* throw() */
{
  STLSOFT_SUPPRESS_UNUSED(backEndId);

  init-&gt;flags |=
    PANTHEIOS_BE_INIT_F_NO_PROCESS_ID;
  init-&gt;flags |= PANTHEIOS_BE_INIT_F_HIDE_DATE;
  init-&gt;flags |=
    PANTHEIOS_BE_INIT_F_HIGH_RESOLUTION;
}
. . .
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 6</td>
	</tr>
</table>

<p>The file <span class="filename">program_identity_globals.h</span> declares a bunch of global constants that collectively define the identity and version of the given program (see Listing 7). The definitions of these constants are provided in each programâ€™s <span class="filename">identity.cpp</span> file (defined as described in <a href="#[2]">[2]</a>).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;SynesisSoftware/SourceTools/common.h&gt;

/* application-defined globals */
#ifdef __cplusplus

extern &quot;C&quot;  const int         sourcetoolVerMajor;
extern &quot;C&quot;  const int         sourcetoolVerMinor;
extern &quot;C&quot;  const int         sourcetoolVerRevision;
extern &quot;C&quot;  const int         sourcetoolBuildNumber;

extern &quot;C&quot;  char const* const sourcetoolToolName;
extern &quot;C&quot;  char const* const sourcetoolSummary;
extern &quot;C&quot;  char const* 
  const sourcetoolCopyright;
extern &quot;C&quot;  char const* const
  sourcetoolDescription;
extern &quot;C&quot;  char const* const sourcetoolUsage;

#else /* ? __cplusplus */
extern      const int         sourcetoolVerMajor;
. . .

#endif /* __cplusplus */
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 7</td>
	</tr>
</table>

<p>The file <span class="filename">standard_argument_helpers.h</span> declares a number of helper functions that are useful when processing the command-line (Listing 8).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
int SS_SrcTools_show_usage(
  clasp_arguments_t const*  args
, clasp_alias_t const*      aliases
, FILE*                     stm
);
int SS_SrcTools_show_version(
  clasp_arguments_t const*  args
, clasp_alias_t const*      aliases
, FILE*                     stm
);
void SS_SrcTools_display_usage_and_ \
    rewind_if_requested(
  clasp_arguments_t const*  args
, char const*               flagLongForm
, FILE*                     stm
);
void SS_SrcTools_display_version_and_ \
    rewind_if_requested(
  clasp_arguments_t const*  args
, char const*               flagLongForm
, FILE*                     stm
);
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 8</td>
	</tr>
</table>

<p>As can be seen plainly, these functions do not have a list of parameters as long as your arm: thatâ€™s because each one is defined (in <span class="filename">show_usage.c</span> and <span class="filename">standard_argument_helpers.cpp</span>) in terms of the requisite <strong>libCLImate</strong> API functions passing the identity globals as appropriate. This leads to much more transparent (and maintainable) application code.</p>

<p>But the real gain is in the two files not yet mentioned: <span class="filename">main.cpp</span> and <span class="filename">tool_main_outer.cpp</span>. <span class="filename">main.cpp</span> (Listing 9 includes <span class="filename">libclimate/main.hpp</span> and defines the (<strong>libCLImate</strong>-perspective) effective entry point <code>libCLImate_program_main()</code> in terms of the declared function <code>tool_main_outer()</code>, which it calls after first checking for, and reacting to, the <code>--help</code> and <code>--version</code> UNIX-standard flags.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;SynesisSoftware/SourceTools/
  program_identity_globals.h&gt;
#include &lt;SynesisSoftware/SourceTools/
  standard_argument_helpers.h&gt;
#include &lt;libclimate/main.hpp&gt;

extern &quot;C++&quot;
int
tool_main_outer(
  clasp::arguments_t const* args
);
int
libCLImate_program_main(
  clasp::arguments_t const* args
)
{
  namespace ssst = SynesisSoftware::SourceTools;

  /* process standard flags */
  ssst::display_usage_and_unwind_if_requested(
    args, &quot;--help&quot;, stdout);
  ssst::display_version_and_unwind_if_requested(
    args, &quot;--version&quot;, stdout);

  /* process command-line */
  return tool_main_outer(args);
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 9</td>
	</tr>
</table>

<p>The function <code>tool_main_outer()</code> is defined in <span class="filename">tool_main_outer.cpp</span> (Listing 10) in terms of the declared (<strong>libSrcToolMain</strong>-perspective) effective entry point <code>tool_main_inner()</code> which it invokes within a try-catch whose catch clauses handle program suite-specific exceptions in a suite-common manner.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
extern &quot;C++&quot;
int
tool_main_inner(
  clasp::arguments_t const* args
);

int
tool_main_outer(
  clasp::arguments_t const* args
)
{
  try
  {
    return tool_main_inner(args);
  }
  catch(&lt;ps-specific-exc1&gt;&amp; x)
  {
    . . .
  }
  . . .
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 10</td>
	</tr>
</table>

<p>While that might seem a lot of code to present in an article, itâ€™s pretty small in terms of a library, and it allows <em>all</em> programs within the program suite to substantially reduce the amount of boilerplate, such that each programâ€™s <span class="filename">entry.cpp</span> (defined as described in <a href="#[2]">[2]</a>) consists solely of the <code>libCLImate_aliases</code> array definition and the effective program entry <code>point tool_main_inner()</code>, as shown in Listing 11 (extracted from the <strong>fsrtax</strong> source toolâ€™s <span class="filename">entry.cpp</span>). The result is maximised application-specific code : boilerplate ratio in each programâ€™s <span class="filename">entry.cpp</span>; all the program suite-specific boilerplate is in the program suite library, and all the CLI boilerplate is in <strong>libCLImate</strong>.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &quot;fsrtax.hpp&quot;
#include &quot;identity.h&quot;
#include &lt;SynesisSoftware/SourceTools/program_identity_globals.h&gt;
. . .
extern &quot;C&quot;
clasp::alias_t const libCLImate_aliases[] =
{
  // standard flags
  SS_SRCTOOLS_STD_FLAG_help(),
  SS_SRCTOOLS_STD_FLAG_version(),

  // program logic
  CLASP_BIT_FLAG(&quot;-D&quot;, &quot;--details&quot;,
    FSRTAX_F_SHOW_DETAILS,
    &quot;displays all details&quot;),
  . . .
  CLASP_ALIAS_ARRAY_TERMINATOR
};
extern &quot;C++&quot;
int
tool_main_inner(
  clasp::arguments_t const* args
)
{
  int flags = clasp::check_all_flags(args,
    libCLImate_aliases);
  . . .
  clasp::verify_all_options_used(args);
  . . .
  return process(flags, . . .);
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 11</td>
	</tr>
</table>

<h2>Summary</h2>

<p>For all that frameworks are loathsome things, restricting freedom and constraining choice, they are often a necessary evil in programming, because sometimes the advantages outweigh the disadvantages. I believe <strong>libCLImate</strong> represents just such a net-positive balance, and have been using it for some time now to focus mostly on the interesting parts of my CLI projects.</p>

<h3>Next time</h3>

<p>In the next instalment (which may be a while because Iâ€™m starting a new job next week!), I want to move away from C and C++ for a bit, perhaps to something a bit more modern such as Go, or maybe flesh out the structure Iâ€™ve adapted for writing Ruby CLI programs of late.</p>

<h2>Acknowledgements</h2>

<p>Thanks to Garth Lancaster for review pointers, and to Steve Love for editorial patience.</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[1]"></a>[1]	Anatomy of a CLI Program written in C, Matthew Wilson, <em>CVu</em> September 2012.</p>

<p class="bibliomixed"><a id="[2]"></a>[2]	Anatomy of a CLI Program written in C++, Matthew Wilson, <em>CVu</em> September 2015.</p>

<p class="bibliomixed"><a id="[3]"></a>[3]	<a href="https://en.wikipedia.org/wiki/Adaptive_Communication_Environment">https://en.wikipedia.org/wiki/Adaptive_Communication_Environment</a></p>

<p class="bibliomixed"><a id="[4]"></a>[4]	<a href="http://c2.com/cgi/wiki?ExecuteAroundMethod">http://c2.com/cgi/wiki?ExecuteAroundMethod</a></p>

<p class="bibliomixed"><a id="[5]"></a>[5]	An Introduction to CLASP, part 1: C, Matthew Wilson, <em>CVu</em>, January 2012</p>

<p class="bibliomixed"><a id="[6]"></a>[6]	<a href="http://pantheios.org/; http://github.com/synesissoftware/Pantheios">http://pantheios.org/; http://github.com/synesissoftware/Pantheios</a></p>

<p class="bibliomixed"><a id="[7]"></a>[7]	<a href="http://recls.org/; http://github.com/synesissoftware/recls">http://recls.org/; http://github.com/synesissoftware/recls</a></p>

<p class="bibliomixed"><a id="[8]"></a>[8]	<a href="http://pantheios.org/; http://github.com/synesissoftware/Pantheios.Extras.Main">http://pantheios.org/; http://github.com/synesissoftware/Pantheios.Extras.Main</a></p>

<p class="bibliomixed"><a id="[9]"></a>[9]	<a href="http://pantheios.org/; http://github.com/synesissoftware/Pantheios.Extras.DiagUtil">http://pantheios.org/; http://github.com/synesissoftware/Pantheios.Extras.DiagUtil</a></p>

<p class="bibliomixed"><a id="[10]"></a>[10]	Quality Matters 5: Exceptions: The Worst Form of Exception Handling, Apart From All the Others, Matthew Wilson, <em>Overload</em>, #98, August 2010</p>

<p class="bibliomixed"><a id="[11]"></a>[11]	Quality Matters 6: Exceptions For Practically-Unrecoverable Conditions, Matthew Wilson, Overload, #99, October 2010</p>

<p class="bibliomixed"><a id="[12]"></a>[12]	<a href="http://stlsoft.org/; http://github.com/synesissoftware/STLSoft-1.9">http://stlsoft.org/; http://github.com/synesissoftware/STLSoft-1.9</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
