#! /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

  
