diff options
Diffstat (limited to 'src/tools/pginclude/pgcheckdefines')
-rwxr-xr-x | src/tools/pginclude/pgcheckdefines | 381 |
1 files changed, 216 insertions, 165 deletions
diff --git a/src/tools/pginclude/pgcheckdefines b/src/tools/pginclude/pgcheckdefines index 2936caf2e0..5db507070f 100755 --- a/src/tools/pginclude/pgcheckdefines +++ b/src/tools/pginclude/pgcheckdefines @@ -39,20 +39,22 @@ $MAKE = "make"; # cause a lot of false-positive results. # open PIPE, "$FIND * -type f -name '*.c' |" - or die "can't fork: $!"; -while (<PIPE>) { - chomp; - push @cfiles, $_; + or die "can't fork: $!"; +while (<PIPE>) +{ + chomp; + push @cfiles, $_; } close PIPE or die "$FIND failed: $!"; open PIPE, "$FIND * -type f -name '*.h' |" - or die "can't fork: $!"; -while (<PIPE>) { - chomp; - push @hfiles, $_ unless - m|^src/include/port/| || - m|^src/backend/port/\w+/|; + or die "can't fork: $!"; +while (<PIPE>) +{ + chomp; + push @hfiles, $_ + unless m|^src/include/port/| + || m|^src/backend/port/\w+/|; } close PIPE or die "$FIND failed: $!"; @@ -61,15 +63,18 @@ close PIPE or die "$FIND failed: $!"; # a hash table. To cover the possibility of multiple .h files defining # the same symbol, we make each hash entry a hash of filenames. # -foreach $hfile (@hfiles) { - open HFILE, $hfile - or die "can't open $hfile: $!"; - while (<HFILE>) { - if (m/^\s*#\s*define\s+(\w+)/) { - $defines{$1}{$hfile} = 1; +foreach $hfile (@hfiles) +{ + open HFILE, $hfile + or die "can't open $hfile: $!"; + while (<HFILE>) + { + if (m/^\s*#\s*define\s+(\w+)/) + { + $defines{$1}{$hfile} = 1; + } } - } - close HFILE; + close HFILE; } # @@ -77,164 +82,210 @@ foreach $hfile (@hfiles) { # files it #include's. Then extract all the symbols it tests for defined-ness, # and check each one against the previously built hashtable. # -foreach $file (@hfiles, @cfiles) { - ($fname, $fpath) = fileparse($file); - chdir $fpath or die "can't chdir to $fpath: $!"; - # - # Ask 'make' to parse the makefile so we can get the correct flags to - # use. CPPFLAGS in particular varies for each subdirectory. If we are - # processing a .h file, we might be in a subdirectory that has no - # Makefile, in which case we have to fake it. Note that there seems - # no easy way to prevent make from recursing into subdirectories and - # hence printing multiple definitions --- we keep the last one, which - # should come from the current Makefile. - # - if (-f "Makefile" || -f "GNUmakefile") { - $MAKECMD = "$MAKE -qp"; - } else { - $subdir = $fpath; - chop $subdir; - $top_builddir = ".."; - $tmp = $fpath; - while (($tmp = dirname($tmp)) ne '.') { - $top_builddir = $top_builddir . "/.."; - } - $MAKECMD = "$MAKE -qp 'subdir=$subdir' 'top_builddir=$top_builddir' -f '$top_builddir/src/Makefile.global'"; - } - open PIPE, "$MAKECMD |" - or die "can't fork: $!"; - while (<PIPE>) { - if (m/^CPPFLAGS :?= (.*)/) { - $CPPFLAGS = $1; - } elsif (m/^CFLAGS :?= (.*)/) { - $CFLAGS = $1; - } elsif (m/^CFLAGS_SL :?= (.*)/) { - $CFLAGS_SL = $1; - } elsif (m/^PTHREAD_CFLAGS :?= (.*)/) { - $PTHREAD_CFLAGS = $1; - } elsif (m/^CC :?= (.*)/) { - $CC = $1; - } - } - # If make exits with status 1, it's not an error, it just means make - # thinks some files may not be up-to-date. Only complain on status 2. - close PIPE; - die "$MAKE failed in $fpath\n" if $? != 0 && $? != 256; - - # Expand out stuff that might be referenced in CFLAGS - $CFLAGS =~ s/\$\(CFLAGS_SL\)/$CFLAGS_SL/; - $CFLAGS =~ s/\$\(PTHREAD_CFLAGS\)/$PTHREAD_CFLAGS/; - - # - # Run the compiler (which had better be gcc) to get the inclusions. - # "gcc -H" reports inclusions on stderr as "... filename" where the - # number of dots varies according to nesting depth. - # - @includes = (); - $COMPILE = "$CC $CPPFLAGS $CFLAGS -H -E $fname"; - open PIPE, "$COMPILE 2>&1 >/dev/null |" - or die "can't fork: $!"; - while (<PIPE>) { - if (m/^\.+ (.*)/) { - $include = $1; - # Ignore system headers (absolute paths); but complain if a - # .c file includes a system header before any PG header. - if ($include =~ m|^/|) { - warn "$file includes $include before any Postgres inclusion\n" - if $#includes == -1 && $file =~ m/\.c$/; - next; - } - # Strip any "./" (assume this appears only at front) - $include =~ s|^\./||; - # Make path relative to top of tree - $ipath = $fpath; - while ($include =~ s|^\.\./||) { - $ipath = dirname($ipath) . "/"; - } - $ipath =~ s|^\./||; - push @includes, $ipath . $include; - } else { - warn "$CC: $_"; +foreach $file (@hfiles, @cfiles) +{ + ($fname, $fpath) = fileparse($file); + chdir $fpath or die "can't chdir to $fpath: $!"; + + # + # Ask 'make' to parse the makefile so we can get the correct flags to + # use. CPPFLAGS in particular varies for each subdirectory. If we are + # processing a .h file, we might be in a subdirectory that has no + # Makefile, in which case we have to fake it. Note that there seems + # no easy way to prevent make from recursing into subdirectories and + # hence printing multiple definitions --- we keep the last one, which + # should come from the current Makefile. + # + if (-f "Makefile" || -f "GNUmakefile") + { + $MAKECMD = "$MAKE -qp"; } - } - # The compiler might fail, particularly if we are checking a file that's - # not supposed to be compiled at all on the current platform, so don't - # quit on nonzero status. - close PIPE or warn "$COMPILE failed in $fpath\n"; - - # - # Scan the file to find #ifdef, #ifndef, and #if defined() constructs - # We assume #ifdef isn't continued across lines, and that defined(foo) - # isn't split across lines either - # - open FILE, $fname - or die "can't open $file: $!"; - $inif = 0; - while (<FILE>) { - $line = $_; - if ($line =~ m/^\s*#\s*ifdef\s+(\w+)/) { - $symbol = $1; - &checkit; + else + { + $subdir = $fpath; + chop $subdir; + $top_builddir = ".."; + $tmp = $fpath; + while (($tmp = dirname($tmp)) ne '.') + { + $top_builddir = $top_builddir . "/.."; + } + $MAKECMD = +"$MAKE -qp 'subdir=$subdir' 'top_builddir=$top_builddir' -f '$top_builddir/src/Makefile.global'"; } - if ($line =~ m/^\s*#\s*ifndef\s+(\w+)/) { - $symbol = $1; - &checkit; + open PIPE, "$MAKECMD |" + or die "can't fork: $!"; + while (<PIPE>) + { + if (m/^CPPFLAGS :?= (.*)/) + { + $CPPFLAGS = $1; + } + elsif (m/^CFLAGS :?= (.*)/) + { + $CFLAGS = $1; + } + elsif (m/^CFLAGS_SL :?= (.*)/) + { + $CFLAGS_SL = $1; + } + elsif (m/^PTHREAD_CFLAGS :?= (.*)/) + { + $PTHREAD_CFLAGS = $1; + } + elsif (m/^CC :?= (.*)/) + { + $CC = $1; + } } - if ($line =~ m/^\s*#\s*if\s+/) { - $inif = 1; + + # If make exits with status 1, it's not an error, it just means make + # thinks some files may not be up-to-date. Only complain on status 2. + close PIPE; + die "$MAKE failed in $fpath\n" if $? != 0 && $? != 256; + + # Expand out stuff that might be referenced in CFLAGS + $CFLAGS =~ s/\$\(CFLAGS_SL\)/$CFLAGS_SL/; + $CFLAGS =~ s/\$\(PTHREAD_CFLAGS\)/$PTHREAD_CFLAGS/; + + # + # Run the compiler (which had better be gcc) to get the inclusions. + # "gcc -H" reports inclusions on stderr as "... filename" where the + # number of dots varies according to nesting depth. + # + @includes = (); + $COMPILE = "$CC $CPPFLAGS $CFLAGS -H -E $fname"; + open PIPE, "$COMPILE 2>&1 >/dev/null |" + or die "can't fork: $!"; + while (<PIPE>) + { + if (m/^\.+ (.*)/) + { + $include = $1; + + # Ignore system headers (absolute paths); but complain if a + # .c file includes a system header before any PG header. + if ($include =~ m|^/|) + { + warn "$file includes $include before any Postgres inclusion\n" + if $#includes == -1 && $file =~ m/\.c$/; + next; + } + + # Strip any "./" (assume this appears only at front) + $include =~ s|^\./||; + + # Make path relative to top of tree + $ipath = $fpath; + while ($include =~ s|^\.\./||) + { + $ipath = dirname($ipath) . "/"; + } + $ipath =~ s|^\./||; + push @includes, $ipath . $include; + } + else + { + warn "$CC: $_"; + } } - if ($inif) { - while ($line =~ s/\bdefined(\s+|\s*\(\s*)(\w+)//) { - $symbol = $2; - &checkit; - } - if (!($line =~ m/\\$/)) { - $inif = 0; - } + + # The compiler might fail, particularly if we are checking a file that's + # not supposed to be compiled at all on the current platform, so don't + # quit on nonzero status. + close PIPE or warn "$COMPILE failed in $fpath\n"; + + # + # Scan the file to find #ifdef, #ifndef, and #if defined() constructs + # We assume #ifdef isn't continued across lines, and that defined(foo) + # isn't split across lines either + # + open FILE, $fname + or die "can't open $file: $!"; + $inif = 0; + while (<FILE>) + { + $line = $_; + if ($line =~ m/^\s*#\s*ifdef\s+(\w+)/) + { + $symbol = $1; + &checkit; + } + if ($line =~ m/^\s*#\s*ifndef\s+(\w+)/) + { + $symbol = $1; + &checkit; + } + if ($line =~ m/^\s*#\s*if\s+/) + { + $inif = 1; + } + if ($inif) + { + while ($line =~ s/\bdefined(\s+|\s*\(\s*)(\w+)//) + { + $symbol = $2; + &checkit; + } + if (!($line =~ m/\\$/)) + { + $inif = 0; + } + } } - } - close FILE; + close FILE; - chdir $topdir or die "can't chdir to $topdir: $!"; + chdir $topdir or die "can't chdir to $topdir: $!"; } exit 0; # Check an is-defined reference -sub checkit { - # Ignore if symbol isn't defined in any PG include files - if (! defined $defines{$symbol}) { - return; - } - # - # Try to match source(s) of symbol to the inclusions of the current file - # (including itself). We consider it OK if any one matches. - # - # Note: these tests aren't bulletproof; in theory the inclusion might - # occur after the use of the symbol. Given our normal file layout, - # however, the risk is minimal. - # - foreach $deffile (keys %{ $defines{$symbol} }) { - return if $deffile eq $file; - foreach $reffile (@includes) { - return if $deffile eq $reffile; +sub checkit +{ + + # Ignore if symbol isn't defined in any PG include files + if (!defined $defines{$symbol}) + { + return; + } + + # + # Try to match source(s) of symbol to the inclusions of the current file + # (including itself). We consider it OK if any one matches. + # + # Note: these tests aren't bulletproof; in theory the inclusion might + # occur after the use of the symbol. Given our normal file layout, + # however, the risk is minimal. + # + foreach $deffile (keys %{ $defines{$symbol} }) + { + return if $deffile eq $file; + foreach $reffile (@includes) + { + return if $deffile eq $reffile; + } } - } - # - # If current file is a .h file, it's OK for it to assume that one of the - # base headers (postgres.h or postgres_fe.h) has been included. - # - if ($file =~ m/\.h$/) { - foreach $deffile (keys %{ $defines{$symbol} }) { - return if $deffile eq 'src/include/c.h'; - return if $deffile eq 'src/include/postgres.h'; - return if $deffile eq 'src/include/postgres_fe.h'; - return if $deffile eq 'src/include/pg_config.h'; - return if $deffile eq 'src/include/pg_config_manual.h'; + + # + # If current file is a .h file, it's OK for it to assume that one of the + # base headers (postgres.h or postgres_fe.h) has been included. + # + if ($file =~ m/\.h$/) + { + foreach $deffile (keys %{ $defines{$symbol} }) + { + return if $deffile eq 'src/include/c.h'; + return if $deffile eq 'src/include/postgres.h'; + return if $deffile eq 'src/include/postgres_fe.h'; + return if $deffile eq 'src/include/pg_config.h'; + return if $deffile eq 'src/include/pg_config_manual.h'; + } } - } - # - @places = keys %{ $defines{$symbol} }; - print "$file references $symbol, defined in @places\n"; - # print "includes: @includes\n"; + + # + @places = keys %{ $defines{$symbol} }; + print "$file references $symbol, defined in @places\n"; + + # print "includes: @includes\n"; } |