Re: Missing #include <config.h>

From: Doug Maxey
Date: Tue Sep 13 2005 - 11:22:58 EST



On Tue, 13 Sep 2005 09:12:33 CDT, Josh Boyer wrote:
>On Tue, 2005-09-13 at 14:56 +0100, Jörn Engel wrote:
>> After spending some hours last night and this morning hunting a bug,
>> I've found that a different include order made a difference. Some
>> files don't work correctly, unless config.h is included before.
>>
>> Here is a very stupid bug checker for the problem class:
>> $ rgrep CONFIG include/ | cut -d: -f1 | sort -u > g1
>> $ rgrep CONFIG include/ | cut -d: -f1 | sort -u | xargs grep "config.h" | cut -d: -f1 | sort -u > g2
>> $ diff -u g1 g2 | grep ^- > g3
>
>Your checker doesn't quite test for nested includes. E.g. if foo.h
>includes bar.h, and bar.h includes config.h, then foo.h doesn't need to
>include config.h explicitly.
>
>For a more concrete example, take include/asm-i386/kprobes.h from your
>list. That includes linux/types.h, which includes linux/config.h.
>
>Making a tool that takes that into account could be interesting.
>
>josh
>
>-
>To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>the body of a message to majordomo@xxxxxxxxxxxxxxx
>More majordomo info at http://vger.kernel.org/majordomo-info.html
>Please read the FAQ at http://www.tux.org/lkml/
>

Going Way Back - there was a perl script floating around last century
named 'inctree' that did what he was looking for...

++doug

#!/usr/local/bin/perl
# $Id: inctree,v 1.1.1.1 2001/11/16 17:16:36 dwm Exp $
# $Header: /cvs/local/share/inctree,v 1.1.1.1 2001/11/16 17:16:36 dwm Exp $
# $Log: inctree,v $
# Revision 1.1.1.1 2001/11/16 17:16:36 dwm
# after rome burned.
#
# Revision 1.1 2001/11/16 17:16:36 dwm
# .
#
# Revision 1.10 1998-06-11 09:35:42-05 dwm
# *** empty log message ***
#
# Revision 1.9 1998-06-11 09:32:20-05 dwm
# *** empty log message ***
#
# Revision 1.8 1996-06-20 11:09:00-05 dwm
# *** empty log message ***
#
# Revision 1.7 1996-06-20 11:06:47-05 dwm
# sucks on AIX build tree.
#
# Revision 1.6 1996-06-20 08:39:46-05 dwm
# *** empty log message ***
#
# Revision 1.5 1996-06-20 08:34:11-05 dwm
# fix for using other compiler.
#
# Revision 1.4 1995-06-07 20:15:35-0500 dwm
# now we exclude the -c, -f*, and -M* compiler flags.
#
# Revision 1.3 1994-06-08 22:46:37-0500 dwm
# added support for C++
#
# Revision 1.2 1993/07/16 04:06:56 dwm
# Zthe -? neeeded a \.
#
# Revision 1.1 1993/07/16 03:51:35 dwm
# Initial revision
#

require 5.004;

# 'inctree' created 93/07/09 11:40 to validate/print the #includes
# for files.
# from the camel book, p274
#################################
############ GLOBALS ############
#################################
( $prog = $0 ) =~ s#.*/##o ; $0 = join(' ', $prog, @ARGV) ;
$CPP = $ENV{'CPP'} || 'gcc -E' ;
$shiftwidth = 4 ;

#################################
########## SUBROUTINES ##########
#################################
sub usage
{
print STDERR @_ if @_ ;
print STDERR <<"EOU" ;
usage: $prog [-d] [-D...] [-I...] [-l] [-m/pattern/] file...

$prog runs the C preprocessor (default $CPP) on the specified files,
passing along any -D or -I switches, then processes the output of
cpp into a tree of who included what. Files included more than
once are marked DUPLICATE.

flags:
-C... preprocessor definition (default $CPP_name).
-D... defines for the preprocessor.
-I... dirs to search for the #include files.
-d prints debugging info.
-h|-? print this message.
-l prints the line numbers of the include statements.
-m/../ outputs any lines including the pattern specified.
-s\d sets shiftwidth (default $shiftwidth).
EOU
exit 1 ;
}

#################################
############ MAIN ############
#################################
# require 'getopts.pl' ;
# &Getopts('dD:I:lm:') || &usage ;
while ( $ARGV[0] =~ /^-/ )
{
$_ = shift ;
if (/^-C(.*)/)
{
$opt_cpp = ( $1 ? $1 : shift ) ;
}
elsif (/^-([DU])(.*)/)
{
$defines .= " -$1" . ($2 ? $2 : shift );
}
elsif (/^-I(.*)/)
{
$includes .= " -I" . ($1 ? $1 : shift );
}
elsif (/^-m(.*)/)
{
push(@pats, $1 ? $1 : shift );
}
elsif ( /^-d/ )
{
$debug++ ;
}
elsif ( /^-l/ )
{
$lines++ ;
}
elsif (/^-s(.*)/)
{
$shiftwidth = ( $1 ? $1 : shift ) ;
}
elsif (/^-h|^-\?/)
{
&usage ;
}
# other compiler flags
elsif (/^-g(.*)|^-O(.*)|^-traditional|^-c|^-f(.*)|^-M(.*)/)
{
next ;
}
elsif (/^-v$/ )
{
$verbose = $_ ;
}
else
{
push (@ccopts, $_);
#&usage("Unrecognized switch $_\n") ;
}

}

print STDERR "$defines\n" if $debug ;
print STDERR "$includes\n" if $debug ;

# build a subroutine to scan for patterns
if ( @pats )
{
$sub = "sub pats ()\n{\n" ;
foreach $pat ( @pats )
{
$sub .= " print '>>>>>>> ',\$_ if m$pat;\n" ;
}
$sub .= "}\n" ;
print STDERR $sub if $debug ;
eval $sub ;
die $@ if $@ ;
++$pats ;
}

# process each file.
foreach $file (@ARGV)
{
if (length $opt_cpp)
{
$CPP_name = $opt_cpp;
}
elsif ($file =~ /.C$|.cc$/) {
$CPP_name = "g++ -E" ;
}
else {
$CPP_name = $CPP ;
}

$ccopts = join (" ", @ccopts);
$pipecmd = "$CPP_name $verbose $ccopts $defines $includes $file|" ;
open(CPP,$pipecmd)
|| die "Can't run $pipecmd: $!\n" ;
$line = 2 ;

while (<CPP>)
{
++$line ;
pats () if $pats ; # avoid expensive call if we can.
next unless /^#/ ;
next unless /^# \d/ ;
(undef, $newline, $filename) = split ;
$filename =~ s/\"//g ;

# now figure out if it's push, pop, or neither.
if ($stack[$#stack] eq $filename)
{
$line = $newline - 1 ;
next ;
}

if ($stack[$#stack - 1] eq $filename) # Leaving file.
{
$indent -= $shiftwidth ;
$line = pop(@lines) - 1 ;
pop(@stack) ;
}
else # New file.
{
printf "%6d ", $line -2 if $lines ;
push(@lines, $line) ;
$line = $newline ;
print "\t" x ($indent / 8), ' ' x ($indent % 8),
$filename ;
print " DUPLICATE" if $seen{$filename}++ ;
print "\n" ;
$indent += $shiftwidth ;
push(@stack, $filename) ;
}
}
close CPP ;
$indent = 0 ;
%seen = () ;
print "\n\n" ;
$line = 0 ;
}
exit 0