1:
2# remove extra #include's
3
4# pgcompinclude must be run before and after pgrminclude.  It must be
5# run before  because we don't want include dependencies to leak into
6# the C program files, and after because removal of includes from headers
7# can cause new include unfulfilled dependencies.
8#
9# Limitations:  2011-09-24
10#
11# Pgrminclude, when processing header files, can cause includes to be
12# removed that require the addition of new illogical header files.
13# This is dependent on what order the header files are processed.
14# Manual review of header files now needed to satisfy pgcompinclude is
15# required.
16#
17# C program files that have #ifdef blocks that contain code that cannot
18# be compiled on the platform from which pgrminclude is run cannot be
19# processed, and are skipped.
20
21: ${CC:=cc}
22: ${PGSRC:=src}
23
24if ! pgdefine
25then	echo "pgdefine must be in your PATH" 1>&2
26	exit 1
27fi
28
29trap "rm -f /tmp/$$.c /tmp/$$.o /tmp/$$ /tmp/$$a /tmp/$$b" 0 1 2 3 15
30
31if [ "$1" = "-v" ]
32then	VERBOSE="Y"
33else	VERBOSE=""
34fi
35
36verbose_output() {
37	if [ "$VERBOSE" ]
38	then	cat /tmp/$$
39		cat /tmp/$$b
40		nl /tmp/$$.c
41	fi
42}
43
44process_includes_in_file() {
45	# loop through all includes mentioned in the file
46	cat "$FILE" |
47	grep "^#include\>" |
48	grep -v '/\* *pgrminclude  *ignore *\*/' |
49	sed 's/^#include[ 	]*[<"]\([^>"]*\).*$/\1/g' |
50	grep -v 'parser/kwlist\.h' |
51	grep -v '\.c$' |
52	while read INCLUDE
53	do	if [ "$VERBOSE" ]
54		then	echo "checking $FILE $INCLUDE"
55		fi
56		compile_file
57	done
58}
59
60compile_file() {
61	[ "$INCLUDE" -a -s /usr/include/"$INCLUDE" ] && continue
62	[ "$INCLUDE" = "postgres.h" ] && continue
63	[ "$INCLUDE" = "postgres_fe.h" ] && continue
64	[ "$INCLUDE" = "pg_config.h" ] && continue
65	[ "$INCLUDE" = "c.h" ] && continue
66	# Stringify macros will expand undefined identifiers, so skip files that use it
67	egrep -q '\<(CppAsString2?|CppConcat)\>' "$FILE" && continue
68
69	# preserve configure-specific includes
70	# these includes are surrounded by #ifdef's
71	grep -B1 '^#include[ 	][ 	]*[<"]'"$INCLUDE"'[>"]' "$FILE" |
72	     egrep -q '^#if|^#else|^#elif' && continue
73	grep -A1 '^#include[ 	][ 	]*[<"]'"$INCLUDE"'[>"]' "$FILE" |
74	     egrep -q '^#else|^#elif|^#endif' && continue
75
76        # Remove all #if and #ifdef blocks because the blocks
77	# might contain code that is not compiled on this platform.
78	cat "$FILE" |
79	grep -v "^#if" |
80	grep -v "^#else" |
81	grep -v "^#elif" |
82	grep -v "^#endif" |
83	# with #if blocks gone, now undef #defines to avoid redefine
84	# warning and failure
85	sed 's/#define[ 	][ 	]*\([A-Za-z0-9_]*\).*$/#undef \1\n&/' >/tmp/$$a
86
87	# set up initial file contents
88	grep -v '^#include[ 	][ 	]*[<"]'"$INCLUDE"'[>"]' \
89		/tmp/$$a >/tmp/$$b
90
91	if [ "$IS_INCLUDE" = "Y" ]
92	then	echo "#include \"postgres.h\"" >/tmp/$$.c
93		# suppress fcinfo errors
94		echo "struct {Datum       arg[1];} *fcinfo;" >>/tmp/$$.c
95	else	>/tmp/$$.c
96	fi
97
98	echo "#include \"/tmp/$$b\"" >>/tmp/$$.c
99
100	if [ "$IS_INCLUDE" = "Y" ]
101	then	echo "Datum include_test(void);" >>/tmp/$$.c
102		echo "Datum include_test() {" >>/tmp/$$.c
103		pgdefine "$FILE" >>/tmp/$$.c
104		echo "return (Datum)0;" >>/tmp/$$.c
105		echo "}" >>/tmp/$$.c
106	fi
107
108	# Use -O1 to get warnings only generated by optimization,
109	# but -O2 is too slow.
110	$CC -fsyntax-only -Werror -Wall -Wmissing-prototypes \
111		-Wmissing-declarations -I$PGSRC/include -I$PGSRC/backend \
112		-I$PGSRC/interfaces/libpq -I`dirname $FILE` $CFLAGS -O1 -c /tmp/$$.c \
113		-o /tmp/$$.o >/tmp/$$ 2>&1
114	if [ "$?" -eq 0 ]
115	then	[ "$INCLUDE" -o "$VERBOSE" ] && echo "$FILE $INCLUDE"
116		grep -v '^#include[ 	][ 	]*[<"]'"$INCLUDE"'[>"]' \
117			"$FILE" >/tmp/$$b
118		mv /tmp/$$b "$FILE"
119		return 0
120	else	return 1
121	fi
122}
123
124# Process include files first because they can affect the compilation
125# of *.c files.
126(find . \( -name .git -a -prune \) -o -type f -name '*.h' -print | sort;
127 find . \( -name .git -a -prune \) -o -type f -name '*.c' -print | sort) |
128grep -v '/postgres.h$' |
129grep -v '/postgres_fe.h$' |
130grep -v '/pg_config.h$' |
131grep -v '\./c.h$' |
132while read FILE
133do
134	if [ `expr $FILE : '.*\.h$'` -ne 0 ]
135	then	IS_INCLUDE="Y"
136	else	IS_INCLUDE="N"
137	fi
138
139	# Can we compile the file with all existing includes?
140	INCLUDE=""
141	compile_file
142	# If the file can't be compiled on its own, there is no sense
143	# trying to remove the include files.
144	if [ "$?" -ne 0 ]
145	then	echo "cannot compile $FILE with existing includes"
146		verbose_output
147	else	process_includes_in_file
148	fi
149done
150