A Python tool for analyzing C code complexity using Halstead and Cyclomatic metrics.
Project description
Halstead++
A sophisticated Python library for analyzing Halstead complexity metrics of C code through AST parsing, with intelligent operator filtering for more accurate complexity assessment. Introduction
Halstead++ is a specialized static analysis tool that calculates Halstead complexity metrics for C programming language code. Unlike traditional Halstead metric tools, Halstead++ employs intelligent filtering to exclude common syntactic operators that tend to artificially inflate complexity scores, such as semicolons, parentheses, braces, and commas. This results in more accurate and meaningful complexity measurements that better reflect the actual cognitive complexity of the code.
The tool leverages pycparser to generate Abstract Syntax Trees (AST) from preprocessed C code and performs comprehensive analysis at both file and function levels, providing detailed metrics including program vocabulary, volume, difficulty, effort, and estimated bug counts.
Installation
From PyPI
pip install halsteadpp
From Source
git clone https://github.com/Morgadineo/Halsteadpp
cd halsteadpp
pip install -e .
Dependencies
Python >= 3.8
pycparser >= 2.21
rich >= 13.0 (for formatted output)
Usage
Prerequisites: Code Preprocessing
Before using Halstead++, C source files must be preprocessed using the provided Makefile. This step is necessary because Halstead++ uses pycparser which requires preprocessed C code and the fake-headers for the libraries.
Why fake headers are needed:
The code is preprocessed with -nostdinc to avoid platform-specific standard headers.
Instead, we use pycparser's fake headers which provide minimal declarations
(like int printf(const char*, ...);) without actual implementations.
This makes the parsing portable across different systems (Linux, Windows, macOS).
Using the Makefile
The repository includes a Makefile for easy preprocessing:
Preprocess a specific file
make main.i # Creates main.i from main.c
make utils.i # Creates utils.i from utils.c
Preprocess all .c files in current directory
make # Or: make preprocess
Preprocess all .c files in a subdirectory
make DIR=src # Processes all .c files in ./src/
make DIR=Examples # Processes all .c files in ./Examples/
Clean generated .i files
make clean # Cleans .i files in current directory
make DIR=src clean # Cleans .i files in ./src/
Basic Usage
from halsteadpp import ParsedCode
# Analyze a C file (without .c extension)
parser = ParsedCode("example_file", "path/to/preprocessed/code/")
# Display comprehensive complexity metrics
parser.print_complexities()
# Display function-level analysis
parser.print_functions()
Advanced Usage
from halsteadpp import ParsedCode
# Initialize parser for specific file
parser = ParsedCode(
filename="algorithm", # File name without extension
file_dir="src/complex/" # Directory containing preprocessed .i file
)
# Access metrics directly
print(f"Program Volume: {parser.volume}")
print(f"Estimated Bugs: {parser.delivered_bugs}")
print(f"Cyclomatic Complexity: {parser.total_mcc}")
# Access function-specific metrics
for function in parser.functions:
print(f"Function: {function.func_name}")
print(f" - Halstead Effort: {function.effort}")
print(f" - McCabe Complexity: {function.total_mcc}")
Example 1: Simple Analysis
hello.c inside 'Example/' folder:
#include <stdio.h>
int main(void)
{
printf("Hello, World!\n");
return 0;
}
Pre-compile:
> make
Preprocessing Examples/hello.c...
Basic main.py:
from halsteadpp import ParsedCode
# Analyze a C file
hello_code = ParsedCode('hello', 'Examples/')
# Print table of complexities
hello_code.print_complexities()
Outputs
Complexities Table
Functions complexity
Operators
Operands
Key Features
Intelligent Operator Filtering
Halstead++ excludes the following syntactic operators from complexity calculations:
Semicolons (;)
Parentheses (())
Braces ({})
Commas (,)
This filtering provides more realistic complexity metrics by focusing on meaningful operators that contribute to actual cognitive load.
Comprehensive Metrics
Halstead Metrics: n1, n2, N1, N2, vocabulary, length, volume, difficulty, level, effort, time, bugs
Cyclomatic Complexity: McCabe complexity at function and file levels
Line Metrics: Total lines, effective lines (excluding comments and empty lines)
Function Analysis: Individual metrics for each function
Rich Visual Output
Formatted tables using the Rich library
Color-coded output for better readability
Detailed operator and operand listings
AST-Based Analysis
Accurate parsing using Python's AST capabilities
Support for complex C constructs (pointers, structs, function calls, etc.)
Real node detection to filter out compiler-generated code
Metric Definitions
n1: Number of distinct operators
n2: Number of distinct operands
N1: Total number of operators
N2: Total number of operands
Volume (V): Program size metric: (N1 + N2) × log₂(n1 + n2)
Difficulty (D): Program complexity: (n1 / 2) × (N2 / n2)
Effort (E): Mental effort required: D × V
Bugs (B): Estimated number of delivered bugs: E^(2/3) / 3000
License
MIT License - see LICENSE file for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file halsteadpp-0.1.3.tar.gz.
File metadata
- Download URL: halsteadpp-0.1.3.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5bcf52c5fff2e3d48c16dba77cd6499eb4ff1329ac597f919feda8bcfa78580
|
|
| MD5 |
1818b167b7274a5146a73c92d555e486
|
|
| BLAKE2b-256 |
be3ce08ac447a525f1b08f80611acab8acc9037c56ec6a94c35419d257fe7a6b
|
File details
Details for the file halsteadpp-0.1.3-py3-none-any.whl.
File metadata
- Download URL: halsteadpp-0.1.3-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff9b7408dc81d53c191bb0dddbaa5aed6b464367f16bb0a1348294ec9879e0f6
|
|
| MD5 |
36c1187f0e9af4577bf97bf6fe80a569
|
|
| BLAKE2b-256 |
17dc3695490a69694f14dec8a0bcc10474fb1cfd283953b17930005f789d0b43
|