#!/usr/bin/perl

# report_bad_macros
# This script checks on C pre-processor macros
# It reports macro definitions that are not properly parenthesized
# Currently it only checks that the macro body is contained in parentheses.
# It could be enhanced to check that each arg is parenthesized.
#
# It processes all files suppled as command-line arguments.
# To get it to process all files under the current directory,
# you could use the following 'find' command:
# find . -type f -print0 | xargs -0 report_bad_macros
# (where it is assumed that the script has been saved as "report_bad_macros")
# 
# Cameron Hayne (macdev@hayne.net)  May 2005
# This program is free software.  You may copy or
# redistribute it under the same terms as Perl itself.

use strict;
use warnings;

while (<>)
{
    if (/^\s*#define/)
    {
        # found a #define
        if (/^\s*#define\s+([\w]+)\(([^)]*)\)\s+(.*)$/)
        {
            # found a function-like macro
            my $name = $1;
            my $arglist = $2;
            my $body = $3;

            # trim leading and trailing white space from $body
            $body =~ s/^\s+//;
            $body =~ s/\s+$//;

            if ($body =~ /^$/)
            {
                # empty body
                next; # go to next line of the file
            }

            if ($body =~ /^\/\*.*?\*\/$/)
            {
                # body consists of a C comment
                next; # go to next line of the file
            }

            if ($body =~ /^do\s+{/)
            {
                # start of the 'do {...} while' construction
                next; # go to next line of the file
            }

            if ($body !~ /^\(.*\)$/)
            {
                # not enclosed in parentheses
                print "Unparenthesized macro body in $ARGV\n";
                print $_;
            }
        }
    }
}

