#! /bin/bash # Last edited on 2021-07-16 21:56:03 by jstolfi # Writes to {stdout} a list of all ".c" or ".h" files in the current # directory that import one or more specified ".h" files, directly or # indirectly. # Usage: ${cmd} module1.h module2.h ... # Relies on a file ".chfiles" in the current dir. # Will not recognize '#include "..."', only "#include <...>'. modules=( "$@" ) tmp="/tmp/$$" # Get list of files: if [[ ! ( -s .chfiles ) ]]; then echo "** file '.chfiles' not found" 1>&2; exit 1 fi ls -l .chfiles rm -f ${tmp}.direct # Get the modules themselves: for m in ${modules[@]} ; do egrep -e "/${m}" .chfiles >> ${tmp}.direct done # Get direct uses: modpat="${modules[*]}" modpat="${modpat/.h /|}" modpat="${modpat/ /|}" modpat="${modpat/.h/}" modpat="#include *<(${modpat})[.]h>" egrep -l -e "${modpat}" `cat .chfiles` \ | egrep -v -e 'JUNK|SAVE' \ | sort | uniq \ >> ${tmp}.direct ( printf "direct: "; cat ${tmp}.direct | wc -l ) 1>&2 # Get indirect uses: cat ${tmp}.direct | sort | uniq > ${tmp}.ind1 cat ${tmp}.direct | sort | uniq > ${tmp}.users for pass in 1 2 3; do # Prepare patterns to find imports of ".h" files in ${tmp}.ind1: cat ${tmp}.ind1 \ | egrep -e '[.]h$' \ | sed -e 's:^:#include *<:g' -e 's:$:>:g' \ > ${tmp}.pats # Search for files than import filesin ${tmp}.ind1: egrep -l -f ${tmp}.pats `cat .chfiles` \ | sort | uniq \ > ${tmp}.ind2 # Exclude those that have already been found: bool 1-2 ${tmp}.ind2 ${tmp}.users > ${tmp}.ind3 ( printf "indirect: "; cat ${tmp}.ind3 | wc -l ) 1>&2 if [[ ! ( -s ${tmp}.ind3 ) ]]; then break; fi # Add those new files to the list of users: cat ${tmp}.users ${tmp}.ind3 | sort | uniq > ${tmp}.aa mv ${tmp}.aa ${tmp}.users # Prepare to search for their imports: mv ${tmp}.ind3 ${tmp}.ind1 done cat ${tmp}.users