#!/usr/bin/perl # A Quick-n-dirty sloc counter. # Print SLOC count for file. sub sloc($); my $gttotalCount = 0; my $gtcodeCount = 0; my $gtcommentCount = 0; # Process all files. foreach my $file (@ARGV) { # I only support C, C++, and header files. if($file =~ /\.(?:c|cc|cpp|cp|C|CC|h|hh|hpp|pl|pm)$/) { # Print SLOC counts for a single file. sloc($file); } } # Print out the grand totals. print "=====================================================" . "==========================\n"; printf "Grand Totals: Code: %s + Comments: %s = Total: %s\n", $gtcodeCount, $gtcommentCount, $gttotalCount; # Perform an SLOC computation on a single file. sub sloc($) { # Get the file name. my $file = shift; # Open the file. open(IN, $file) or die "Couldn't open $file\n"; # Initialize variables. my $line; my $totalCount = 0; my $codeCount = 0; my $commentCount = 0; my @statements; my $inComment = 0; $line = ; chomp $line; $moreData = defined $line; # Process each line. while($moreData) { # Inside a /* ... */ comment. if($inComment) { ++$totalCount; ++$commentCount; if($line =~ /^.*\*\/(.*)$/) { # Strip out the non-comment part. $line = $1; $inComment = 0; # Process the rest of the line. next; } } # See if I am starting a /* ... */ comment. if($line =~ /^(.*)\/\*.*$/) { ++$totalCount; ++$commentCount; # Strip out the non-comment part. $line = $1; $inComment = 1; # Process the rest of the line. next; } # // Comment. if($line =~ /^(.*)\/\/.*$/) { ++$totalCount; ++$commentCount; # Now pull off the non-comment section and keep looking. $line = $1; # Process the rest of the line. next; } # # Comment. if($line =~ /^(.*)\#.*$/) { ++$totalCount; ++$commentCount; # Now pull off the non-comment section and keep looking. $line = $1; # Process the rest of the line. next; } # If the line is "significant", process it. if($line !~ /^\s*(?:\{|\}|\}\s*;)\s*$/) { # A for statement is a single statement, even though it has # semicolons. if($line =~ /^\s*for\([^)]*\)\s*\{?(.*)$/) { # Save the rest of the line. $line = $1; ++$totalCount; ++$codeCount; # Process the rest of the line. next; } # Check for semicolon delimited statements. @statements = ($line =~ /(\s*[^;]+;)/gsm); $codeCount += scalar @statements; $totalCount += scalar @statements; # Now check for a statement without a semicolon. if(!scalar @statements) { if($line =~ /^\s*\S+.*$/) { ++$totalCount; ++$codeCount; } } } # Read the next line. $line = ; chomp $line; $moreData = defined $line; } # I'm done with the file. close(IN); $gtcodeCount += $codeCount; $gtcommentCount += $commentCount; $gttotalCount += $totalCount; # If these values are too big to fit, change them to K notation. if($codeCount > 9999) { $codeCount = ($codeCount / 1000) . "k"; } if($commentCount > 9999) { $commentCount = ($commentCount / 1000) . "k"; } if($totalCount > 9999) { $totalCount = ($totalCount / 1000) . "k"; } # Print out the totals. printf "%-36s: Code: %4s + Comments: %4s = Total: %4s\n", $file, $codeCount, $commentCount, $totalCount; }