1#!/bin/sh
2# ----------------------------------------------------------------------------
3# "THE BEER-WARE LICENSE" (Revision 42):
4# <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5# can do whatever you want with this stuff. If we meet some day, and you think
6# this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7# ----------------------------------------------------------------------------
8#
9#
10# This script tries to find #include statements which are not needed in
11# the FreeBSD kernel tree.
12#
13
14set -e
15
16# Base of the kernel sources you want to work on
17cd /sys
18
19# Set to true to start from scratch, false to resume
20init=false
21
22# Which kernels you want to check
23kernels="LINT GENERIC"
24
25NO_MODULES=yes
26export NO_MODULES
27
28if $init ; then
29	(
30	echo "Cleaning modules"
31	cd modules
32	make clean > /dev/null 2>&1
33	make cleandir > /dev/null 2>&1
34	make cleandir > /dev/null 2>&1
35	make clean > /dev/null 2>&1
36	make clean > /dev/null 2>&1
37	)
38
39	(
40	echo "Cleaning compile"
41	cd compile
42	ls | grep -v CVS | xargs rm -rf
43	)
44fi
45
46(
47echo "Cleaning temp files"
48find . -name '*.h_' -print | xargs rm -f
49find . -name '::*' -print | xargs rm -f
50find . -name '*.o' -size 0 -print | xargs rm -f
51)
52
53echo "Configuring kernels"
54(
55	cd i386/conf
56	make LINT
57	if $init ; then
58		rm -rf ../../compile/LINT ../../compile/GENERIC
59	fi
60	config LINT
61	config GENERIC
62)
63
64for i in $kernels
65do
66	(
67	echo "Compiling $i"
68	cd compile/$i
69	make > x.0 2>&1
70	tail -4 x.0
71	if [ ! -f kernel ] ; then
72		echo "Error: No $i kernel built"
73		exit 1
74	fi
75	)
76done
77
78(
79echo "Compiling modules"
80cd modules
81make > x.0 2>&1
82)
83
84# Generate the list of object files we want to check
85# you can put a convenient grep right before the sort
86# if you want just some specific subset of files checked
87(
88cd modules
89for i in *
90do
91	if [ -d $i -a $i != CVS ] ; then
92		( cd $i ; ls *.o 2>/dev/null || true)
93	fi
94done
95cd ../compile
96for i in $kernels
97do
98	( cd $i ; ls *.o 2>/dev/null )
99done
100) | sed '
101/aicasm/d
102/genassym/d
103/vers.o/d
104/setdef0.o/d
105/setdef1.o/d
106' | sort -u > _
107
108objlist=`cat _`
109
110
111for o in $objlist
112do
113	l=""
114	src=""
115	for k in $kernels
116	do
117		if [ ! -f compile/$k/$o ] ; then
118			continue;
119		fi
120		l="$l compile/$k"
121		if [ "x$src" = "x" ] ; then
122			cd compile/$k
123			mv $o ${o}_
124			make -n $o > _
125			mv ${o}_ $o
126			src=compile/$k/`awk '$1 == "cc" {print $NF}' _`
127			cd ../..
128			if expr "x$src" : 'x.*\.c$' > /dev/null ; then
129				true
130			else
131				echo NO SRC $o
132				src=""
133			fi
134		fi
135	done
136	for m in modules/*
137	do
138		if [ ! -d $m -o ! -f $m/$o ] ; then
139			continue;
140		fi
141		l="$l $m"
142		if [ "x$src" = "x" ] ; then
143			cd $m
144			mv $o ${o}_
145			make -n $o > _
146			mv ${o}_ $o
147			src=`awk '$1 == "cc" {print $NF}' _`
148			cd ../..
149			if expr "x$src" : 'x.*\.c$' > /dev/null ; then
150				if [ "`dirname $src`" = "." ] ; then
151					src="$m/$src"
152				fi
153				true
154			else
155				echo NO SRC $o
156				src=""
157			fi
158		fi
159	done
160	if [ "x$src" = "x" ] ; then
161		echo "NO SOURCE $o"
162		continue
163	fi
164	echo "OBJ	$o"
165	echo "	SRC	$src"
166
167	grep -n '^[ 	]*#[ 	]*include' $src | sed '
168	s/^\([0-9]*\):[ 	]*#[ 	]*include[ 	]*[<"]/\1 /
169	s/[">].*//
170	/ opt_/d
171	' | sort -rn | while read lin incl
172	do
173		S=""
174		echo "		INCL	$lin	$incl"
175		cp $src ${src}_
176
177		# Check if we can compile without this #include line.
178
179		sed "${lin}s/.*//" ${src}_ > ${src}
180		for t in $l
181		do
182			cd $t
183			mv ${o} ${o}_
184			if make ${o} > _log 2>&1 ; then
185				if cmp -s ${o} ${o}_ ; then
186					echo "			$t	same object"
187				else
188					echo "			$t	changed object"
189					S=TAG
190				fi
191			else
192				echo "			$t	used"
193				S=TAG
194			fi
195			mv ${o}_ ${o}
196			cd ../..
197			if [ "x$S" != "x" ] ; then
198				break
199			fi
200		done
201		if [ "x$S" != "x" ] ; then
202			mv ${src}_ ${src}
203			continue
204		fi
205
206		# Check if this is because it is a nested #include
207		for t in $l
208		do
209			cd $t
210			rm -rf foo
211			mkdir -p foo/${incl}
212			rmdir foo/${incl}
213			touch foo/${incl}
214			mv ${o} ${o}_
215			if make INCLMAGIC=-Ifoo ${o} > _log2 2>&1 ; then
216				if cmp -s ${o} ${o}_ ; then
217					echo "			$t	still same object"
218				else
219					echo "			$t	changed object"
220					S=TAG
221				fi
222			else
223				echo "			$t	nested include"
224				S=TAG
225			fi
226			rm -rf foo
227			mv ${o}_ ${o}
228			cd ../..
229			if [ "x$S" != "x" ] ; then
230				break
231			fi
232		done
233		if [ "x$S" != "x" ] ; then
234			mv ${src}_ ${src}
235			continue
236		fi
237
238		# Check if this is because it is #ifdef'ed out
239
240		sed "${lin}s/.*/#error \"BARF\"/" ${src}_ > ${src}
241		for t in $l
242		do
243			cd $t
244			mv ${o} ${o}_
245			if make ${o} > /dev/null 2>&1 ; then
246				echo "			$t	line not read"
247				S=TAG
248			fi
249			mv ${o}_ ${o}
250			cd ../..
251			if [ "x$S" != "x" ] ; then
252				break
253			fi
254		done
255
256		mv ${src}_ ${src}
257		if [ "x$S" != "x" ] ; then
258			continue
259		fi
260
261		# Check if the warnings changed.
262
263		for t in $l
264		do
265			cd $t
266			mv ${o} ${o}_
267			if make ${o} > _ref 2>&1 ; then
268				if cmp -s _ref _log ; then
269					echo "			$t	same warnings"
270				else
271					echo "			$t	changed warnings"
272					S=TAG
273				fi
274			else
275				echo "ARGHH!!!"
276				exit 9
277			fi
278
279			mv ${o}_ ${o}
280			cd ../..
281			if [ "x$S" != "x" ] ; then
282				break
283			fi
284		done
285		if [ "x$S" != "x" ] ; then
286			continue
287		fi
288		cp $src ${src}_
289		sed "${lin}d" ${src}_ > ${src}
290		rm ${src}_
291		touch _again
292		echo "BINGO $src $lin $incl $obj $l"
293	done
294done
295