<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>A Qualified Replacement for #pragma once</title>
<meta name="date" content="2016-10-27" />
<meta name="author" content="Matthew Woehlke (mwoehlke.floss&#64;gmail.com)" />
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
  overflow: hidden;
}

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left, .figure.align-left, object.align-left {
  clear: left ;
  float: left ;
  margin-right: 1em }

img.align-right, .figure.align-right, object.align-right {
  clear: right ;
  float: right ;
  margin-left: 1em }

img.align-center, .figure.align-center, object.align-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.align-left {
  text-align: left }

.align-center {
  clear: both ;
  text-align: center }

.align-right {
  text-align: right }

/* reset inner alignment in figures */
div.align-right {
  text-align: inherit }

/* div.align-center * { */
/*   text-align: left } */

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font: inherit }

pre.literal-block, pre.doctest-block, pre.math, pre.code {
  margin-left: 2em ;
  margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
  border: 0px;
  border-top: 2px solid;
  border-bottom: 2px solid;
  border-collapse: collapse;
}
table.docutils.booktabs * {
  border: 0px;
}
table.docutils.booktabs th {
  border-bottom: thin solid;
  text-align: left;
}

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="a-qualified-replacement-for-pragma-once">
<h1 class="title">A Qualified Replacement for <tt class="docutils literal">#pragma once</tt></h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Document:</th><td class="field-body">P0538R0</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
<td>2016-10-27</td></tr>
<tr class="field"><th class="docinfo-name">Project:</th><td class="field-body">ISO/IEC JTC1 SC22 WG21 Programming Language C++</td>
</tr>
<tr class="field"><th class="docinfo-name">Audience:</th><td class="field-body">Evolution Working Group</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Matthew Woehlke (<a class="reference external" href="mailto:mwoehlke.floss&#64;gmail.com">mwoehlke.floss&#64;gmail.com</a>)</td></tr>
</tbody>
</table>
<style>
  html { color: black; background: white; }
  table.docinfo { margin: 2em 0; }
  p, li { text-align: justify; }
</style><div class="section" id="abstract">
<h1><a class="toc-backref" href="#id2">Abstract</a></h1>
<p>This proposal recommends to standardize <code class="cpp c++"><span class="comment preproc">#once
</span></code> as an improved mechanism for preventing multiple inclusion of a header, and a related directive <code class="cpp c++"><span class="comment preproc">#forget
</span></code>.</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#abstract" id="id2">Abstract</a></li>
<li><a class="reference internal" href="#problem" id="id3">Problem</a></li>
<li><a class="reference internal" href="#proposal" id="id4">Proposal</a><ul>
<li><a class="reference internal" href="#once" id="id5"><code class="cpp c++"><span class="comment preproc">#once
</span></code></a></li>
<li><a class="reference internal" href="#forget" id="id6"><code class="cpp c++"><span class="comment preproc">#forget
</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#comments-and-examples" id="id7">Comments and Examples</a><ul>
<li><a class="reference internal" href="#static-analysis" id="id8">Static Analysis</a><ul>
<li><a class="reference internal" href="#example" id="id9">Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#proper-use-of-versioning" id="id10">Proper Use of Versioning</a><ul>
<li><a class="reference internal" href="#id1" id="id11">Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#performance" id="id12">Performance</a></li>
</ul>
</li>
<li><a class="reference internal" href="#discussion" id="id13">Discussion</a><ul>
<li><a class="reference internal" href="#why-not-reuse-pragma" id="id14">Why not reuse <code class="cpp c++"><span class="comment preproc">#pragma
</span></code>?</a></li>
<li><a class="reference internal" href="#won-t-modules-make-this-irrelevant" id="id15">Won't modules make this irrelevant?</a></li>
<li><a class="reference internal" href="#shouldn-t-this-go-to-c-first" id="id16">Shouldn't this go to C first?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#summary" id="id17">Summary</a></li>
<li><a class="reference internal" href="#acknowledgments" id="id18">Acknowledgments</a></li>
</ul>
</div>
</div>
<div class="section" id="problem">
<h1><a class="toc-backref" href="#id3">Problem</a></h1>
<p>It is well known that when compiling code of non-trivial complexity, the complete set of <code class="cpp c++"><span class="comment preproc">#include
</span></code> directives may reference the same header more than once. This often occurs when a translation unit uses several distinct components which each rely on the same base component (especially library configuration headers, headers that provide export decoration symbols, and the like). While this is correct for each component header in order to allow it to be used on its own, the combination of multiple components requires a mechanism to prevent the definitions in a header from being parsed twice, which would lead to compile errors.</p>
<p>Traditionally, this is accomplished with &quot;include guards&quot;, which take the form:</p>
<pre class="code c++ literal-block">
<span class="comment single">// foo.h
</span><span class="comment preproc">#ifndef _MYLIB_FOO_H_INCLUDED
#define _MYLIB_FOO_H_INCLUDED
</span><span class="punctuation">...</span>
<span class="comment preproc">#endif </span><span class="comment single">// _MYLIB_FOO_H_INCLUDED</span>
</pre>
<p>At least one problem with this is obvious; the guard symbol is repeated as many as three times (the last occurrence in the comment is optional and at least has no impact on compiling if it is incorrect), leading to the possibility of mistakes when retyping the symbol that cause the guard to be ineffective. Less obvious, but even more problematic, it is common for headers to be copied, which can lead to difficult to diagnose errors if the programmer neglects to adjust the guard when doing so.</p>
<p>Some compilers support <tt class="docutils literal">#pragma once</tt> as an alternate mechanism for preventing multiple inclusions. However, many problems with this mechanism are known. It is difficult for compiler authors to implement correctly, especially in the presence of pathological source trees (involving copies of headers, whether by symlink, or worse, the same physical file accessible via different mount points). There is also a question of how distinct headers providing similar definitions should be handled. These problems are well addressed by traditional include guards.</p>
</div>
<div class="section" id="proposal">
<h1><a class="toc-backref" href="#id4">Proposal</a></h1>
<p>We propose to introduce three new preprocessor directives in an attempt to address this issue.</p>
<div class="section" id="once">
<h2><a class="toc-backref" href="#id5"><code class="cpp c++"><span class="comment preproc">#once
</span></code></a></h2>
<blockquote>
<strong>#once</strong> <em>identifier</em> [ <em>&lt;whitespace&gt;</em> <em>version</em> ]</blockquote>
<p>The <em>identifier</em> shall consist of one or more C++ identifiers (sequences of alphanumeric characters and/or <tt class="docutils literal">_</tt>, not starting with a digit) joined by <tt class="docutils literal">::</tt> (henceforth referred to as a &quot;qualified name&quot;). The <em>version</em>, if specified, shall be a token string consisting of alphanumeric characters and/or the <tt class="docutils literal">_</tt> or <tt class="docutils literal">.</tt> characters, or a string literal, and shall set the version associated with the specified <em>identifier</em>.</p>
<p>If a previous <code class="cpp c++"><span class="comment preproc">#once
</span></code> directive having the same <em>identifier</em> and <em>version</em> has been previously seen, the compiler shall ignore the remainder of the <code class="cpp c++"><span class="comment preproc">#include
</span></code> unit. If the <em>identifier</em> is known but the <em>version</em> does not match, the program shall be ill-formed. (If <em>version</em> is unspecified, the version shall be the empty string.)</p>
</div>
<div class="section" id="forget">
<h2><a class="toc-backref" href="#id6"><code class="cpp c++"><span class="comment preproc">#forget
</span></code></a></h2>
<blockquote>
<strong>#forget</strong> <em>identifier</em></blockquote>
<p>The compiler shall remove the <em>identifier</em> from its collection of previously seen identifiers. This directive provides a mechanism to force the multiple inclusion of an <code class="cpp c++"><span class="comment preproc">#include
</span></code> unit which uses <code class="cpp c++"><span class="comment preproc">#once
</span></code>.</p>
</div>
</div>
<div class="section" id="comments-and-examples">
<h1><a class="toc-backref" href="#id7">Comments and Examples</a></h1>
<div class="section" id="static-analysis">
<h2><a class="toc-backref" href="#id8">Static Analysis</a></h2>
<p>As mentioned, one of the problems with traditional guards is that they can easily get out of sync with the header file they guard. While it is possible to write static analysis tools to detect such errors, the proliferation of different styles of guards make it difficult to write a single heuristic that works across a broad base of existing software. In turn, this means that such tools tend to be project specific and are at best run when code is committed to a repository. It would be far better for such checks to be integrated into the compiler, so that they run at build time, and can be promoted to errors.</p>
<p>We address this by making the guard identifier a qualified name. Besides being more consistent with C++ conventions (for example, the namespace of the guard could match the namespace of the project which owns the header), this, combined with the introduction of a new feature, makes it straight forward to stipulate that the unqualified portion of the identifier shall match the name of the <code class="cpp c++"><span class="comment preproc">#include
</span></code> unit (excluding a file extension, if any).</p>
<p>Moreover, it is not inconceivable that we could agree that the namespace portion of the qualified identifier shall match the namespace of the definitions provided by the <code class="cpp c++"><span class="comment preproc">#include
</span></code> unit (so that all parts of the guard identifier are checked for correctness), with the compiler issuing a diagnostic if the <code class="cpp c++"><span class="comment preproc">#include
</span></code> unit does not include at least one declaration in the same namespace.</p>
<p>Since we are talking about QoI issues here, we feel that it is not necessary that these checks be normative. Instead, we would prefer to let the compiler community agree on what conventions should be expected and diagnosed.</p>
<div class="section" id="example">
<h3><a class="toc-backref" href="#id9">Example</a></h3>
<pre class="code c++ literal-block">
<span class="comment single">// foo.h
</span><span class="comment preproc">#once MyLibrary::bar </span><span class="comment single">// warning: guard should be 'MyLibrary::foo'
</span>
<span class="comment single">// bar.h
</span><span class="comment preproc">#once bar </span><span class="comment single">// warning: guard should be namespaced
</span>
</pre>
</div>
</div>
<div class="section" id="proper-use-of-versioning">
<h2><a class="toc-backref" href="#id10">Proper Use of Versioning</a></h2>
<p>Although the &quot;obvious&quot; way to use version directives is to include the version of the software package to which a header belongs in every single header, this leads to an obvious and significant maintenance burden. A better solution which will be equally adequate in almost every instance is to maintain such version information in a single, global header file (e.g. <tt class="docutils literal">version.h</tt>, <tt class="docutils literal">config.h</tt>, <tt class="docutils literal">exports.h</tt>) which is always included via an <code class="cpp c++"><span class="comment preproc">#include
</span></code> directive (prior to <code class="cpp c++"><span class="comment preproc">#once
</span></code>) whose path is marked with quotes (<tt class="docutils literal">&quot;&quot;</tt>) rather than angle brackets (<tt class="docutils literal">&lt;&gt;</tt>). This ensures that the global header is always found in a known location relative to the header being processed, and will in almost all cases be sufficient to catch mismatching versions of the header which includes the global header.</p>
<p>Another option, which can be employed in tandem, is to use a monotonically increasing version number that is unique to each header and is incremented whenever the interface(s) defined in the header change. Because this number is unique to the header, and only changes when the header changes (and possibly not even that frequently), the maintenance burden is significantly reduced.</p>
<p>The relatively liberal specification of allowed version strings was chosen with the specific intention of encouraging the version string to be generated by the build system, and in particular to allow the version string to include a VCS identifier. In this way, we may ensure that headers from a development version of software are not mixed with those from a release version or different development version, even if the normative version number does not differ between such versions.</p>
<div class="section" id="id1">
<h3><a class="toc-backref" href="#id11">Example</a></h3>
<pre class="code c++ literal-block">
<span class="comment single">// version.h
</span><span class="comment preproc">#once MyLibrary::version 0.1.0 </span><span class="comment single">// MyLibrary version 0.1.0
</span>
<span class="comment single">// widget.h
</span><span class="comment preproc">#include &quot;version.h&quot;
#once MyLibrary::widget 2 </span><span class="comment single">// widget API version 2
</span>
<span class="comment single">// common.h
</span><span class="comment preproc">#include &quot;version.h&quot;
#once MyLibrary::common </span><span class="comment single">// no version
</span>
</pre>
</div>
</div>
<div class="section" id="performance">
<h2><a class="toc-backref" href="#id12">Performance</a></h2>
<p>One of the points that is frequently raised in favor of <code class="cpp c++"><span class="comment preproc">#pragma once
</span></code> is that it allows the compiler to skip reading a file that it has already included. However, the problem with this is that if the compiler is not able to correctly determine if a header has already been included, it is likely that the translation unit will fail to compile.</p>
<p>In fact, compilers may and do already implement similar logic for traditional include guards. By employing a heuristic, a compiler may determine that a header's contents are entirely guarded. Having done so, the header and its guard may be entered into a map, such that the compiler may choose not to read the header a second time if it observes that an <code class="cpp c++"><span class="comment preproc">#include
</span></code> directive would reference a header that has been previously processed and whose include guard is defined. This is safer, since in case of a wrong guess, the compiler will read the header anyway and process it as empty due to the traditional guard, which has a small performance penalty but does not affect correctness of the program.</p>
<p>Our model for <code class="cpp c++"><span class="comment preproc">#once
</span></code> provides these same benefits, while making explicit (and enforcing) that the entire header may be skipped if the compiler &quot;knows&quot; it has been included already. The proposed directive therefore provides the same performance benefits as <code class="cpp c++"><span class="comment preproc">#pragma once
</span></code>, but without the potential pitfalls. (In cases such as described above, where one or more <code class="cpp c++"><span class="comment preproc">#include
</span></code> directives precede <code class="cpp c++"><span class="comment preproc">#once
</span></code>, the compiler would need to track the recursive set of guards which make a second inclusion a no-op. While somewhat more complicated, this still seems achievable.)</p>
</div>
</div>
<div class="section" id="discussion">
<h1><a class="toc-backref" href="#id13">Discussion</a></h1>
<div class="section" id="why-not-reuse-pragma">
<h2><a class="toc-backref" href="#id14">Why not reuse <code class="cpp c++"><span class="comment preproc">#pragma
</span></code>?</a></h2>
<p>The obvious answer is that <code class="cpp c++"><span class="comment preproc">#pragma
</span></code> as a whole is implementation defined. Choosing an entirely new directive makes it clear that this feature is &quot;blessed&quot; by the standard and not an implementation defined feature. The exact names used, however, are subject to the usual bikeshedding. We would encourage the committee to consider the feature first on its merits; if it seems useful, we are completely open to choosing some other name or even syntax for the directives. (It might even make sense to use a syntax that is evocative of that used by modules.)</p>
</div>
<div class="section" id="won-t-modules-make-this-irrelevant">
<h2><a class="toc-backref" href="#id15">Won't modules make this irrelevant?</a></h2>
<p>It is possible that modules will significantly reduce the need for this feature, but modules aren't here yet, and it is likely that we will continue to have traditional headers for a long time. Since this feature happens entirely at the preprocessor level, it is our sincere hope that compilers will choose to implement the feature early, and enable it regardless of the language level requested. This means that existing software may be able to take advantage of the feature much sooner than such software can be ported to modules (which will involve a much more invasive change).</p>
</div>
<div class="section" id="shouldn-t-this-go-to-c-first">
<h2><a class="toc-backref" href="#id16">Shouldn't this go to C first?</a></h2>
<p>While we would certainly love to see this feature adopted by C as well, we don't think it makes sense that preprocessor features <em>must</em> be adopted by C first. In particular, we note that the use of a C++ qualified identifier gives us a very good reason to adopt this feature in C++ first, as C will have to decide to either accept C++ qualified identifiers for this purpose or find an alternate solution that solves the same problems that are addressed by the use of a qualified name.</p>
<p>Moreover, we note that it does not make a significant difference in practice which language adopts a preprocessor feature first. Since most compilers share preprocessor function between C and C++ front-ends, adoption of this feature by C++ will likely make it a de facto C standard.</p>
</div>
</div>
<div class="section" id="summary">
<h1><a class="toc-backref" href="#id17">Summary</a></h1>
<p>We have shown a mechanism for implementing a next generation system for preventing multiple inclusion of headers. This system is semantically equivalent to traditional guards, and so avoids the known issues of present implementations of <code class="cpp c++"><span class="comment preproc">#pragma once
</span></code> (without an identifier). By also providing a <code class="cpp c++"><span class="comment preproc">#forget
</span></code>, we address the issue of how to force multiple inclusion when necessary in a way that does not require editing the header in question. By using a qualified identifier, we provide an improved mechanism for avoiding collisions that is also amenable to the use of static analysis tools to detect the sorts of improper use that are the major complaint against traditional guards. By also specifying an optional mechanism for providing version information, we provide a means to diagnose accidental mixing of different versions of headers.</p>
</div>
<div class="section" id="acknowledgments">
<h1><a class="toc-backref" href="#id18">Acknowledgments</a></h1>
<p>We wish to thank Hans Guijt for complaining loudly enough about standardizing <code class="cpp c++"><span class="name">pragma</span> <span class="name">once</span></code> that we decided to actually write a proposal, Tim Song for valuable feedback on the initial draft, and everyone else on the <tt class="docutils literal"><span class="pre">std-proposals</span></tt> forum that contributed comments on this topic.</p>
<!-- .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. -->
<!-- kate: hl reStructuredText -->
</div>
</div>
</body>
</html>
