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:
The defined symbols cannot spread over more than one line, i.e. you cannot use the backslash character to escape the line break.
Symbol substitution is done inside comments (which should not be a problem) and strings. If you stick to all-uppercase symbols, the latter won’t do much harm either. It could even be used to make chunks of text variable. It’s not a clean implementation, though.
There is no way to define macros.
The preprocessor does not recognise the Inform symbols. As a special case, the
TARGET_GLULX
/TARGET_ZCODE
constants are defined depending on a-G
flag being passed to the biplatform compiler or not. TheWORKSIZE
,DEBUG
,STRICT
andINFIX
variables are not set, however. These affect mainly the libraries.The system call to Inform redirects the output from the strout which works fine for Windows/DOS. On other systems, the output might be sent to
stderr
or to bothstdout
andstderr
, depending on the nature of the message. In that case, you’ll have to change the>
in the system call (search forsystem
below) to>&>
or2>
or somthing like that.