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