Coan is a software engineering tool for investigating configurations of C or C++ source code. It is a commandline tool. A configuration is a list of assumptions about the status of some preprocessor symbols when the source code is compiled. You can assume that a symbol is defined, possibly with a specified value, or assume that a symbol is undefined. Here is an example configuration as you would write it on the commandline:

-DARCH=X86 -UDEBUG -DLINUX -UWINDOWS -DMAJOR_VER=4 -DMINOR_VER=3 -DPATCH_VER=2

This configuration expresses the preprocessor assumptions:

#define ARCH X86
#undef DEBUG
#define LINUX
#undef WINDOWS
#define MAJOR_VER 4
#define MINOR_VER 3
#define PATCH_VER 2

Coan applies a given configuration to all the source files you specify to let you observe its effects. It is important to understand that Coan will consider a symbol to be undefined only if you state an assumption to that effect, or use the --implicit option. By default, if a symbol is not mentioned in any of your assumptions then Coan considers it undetermined: not defined and not undefined.

Source files might themselves contain #define or #undef directives that are active under the given configuration and which may influence its effects. To capture that influence, Coan temporarily adds each active #define or #undef directive to the configuration just for the duration of the source file in which it is found.

Given a configuration and some source code, Coan can answer a range of questions about how the source code would appear to the C/C++ preprocessor if that configuration of symbols had been applied in advance.

The most useful of the questions that Coan can answer is:

What would the source code look like if re-written with all of the simplifications that follow from the given configuration?

Coan can produce the simplified re-write that answers this question. So, if the source code contains redundant preprocessor clutter that is controlled by the status of some preprocessor symbols, Coan can be given a configuration that expresses what the status of those symbols should be, and it will output a new version of the source code from which the redundant clutter has been eliminated. Or, if the source code is obscured by preprocessor logic that differentiates several variants by reference to preprocessor symbols, Coan can be given a configuration that specifies any of these variants and will be able to generate a simpler version of the source code that represents only the specifed variant.

For example, if a copy of your source code is in the current directory, you can apply the example configuration above with the command:

$>coan source -DARCH=X86 -UDEBUG -DLINUX -UWINDOWS -DMAJOR_VER=4 -DMINOR_VER=3 -DPATCH_VER=2 --replace *.c .*h

This will replace all the .c and .h files in the current directory with versions that have been simplified in accordance with the chosen configuration.

Or, if the source code is organised under a directory called app, you can achieve the same effect with the command:

$>coan source -DARCH=X86 -UDEBUG -DLINUX -UWINDOWS -DMAJOR_VER=4 -DMINOR_VER=3 -DPATCH_VER=2 --filter c,h --recurse app

Source code re-written by Coan is not preprocessed code as produced by the C preprocessor. It still contains comments, macro-invocations, and #-directives. It is still source code, but simplified in accordance with the chosen configuration.

Coan strives to be an accurate and nearly complete parser for the C preprocessor language. (The conspicuous omission at this time is expansion of function-like macros). This enables it to apply simplifications to source code that depend upon complex #if conditions, e.g. given the configuration above, Coan will be able to evaluate an #if condition such as:

#if (defined(LINUX) && \
DEBUG == 0 && (MAJOR_VER >= \
4 && ((MINOR_VER == 3 && PATCH_VER < 3) || PREQ_9631)))
/* Retain... */
#else
/* Drop... */
#endif

and will output only the code commented /* Retain... */ - despite the fact that PREQ_9631 is an unknown symbol.

And where Coan is unable to fully evaluate an #if condition on the basis of the configuration, it will still simplify the condition as much as the configuration permits. E.g. given the configuration above, Coan would simplify the code:

#if (defined(LINUX) && \
DEBUG == 0 && (MAJOR_VER >= \
4 && (MINOR_VER == 3 && PATCH_VER < 3 && PREQ_9631)))
/* Retain... */
#else
/* Drop... */
#endif

to:

#if PREQ_9631
/* Retain... */
#else
/* Drop... */
#endif

Other questions that Coan can answer include ones about the preprocessor symbols that appear in the source code and their properties under a given configuration, e.g.

What symbols would appear within active preprocessor directives under a given configuration?

(A preprocessor directive is active if it is not within the scope of any false #if). Supposing again that you are interested in the C-source in app, you can display a list of these symbols, with file names and line numbers, with the command:

$>coan symbols --recurse --locate --active --once --filter c,h app

Coan can also answer a range of questions about any category of preprocessor directive that might appear in the source code, e.g.

What #include directives that import system header files are operative under a given configuration?

You can list these #include directives from the C-source in app with the command:

$>coan includes --recurse --system --locate --active --filter c,h app

As these examples indicate, a Coan command has the form:

coan command [options] [{ file | directory }...]

where command specifies the type of analysis you want to run, options are parameters of the analysis, and { file | directory }... are the files or directories containing the source code you want to analyse. The full set of Coan commands is:

source
symbols
includes
defs
pragmas
errors
directives
help
version

Complete documentation of these commands and their options is given in The Coan Man Page.