1236769Sobrien:
2236769Sobrien# NAME:
3236769Sobrien#	mkdeps - generate dependencies
4236769Sobrien#
5236769Sobrien# SYNOPSIS:
6236769Sobrien#	mkdeps [options] file ...
7236769Sobrien#
8236769Sobrien# DESCRIPTION:
9236769Sobrien#	This script updates "makefile" with dependencies for
10236769Sobrien#	"file"(s).  It borrows ideas from various makedepend scripts
11236769Sobrien#	and should be compatible with most.
12236769Sobrien#
13236769Sobrien#	By default we use grep to extract include file names from
14236769Sobrien#	source files.  We source an "rc" file '$Mydir/.${Myname}rc' which
15236769Sobrien#	can contain variable assignments such as:
16236769Sobrien#.nf
17236769Sobrien#   
18236769Sobrien#	cpp_c=/usr/lib/cpp
19236769Sobrien#	cpp_cc=g++ -E
20236769Sobrien#	...
21236769Sobrien#
22236769Sobrien#.fi
23236769Sobrien#	If the variable 'cpp_$suffix' is set, we use it as our cpp in
24236769Sobrien#	place of grep.  The program referenced by these variables are
25236769Sobrien#	expected to produce output like:
26236769Sobrien#.nf
27236769Sobrien#
28236769Sobrien#	# 10 \"/usr/include/stdio.h\" 1
29236769Sobrien#
30236769Sobrien#.fi
31236769Sobrien#	This allows us to skip most of our processing.  For lex,yacc
32236769Sobrien#	and other source files, grep is probably just as quick and
33236769Sobrien#	certainly more portable.
34236769Sobrien#
35236769Sobrien#	If the "rc" file does not exist, we create it and attempt to
36236769Sobrien#	find cpp or an equivalent cc invocation to assign to 'cpp_c'.
37236769Sobrien#		
38236769Sobrien# AUTHOR:
39236769Sobrien#	Simon J. Gerraty <sjg@zen.void.oz.au>
40236769Sobrien#
41236769Sobrien
42236769Sobrien# RCSid:
43236769Sobrien#	$Id: mkdeps.sh,v 1.23 2002/11/29 06:58:59 sjg Exp $
44236769Sobrien#
45236769Sobrien#	@(#) Copyright (c) 1993 Simon J. Gerraty
46236769Sobrien#
47236769Sobrien#	This file is provided in the hope that it will
48236769Sobrien#	be of use.  There is absolutely NO WARRANTY.
49236769Sobrien#	Permission to copy, redistribute or otherwise
50236769Sobrien#	use this file is hereby granted provided that 
51236769Sobrien#	the above copyright notice and this notice are
52236769Sobrien#	left intact. 
53236769Sobrien#      
54236769Sobrien#	Please send copies of changes and bug-fixes to:
55236769Sobrien#	sjg@zen.void.oz.au
56236769Sobrien#
57236769Sobrien
58236769SobrienMyname=`basename $0 .sh`
59236769SobrienMydir=`dirname $0`
60236769Sobrien
61236769Sobriencase `echo -n .` in
62236769Sobrien-n*)	N=; C="\c";;
63236769Sobrien*)	N=-n; C=;;
64236769Sobrienesac
65236769Sobrien
66236769Sobriencc_include=-I/usr/include
67236769Sobrien
68236769SobrienTF=/tmp/dep.$$
69236769SobrienEF=/tmp/deperr.$$
70236769Sobrien> $EF
71236769Sobrien
72236769Sobriencase "$*" in
73236769Sobrien*-n*)				# don't use rc file
74236769Sobrien  rc=/dev/null
75236769Sobrien  norc=yes;;
76236769Sobrien*)
77236769Sobrien  rc=$Mydir/.${Myname}rc
78236769Sobrien  ;;
79236769Sobrienesac
80236769Sobrien
81236769Sobrienupdate=
82236769SobrienInclude=include
83236769Sobrien
84236769Sobrienif [ x"$norc" = x -a -f $rc ]; then
85236769Sobrien  . $rc
86236769Sobrienelse
87236769Sobrien  # if /usr/lib/cpp or equivalent is available it is better than
88236769Sobrien  # grepping .c files.
89236769Sobrien  # See what (if anything) works on this system...
90236769Sobrien  echo : > $rc
91236769Sobrien  echo "# pre-processor for .c files" >> $rc
92236769Sobrien  # try a couple of sane places first
93236769Sobrien  for d in /usr/libexec /usr/lib /usr/bin /lib /usr/ccs/bin
94236769Sobrien  do
95236769Sobrien    cpp_c=$d/cpp
96236769Sobrien    [ -x $cpp_c ] && break
97236769Sobrien  done
98236769Sobrien  
99236769Sobrien  if [ -x $cpp_c ]; then
100236769Sobrien    echo cpp_c=$cpp_c >> $rc
101236769Sobrien  else
102236769Sobrien    cpp_c=
103236769Sobrien    # rats see if cc can be used
104236769Sobrien    echo "#include <stdio.h>" > /tmp/f$$.c
105236769Sobrien    echo "main() { return 0; }" >> /tmp/f$$.c
106236769Sobrien    # try some sensible args to cc
107236769Sobrien    for arg in -E -P -M
108236769Sobrien    do
109236769Sobrien      ok=`${REALCC:-${CC:-cc}} $arg /tmp/f$$.c 2>/dev/null | grep '^#.*stdio.h' | tail -1`
110236769Sobrien      case "$ok" in
111236769Sobrien      "") ;;
112236769Sobrien      *)
113236769Sobrien        cpp_c="${REALCC:-${CC:-cc}} $arg"
114236769Sobrien        echo cpp_c="'$cpp_c'" >> $rc
115236769Sobrien        break;;
116236769Sobrien      esac
117236769Sobrien    done
118236769Sobrien    rm -f /tmp/f$$.c
119236769Sobrien  fi
120236769Sobrienfi
121236769Sobrien
122236769Sobrienclean_up() {
123236769Sobrien  trap "" 2 3
124236769Sobrien  trap 0
125236769Sobrien  if [ -s $EF ]; then
126236769Sobrien          egrep -vi "included from|warning" $EF > ${EF}2
127236769Sobrien          if [ -s ${EF}2 ]; then
128236769Sobrien	          cat $EF >&2
129236769Sobrien                  rm -f .depend
130236769Sobrien                  ests=1
131236769Sobrien	  fi
132236769Sobrien  fi
133236769Sobrien  rm -f $TF $EF*
134236769Sobrien  exit ${ests:-0}
135236769Sobrien}
136236769Sobrien
137236769Sobrien# this lot does not work on HPsUX - complain to Hp.
138236769Sobrientrap clean_up 0
139236769Sobrientrap exit 2 3
140236769Sobrien
141236769Sobrienget_incs() {
142236769Sobrien  case "$cpp" in
143236769Sobrien  grep)
144236769Sobrien    # set IGNORE="<" to skip system includes
145236769Sobrien    egrep '^#[ 	]*include' $* | egrep -v "$IGNORE" | \
146236769Sobrien      sed -e 's/^.*include[^"<]*["<]//' -e 's/[">].*//g';;
147236769Sobrien  *)
148236769Sobrien    # $cpp (eg. /usr/lib/cpp or cc -E) should produce output like:
149236769Sobrien    # 1 "/usr/include/stdio.h" 2
150236769Sobrien    # set IGNORE=/usr/include to skip system includes
151236769Sobrien    $cpp $cpp_opts $cc_include $* 2>> $EF | egrep '^#.*\.h"' | sed 's,^#.*"\(.*\)".*,\1,' |
152236769Sobrien      egrep -v "$IGNORE" | sort -u;;
153236769Sobrien  esac
154236769Sobrien}
155236769Sobrien
156236769Sobriengen_deps() {
157236769Sobrien  llen=$1
158236769Sobrien  shift
159236769Sobrien
160236769Sobrien  for ifile in $*
161236769Sobrien  do
162236769Sobrien    case "$cpp" in
163236769Sobrien    grep)
164236769Sobrien      # this lot is not needed if not using grep.
165236769Sobrien      for dir in $srcdir $dirlist /usr/include
166236769Sobrien      do
167236769Sobrien        [ -f "$dir/$ifile" ] && break
168236769Sobrien      done
169236769Sobrien
170236769Sobrien      if [ ! -f "$dir/$ifile" ]; then
171236769Sobrien        # produce a useful error message (useful to emacs or error)
172236769Sobrien        iline=`grep -n ".*include.*[\"<]$ifile[\">]" $file | cut -d: -f1`
173236769Sobrien        echo "\"$file\", line $iline: cannot find include file \"$ifile\"" >> $EF
174236769Sobrien        # no point adding to dependency list as the resulting makefile
175236769Sobrien        # would not work anyway...
176236769Sobrien        continue
177236769Sobrien      fi
178236769Sobrien      ifile=$dir/$ifile
179236769Sobrien      
180236769Sobrien      # check whether we have done it yet
181236769Sobrien      case `grep "$ifile" $TF` in
182236769Sobrien      "") echo "$ifile" >> $TF;;
183236769Sobrien      *)	continue;;		# no repeats...
184236769Sobrien      esac
185236769Sobrien      ;;
186236769Sobrien    esac
187236769Sobrien    
188236769Sobrien    len=`expr "$ifile " : '.*'`
189236769Sobrien    if [ "`expr $llen + $len`" -gt ${width:-76} ]; then
190236769Sobrien      echo "\\" >> .depend
191236769Sobrien      echo $N "	$C" >> .depend
192236769Sobrien      llen=8
193236769Sobrien    fi
194236769Sobrien    echo $N "$ifile $C" >> .depend
195236769Sobrien    llen=`expr $llen + $len`
196236769Sobrien    
197236769Sobrien    case "$cpp" in
198236769Sobrien    grep)
199236769Sobrien      # this lot is not needed unless using grep.
200236769Sobrien      ilist=`get_incs $ifile` # recurse needed?
201236769Sobrien      [ "$ilist" ] && llen=`gen_deps $llen $ilist`
202236769Sobrien      ;;
203236769Sobrien    esac
204236769Sobrien  done
205236769Sobrien  echo $llen
206236769Sobrien}
207236769Sobrien
208236769Sobrienfor f in makefile Makefile
209236769Sobriendo
210236769Sobrien  test -s $f && { MAKEFILE=$f; break; }
211236769Sobriendone
212236769Sobrien
213236769SobrienMAKEFILE=${MAKEFILE:-makefile}
214236769SobrienIGNORE=${IGNORE:-"^-"}		# won't happen
215236769Sobrienobj=o
216236769Sobriencpp_opts=			# incase cpp != grep
217236769Sobrienvpath=
218236769Sobrienappend=
219236769SobrienprogDep=
220236769Sobrien
221236769Sobrienset -- `getopt "AanNV:s:w:o:I:D:b:f:i:p" "$@"`
222236769Sobrienfor key in "$@"
223236769Sobriendo
224236769Sobrien  case $key in
225236769Sobrien  --)	shift; break;;
226236769Sobrien  -A)	Include=;;		# cat .depend >> $MAKEFILE
227236769Sobrien  -a)	append=yes; shift;;
228236769Sobrien  -n)	shift;;			# ignore rc
229236769Sobrien  -N)	update=no; shift;;	# don't update $MAKEFILE
230236769Sobrien  -I)	cpp_opts="$cpp_opts$1$2 "; dirlist="$dirlist $2"; shift 2;;
231236769Sobrien  -o)	obj=$2; shift 2;;
232236769Sobrien  -s)	shift 2;;		# can't handle it anyway...
233236769Sobrien  -w)	width=$2; shift 2;;
234236769Sobrien  -f)	MAKEFILE=$2; shift 2;;
235236769Sobrien  -b)	BASEDIR=$2; shift 2;;
236236769Sobrien  -i)	IGNORE="$2"; shift 2;;	# ignore headers matching this...
237236769Sobrien  -D)	cpp_opts="$cpp_opts$1$2 "; shift 2;;
238236769Sobrien  -V)	VPATH="$2"; shift 2;;	# where to look for files
239236769Sobrien  -p)	progDep=yes; shift;;
240236769Sobrien  esac
241236769Sobriendone
242236769Sobrien
243236769Sobrien[ "$VPATH" ] && vpath=`IFS=:; set -- $VPATH; echo $*`
244236769Sobrien
245236769Sobrien[ "$append" ] || > .depend
246236769Sobrien
247236769Sobrienfor file in $*
248236769Sobriendo
249236769Sobrien  cpp=
250236769Sobrien  suffix=`expr $file : '.*\.\([^.]*\)'`
251236769Sobrien
252236769Sobrien  eval cpp=\"\${cpp_${suffix}:-grep}\"
253236769Sobrien  
254236769Sobrien  if [ ! -f $file -a "$vpath" ]; then
255236769Sobrien    for d in . $vpath
256236769Sobrien    do
257236769Sobrien      [ -f $d/$file ] && { file=$d/$file; break; }
258236769Sobrien    done
259236769Sobrien  fi
260236769Sobrien  srcdir=`dirname $file`
261236769Sobrien  base=`basename $file .$suffix`
262236769Sobrien  
263236769Sobrien  ilist=`get_incs $file`
264236769Sobrien
265236769Sobrien  if [ "$ilist" ]; then
266236769Sobrien    > $TF
267236769Sobrien    if [ "$progDep" ]; then
268236769Sobrien      echo "$base:	$file \\" >> .depend
269236769Sobrien    else
270236769Sobrien      echo "$base.$obj:	$file \\" >> .depend
271236769Sobrien    fi
272236769Sobrien    echo $N "	$C" >> .depend
273236769Sobrien    llen=8
274236769Sobrien    llen=`gen_deps $llen $ilist`
275236769Sobrien    echo >> .depend
276236769Sobrien    echo >> .depend
277236769Sobrien  elif [ "$progDep" ]; then
278236769Sobrien    echo "$base:	$file" >> .depend
279236769Sobrien    echo >> .depend
280236769Sobrien  fi
281236769Sobriendone
282236769Sobrien
283236769Sobrienif [ -s .depend ]; then
284236769Sobrien  # ./foo.h looks ugly
285236769Sobrien  mv .depend $TF
286236769Sobrien  { test "$BASEDIR" && sed -e "s;$BASEDIR;\$(BASEDIR);g" $TF || cat $TF; } |
287236769Sobrien    sed 's;\([^.]\)\./;\1;g' > .depend 
288236769Sobrien
289236769Sobrien  #
290236769Sobrien  # Save the manually updated section of the makefile
291236769Sobrien  #
292236769Sobrien  if [ x$update != xno ]; then
293236769Sobrien    trap "" 2			# don't die if we got this far
294236769Sobrien
295236769Sobrien    # if make doesn't support include, then append our deps...
296236769Sobrien    depended=`grep 'include.*\.depend' $MAKEFILE`
297236769Sobrien    test "$depended" && clean_up
298236769Sobrien  
299236769Sobrien    sed '/^# DO NOT DELETE.*depend.*$/,$d' < $MAKEFILE > $TF
300236769Sobrien    mv $TF $MAKEFILE
301236769Sobrien    cat <<! >> $MAKEFILE
302236769Sobrien# DO NOT DELETE THIS LINE -- make depend depends on it
303236769Sobrien# Do not edit anything below, it was added automagically by $Myname.
304236769Sobrien
305236769Sobrien!
306236769Sobrien  
307236769Sobrien    case "$Include" in
308236769Sobrien    "")	cat .depend >> $MAKEFILE;;
309236769Sobrien    .include)	echo '.include ".depend"' >> $MAKEFILE;;
310236769Sobrien    include)	echo include .depend >> $MAKEFILE;;
311236769Sobrien    esac
312236769Sobrien  fi
313236769Sobrienfi
314236769Sobrienclean_up
315