1XCOMM!/bin/sh
2XCOMM
3XCOMM	Do the equivalent of the 'makedepend' program, but do it right.
4XCOMM
5XCOMM	Usage:
6XCOMM
7XCOMM	makedepend [cpp-flags] [-w width] [-s magic-string] [-f makefile]
8XCOMM	  [-o object-suffix] [-v] [-a] [-cc compiler] [-d dependencyflag]
9XCOMM
10XCOMM	Notes:
11XCOMM
12XCOMM	The C compiler used can be overridden with the environment
13XCOMM	variable "CC" or the command line flag -cc.
14XCOMM
15XCOMM	The "-v" switch of the "makedepend" program is not supported.
16XCOMM
17XCOMM
18XCOMM	This script should
19XCOMM	work on both USG and BSD systems.  However, when System V.4 comes out,
20XCOMM	USG users will probably have to change "silent" to "-s" instead of
21XCOMM	"-" (at least, that is what the documentation implies).
22XCOMM
23
24CC=PREPROC
25
26silent='-'
27
28TMP=`pwd`/.mdep$$
29
30rm -rf ${TMP}
31if ! mkdir -p ${TMP}; then
32  echo "$0: cannot create ${TMP}, exit." >&2
33fi
34
35CPPCMD=${TMP}/a
36DEPENDLINES=${TMP}/b
37TMPMAKEFILE=${TMP}/c
38MAGICLINE=${TMP}/d
39ARGS=${TMP}/e
40
41trap "rm -rf ${TMP}; exit 1" 1 2 15
42trap "rm -rf ${TMP}; exit 0" 1 2 13
43
44echo " \c" > $CPPCMD
45if [ `wc -c < $CPPCMD` -eq 1 ]
46then
47    c="\c"
48    n=
49else
50    c=
51    n="-n"
52fi
53
54echo $n "$c" >$ARGS
55
56files=
57makefile=
58magic_string='# DO NOT DELETE'
59objsuffix='.o'
60width=78
61endmarker=""
62verbose=n
63append=n
64compilerlistsdepends=n
65
66while [ $# != 0 ]
67do
68    if [ "$endmarker"x != x ] && [ "$endmarker" = "$1" ]; then
69	endmarker=""
70    else
71	case "$1" in
72	    -D*|-I*|-U*)
73		echo $n " '$1'$c" >> $ARGS
74		;;
75
76	    -g|-O)	# ignore so we can just pass $(CFLAGS) in
77		;;
78
79	    *)
80		if [ "$endmarker"x = x ]; then
81		    case "$1" in
82			-w)
83			    width="$2"
84			    shift
85			    ;;
86			-s)
87			    magic_string="$2"
88			    shift
89			    ;;
90			-f*)
91			    if [ "$1" = "-f-" ]; then
92				makefile="-"
93			    elif [ "$1" = "-f" ]; then
94				makefile="$2"
95				shift
96			    else
97				echo "$1" | sed 's/^\-f//' >${TMP}arg
98				makefile="`cat ${TMP}arg`"
99				rm -f ${TMP}arg
100			    fi
101			    ;;
102			-o)
103			    objsuffix="$2"
104			    shift
105			    ;;
106
107			--*)
108			    echo "$1" | sed 's/^\-\-//' >${TMP}end
109			    endmarker="`cat ${TMP}end`"
110			    rm -f ${TMP}end
111			    if [ "$endmarker"x = x ]; then
112				endmarker="--"
113			    fi
114			    ;;
115			-v)
116			    verbose="y"
117			    ;;
118
119			-a)
120			    append="y"
121			    ;;
122
123			-cc)
124			    CC="$2"
125			    shift
126			    ;;
127
128			# Flag to tell compiler to output dependencies directly
129			# For example, with Sun compilers, -xM or -xM1 or
130			# with gcc, -M
131		        -d)
132			    compilerlistsdepends="y"
133			    compilerlistdependsflag="$2"
134			    shift
135			    ;;
136
137			-*)
138			    echo "Unknown option '$1' ignored" 1>&2
139			    ;;
140			*)
141			    files="$files $1"
142			    ;;
143		    esac
144		fi
145		;;
146	esac
147    fi
148    shift
149done
150echo ' $*' >> $ARGS
151
152if [ "$compilerlistsdepends"x = "y"x ] ; then
153  CC="$CC $compilerlistdependsflag"
154fi
155
156echo "#!/bin/sh" > $CPPCMD
157echo "exec $CC `cat $ARGS`" >> $CPPCMD
158chmod +x $CPPCMD
159rm $ARGS
160
161case "$makefile" in
162    '')
163	if [ -r makefile ]
164	then
165	    makefile=makefile
166	elif [ -r Makefile ]
167	then
168	    makefile=Makefile
169	else
170	    echo 'no makefile or Makefile found' 1>&2
171	    exit 1
172	fi
173	;;
174    -)
175	makefile=$TMPMAKEFILE
176	;;
177esac
178
179if [ "$verbose"x = "y"x ]; then
180    cat $CPPCMD
181fi
182
183echo '' > $DEPENDLINES
184
185if [ "$compilerlistsdepends"x = "y"x ] ; then
186    for i in $files
187    do
188	$CPPCMD $i >> $DEPENDLINES
189    done
190else
191for i in $files
192do
193    $CPPCMD $i \
194      | sed -n "/^#/s;^;$i ;p"
195done \
196  | sed -e 's|/[^/.][^/]*/\.\.||g' -e 's|/\.[^.][^/]*/\.\.||g' \
197    -e 's|"||g' -e 's| \./| |' \
198  | awk '{
199	if ($1 != $4  &&  $2 != "#ident" && $2 != "#pragma")
200	    {
201	    numparts = split( $1, ofileparts, "\." )
202	    ofile = ""
203	    for ( i = 1; i < numparts; i = i+1 )
204		{
205		if (i != 1 )
206		    ofile = ofile "."
207		ofile = ofile ofileparts[i]
208		}
209	    print ofile "'"$objsuffix"'", $4
210	    }
211	}' \
212  | sort -u \
213  | awk '
214	    {
215	    newrec = rec " " $2
216	    if ($1 != old1)
217		{
218		old1 = $1
219		if (rec != "")
220		    print rec
221		rec = $1 ": " $2
222		}
223	    else if (length (newrec) > '"$width"')
224		{
225		print rec
226		rec = $1 ": " $2
227		}
228	    else
229		rec = newrec
230	    }
231	END \
232	    {
233	    if (rec != "")
234		print rec
235	    }' \
236  | egrep -v '^[^:]*:[ 	]*$' >> $DEPENDLINES
237fi
238
239trap "" 1 2 13 15	# Now we are committed
240case "$makefile" in
241    $TMPMAKEFILE)
242	;;
243    *)
244	rm -f $makefile.bak
245	cp $makefile $makefile.bak
246	echo "Appending dependencies to $makefile"
247	;;
248esac
249
250XCOMM
251XCOMM If not -a, append the magic string and a blank line so that
252XCOMM /^$magic_string/+1,\$d can be used to delete everything from after
253XCOMM the magic string to the end of the file.  Then, append a blank
254XCOMM line again and then the dependencies.
255XCOMM
256if [ "$append" = "n" ]
257then
258    cat >> $makefile << END_OF_APPEND
259
260$magic_string
261
262END_OF_APPEND
263    ed $silent $makefile << END_OF_ED_SCRIPT
264/^$magic_string/+1,\$d
265w
266q
267END_OF_ED_SCRIPT
268    echo '' >>$makefile
269fi
270
271cat $DEPENDLINES >>$makefile
272
273case "$makefile" in
274    $TMPMAKEFILE)
275	cat $TMPMAKEFILE
276	;;
277
278esac
279
280rm -rf ${TMP}*
281exit 0
282