C-style cast finder Perl script

From: Andrew Dunbar (hippietrail@yahoo.com)
Date: Mon May 12 2003 - 08:36:08 EDT

  • Next message: Rui Miguel Seabra: "0.9.1 rpms for RedHat 9 at Savannah"

    Due to the ever-popular nature of my C->C++ cast
    upgrade patches, I've finally got around to making a
    Perl script to find most of them in the source code.
    It does a better job than the VI regex I was using.

    It should run on all platforms like this:

     perl findcasts.pl dir

    Where dir is the topmost directory you wish to search.
    It's recursive and will search all subdirectories and
    all files ending in .h and .cpp

    If you look at the source you will see it currently
    filters out all platfrom-specific files except Unix.
    Modify lines 30-34 to change this.

    Please use this tool on code you are familiar with:
    you know better than me which casts to use on such
    code and it will help me avoid dom's wrath for using
    the static_cast in place of reinterpret_cast and vice
    versa (:

    If somebody can tell me which dir is appropriate I
    will
    commit it to cvs.

    Andrew.

    =====
    http://linguaphile.sourceforge.net/cgi-bin/translator.pl http://www.abisource.com

    __________________________________________________
    Yahoo! Plus
    For a better Internet experience
    http://www.yahoo.co.uk/btoffer

    #!/usr/bin/perl
    #
    # Find C-style casts in C++ sourc code
    #
    # © 2003 Andrew Dunbar

    use strict;

    use File::Find;

    my $dir;

    # Mac file open dialog
    # TODO this code for Macs, interpret command line args for others
    if ($^O eq 'MacOS') {
            $dir = MacPerl::Choose(GUSI::AF_FILE(), 0, 'Pick a folder ... ', '',
                    GUSI::CHOOSE_DIR());
    } else {
            $dir = $ARGV[0];
    }

    if ($dir) {
            print "Searching all files '$dir'...\n";
            find(\&wanted, $dir);
    } else {
            print "Nothing to Convert.\n";
    }

    sub wanted {
            return if (/BeOS/);
            return if (/QNX/);
            return if (/Mac/);
            return if (/Cocoa/);
            return if (/Unix/);
            #if (/\.(h|hpp)$/) {
            if (/\.(cpp)$/) {
                    filter($File::Find::name, $_);
            }
    }

    sub filter {
            my ($path, $file) = @_;
            if (open(fh, "<$file")) {
                    binmode fh;
                    my $lino = 0;
                    while (<fh>) {
                            ++$lino;
                            if (/^(.*)(\(\s*(\w+(\s*(\w+|\*))*)\s*\)\s*((--|\+\+|&|-|!|\*)?\w+))(.*)/) {
                                    my $ml = $_;
                                    my $pre = $1;
                                    my $mat = $2;
                                    my $ctype = $3;
                                    my $cexp = $6;
                                    my $post = $8;

                                    # inside comment
                                    next if ($pre =~ /\/\//);
                                    next if ($pre =~ /\/\*/ && $pre !~ /\*\//);

                                    # copyright
                                    next if (lcfirst($ctype) eq 'c' && $cexp >= 1900 && $cexp < 3000);

                                    # const member function declaration
                                    next if ($cexp eq 'const');

                                    # to the left is alphabetic
                                    if ($pre =~ /\w\s*$/) {
                                            next unless ($pre =~ /return\s*$/);
                                    }

                                    print STDOUT "$File::Find::name:$lino: $ml";
                                    print STDOUT "$File::Find::name:$lino: $mat -> xxx_cast<$ctype>($cexp...)\n\n";
                            }
                            if (/^(.*)(\(\s*(\w+(\s*(\w+|\*))*)\s*\)\s*)(\(.*)/) {
                                    my $ml = $_;
                                    my $pre = $1;
                                    my $mat = $2;
                                    my $ctype = $3;
                                    my $post = $6;

                                    # inside comment
                                    next if ($pre =~ /\/\//);
                                    next if ($pre =~ /\/\*/ && $pre !~ /\*\//);

                                    # to the left is alphabetic
                                    if ($pre =~ /\w\s*$/) {
                                            next unless ($pre =~ /return\s*$/);
                                    }

                                    print STDOUT "$File::Find::name:$lino: $ml";
                                    print STDOUT "$File::Find::name:$lino: ($ctype)(...) -> xxx_cast<$ctype>(...)\n\n";
                            }
                    }
                    close(fh);
            } else {
                    print "Can't open input $file $!\n";
            }
    }



    This archive was generated by hypermail 2.1.4 : Mon May 12 2003 - 08:49:17 EDT