123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- #!/usr/bin/perl
- use strict;
- use warnings;
- use File::Basename;
- # Desired indentation.
- my $indentation = 2;
- if ($#ARGV != 0) {
- print "\nUsage: stylecheck.pl source\n";
- exit;
- }
- my $source = $ARGV[0];
- open(my $in, "<", $source) or die "Can't open source: $!";
- my $lineno = 0;
- my @c_source = <$in>;
- my $filename = $source;
- $filename =~ y/\\/\//;
- $filename = basename($filename);
- my $i_level = 0;
- my $c_comment = "";
- my $state = "start";
- my $cr = "\r";
- my $lf = "\n";
- my $tab = "\t";
- my $f_lineno = 0;
- my $f_params = "";
- my $t_lineno = 0;
- my $t_type = "";
- my $e_lineno = 0;
- my $e_name = "";
- my $d_lineno = 0;
- my $d_name = "";
- my $d_name2 = "";
- my $d_name_app = "";
- my $scope = "";
- sub style {
- my $desc = shift;
- print("style: $desc at line $lineno in \"$filename\"\n");
- }
- sub error {
- my $desc = shift;
- print("error: $desc at line $lineno in \"$filename\"\n");
- }
- # Indentation check.
- sub check_indentation {
- shift =~ /^(\s*)/;
- if (length($1) != $i_level) {
- style "indentation violation";
- }
- }
- my $emptycnt = 0;
- foreach my $line (@c_source) {
- $lineno += 1;
- #****************************************************************************
- # Check on EOL.
- if (not ($line =~ /$cr$lf$/)) {
- error "detected malformed EOL";
- }
- $line =~ s/$cr//;
- $line =~ s/$lf//;
- #****************************************************************************
- # Check on trailing spaces.
- if ($line =~ /\s$/) {
- style "detected trailing spaces";
- }
- #****************************************************************************
- # Check on TABs.
- if ($line =~ /$tab/) {
- style "detected TAB";
- $line =~ s/$tab/ /;
- }
- #****************************************************************************
- # Check on empty lines.
- my $tmp = $line;
- $tmp =~ s/\s//;
- if (length($tmp) == 0) {
- $emptycnt = $emptycnt + 1;
- if ($emptycnt == 2) {
- style "detected multiple empty lines"
- }
- next;
- }
- else {
- $emptycnt = 0;
- }
- #****************************************************************************
- # Stripping strings content for ease of parsing, all strings become _string_.
- $line =~ s/\\\"//;
- if ($line =~ s/(\"[^"]*\")/_string_/) {
- # print "string: $1 replaced by _string_\n";
- }
- #******************************************************************************
- # State machine handling.
- if ($state eq "start") {
- # Searching for a global code element or a comment start.
- # Indentation check.
- check_indentation $line;
- #******************************************************************************
- # Functions matching, triggered by the "(".
- if ($line =~ /^(static|)\s*(struct|union|)\s*([a-zA-Z_][a-zA-Z0-9_]*\s*[*]*)\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/) {
- # $1=scope $2$3=return type $4=name
- $line =~ s/^(static|)\s*(struct|union|)\s*([a-zA-Z_][a-zA-Z0-9_]*\s*[*]*)\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\(//;
- # print "function: " . $1 . " " . $2 . " " . $3 . " " . $4 . "(";
- # Size of the match up to parameters.
- my $size = $+[0] - $-[0];
- # Function line number.
- $f_lineno = $lineno;
-
- # Checking if all parameters are on the same line.
- if ($line =~ /.*\)\s*{\s*$/) {
- $line =~ s/\)\s*{\s*$//;
- # print $line . "\n";
- $f_params = $line;
- $i_level = $indentation;
- $state = "infunc";
- }
- else {
- # print $line;
- $f_params = $line;
- $i_level = $size;
- $state = "inparams";
- }
- }
- #******************************************************************************
- # Structures matching.
- elsif ($line =~ /^\s*struct\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
- }
- #******************************************************************************
- # Single line "typedef" matching.
- elsif ($line =~ /^\s*typedef\s+([\sa-zA-Z0-9_]*\*+)\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*;\s*$/ or
- $line =~ /^\s*typedef\s+([\sa-zA-Z0-9_]*)\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*;\s*$/) {
- }
- #******************************************************************************
- # Single line "typedef function" matching.
- elsif ($line =~ /^\s*typedef\s+.*\(\s*\*\s*([a-zA-Z0-9_]*)\s*\)\(/) {
- }
- #******************************************************************************
- # Multi line "typedef struct" matching.
- elsif ($line =~ /^\s*typedef\s*struct\s*([a-zA-Z_][a-zA-Z0-9_]*|\s?)?/) {
- $t_lineno = $lineno;
- $t_type = "struct " . $1;
- $state = "intypedef";
- }
- #******************************************************************************
- # Multi line "typedef enum" matching.
- elsif ($line =~ /^\s*typedef\s*enum\s*([a-zA-Z_][a-zA-Z0-9_]*|\s?)?/) {
- $t_lineno = $lineno;
- $t_type = "enum " . $1;
- if ($line =~ /([a-zA-Z_][a-zA-Z0-9_]*)\s*;\s*$/) {
- # Special case of a single-line typedef enum.
- }
- else {
- $state = "intypedef";
- }
- }
- #******************************************************************************
- # Multi line "enum" matching.
- elsif ($line =~ /^\s*enum\s*([a-zA-Z_][a-zA-Z0-9_]*)/) {
- $e_name = $1;
- $e_lineno = $lineno;
- if ($line =~ /;\s*$/) {
- # Special case of a single-line enum.
- }
- else {
- $state = "inenum";
- }
- }
- #******************************************************************************
- # Struct variable matching.
- elsif ($line =~ /^\s*(static|)\s+([\sa-zA-Z0-9_]*)\s+([a-zA-Z_][a-zA-Z0-9_]*\[.*\]|[a-zA-Z_][a-zA-Z0-9_]*)\s*(;\s*$|=)/ or
- $line =~ /^\s*(static|)\s+([\sa-zA-Z0-9_]*\*+)\s*([a-zA-Z_][a-zA-Z0-9_]*\[.*\]|[a-zA-Z_][a-zA-Z0-9_]*)\s*(;\s*$|=)/) {
- }
- #******************************************************************************
- # Variable matching.
- elsif ($line =~ /^\s*(static|).*\s+([a-zA-Z_][a-zA-Z0-9_]*\s*\*+|[a-zA-Z_][a-zA-Z0-9_]*)\s*([a-zA-Z_][a-zA-Z0-9_]*\[.*\]|[a-zA-Z_][a-zA-Z0-9_]*)\s*(;\s*$|=)/) {
- # variable declaration.
- }
- #******************************************************************************
- # #nclude matching.
- elsif ($line =~ /^\s*#include\s+"([^"]+)"/) {
- }
- #******************************************************************************
- # #if matching.
- elsif ($line =~ /^\s*#if\s+(.+)/) {
- }
- #******************************************************************************
- # #ifdef matching.
- elsif ($line =~ /^\s*#ifdef\s+([\w_]+)/) {
- }
- #******************************************************************************
- # #define matching.
- elsif ($line =~ /^\s*#define\s+([\w_]+)\s*(.*)/) {
- $d_lineno = $lineno;
- $d_name = $1;
- $d_name2 = $2;
- # enum typedef declaration.
- if ($line =~ /[^\\]$/) {
- # Special case of a single-line typedef enum.
- }
- else {
- $state = "indefine";
- }
- }
- #******************************************************************************
- # Comment start matching.
- elsif ("$line" =~ /^\s*\/\*/) {
- if ("$line" =~ /\*\//) {
- # Special case of single line comments.
- $line =~ /^\s*(\/\*.*\*\/)/;
- }
- else {
- # Start of multi-line comment.
- $line =~ /(\/\*.*)/;
- $c_comment = $1 . " ";
- $state = "incomment";
- }
- }
- }
- #******************************************************************************
- # Scanning for function parameters end and function body begin.
- elsif ($state eq "inparams") {
- # Indentation check.
- check_indentation $line;
- if ($line =~ /.*\)\s*{\s*$/) {
- # print $line . "\n";
- $line =~ s/\)\s*{\s*$//;
- $f_params = $f_params . $line;
- $i_level = $indentation;
- $state = "infunc";
- print "$f_params\n";
- }
- else {
- $f_params = $f_params . $line;
- # print $line;
- }
- }
- #******************************************************************************
- # Scanning for function end.
- elsif ($state eq "infunc") {
-
- # Checking for function end, the final "}".
- if ($line =~ /^\}/) {
- $i_level = 0;
- $state = "start";
- next;
- }
-
- # Indentation check.
- check_indentation $line;
- if ($line =~ /(\/\*.*\*\/)/) {
- # Single line comments inside functions.
- }
- elsif ("$line" =~ /(\/\*.*)/) {
- # Start of multi-line comment inside a function.
- $c_comment = $1 . " ";
- $state = "infunccomment";
- }
- }
- #******************************************************************************
- # Scanning for comment end within a function body.
- elsif ($state eq "infunccomment") {
- if ("$line" =~ /\*\/\s*$/) {
- # End of mult-line comment.
- $line =~ /(.*\*\/)/;
- $c_comment .= $1;
- $state = "infunc";
- }
- else {
- # Add the whole line.
- $c_comment .= $line . " ";
- }
- }
- #******************************************************************************
- # Scanning for comment end.
- elsif ($state eq "incomment") {
- if ("$line" =~ /\*\/\s*$/) {
- # End of mult-line comment.
- $line =~ /(.*\*\/)/;
- $c_comment .= $1;
- $state = "start";
- }
- else {
- # Add the whole line.
- $c_comment .= $line . " ";
- }
- }
- #******************************************************************************
- # Scanning for typedef end.
- elsif ($state eq "intypedef") {
- if ($line =~ /^\s*}\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*;\s*$/) {
- # typedef end because the final '} <name>;'.
- $state = "start";
- }
- }
- #******************************************************************************
- # Scanning for enum end.
- elsif ($state eq "inenum") {
- if ($line =~ /^\s*}\s*;\s*$/) {
- # enum end because the final '};'.
- $state = "start";
- }
- }
- #******************************************************************************
- # Scanning for define end.
- elsif ($state eq "indefine") {
- if ($line =~ /[^\\]$/) {
- # define end because the final 'not \'.
- # remove blank from starting of the line
- $line =~ s/^\s+|\s+$//g;
- # Add the whole line.
- $d_name2 .= $line;
- $state = "start";
- }
- else {
- # Add the whole line.
- # $line =~ s/^\s+|\s+$//g;
- $line =~ s/^\s*(.*?)\s*$/$1/;
- $d_name2 .= $line;
- }
- }
- }
- close $in or die "$in: $!";
|