[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. 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. 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.

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 complexity usage help (-?)

This is the automatically generated usage text for complexity:

 
complexity (GNU Complexity) - Measure complexity of C source - Ver. 0.4
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
   ->, --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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 demi-nesting-penalty option

This is the “score multiplier for nested expressions” option. 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 histogram option (-h)

This is the “display histogram of complexity numbers” option.

This option has some usage constraints. It:

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 horrid-threshold option

This is the “zero exit threshold” option. 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 ignore option (-I)

This is the “procedure name to be ignored” option.

This option has some usage constraints. It:

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6 input option (-i)

This is the “file of file list” option. Instead of either a command line list of input files or reading them from standard input, read the list of files from this file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7 nesting-penalty option (-n)

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


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8 no-header option (-H)

This is the “do not print scoring header” option.

This option has some usage constraints. It:

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


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.9 scale option (-s)

This is the “complexity scaling factor” option. 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

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.10 scores option (-c)

This is the “display the score for each procedure” option.

This option has some usage constraints. It:

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


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.11 threshold option (-t)

This is the “reporting threshold” option. 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.12 trace option

This is the “trace output file” option. Print intermediate scores to a trace file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.13 unif-exe option

This is the “specify the unifdef program” option. Alternate program to use for unifdef-ing the input.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.14 unifdef option (-u)

This is the “run the source(s) through unifdef(1bsd)” option.

This option has some usage constraints. It:

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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.15 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:

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 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).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.16 complexity exit codes

One of the following exit values will be returned:

0

Successful program execution.

1

The operation failed or the command syntax was not valid.

3

insufficient memory to run program

4

One or more functions scored over 100

5

No qualifying procedures were found.

32

one or more input files were unreadable or empty.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.17 complexity Description

The weight of each statement is the number of lines the statement uses. This value is multiplied by the nested logic weighting (2.0 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.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.18 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.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Bruce Korb on May 15, 2011 using texi2html 1.82.