Invoking complexity
*******************

Compute the complexity of source code not just with a path-through-the-code count, but also amplifying line counts by logic level nesting.

The weight of each statement is the number of lines the statement uses.  This value is multiplied by the nested logic weighting (1.9 by default) for each layer of logic.  For example, this snippet:

     if (foo) {
       if (bar) {
         bumble; baz;
       }
     }

will score 11.  This score is then scaled to approximate pmccabe results by dividing by 20 and rounding.  This scores "1" at the end. pmccabe scores higher on simple procedures and complexity scores higher with more deeply nested logic.

The scoring can be tweaked by adjusting the --nesting-penalty and --scale-ing factors.  The default values were calibrated by comparing the average results of millions of lines of code with the results of pmccabe.

For the purposes of this program, a procedure is identified by a name followed by a parenthesized expression and then an opening curly brace. It ends with a closing curly brace in column 1.

This chapter was generated by AutoGen, using the agtexi-cmd template and the option descriptions for the complexity program. This software is released under the GNU General Public License, version 3 or later.

complexity help/usage (--help)
==============================

This is the automatically generated usage text for complexity.

The text printed is the same whether selected with the help option (--help) or the more-help option (--more-help).  more-help will print the usage text by passing it through a pager program. more-help is disabled on platforms without a working fork(2) function.  The PAGER environment variable is used to select the program, defaulting to more.  Both will exit with a status code of 0.

     complexity (GNU Complexity) - Measure complexity of C source
     Usage:  complexity [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \
                     [ <file-name> ... ]

        -t, --threshold=num        Reporting threshold
            --horrid-threshold=num zero exit threshold
        -n, --nesting-penalty=str  score multiplier for nested code
            --demi-nesting-penalty=str score multiplier for nested expressions
        -s, --scale=num            complexity scaling factor
        -h, --histogram            Display histogram of complexity numbers
                                     - disabled as '--no-histogram'
                                     - may not be preset
        -c, --scores               Display the score for each procedure
                                     - disabled as '--no-scores'
                                     - may not be preset
        -I, --ignore=str           procedure name to be ignored
                                     - may appear multiple times
        -H, --no-header            do not print scoring header
                                     - may not be preset
        -u, --unifdef=str          Run the source(s) through unifdef(1BSD)
                                     - may appear multiple times
            --unif-exe=str         Specify the unifdef program
        -i, --input=str            file of file list
            --trace=str            trace output file
        -v, --version[=arg]        output version information and exit
        -?, --help                 display extended usage information and exit
        -!,  --- help           display extended usage information and exit
        ->, --save-opts[=arg]      save the option state to a config file
        -<, --load-opts=str        load options from a config file
                                     - disabled as '--no-load-opts'
                                     - may appear multiple times

     Options are specified by doubled hyphens and their name or by a single
     hyphen and the flag character.
     Compute the complexity of source code not just with a path-through-the-code
     count, but also amplifying line counts by logic level nesting.

     If no arguments are provided, input arguments are read from stdin,
     one per line; blank and '#'-prefixed lines are comments.
     'stdin' may not be a terminal (tty).

     The following option preset mechanisms are supported:
      - reading file $@/complex.conf
      - reading file $HOME/.complexityrc
      - reading file $PROJECT_ROOT/complex.conf
      - reading file ./.complexityrc
      - examining environment variables named COMPLEXITY_*
     'complexity' ignores all cpp preprocessor directives - calculating the
     complexity of the appearance of the code, rather than the complexity after
     the preprocessor manipulates the code.  'getchar(3)', for example, will
     expand into quite complicated code.

     Please send bug reports to:  <bkorb@gnu.org>

threshold option (-t)
=====================

This is the ``reporting threshold'' option. This option takes a number argument minimum. Ignore any procedures with a complexity measure below this threshold. By default, a complexity score of under 30 is not printed. However, if a histogram and statistics are to be printed, but not individual procedure scores, then the default is set to zero. Procedures below this limit are not counted in the statistics.

horrid-threshold option
=======================

This is the ``zero exit threshold'' option. This option takes a number argument minimum. If any procedures score higher than this threshold, then the program will exit non-zero.  (4/COMPLEX_EXIT_HORRID_FUNCTION, if no other problems are encountered.)  By default, this program exits zero unless one function exceeds the horrid score of 100.

nesting-penalty option (-n)
===========================

This is the ``score multiplier for nested code'' option. This option takes a string argument factor. Linguistic constructs weigh more heavily the more deeply nested they are.  By default, each layer penalizes by a factor of 1.9.  The option argument is a floating point number.  The penalty may be 1, but not less.

demi-nesting-penalty option
===========================

This is the ``score multiplier for nested expressions'' option. This option takes a string argument factor. By default, this value is halfway between 1.0 and the nesting penalty (specifically, the square root of the nesting penalty). It refers to a parenthesized sub-expression. e.g.

     ((a > b) && (c > d))

contains two parenthesized sub-expressions.  This would count 3.5 points. On the other hand, this:

     (a > b && c > d)

contains two relation operators and a logical operator at the same level. These nested counts will be multiplied together and yield 2.5 * 2.5, or 6.25.  Don't do that.  It gets even worse if you have logical ands and ors at the same level.

scale option (-s)
=================

This is the ``complexity scaling factor'' option. This option takes a number argument factor. By default, the scaling is 20 which divides the raw score by 20. This was normalized to roughly correspond to the pmccabe scores:

0-9
     Easily maintained code.

10-19
     Maintained with little trouble.

20-29
     Maintained with some effort.

30-39
     Difficult to maintain code.

40-49
     Hard to maintain code.

50-99
     Unmaintainable code.

100-199
     Crazy making difficult code.

200+
     I only wish I were kidding.

          Score | ln-ct | nc-lns| file-name(line): proc-name
           4707    3815    2838   lib/vasnprintf.c(1747): VASNPRINTF

histogram option (-h)
=====================

This is the ``display histogram of complexity numbers'' option.

This option has some usage constraints.  It:

  * can be disabled with --no-histogram.

  * may not be preset with environment variables or configuration (rc/ini) files.

Instead of printing out each function's score, a summary is printed at the end showing how many functions had particular ranges of scores. Unless --scores is specifically called out, the scores will not print with this option specified.  The minimum scoring threshold will also be reduced to zero (0), unless --threshold is specified.

scores option (-c)
==================

This is the ``display the score for each procedure'' option.

This option has some usage constraints.  It:

  * can be disabled with --no-scores.

  * may not be preset with environment variables or configuration (rc/ini) files.

If you specify --histogram, individual scores will not be displayed, unless this option is specified.

ignore option (-I)
==================

This is the ``procedure name to be ignored'' option. This option takes a string argument.

This option has some usage constraints.  It:

  * may appear an unlimited number of times.

Some code has macros defined that confuse the lexical analysis. This will cause them to be ignored.  Other ways to cause functions to be ignored are:

 1. Use K&R syntax for a procedure header.

 2. Use a preprocessing macro to assemble the procedure header.

 3. Simplify your code.

Generally speaking, anything you do that alters normal C syntax will confuse the lexical analysis.  If a procedure is not seen, then it will not get counted.  If code within a procedure is incomprehensible, you will likely get inappropriate results.

no-header option (-H)
=====================

This is the ``do not print scoring header'' option.

This option has some usage constraints.  It:

  * may not be preset with environment variables or configuration (rc/ini) files.

If a script is going to process the scoring output, parsing is easier without a header.  The histogram output will always have a header.

unifdef option (-u)
===================

This is the ``run the source(s) through unifdef(1bsd)'' option. This option takes a string argument unifdef-opt.

This option has some usage constraints.  It:

  * may appear an unlimited number of times.

Strip out sections of code surrounded by #if/#endif directives. The option argument is passed as an argument to the unifdef(1BSD) program.  For example:

     complexity -u-Dsymbol

would cause symbol to be defined and remove sections of code preceded by #ifndef symbol directives.

Please see the unifdef documentation for more information.

unif-exe option
===============

This is the ``specify the unifdef program'' option. This option takes a string argument prog. Alternate program to use for unifdef-ing the input.

input option (-i)
=================

This is the ``file of file list'' option. This option takes a string argument file-name. Instead of either a command line list of input files or reading them from standard input, read the list of files from this file.

trace option
============

This is the ``trace output file'' option. This option takes a string argument file-name. Print intermediate scores to a trace file.

presetting/configuring complexity
=================================

Any option that is not marked as not presettable may be preset by loading values from configuration ("rc" or "ini") files, and values from environment variables named COMPLEXITY and COMPLEXITY_<OPTION_NAME>.  <OPTION_NAME> must be one of the options listed above in upper case and segmented with underscores. The COMPLEXITY variable will be tokenized and parsed like the command line.  The remaining variables are tested for existence and their values are treated like option arguments.

libopts will search in 4 places for configuration files:

  * $(pkgdatadir)/complex.conf

  * $HOME

  * $PROJECT_ROOT/complex.conf

  * $PWD

The value for $(pkgdatadir) is recorded at package configure time and replaced by libopts when complexity runs. The environment variables HOME, PROJECT_ROOT, and PWD are expanded and replaced when complexity runs. For any of these that are plain files, they are simply processed. For any that are directories, then a file named .complexityrc is searched for within that directory and processed.

Configuration files may be in a wide variety of formats. The basic format is an option name followed by a value (argument) on the same line.  Values may be separated from the option name with a colon, equal sign or simply white space.  Values may be continued across multiple lines by escaping the newline with a backslash.

Multiple programs may also share the same initialization file. Common options are collected at the top, followed by program specific segments.  The segments are separated by lines like:

     [COMPLEXITY]

or by

     <?program complexity>

Do not mix these styles within one configuration file.

Compound values and carefully constructed string values may also be specified using XML syntax:

     <option-name>
        <sub-opt>...&lt;...&gt;...</sub-opt>
     </option-name>

yielding an option-name.sub-opt string value of

     "...<...>..."

AutoOpts does not track suboptions.  You simply note that it is a hierarchicly valued option.  AutoOpts does provide a means for searching the associated name/value pair list (see: optionFindValue).

The command line options relating to configuration and/or usage help are:

version (-v)
------------

Print the program version to standard out, optionally with licensing information, then exit 0.  The optional argument specifies how much licensing detail to provide.  The default is to print the license name with the version.  The licensing information may be selected with an option argument. Only the first letter of the argument is examined:

version
     Only print the version.

copyright
     Name the copyright usage licensing terms.  This is the default.

verbose
     Print the full copyright usage licensing terms.

complexity exit status
======================

One of the following exit values will be returned:

0 (EXIT_SUCCESS)
     Successful program execution.

1 (EXIT_FAILURE)
     The operation failed or the command syntax was not valid.

3 (EXIT_NOMEM)
     insufficient memory to run program

4 (EXIT_HORRID_FUNCTION)
     One or more functions scored over 100

5 (EXIT_NO_DATA)
     No qualifying procedures were found.

6 (EXIT_ASSERT)
     Assertion failed

32 (EXIT_BAD_FILE)
     one or more input files were unreadable or empty.

66 (EX_NOINPUT)
     A specified configuration file could not be loaded.

70 (EX_SOFTWARE)
     libopts had an internal operational error.  Please report it to autogen-users@lists.sourceforge.net.  Thank you.

complexity Bugs
===============

This program does not recognize K&R procedure headers.

Some procedures still get missed.  Usually, these are procedures that use the C pre-processor to extend the C language in some way.

Initialized variable definitions within procedures have the initializing elements counted in the complexity calculation.