			C Program Checker
			-----------------

This program has been posted as a result of a discussion in comp.lang.c
concerning some possible errors in writing C programs.  It is a C syntax
checker, to be used as an adjunct to lint, not a replacement.  It makes
no attempt to duplicate any warning given by the standard lint, and is not
at all forgiving about simple syntax errors.  It warns about the following
possible errors :-

1.	Assignment in conditional context
	A warning is issued for any assignment in any conditional context,
	where the programmer might have mistyped = when == was intended.
	Thus, 'if (a=b)' will give a warning, while 'if ((a=b)!=0)' will not.
	(NOTE:  I am not saying that people should not write 'if (a=b)' and
	similar constructs - I frequently do - but that on SOME occasions
	programmers make typing errors which are not picked up by lint or cc,
	and are not easily visually seen as errors.)

2.	if with neither then nor else
	One of my colleagues once wrote
		if	(a == b);
		{
			lots of useful code ...
		}
	and we spent a whole day tracking down why this was not doing as
	we expected before I noticed the extra semicolon.  (The condition
	was actually more complicated, so the semicolon was not as obvious,
	and we spent our time working out why the condition did not appear
	to have the right value.  We were also working on a machine which
	did not supply adb, only sdb, and that did not work!)

3.	I come from an Algol68 background, and I HATE the 'dangling-else'
	language ambiguity in C, Pascal, ...!  So, not that I have ever
	seen it as a problem in practice, the program warns about potentially
	ambiguous elses :-

		if	(a == b)
			if	(c == d)
				action1 ();
			else	action2 ();
	will generate a warning, while :-

		if	(a == b)
		{
			if	(c == d)
				action1 ();
			else	action2 ();
		}
	will not.

4.	Nested comment
	I just added this as a result of further net discussion of errors;
	this will give a warning if '/*' is seen inside a comment, so that
	errors such as that below are noticed.
	a = 1;	/* initialise a
	b = 2;  /* initialise b  */
	The current line number and that where the outer comment started are
	included in the warning message.

5.	Unterminated comment
	If end-of-file is reached while in a comment.  This is also noticed
	by both cpp and cc, but check gives the line number where the comment
	started, not just the line number where the error was detected, i.e.,
	the last line!


The program uses yacc and lex.  The grammar was written by me, and is not a
complete C grammar - some obsolete or weird constructs are (deliberately) not
supported.  ('Weird' as defined by me!!)  No attempt has been made (yet) to
support ANSI C.  It is not very fast - profiling shows that most of the time
is spent in the lex-generated analyser, as one might expect.

There is some code, mostly commented out, to calculate and print software
metrics, but this needs changes to the lexing, parsing and symbol handling
which I have not yet done.  If anyone completes this work, or has any improved
metrics to suggest, please send it back to me!

As an example, the output of 'check *.c' in the check source directory is :-
lex.c: assignment in conditional context at or near line 163
lex.c: assignment in conditional context at or near line 588
lex.c: assignment in conditional context at or near line 616
symbol.c: assignment in conditional context at or near line 79
test.c: nested comment, starting at line 20, at or near line 21
test.c: unterminated comment, starting at line 194, at or near line 202
test.c: IF with neither THEN nor ELSE at or near line 93
test.c: potentially mismatched ELSE - use {} at or near line 117
test.c: assignment in conditional context at or near line 132

This program is in no way derived from lint sources, which I have not even
looked at, and is free of all copyright restrictions.

Wed Jan 20 1988

Nick Crossley
Computer Consoles Inc.
9801 Muirlands Boulevard,
Irvine
CA 92718
(714) 458-7282
email: ...!uunet!ccicpg!nick
