| 1 | #!/usr/bin/env bash
|
|---|
| 2 | #
|
|---|
| 3 | # usage: inclosure [ -I dir ] ... [ -G header-name ] ... header-name ...
|
|---|
| 4 | #
|
|---|
| 5 | # Locates each standard header and argument header-name in the
|
|---|
| 6 | # specified "-I" include path (default is /usr/include) and parses
|
|---|
| 7 | # any header names out of its #include directives. These names are
|
|---|
| 8 | # treated recursively to identify a _transitive_closure_ of standard
|
|---|
| 9 | # header names, which is sorted and sent to standard output. Headers
|
|---|
| 10 | # not specified with -G, and included somewhere but not located are
|
|---|
| 11 | # reported.
|
|---|
| 12 | #
|
|---|
| 13 | # Each header reported by this program must be "shadowed" by a
|
|---|
| 14 | # file of the same name in a C++ header. See
|
|---|
| 15 | # http://www.cantrip.org/cheaders.html
|
|---|
| 16 | #
|
|---|
| 17 | # BUGS:
|
|---|
| 18 | # - Cannot cope with header file names that contain spaces
|
|---|
| 19 | # - Ignores comment-block delimiters
|
|---|
| 20 | # - Ignores sub-includes under #include_next headers.
|
|---|
| 21 |
|
|---|
| 22 | OLDH=/tmp/old$$
|
|---|
| 23 | echo "this-compensates-for-a-stupid-bug-in-GNU-fgrep." >$OLDH
|
|---|
| 24 | HDRS=/tmp/hdrs$$
|
|---|
| 25 | >$HDRS
|
|---|
| 26 | NEW=/tmp/new$$
|
|---|
| 27 | >$NEW
|
|---|
| 28 | IGNORES=/tmp/ignores$$
|
|---|
| 29 | echo "this-compensates-for-a-stupid-bug-in-GNU-fgrep.">$IGNORES
|
|---|
| 30 |
|
|---|
| 31 | trap "rm -f $NEW $HDRS $OLDH $IGNORES" 0
|
|---|
| 32 |
|
|---|
| 33 | # process arguments
|
|---|
| 34 | unset INCPATH
|
|---|
| 35 | while [ $# != 0 -a "$1" != "${1#-}" ]; do
|
|---|
| 36 | FLAG="${1%%${1##-?}}"
|
|---|
| 37 | case "$FLAG" in -I|-G)
|
|---|
| 38 | ARG="${1##${FLAG}}"
|
|---|
| 39 | if [ "$ARG" = "" ]; then
|
|---|
| 40 | if [ $# != 0 ]; then
|
|---|
| 41 | shift;
|
|---|
| 42 | ARG="$1"
|
|---|
| 43 | else
|
|---|
| 44 | echo "$0: $FLAG needs an argument."
|
|---|
| 45 | exit
|
|---|
| 46 | fi
|
|---|
| 47 | fi ;;
|
|---|
| 48 | esac
|
|---|
| 49 | shift
|
|---|
| 50 | case "$FLAG" in
|
|---|
| 51 | -I) INCPATH="$INCPATH $ARG" ;;
|
|---|
| 52 | -G) echo " $ARG " >>$IGNORES ;;
|
|---|
| 53 | esac
|
|---|
| 54 | done
|
|---|
| 55 | INCPATH=${INCPATH-"/usr/include"}
|
|---|
| 56 |
|
|---|
| 57 | # identify headers
|
|---|
| 58 |
|
|---|
| 59 | STDHDRS="assert.h ctype.h errno.h float.h limits.h \
|
|---|
| 60 | locale.h math.h setjmp.h signal.h stdarg.h stddef.h \
|
|---|
| 61 | stdio.h stdlib.h string.h time.h wchar.h wctype.h "
|
|---|
| 62 | OTHERS="$*"
|
|---|
| 63 |
|
|---|
| 64 | for file in $STDHDRS $OTHERS; do
|
|---|
| 65 | echo "$file"
|
|---|
| 66 | done >$HDRS
|
|---|
| 67 |
|
|---|
| 68 | until cmp -s $OLDH $HDRS; do # (until no new headers found)
|
|---|
| 69 |
|
|---|
| 70 | fgrep -v -f $OLDH $HDRS \
|
|---|
| 71 | | while read file; do
|
|---|
| 72 | found=no
|
|---|
| 73 | for dir in $INCPATH; do
|
|---|
| 74 | name="$dir/$file"
|
|---|
| 75 | if [ -f "$name" ]; then
|
|---|
| 76 | cat "$name"
|
|---|
| 77 | found=yes
|
|---|
| 78 | break;
|
|---|
| 79 | fi
|
|---|
| 80 | done
|
|---|
| 81 | if [ "$found" = no ]; then # && echo " $file " | fgrep -v -q -f $IGNORES
|
|---|
| 82 | echo "$0: warning: header $file not found in include path." $1>&2
|
|---|
| 83 | fi
|
|---|
| 84 | done \
|
|---|
| 85 | | sed -n -e \
|
|---|
| 86 | '/^[ ]*#[ ]*include[ ]*<[^>]*>/s/^[^<]*<\([^>]*\)>.*/\1/p' \
|
|---|
| 87 | | while read file; do
|
|---|
| 88 | drop=no
|
|---|
| 89 | for ignore in `cat $IGNORES`; do
|
|---|
| 90 | if [ "$ignore" = "$file" ]; then drop=yes; fi
|
|---|
| 91 | done
|
|---|
| 92 | case "$file" in /*) drop=yes;; esac # no absolute paths
|
|---|
| 93 | case $drop in no) echo "$file";; esac
|
|---|
| 94 | done >$NEW
|
|---|
| 95 | mv $HDRS $OLDH
|
|---|
| 96 | cat $OLDH $NEW | sort -u -o $HDRS
|
|---|
| 97 |
|
|---|
| 98 | done
|
|---|
| 99 | cat $HDRS
|
|---|
| 100 |
|
|---|
| 101 |
|
|---|
| 102 |
|
|---|