C-like Inform Preprocessor

This is a cheap C-like preprocessor for a conditional compilation of Inform files. This could be used for a single source file containing the data for two languages.

This script was a first draft for a conditional conmpilation and was written in response to a discussion on Rakonto Interactiva. For multilingual compilation of an Inform game, the script lang.pl, which is a logical sucessor to this script here, seems more suitable and easier to use.

The code’s framework, which generates a temporary input file, runs the Inform compiler and then maps the line numbers of the tmp file to the original file numbers, is quite interesting, though, and might be used for other purposes.

Usage:

perl pre.pl [inf-compiler] {inf-options} [src] {game}

or possibly:

./pre.pl [inf-compiler] {inf-options} [src] {game}

[Square brackets] denote mandatory, {curly braces} optional items.

This emulates a C-like preprocessor which passes through the whole text, includes files as necessary, writes one temporary file, evokes the inform compiler with the desired settings and filters the output in order to replace the references to the temporary file into the original places.

[inf-compiler] is the Inform compiler to use, perhaps with a full path name prepended. [src] is the source file and {game} the game file to be written which defaults to the source’s base name with a z-Code suffix.

{inf-options} are the usual options of the Inform compiler, {pre-options} are special to the preprocessor. These options may be interspersed arbitrarily. Notably, preprocesor options may be specified in ICL files. (But note that this renders these files useless for normal Inform compilation. But then, placing question marks in your source code does this, too.)

Preprocessor options:

-P<flag>

sets a special flag for the preprocessor which may be one of:

dry — dry run, just print the compilation command line and exit.

fast — do not replace defined symbols in the source text. This will increase performance and is okay if you just want to use the defined symbols for conditional compilation.

verbose — be verbose on preprocessing. This usually prints reams of text but might be useful for debugging.

-D<symbol>=<value>

Define the preprocessor <symbol> and assign <value> to it. If the equals sign and the value are omitted, a default value of 0 is assigned.

Note that the -D option is also the Inform switch for including the debugging facilities of the Inform library. If you want to use this switch in that sense, put it on its own -D or define it in a sequence of switches where it must not come first. So, -DSX defines the symbol SX, whereas -XDS activates Infix, Debug and Strict Mode which is probably what you want. (The -D syntax was chosen because it looks like the C syntax.)

Since the hash symbol is used by inform for writing directives inside routines (and often outside them, too), the question mark must be used to introduce a preprocessor command. It may be followed by an optional hash sign so that the preprocessor directives look a bit more familiar. Preprocessor directives run up to the end of the line without any trailing comma. There may be white space before the question mark.

This script implements only the most basic of preprocessor directives:

?include "file"

Include the given file name which must be in the present directory. You should only ?include your own modules, library files should be included with Inform’s own Include syntax.

?include <file>

Ditto, but looks in the whole search path for include files as specified with the command line directive +include_path.

?define <symbol> <value>

Define the <symbol> and assign <value>. All occurrences of <symbol> are replaced with <value> in the main body of the source file. The <value> defaults to 0. Unlike Inform symbols, preprocessor symbols are case-sensitive.

?undef <symbol>

Delete <symbol> from the definition table.

?ifdef <symbol>

Include code up to the following ?endif if <symbol> is defined and skip it otherwise. Note that this only applies to symbols defined with ?define, not to Inform symbols. Conditionally compiled blocks may be nested.

?ifndef <symbol>

Like ?ifdef, but includes the following code block if <symbol> is not defined.

?ifnot

This is the “else” of conditional compiling which reverses the effect of the last condition.

?endif

Ends a conditional block.

Download

pre.pl

Inform 6 preprocessor
Doenload zip archive with example

This is a Perl script and requires Perl 5. No special packages are required.

Bugs and Limitations:

This implementation is very basic and it lacks the features of a complete preprocessor. In particular, there are the following issues: