zapif
algebraic simplifies C proprocessor conditionals and removes code that would never be selected by the preprocessor.
Unlike unifdef
, zapif
simplifies conditionals that it cannot eliminate. For example, given a file demo.c
with:
#if foo && bar || quod
void f() {}
#endif
the command ``zapif -Dbar=1 -Dquod=0 demo.c` will produce:
#if foo
void f() {}
#endif
When simplifying a preprocessor directive, zapif
tries to preserve whitespace
and the original form of numerals when simplifying. Literal numerals such as
0
and 1
are treated as unknown values unless the -k
option is present.
Examples of the simplifications that zapif
knows:
- 0 || y -> y
- x || y -> 1 if x or y is nonzero.
- 0 && y -> 0
- 0 | y -> y
- 0 ^ y -> y
- 0 & y -> 0
Algebraic simplifications are limited to ones that seem to be useful for real C++ and C source. If you think I've missed a useful one, please open an issue, ideally with a citation to the source code.
I developed zapif
on Mac OS X, but it should build on Linux without
difficulty. To build zapif
you will need:
- flex 2.5 or 2.6
- bison 2.3 or 3.0
- a C++11 compiler. The default is
g++
.
cd build
make
The 2nd step builds the executable and tests it. If the test fails, you will see output from diff
.
The basic syntax is:
zapif
options [inputfile]
If no input file is specified, input is stdin
.
Output always goes to stdout
.
The recognized options are:
-Dfoo=42
- treatfoo
as having the value42
.-Dfoo
- same as-Dfoo=1
-Ufoo
- treatfoo
as undefined. The preprocessor expressiondefined(foo)
will evaluate to 0, andfoo
will be treated as 0 in other preprocessor expressions.-c
- assume input is C, not C++. Causesand
,false
,not
,or
,true
andxor
to be treated as identifiers instead of their C++ meanings in#if
expressions.-k
- interpret numerals in preprocessor expressions. Without this option, numerals such as0
are treated as unknown values.-n
- normalize#if defined(x)
to#ifdef x
if the whole expression was the result of simplification. Do likewise for#if !defined(x)
and the equivalent parentheses-free forms.-v
- print version information and exit.
- Numerals are recognized as having values only if they fit in a C++
long long
, follow the C conventions for decimal, octal, or hexadecimal, and do not have any suffixes.