UNIFDEF(1)

UNIFDEF(1) | General Commands Manual | UNIFDEF(1)

# NAME

`unifdef`, `unifdefall` —
remove preprocessor conditionals from code

# SYNOPSIS

`unifdef` | [`-ceklst`] [`-I`path] [`-D`sym[=val]] [`-U`sym] [`-iD`sym[=val]] [`-iU`sym] ... [`-o` output] [file]

`unifdefall` | [`-I`path] ... file

# DESCRIPTION

The `unifdef` utility selectively processes conditional cpp(1) directives. It removes from a file both the directives and any additional text that they specify should be removed, while otherwise leaving the file alone.

The `unifdef` utility acts on `#if`, `#ifdef`, `#ifndef`, `#elif`, `#else`, and `#endif` lines, and it understands only the commonly-used subset of the expression syntax for `#if` and `#elif` lines. It handles integer values of symbols defined on the command line, the `defined`() operator applied to symbols defined or undefined on the command line, the operators `!`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `&&`, `||`, and parenthesized expressions. Anything that it does not understand is passed through unharmed. It only processes `#ifdef` and `#ifndef` directives if the symbol is specified on the command line, otherwise they are also passed through unchanged. By default, it ignores `#if` and `#elif` lines with constant expressions, or they may be processed by specifying the `-k` flag on the command line.

The `unifdef` utility also understands just enough about C to know when one of the directives is inactive because it is inside a comment, or affected by a backslash-continued line. It spots unusually-formatted preprocessor directives and knows when the layout is too odd to handle.

A script called `unifdefall` can be used to remove all conditional cpp(1) directives from a file. It uses `unifdef` `-s` and `cpp` `-dM` to get lists of all the controlling symbols and their definitions (or lack thereof), then invokes `unifdef` with appropriate arguments to process the file.

Available options:

`-D` sym[=val]
  Specify that a symbol is defined, and optionally specify what value to give it for the purpose of handling `#if` and `#elif` directives.
`-U` sym
  Specify that a symbol is undefined. If the same symbol appears in more than one argument, the last occurrence dominates.
`-c`
  If the `-c` flag is specified, then the operation of `unifdef` is complemented, i.e., the lines that would have been removed or blanked are retained and vice versa.
`-e`
  Because `unifdef` processes its input one line at a time, it cannot remove preprocessor directives that span more than one line. The most common example of this is a directive with a multi-line comment hanging off its right hand end. By default, if `unifdef` has to process such a directive, it will complain that the line is too obfuscated. The `-e` option changes the behaviour so that, where possible, such lines are left unprocessed instead of reporting an error.
`-k`
  Process `#if` and `#elif` lines with constant expressions. By default, sections controlled by such lines are passed through unchanged because they typically start “`#if 0`” and are used as a kind of comment to sketch out future or past development. It would be rude to strip them out, just as it would be for normal comments.
`-l`
  Replace removed lines with blank lines instead of deleting them.
`-o` output
  The argument given is the name of an output file to be used instead of the standard output. This file can be the same as the input file.
`-s`
  Instead of processing the input file as usual, this option causes `unifdef` to produce a list of symbols that appear in expressions that `unifdef` understands. It is useful in conjunction with the `-dM` option of cpp(1) for creating `unifdef` command lines.
`-t`
  Disables parsing for C comments and line continuations, which is useful for plain text.
`-iD` sym[=val]
`-iU` sym
  Ignore `#ifdef`s. If your C code uses `#ifdef`s to delimit non-C lines, such as comments or code which is under construction, then you must tell `unifdef` which symbols are used for that purpose so that it will not try to parse comments and line continuations inside those `#ifdef`s. One specifies ignored symbols with `-iD`sym[=val] and `-iU`sym similar to `-D`sym[=val] and `-U`sym above.
`-I` path
  Specifies to `unifdefall` an additional place to look for `#include` files. This option is ignored by `unifdef` for compatibility with cpp(1) and to simplify the implementation of `unifdefall`.

The `unifdef` utility copies its output to stdout and will take its input from stdin if no file argument is given.

The `unifdef` utility works nicely with the `-D`sym option of diff(1).

# DIAGNOSTICS

- Too many levels of nesting.
- Inappropriate `#elif`, `#else` or `#endif`.
- Obfuscated preprocessor control line.
- Premature `EOF` (with the line number of the most recent unterminated `#if`).
- `EOF` in comment.

The `unifdef` utility exits 0 if the output is an exact copy of the input, 1 if not, and 2 if in trouble.

# SEE ALSO

cpp(1), diff(1)

# HISTORY

The `unifdef` command appeared in 4.3BSD. ANSI C support was added in FreeBSD 4.7.

# BUGS

Expression evaluation is very limited.

Preprocessor control lines split across more than one physical line (because of comments or backslash-newline) cannot be handled in every situation.

Trigraphs are not recognized.

There is no support for symbols with different definitions at different points in the source file.

The text-mode and ignore functionality does not correspond to modern cpp(1) behaviour.

June 5, 2009 | NetBSD 9.0