Syntax errors in include files????

Michael Condict condict at cs.vu.nl
Mon May 7 22:31:57 AEST 1990


In article <594 at atcmpe.atcmp.nl> jc at atcmp.nl (Jan Christiaan van Winkel) writes:
>
> In article <222 at dynasys.UUCP> jessea at dynasys.UUCP () writes:
>>I'm getting all kinds of syntax errors from include files when I try
>>to compile stuff - like times.h, types.h.  Can anyone tell me why
>>I'm getting syntax errors from my include files?  I haven't done any
>
>Suggestion: try running the C preprocessor alone. This may give you more info
>on where exactly the problem is.

Having used this approach in the past to debug problems with the order of
declarations in multiple include files, I've found it difficult to see what's
going on, due to the difficulty of determining which include files each
piece of the preprocessed text came from.  The information is there in the
output of most C preprocessors, in the form of lines that start with "#" and
have filenames and mysterious numbers in them, but it is illegible to the
human eye.  Also, there are too many empty lines in the output, further
reducing its comprehensibility.

I made a shell script called "cincl" that runs the C preprocessor and filters
the output into something more decipherable.  It puts an easily recognizable
marker (with filename) at the top and bottom of each piece of output that
comes from an include file.  Also, it indents each such piece  by an amount
proportional to the "#include" nesting level.  By default, it only outputs
the tree of include file names, using indenting to show nesting level.  Run
with the verbose flag (-v), however, it outputs the contents of the include
files and top-level source file as well.  In this case, it suppresses empty
lines.

I've been told by the users of it here that it especially eases the pain of
debugging problems with nested includes and conditional includes.

The script is appended below.  Note that it expects the preprocessor output
to be as in BSD UNIX or SunOs.  Minor changes should allow it to work for
System V and other versions of UNIX.

As an example of its use, consider the following four files:

	incl2a.h:
		char broiled;

	incl2b.h:
		long johns;

	incl1.h":
		#include "incl2a.h"
		#include "incl2b.h"
		int imate;

	prog.c:
		#include "incl1.h"
		#include <stdio.h>
		main() {
			long arrested = (int)imate + johns;
		}

On SunOS, the command "cincl prog.c" produces the following output:

	./incl1.h
		./incl2a.h
		./incl2b.h
	/usr/include/errno.h
		/usr/include/sys/errno.h

And "cincl -v prog.c" produces:

	#include "./incl1.h"
		#include "./incl2a.h"
			char broiled;
		#endinclude "./incl2a.h"
	 
		#include "./incl2b.h"
			long johns;
		#endinclude "./incl2b.h"

		int imate;
	#endinclude "./incl1.h"
 
	#include "/usr/include/errno.h"

		#include "/usr/include/sys/errno.h"

		#endinclude "/usr/include/sys/errno.h"
	 
		extern int errno;
	#endinclude "/usr/include/errno.h"

	main() { 
		long arrested = (int)imate + johns;
	}

I hope others find this useful.

Michael Condict
Vrije University
Amsterdam

--------------------------- cincl shell script -------------------------------
#
# See Usage, below, for description
#

if [ $# -eq 0 ]; then
	set - "-?"
fi

# Default options:
case `basename $0` in
	am*)	CC=amcc ;;
	*)	CC=cc
esac
verbose=0
cc_flags=""

while [ $# -gt 0 ] ; do
	case "$1" in
		-v)	verbose=1 ;;
		"-?"|-o|-c)
			cat 1>&2 <<EOF
Usage: $0 [ -v ] [ -Ddef ] [ -Iinclude-dir ]...  C-file...

Runs cpp on the C-files and prints tree of nested include file names.
With -v, also prints pre-processed contents of the C-files and include files.
EOF
			exit 1 ;;
		-*)	cc_flags="$cc_flags $1" ;;
		*)	break ;;
	esac
	shift
done
$CC -E $cc_flags "$@" |
	awk 'BEGIN	  {	prev_line_blank = 0
				level = 0
			  }
	    /^#.*[0-9]$/  {
				if ($4 == 1) {
					for (i=0; i<level; i++)
						printf("	")
					if ('$verbose')
						printf("#include %s\n", $3)
					else
						printf("%s\n", \
						    substr($3, 2, length($3)-2))
					name[level] = $3
					level = level + 1
					prev_line_blank = 0
				} else if ($4 == 2) {
					level = level - 1
					if ('$verbose') {
						for (i=0; i<level; i++)
							printf("	")
						print "#endinclude " \
								name[level] "\n"
						prev_line_blank = 1
					} else
						prev_line_blank = 0
				}
				next
			  }
	    /^#/	  {	next
			  }
	    /^[ 	]*$/ {	if ('$verbose' && !prev_line_blank)
					print $0
				prev_line_blank = 1
				next
			  }
		    	  {	if ('$verbose') {
					for (i=0; i<level; i++)
						printf("	")
					printf ("%s\n", \
						    substr($0, 1, 79 - 8*level))
					prev_line_blank = 0
				}
				next
			  }'
--------------------------- End cincl shell script ----------------------------
--
Michael Condict		condict at cs.vu.nl
Vrije University
Amsterdam



More information about the Comp.lang.c mailing list