<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
                      "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
  <title>Replacing define's with const's in VTK 3.1.2</title>
  <meta http-equiv="Content-Type" content="text/html">
</head>

<body>
<h1>Replacing define's with const's in VTK 3.1.2</h1>

<h2>1 Experiment</h2>

<h3>1.1 Introduction</h3>

<p>To improve the usability of <em>VTK</em> I decided to investigate the
posibility of converting all <code>#define</code>'s into <code>const</code>'s,
where appropriate. The focus was on numeric constants.</p>

<h3>1.2 Procedure</h3>

<p>Code modifications were restricted to the <code>common</code>,
<code>graphics</code> and <code>imaging</code> directories. These directories
represent the library core and are of the most interest. To convert the
<code>#define</code>'s a <em>perl</em> script was written to automatically
search for the pattern:</p>
<pre><code>        #define identifier numeric-literal comment</code></pre>

<p>and replace it with:</p>
<pre><code>        comment
        const numeric-literal-type identifer = numeric-literal;</code></pre>

<p>There are actually a few subtle details involved in this change that must
be explained.</p>

<p>The change from <code>#define</code> to <code>const</code> does not
introduce any extra run-time overhead, in general. There may be a few
pathological cases where this is not true as we'll see.</p>

<p>The type of a floating point literal is easy to determine. No suffix makes
the type <code>double</code>, the suffix <code>F</code> makes the type
<code>float</code>, and the suffix <code>L</code> makes the type <code>long
double</code>. (ARM, p.10)</p>

<p>The type of an integer literal is somewhat complicated. The type depends on
the base in which the literal is written, the architecture's word size, any
suffix modifiers and the value of the literal. With all these constraints, in
general, the goal is to pick the smallest type possible of <code>int</code>,
<code>unsigned int</code>, <code>long int</code> or <code>unsigned long
int</code> that will hold the literal. The first thing to evaluate is the
suffix: <code>U</code> makes the type <code>unsigned int</code> or
<code>unsigned long int</code>, <code>L</code> makes the type <code>long
int</code> or <code>unsigned long int</code>, and <code>UL</code> uniquely
determines the type to be <code>unsigned long int</code>. Next, assuming the
absence of <code>UL</code>, the base is evaluated, if it is base10 and there
is no <code>U</code> suffix, then the type can not be <code>unsigned
int</code>, otherwise the type can be any one of the four possible types
subject, of course, to the previously determined suffix constraints. Finally,
the type is chosen as the smallest choice that will hold the value. This final
type decision is of course, machine dependent.(ARM, p.8)</p>

<p>What all this means is that going from a <code>#define</code> to a
<code>const</code> fixes the type of the literal to be the same on all
platforms. One, possibly negative, aspect of this is that some numbers that
could be represented as an <code>int</code> on a 64-bit word architecture will
instead be stored as <code>long int</code> since the word size was assumed to
be 32-bit when the code changes were made. This could also mean that the code
will no longer compile on a 16-bit word machine. In practice I'm not expecting
this to be a serious issue given the code I reviewed.</p>

<p>Finally, <code>const</code> globals have internal linkage. This means that
the constants defined in header files will possibly be replicated in every
object file. I don't think this will add appreciable storage overhead. Having
the constants duplicated in every object file will not cause a problem a
different files accessing different values of the same name, since the values
can not be changed.</p>

<p>Once the code changes were made, a patch file was then generated and
inspected by hand. Further changes were carried out by hand as a result of the
inspection to correct mistakes made by the script.</p>

<p>The warnings patch discussed in, <a
href="http://public.kitware.com/pipermail/vtkusers/2001-February/005589.html">VTK
3.1.2 GCC 2.91.66 Warnings</a> was applied and the library was compiled to
ensure that it still compiled warning free.</p>

<h3>1.3 Results</h3>

<p>The <em>perl</em> script is actually somewhat complex (probably due to my
being a <em>perl</em> novice) and contains several bugs and weaknesses:</p>
<ul>
  <li><code>float</code> and <code>long double</code> literals are not
    detected</li>
  <li>One <code>0</code> was mysteriously not handled properly</li>
  <li>does not remove unecessary <code>#undef</code>'s</li>
  <li>does not deal with <code>#define identifier1 identifier2</code></li>
  <li>can only treat literals as a 32-bit compiler would</li>
  <li>missed <code>#define</code>'s with lower-case identifiers</li>
</ul>

<p>Despite the bugs and weaknesses, the script took me most of the way towards
converting all the <code>#define</code>'s, which is why the script was not
fully debugged. (It was faster to continue on by hand.)</p>

<p>In total, 551 <code>#define</code>'s were changed in 107 files.</p>

<p>To support the use of <code>const</code> instead of <code>#define</code>
and still provide warning free compiles, one code change was required: the
type of <code>vtkDicer::MemoryLimit</code> was changed from <code>unsigned
long</code> to <code>int</code>. This is a safe change since the value of the
member is clamped to a sub-range of <code>int</code>.</p>

<h3>1.4 Patch File</h3>

<p>A patch file, vtk312-define-const.patch (102k), has been created which
cleans up approximately 550 <code>#define</code>'s in <em>VTK 3.1.2</em>. To
apply the patch follow these steps:</p>
<ol>
  <li><code>tar xvf vtk312Unix.tar</code></li>
  <li><code>cd vtk31</code></li>
  <li>copy <code>vtk312-define-const.patch</code> into this directory</li>
  <li><code>patch -p1 &lt; vtk312-define-const.patch</code></li>
  <li><code>./configure</code></li>
  <li><code>make</code></li>
</ol>

<p>Obviously, if you've got an existing install, especially one with your own
patches, you'll want to follow a slightly different procedure. The patch file
was created by <code>diff -r -C2 vtk31-old/ vtk31-new/</code>.</p>

<h3>1.5 Conclusion</h3>

<p>Code changes of any sort can sometimes introduce bugs. I've been very
careful to document my changes and the reasons for them, and to ensure that
the changes I actually made match the documentation. However, there is always
the possibility that I broke something somewhere. Hopefully, I didn't break
anything since the point of this exercise was to improve the code by making it
harder for the preprocessor to screw it up.</p>

<p>-- end --</p>
</body>
</html>