[net.sources] postlint: annotate line messages with source code lines

perlman@wanginst.UUCP (Gary Perlman) (10/05/86)

postlint is a simple filter that tries to annotate the output
from lint (the C program checker) with the lines lint complains
about, along with some context lines where appropriate.  It is
not very smart about how it reads lint's output, but then, lint
is not very smart about how it formats its output, eh?

Gary Perlman   decvax!wanginst!perlman

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	postlint.1
#	makefile
#	postlint.c
#	human.c
# This archive created: Sat Oct  4 20:53:45 1986
# By:	Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(348 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	Xpostlint is a simple filter that tries to annotate the output
	Xfrom lint (the C program checker) with the lines lint complains
	Xabout, along with some context lines where appropriate.  It is
	Xnot very smart about how it reads lint's output, but then, lint
	Xis not very smart about how it formats its output, eh?
	X
	XGary Perlman   decvax!wanginst!perlman
SHAR_EOF
if test 348 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 348 characters)'
fi
fi
echo shar: "extracting 'postlint.1'" '(1252 characters)'
if test -f 'postlint.1'
then
	echo shar: "will not over-write existing file 'postlint.1'"
else
sed 's/^	X//' << \SHAR_EOF > 'postlint.1'
	X.TH POSTLINT "1" "Friday 3 October 1986" "Wang Institute" "UNIX Programmers's Manual" 
	X.SH NAME
	Xpostlint \- postprocessing filter for lint messages
	X.SH USAGE
	X.B postlint 
	X[number-of-context-lines] < lint-output
	X.SH DESCRIPTION
	XThe input to
	X.I postlint
	Xis the output from the
	X.I lint(1)
	XC program checker.
	X.I postlint
	Xreads the
	X.I lint
	Xoutput and prints the flagged lines in the files
	X.I lint
	Xwas working on.
	X.I postlint
	Xsimply looks for numbers in parentheses to find line numbers,
	Xand it prints those lines,
	Xpreceded by a controllable number of context lines.
	XThese context lines are often where the error occurred,
	Xnot on the line mentioned.
	XBy default, the number of context lines is two.
	XWhen printing lines from system
	X.I lint
	Xfiles,
	Xonly one line is printed.
	X.I postlint
	Xdetermines the current file by looking for a name
	Xbefore the parenthesized line number or by looking
	Xfor lines with just one field.
	XFor example, when
	X.I lint
	Xis working on postlint.c,
	Xit prints
	X.ti +.5i
	Xpostlint.c:
	X.br
	X.SH FILES
	X.nf
	X.ta 1.5i
	X/usr/lib/lint	Berkeley directory of standard function type declarations
	X/usr/lib	System V directory of standard function type declarations
	X.fi
	X.SH "SEE ALSO"
	Xlint(1)
	X.SH AUTHOR
	XGary Perlman 
	X.SH STATUS
	Xnew, probably not smart enough
SHAR_EOF
if test 1252 -ne "`wc -c < 'postlint.1'`"
then
	echo shar: "error transmitting 'postlint.1'" '(should have been 1252 characters)'
fi
fi
echo shar: "extracting 'makefile'" '(236 characters)'
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'makefile'
	X# if compiling on System V, use -DSYSV
	XCFLAGS=-O -DSYSV
	XCFLAGS=-O
	X
	Xpostlint: postlint.o
	X	cc -o postlint postlint.o
	X
	Xarchive: README postlint.1 makefile postlint.c human.c
	X	shar -a README postlint.1 makefile postlint.c human.c > archive
SHAR_EOF
if test 236 -ne "`wc -c < 'makefile'`"
then
	echo shar: "error transmitting 'makefile'" '(should have been 236 characters)'
fi
fi
echo shar: "extracting 'postlint.c'" '(4159 characters)'
if test -f 'postlint.c'
then
	echo shar: "will not over-write existing file 'postlint.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'postlint.c'
	X/*OVERVIEW
	X	postlint [#context-lines] < lint-messages
	X
	X	prints lint messages with context lines from file
	X
	X	postlint reads lint output and reacts to two patterns:
	X		^name[:]$  sets current input file to "name"
	X				   if it can't find the name, it looks in LINTLIB
	X		([0-9]+)   line number + Context lines before are printed after message
	X*/
	X
	X#ifdef	SYSV
	X# define	LINTLIB   "/usr/lib"         /* where lint types are kept */
	X#else
	X# define	LINTLIB   "/usr/lib/lint"    /* where lint types are kept */
	X#endif
	X
	X#include <stdio.h>
	X#include <ctype.h>
	X
	X#define	EOS  '\0'
	X
	Xchar	Lintfile[BUFSIZ];    /* current file lint is talking about */
	Xint 	Linecount = 0;       /* line number in Lintfile */
	Xint 	Context = 2;         /* number of context lines to print */
	XFILE	*getioptr ();
	X
	X/*FUNCTION main: loop through files in classic UNIX filter style */
	Xmain (argc, argv)
	Xint 	argc;     /* argument count */
	Xchar	**argv;   /* argument vector */
	X	{
	X	if (argc > 1)
	X		{
	X		if (isdigit (argv[1][0]))
	X			Context = atoi (argv[1]);
	X		else
	X			fprintf (stderr, "Usage: postlint [number of context lines]\n");
	X		}
	X	
	X	dolines ();
	X	exit (0);
	X	}
	X
	X/*FUNCTION dolines: process the lint error messages */
	Xdolines ()
	X	{
	X	char	line[BUFSIZ];
	X	int 	lineno;
	X	char	*ptr;
	X	char	buf[BUFSIZ];     /* buffer to hold names */
	X	FILE	*ioptr = NULL;
	X
	X	while (gets (ptr = line))
	X		{
	X		putchar ('\n');
	X		puts (line);
	X		if (onefield (line)) /* file name */
	X			{
	X			for (ptr = line; isspace (*ptr); ptr++)
	X				continue;
	X			(void) strcpy (buf, ptr);
	X			for (ptr = buf; *ptr && !isspace (*ptr) && *ptr != ':'; ptr++)
	X				continue;
	X			*ptr = EOS;
	X			ioptr = getioptr (buf, ioptr);
	X			}
	X		else
	X			for (ptr = line; *ptr; ptr++)
	X				if (*ptr == '(')
	X					{
	X					*ptr = EOS;
	X					if (lineno = atoi (ptr+1))
	X						{
	X						if (getname (line, ptr, buf))
	X							ioptr = getioptr (buf, ioptr);
	X						printlines (ioptr, lineno);
	X						}
	X					}
	X		}
	X	}
	X
	X
	X/*FUNCTION printlines: print the appropriate lines from source files */
	X#define	printit(line,lineno,what) printf ("%7d %-7s %s", lineno, what, line)
	Xprintlines (ioptr, lineno)
	XFILE	*ioptr;
	Xint 	lineno;
	X	{
	X	char	line[BUFSIZ];
	X	int 	nlines = Context;    /* print this many lints before target */
	X
	X	if (ioptr == NULL)
	X		return;
	X
	X	if (!strncmp (LINTLIB, Lintfile, strlen (LINTLIB))) /* print one line */
	X		nlines = 0;
	X
	X	if (lineno-nlines < Linecount) /* we are too far into the file */
	X		{
	X		rewind (ioptr);
	X		Linecount = 0;
	X		}
	X
	X	while (fgets (line, BUFSIZ, ioptr))
	X		{
	X		Linecount++;
	X		if (Linecount == lineno)
	X			{
	X			printit (line, Linecount, ">>>");
	X			return;
	X			}
	X		else if (Linecount >= (lineno-nlines))
	X			printit (line, Linecount, "");
	X		}
	X	}
	X
	X/*UTILITIES*/
	X/*FUNCTION getname: get last field on line and stuff in buf */
	Xgetname (line, eptr, buf)
	Xchar	*line, *eptr, *buf;
	X	{
	X	while (eptr > line && !isspace (*(eptr-1)) && *(eptr-1) != EOS)
	X		eptr--;
	X	(void) strcpy (buf, eptr);
	X	return (*eptr != EOS);
	X	}
	X
	X/*FUNCTION getiooptr: gets new ioptr based on passed filename */
	X/*
	X	once this procedure is done,
	X		the global filename Lintfile is set
	X*/
	XFILE *
	Xgetioptr (filename, ioptr)
	Xchar	*filename;
	XFILE	*ioptr;
	X	{
	X	char	fullpath[BUFSIZ];
	X	FILE	*newioptr;
	X
	X	if (!strcmp (filename, Lintfile)) /* same as current file */
	X		return (ioptr);
	X	if (*filename == EOS) /* no file? */
	X		return (ioptr);
	X	newioptr = fopen (filename, "r");
	X	if (newioptr == NULL)
	X		{
	X		(void) sprintf (fullpath, "%s/%s", LINTLIB, filename);
	X		newioptr = fopen (fullpath, "r");
	X		filename = fullpath;
	X		}
	X	if (newioptr != NULL)
	X		{
	X		(void) strcpy (Lintfile, filename);
	X		if (ioptr)
	X			(void) fclose (ioptr);
	X		}
	X	else /* leave thinsg as they were */
	X		newioptr = ioptr;
	X	Linecount = 0;
	X	return (newioptr);
	X	}
	X
	X/*FUNCTION onefield: returns true if arg line has one name field */
	Xonefield (line)
	Xchar	*line;
	X	{
	X	int 	alpha = 0;       /* number of alpha chars on line */
	X	int 	nonalpha = 0;    /* number of nonalpha chars on line */
	X	while (isspace (*line))
	X		line++;
	X	if (*line == EOS)
	X		return (0);
	X	while (*line && !isspace (*line))
	X		{
	X		if (isalpha (*line))
	X			alpha++;
	X		else
	X			nonalpha++;
	X		line++;
	X		}
	X	while (isspace (*line))
	X		line++;
	X	return (*line == EOS && alpha > nonalpha);
	X	}
SHAR_EOF
if test 4159 -ne "`wc -c < 'postlint.c'`"
then
	echo shar: "error transmitting 'postlint.c'" '(should have been 4159 characters)'
fi
fi
echo shar: "extracting 'human.c'" '(642 characters)'
if test -f 'human.c'
then
	echo shar: "will not over-write existing file 'human.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'human.c'
	X#define morals Y
	X#define morals Z
	Xextern float allegiance;
	Xint	principles ();
	Xmain ()
	X	{
	X	char	*principles ();
	X	psyche;
	X	human ();
	X	bowels ();
	X	conscience ();
	X	moral_sense ();
	X	religion (principles ());
	X	marriage (allegiance);
	X	}
	Xextern float	allegiance;
	Xhuman ()
	X	{
	X	int appendix;
	X	struct	brain {short intelligence; long pride;} brain;
	X	marriage (allegiance,principles(),allegiance);
	X	return;
	X	religion (brain);
	X	happiness ();
	X	}
	Xbowels () { return (1); }
	Xconscience () { return (0); }
	Xcommon_sense () { exit (moral_sense ()); }
	Xmoral_sense () { return (1); }
	Xdouble entendre () {return (entendre ());}
	Xreligion (based_on_data) {int devil;}
SHAR_EOF
if test 642 -ne "`wc -c < 'human.c'`"
then
	echo shar: "error transmitting 'human.c'" '(should have been 642 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
Gary Perlman  Wang Institute  Tyngsboro, MA 01879  (617) 649-9731
UUCP: decvax!wanginst!perlman             CSNET: perlman@wanginst