coan(1)
π
coan(1) β C/C++ configuration analyser π
okay bestie, welcome to the coan(1) manual page β the header says User Commmands β and this is your new fave tool for investigating configurations of C or C++ source code. slay
πΈ NAME πΈ
coan β C/C++ configuration analyser
β¨ SYNOPSIS β¨
coan COMMAND [OPTION...] [file...] [directory...]
Where no files or directories are specified, input will be read from the standard input. The output of a command is written either to the standard output or to new files, depending upon the command and the options.
π¦ DESCRIPTION π¦
Coan is a tool for investigating configurations of C or C++ source code. A configuration is a (possibly empty) list of assumptions about the status of some preprocessor symbols when the source code is compiled. It may be assumed that a symbol is defined for the preprocessor, possibly with formal parameters and possibly with a specified definition, or it may be assumed that a symbol is undefined.
It is important to understand that coan shall consider a symbol to be undefined only if there is an assumption to that effect, or if you use the --implicit option. By default, a symbol that is not mentioned in any assumption is considered to be undetermined.
A configuration may be thought of as list of #define and/or #undef directives that are applied to every file in the source code to observe their effects. The 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 preprocessor 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 complexities that depend on the status of some preprocessor symbols, coan can be given a configuration that specifies the status of those symbols, and it will output an new version of the source code from which those redundant complexities have 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.
Source code re-written by coan is not pre-processed code as produced by the preprocessor. It still contains comments, macro-invocations, and #-directives. It is still source code, but simplified.
Other questions that coan can answer include ones about the preprocessor symbols that are invoked in the source code and their properties under a given configuration. For example: What symbol references would appear within active preprocessor directives under a given configuration, and could thus influence the preprocessor under that configuration? What are the macro-expansions of symbol references? How are those macro-expansions derived? What integer values would accrue to the symbol references that can be evaluated under a given configuration?
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 would be active under a given configuration? When coan is invoked to identify the symbol references or directives that satisfy certain criteria, it will output a list of the references or directives of interest, and optionally their locations in the source code.
π COMMANDS π
helpβ Display a usage summary and exit. πversionβ Display version information and exit. β¨source [OPTION...] [file...] [directory...]β Read the input files and rewrite them in accordance with the options.spin [OPTION...] [file...] [directory...]β Like thesource, with all output files organised beneath a specified directory mirroring their original structure.symbols [OPTION...] [file...] [directory...]β Select references of preprocessor symbols from the input files in accordance with the options and report them on the standard output in accordance with the options.includes [OPTION...] [file...] [directory...]β Select#includedirectives from the input files in accordance with the options and report them on the standard output in accordance with the options.defs [OPTION...] [file...] [directory...]β Select#defineand#undefdirectives from the input files in accordance with the options and report them on the standard output in accordance with the options.pragmas [OPTION...] [file...] [directory...]β Select#pragmadirectives from the input files in accordance with the options and report them on the standard output in accordance with the options.errors [OPTION...] [file...] [directory...]β Select#errordirectives from the input files in accordance with the options and report them on the standard output in accordance with the options.lines [OPTION...] [file...] [directory...]β Select#linedirectives from the input files in accordance with the options and report them on the standard output in accordance with the options.directives [OPTION...] [file...] [directory...]β Select preprocessor directives from the input files in accordance with the options and report them on the standard output in accordance with the options.
π OPTIONS π
π GENERAL OPTIONS π
These options may be given with any command. iykyk
-fargfile,--file argfileβ Read (more) arguments from file argfile. Arguments may be written free-form, separated by whitespace, in argfile. These arguments will be parsed exactly as if they were listed on the commandline at the position of-fargfile.-Dsymbol[(param1[,param2...])]=definition,--define symbol[(param1[,param2...])]=definitionβ Assume that the macro definitionsymbol[(param1[,param2...])]=definitionis in force for processing the input file(s). If=definitionis unspecified then string defaults to the empty string.-Usymbol,--undef symbolβ Assume that the macro symbol is undefined for processing the input file(s).-m,--implicitβ Assume that any symbol that is not--define-edis implicitly--undef-ed.
This option is not allowed to have the perverse effect that an initial invocation, with arguments, of an unconfigured symbol, e.g. sym(a,b), is expanded as 0(a,b) to provoke a syntax error. The invocation is taken to imply that sym has a conforming but unknown definition and is passed through unresolved. However, once sym has been invoked either with arguments or without then subsequent invocations are expected to be of the same form unless sym is redefined or undefined in the meanwhile. no cap, that's the rule
-R,--recurseβ Recurse into directories to find input files. (With thesourcecommand,--recurseimplies--replace). With--recurse, the input files may include directories: otherwise a directory provokes a non-fatal error.
All files beneath a directory will be selected for input unless the --filter option is given: otherwise all files will be selected that match the --filter option.
When --recurse is in effect, coan builds a graph of all unique input files once and for all as it parses the filenames that are explicitly supplied and before it processes any of them. New files that may later appear in input directories during execution will not be processed, and files that have disappeared from input directories when they are due to be processed will provoke fatal errors. fr fr, it means it
-Fext1[,ext2...],--filter ext1[,ext2...]β Process only input files that have one of the file extensionsext1,ext2...A file extension is the terminal segment of a filename that immediately follows the final..-g[p|i|w|e|a],--gag [progress | info | warning | error | abend]β Suppress diagnostics no worse than[progress | info | warning | error | abend].-gs,--gag summaryβ Suppress summary diagnostics at end of input.-V,--verboseβ Output all diagnostics,
If neither -V nor -garg is specified defaults are -gp -gi -gs.
-E,--evalconstsβ Constants occurring as truth-functional operands in#ifexpressions shall be evaluated and eliminated. By default constants as truth-functional operands are treated as unknowns, i.e. like macros that are not subject to any assumptions. Constants are always evaluated and eliminated when they are arithmetic or bitwise operands.
The default behaviour preserves "work-in-progress" directives such as #if 1 and #if 0 along with the code they control. With --evalconsts these directives are evaluated.
-K,--keepgoingβ If a parse error is encountered in an input file, continue processing subsequent input files. An event of severity abend will terminate processing regardless of--keepgoing.--no-transientsβ By default an in-source#define SYMor#undef SYMdirective is transiently treated as a-DSYMor-USYMoption within the source file where it is found. This option suppresses the default behaviour at your own risk. bestie, they said at your own risk for a reason π-P,--podβ Apart from#-directives, input is to be treated as Plain Old Data. C or C++ comments and quotations will not be parsed.
π OPTIONS FOR THE source COMMAND π
-r,--replaceβ Replace each input file with the corresponding output file. This option must be specified to process multiple input files.
The option changes the default behaviour of the command when no input files are specified. In that case, input is acquired from the standard input. If --replace is not specified, then a single input file is read from the standard input. If --replace is specified then the names of the input files are read from the standard input. Note that the --recurse option implies --replace.
If you wish to preserve the original files with the --replace option, use the --backup option as well.
If the names of the input files are read from stdin, the filenames are delimited by whitespace unless enclosed in double-quotes.
-bsuffix,--backup suffixβ Backup each input file before replacing it, the backup file having the same name as the input file with suffix appended to it. protect the originals, bestie π«Ά-x[d|c|e],--conflict [delete | comment | error]β okay so this is the βwhat do we do when a#defineor#undefin an input file conflicts with one of the-Dor-Uassumptions?β knob. Pick your fighter:d,deleteβ delete the conflicting directive. gone. πc,commentβ replace the conflicting directive with a diagnostic comment. this is the default β¨.e,errorβ replace the conflicting directive with a diagnostic#errordirective. dramatic, but valid π.
-k[d|b|c],--discard [drop | blank | comment]β select the policy for discarding lines from output:d,dropβ drop discarded lines.b,blankβ blank discarded lines.c,commentβ comment out discarded lines.
--lineβ output#linedirectives in place of discarded lines to preserve the line numbers of retained lines. yes bestie, the line numbers stay cute π.-c,--complementβ output the lines that ought to be dropped and vice versa. chaotic? iconic. π₯
β¨ OPTIONS FOR THE spin COMMAND β¨
The --recurse and --replace options are implied for this command. no cap.
-x[d|c|e],--conflict [delete | comment | error]β select the action to be taken when a#defineor#undefdirective is encountered in an input file that conflicts with one of the-Dor-Uassumptions:d,deleteβ delete the conflicting directive.c,commentβ replace the conflicting directive with a diagnostic comment. this one is the default β¨.e,errorβ replace the conflicting directive with a diagnostic#errordirective.
-k[d|b|c],--discard [drop | blank | comment]β select the policy for discarding lines from output:d,dropβ drop discarded lines.b,blankβ blank discarded lines.c,commentβ comment out discarded lines.
--lineβ output#linedirectives in place of discarded lines to preserve the line numbers of retained lines.-c,--complementβ output the lines that ought to be dropped and vice versa.--dir dirnameβ generate a spin under the directorydirname. the output files are generated relative todirname, mirroring their original structure.dirnameand subdirectories will be created as required. pre-existing output files will be overwritten. a fatal error is given ifdirnameincludes, or is included by or is identical with any input directory. π«Ά-ppathame,--prefix pathnameβ in organising output files beneath the spin directorydir,dirwill be equated with the path prefixpathnameof any input file. this enables any common prefix of all input files to be deleted from all the output files underdirif desired. π¦
π¦ OPTIONS FOR THE symbols COMMAND π¦
-i,--ifsβ list symbol references that occur in#if,#if[n]defand#elifdirectives.-d,--defsβ list symbol references that occur in#definedirectives.-u,--undefsβ list symbol references that occur in#undefdirectives.--includesβ list symbol references that occur in#includedirectives.--lnsβ list symbol references that occur in#linedirectives.
If none of -i, -d, -u, --includes or --lns is given then they are all defaults. all of them. the whole squad. π
-o,--once-onlyβ list only the first occurrence of each distinct reference of a symbol.--once-per-fileβ list only the first occurrence per input file of each distinct reference of a symbol.
If neither --once-only nor --once-per-file is given then all of a symbolβs references are listed.
-A,--activeβ list only references from operative directives.-I,--inactiveβ list only references from inoperative directives.-L,--locateβ report the source file and line number of each listed reference.-e,--expandβ report the macro expansion of each reported symbol reference, and the integer to which it evaluates, if any. an expansion will be reported for a reference of the symbolsymbolifsymbolis configured by a-Doptionor a-Uoption, or transiently configured by a#defineor#undefdirective in the current file. π- In the case
-Dsymbol, the expansion ofsymbolis the empty string (since that is the C preprocessorβs default definition for defined symbols). - In the case
-Usymbol, the expansion ofsymbolis the numeral0(since0is the value assigned by the preprocessor to an undefined symbol). - In the case
-Dsymbol[(param1[,param2...])]=definition, the expansion of the reference is the string that results by, first, substituting the arguments of the references, if any, for the corresponding formal parameters of the symbol in its definition and then recursively replacing each symbol reference in the result with its expansion.
- In the case
If a symbol is not configured then its references are reported as insoluble. likewise if it is configured but a reference has a circular expansion. π
--explainβ report the successive steps of macro expansion for each reported symbol reference. implies--expand. bestie this one is very main character energy π--select name1[*][,name2[*]...]β select by name the symbols to be reported. a symbol reference will be reported only if its name matches one of the comma-separated names or*-terminated names. a*-terminated name is interpreted as a wildcard name prefix. if not specified then--select *is the default. π
π OPTIONS FOR THE includes COMMAND π
-s,--systemβ list system headers, e.g.<header.h>.-l,--localβ list local headers, e.g."header.h".
If neither -s or -L is given then both are defaults.
-o,--once-onlyβ list only the first occurrence of each header.--once-per-fileβ list only the first occurrence per input file of each header.
If neither --once-only nor --once-per-file is given then all occurrences of a header are listed.
-A,--activeβ list only headers from operative directives.-I,--inactiveβ list only headers from inoperative directives.-L,--locateβ report the source file and line number of each listed occurrence.
πΈ OPTIONS FOR THE defs COMMAND πΈ
-o,--once-onlyβ list only the first occurrence of each distinct#defineor#undefdirective.--once-per-fileβ list only the first occurrence per input file of each distinct#defineor#undefdirective.
For the purpose of determining whether two occurrences express the same directive or not, coan reduces the text of each occurrence to a canonical form, i.e. all comments are stripped out, all whitespace sequences are collapsed to a single space and all tokens are separated by a single space. this applies for all commands that accept the --once-only or --once-per-file option. lowkey obsessed with this little canonical-form moment β¨
If neither --once-only nor --once-per-file is given then all occurrences of a distinct #define or #undef directive are listed.
-A,--activeβ list only operative#defineand#undefdirectives.-I,--inactiveβ list only inoperative#defineand#undefdirectives.-L,--locateβ report the source file and line number of each listed occurrence.
π OPTIONS FOR THE pragmas COMMAND π
-o,--once-onlyβ list only the first occurrence of each distinct pragma.--once-per-fileβ list only the first occurrence per input file of each distinct pragma.
If neither --once-only nor --once-per-file is given then all occurrences of a pragma are listed.
-A,--activeβ list only operative pragmas.-I,--inactiveβ list only inoperative pragmas.-L,--locateβ report the source file and line number of each listed occurrence.
π OPTIONS FOR THE errors COMMAND π
-o,--once-onlyβ list only the first occurrence of each#errordirective.--once-per-fileβ list only the first occurrence per input file of each#errordirective.
If neither --once-only nor --once-per-file is given then all occurrences of a distinct #error directive are listed.
-A,--activeβ list only operative#errordirectives.-I,--inactiveβ list only inoperative#errordirectives.-L,--locateβ report the source file and line number of each listed occurrence.
π§ OPTIONS FOR THE directives COMMAND π§
-o,--once-onlyβ list only the first occurrence of each distinct directive.--once-per-fileβ list only the first occurrence per input file of each distinct directive.
If neither --once-only nor --once-per-file is given then all occurrences of a distinct directive are listed.
-A,--activeβ list only operative directives.-I,--inactiveβ list only inoperative directives.-L,--locateβ report the source file and line number of each listed occurrence. π«Ά
π DIAGNOSTICS π
okay so diagnostics that get written to stderr are classified by severity, and every single one includes a distinct hexadecimal code of the form 0xXXXXX that encodes its severity. There are 5 severities, bestie:
- progress β Progress messages (
0xXXXXX & 0x00800is true) - info β Noteworthy information (
0xXXXXX & 0x01000is true) - warning β Indicating problematic input (
0xXXXXX & 0x02000is true) - error β Indicating invalid input (
0xXXXXX & 0x04000is true) - abend β Indicating a fatal environment or internal error (
0xXXXXX & 0x08000is true)
If --gag summary is not in force, coan can write summary diagnostics at the end of processing. A summary diagnostic has a hexadecimal code S that encodes one of the severities and in addition S & 0x10000 is true.
Even if --gag summary is not in force, a summary will not be written if its severity is suppressed by one of the specified or default --gag options. Since all summaries have severity info or warning, and since the --gag defaults are info, warning and summary, you should specify --gag info to see only warning summaries, and to see all summaries you should specify --verbose.
The summaries include:
- info β The number of input files that were reached and the number that were not reached (due to abend).
- info β The number of input files reached that were abandoned (due to errors).
If there was no abend or error, then additional summaries are written (unless suppressed) indicating each of the following outcomes that has occurred:
- info β Input lines were dropped through simplification.
- info β Input lines were changed through simplification. If the option
--discard commentis in effect, causing discarded lines to be commented out, then discarded lines are counted as changed, not dropped. - warning β Input lines were changed to
#errordirectives. - warning β
#errordirectives were operative (either in the input source or as a result of simplification).
coan returns a system code SC of which the low order half of the low order byte is always meaningful:
SC & 1β Informational diagnostics accrued.SC & 2β Warnings diagnostics accrued.SC & 4β Error diagnostics accrued. (Input files provoking errors will be unchanged notwithstanding the--replaceoption.)SC & 8β An abend occurred. Some input files may not have been reached.
If no error or abend is indicated, then the high order half of the low order byte is also meaningful:
SC & 16β Input lines were dropped through simplification.SC & 32β Input lines were changed through simplification.SC & 64β Input lines were changed to#errordirectives.SC & 128β#errordirectives were operative.
The system code reflects diagnostics that were provoked even if they were not actually output due to --gag options.
π BUGS π
Trigraphs are not parsed. yep, thatβs the vibe.
Files that are #include-ed by input files are not parsed, hence any #define or #undef directives they contain will not be factored into the evaluation of the file.
Please report bugs to bugs dot coan at burroingroingjoing dot com
π AUTHOR π
Mike Kinghan imk at burroingroingjoing dot com
okay thatβs the whole page, bestie β the footer source/version/date lineup is AUGUST 2014 Β· burroingroingjoing.com Β· coan(1) πβ¨
π¦ where this page comes from
- nixos 26.05: coan 6.0.1
- nixpkgs unstable: coan 6.0.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms