Reference Developer Tutorial 1 Introduction 2 Macros 3 Typesetting 4 Example 5 Hints 6 Examples 7 Webmaking SEARCH

5.5 Fudging Conditionals

As a macro preprocessor, one facility that FunnelWeb lacks is a conditional facility (such as C's `#ifdef`). It might, therefore, come as a surprise to know that the FunnelWeb V1 actually had a built in conditional facility. The facility allowed the programmer to specify a construct that would select from one of a number of macro expressions depending on the value of a controlling macro expression.

In three years the construct was never used.

The reason was that conditional constructs could be fudged nearly as easily as they could be used. Because of this, the inbuilt conditional feature was removed in the FunnelWeb V2. Not only did this simplify the program, but is also allowed recursive macros to be detected through static analysis rather than during macro expansion.

There are two basic ways to fudge a conditional. First, the comment facility of the target programming language may be employed. For example, in Ada, comments commence with "`--`" and terminate at the end of the line. Using this fact, it is easy to construct macros that can be called at the start of each target line and which turn on and off the lines so marked by defining the macro to be the empty string (ON) or the comment symbol (`--`) (OFF). For example:

    @A@<Debug Macro@>

    The following macro determines whether debug code
    will be included in the program. All lines of
    debug code commence with a call to this macro and
    so we can turn all that code on or off here by
    defining this macro to be either empty or the
    single-line comment symbol (--). Note
    the use of a quick macro name.

    @$@#D@M==@{@}  @! Turns the debug code ON.
    @! Use this definition to turn
    @! the debug code OFF: @$@#D==@{--@}

    ... then later in the file...

    @$@<Sloth incrementing loop@>==@{@-
    while sloth<walrus loop
       @#D assert(sloth<walrus,"Sloth bomb.");
       @#D assert(timer<timermax,"Timer bomb.");
       inc(sloth);
    end loop@}

The other way to fudge a conditional is to define a macro with a single parameter. A call to the macro is then wrapped around all the conditional code in the program. The macro can then be defined to present or ignore the code of its argument. For example:

    @A@<Debug Macro@>

    The following macro determines whether debug code
    will be included in the program. All debug code is
    wrapped by a call to this macro and so we can turn
    all the debug code on or off here by defining this
    macro to be either empty or its parameter.

    @$@#D@(@1@)@M==@{@1@}  @! Debug code ON.
    @! Use this definition to turn the
    @! debug code OFF: @$@#D@(@1@)==@{@}

    ... then later in the file...

    @$@<Sloth incrementing loop@>==@{@-
    while sloth<walrus loop
       @#D@(assert(sloth<walrus,"Sloth bomb.");
            assert(timer<timermax,"Timer bomb");@)
       inc(sloth);
    end loop@}

In languages that allow multi-line comments (e.g. C with `/*` and `*/`), comments can be used to eliminate the conditioned code rather than absence. For example:

    @! Comments out the debug code
    @$@#D@(@1@)@M==@{/* @1 */@}

(Note: If this example were ever actually used, the programmer would have to be careful not to place comments in the argument code. Nested comments in C are non-portable.)

The parameterized macro idea can be generalized to support the choice of more than one mutually exclusive alternative. For example:

    @A This module contains non-portable code that
    must execute on Hewlett Packard, Sun, and DEC
    workstations. The following FunnelWeb macro is
    defined to choose between these three. The first
    parameter is the HP code, the second is the Sun
    code, and the third is the DEC code. Whichever
    parameter constitutes the body of this macro
    determines which machine the code is being
    targeted for.

    @$@<Machine specific code@>@(@3@)@M==@{@-
    @1@}  @! Configure for HP.

    ...then later in the file...

    @<Machine specific code@>@(
    @"get_command_line(comline)@"           @, @! HP.
    @"scan_command_line(128,comline);@"     @, @! Sun.
    @"dcl_get_command_line(comline,256);@"  @) @! DEC.

Of course, this could also be performed using three separate macros. The main advantage of using a single macro is that the mutual exclusivity is enforced. Also, because FunnelWeb ensures that the number of formal and actual parameters are the same, this method lessens the chance that a machine will be forgotten in some places.

Webmaster Copyright © Ross N. Williams 1992,1999. All rights reserved.