How to get rid of the unuseful includes in a source file? In my team, this is a real nightmare, some guys are including everything they can think of... I would like to clean up this mess. But how to do it effectively?

This script will try to do the job:
#!/bin/ksh

try=/tmp/include_try_$$.c

comp="$1"
shift
while [[ $# > 0 ]]
  do
    first_letter=` echo $1 | sed 's/\(.\).*/\1/' `
    if [[ "$1" = "-o" ]]; then
      # ignore the target file name
      shift 2
    elif [[ "$first_letter" = "-" ]]; then
      # keep the flag
      comp="$comp $1"
      shift
    elif [[ "$first_letter" = "+" ]]; then
      # keep the flag
      comp="$comp $1"
      shift
    else
      # ignore the source file name
      source=$1
      shift
    fi
  done

grep '^[  ]*#[  ]*include[  ]*' $source | while read line
  do
    sed "s+^$line\$++" $source > $try
    if ( 1>&- 2>&- $comp -o ${try%.c}.o $try )
      then
        rm ${try%.c}.o
        echo line \"$line\" can be removed in $source
      fi
    rm $try
  done

and run it via make:
make "CXX=script CC"

But this is not good at all: before cleaning the code, we must clean the header files themselves.
Some headers are missing (i.e. a header file a.h uses a type/routine defined in another header b.h, but a.h does not include b.h). A quick way to test this is to try to compile a.h included in an empty code file (i.e. a file containing the single line #include "a.h"), but what about the types/routines which are in macros (e.g. if a.h contains #define DEBUG(x) printf(x))?
Some headers include non useful headers. Of course, once cleaned, the code files may not compile anymore because once b.h is not included anymore in a.h, it will have to be included in a.c. But this is not an issue.
I hope that once we have cleaned up the headers, we do not have such situations such as a.h including b.h and b.h including a.h (I'm pretty sure that due to design errors, we will have this). In this case, the previous script will not work.
In fact, I need a real preprocessor / C++ analyzer (which is more difficult than a simple C++ parser).
This is too difficult :-( If you have any idea/tool, I'm interested...

By the way, this script also improperly handles the architecture dependent preprocessing (e.g. #if defined(solaris) #include <sys/solaris.h> #endif).
 



Last update: April 7th, 2001 - Laurent