[alt.sources] cgrind revisited

davidsen@sungod.crd.ge.com (William Davidsen) (06/08/89)

cgrind as posted was useful, but I wanted to use it with the "psf"
program posted recently, so I could get 2 or 4 logical pages to a sheet.
While I was at it I thought it would be useful to generate ANSI escapes
as well, since that allows viewing with attributes on most systems. Then
I decided that I should *really* hack it and write a man page. I realize
that nothing with a man page should be posted here ;-)

Anyway, the man page and diffs were about 1k shorter than the whole
thing, and I'm sure someone missed the original as would post a note
saying "will someone send..." so here it is, cgrind as hacked to do
additional things.

#!/bin/sh
# shar:	Shell Archiver  (v1.24)
#
#	Run the following text with /bin/sh to create:
#	  cgrind.1
#	  cgrind.c
#	  cgrind.h
#
echo "x - extracting cgrind.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > cgrind.1 &&
X'\" @(#)skeleton	3.3 - 12/21/83
X'\" [c][e][t] (only if preprocessing by cw, eqn, and/or tbl required)
X.TH CGRIND 1 local
X'\" Heading: name(sect)    center (paren)    name(sect)
X.SH NAME
Xcgrind \- format a C program for Postscript or ANSI display
X.SH SYNOPSIS
Xcgrind [options] [file [file]]
X.SH DESCRIPTION
X.B cgrind
Xreads C source from either the list of files provided on the command line
Xor
X.BR stdin .
XThe file is formatted with reserved words in
X.B bold
Xand comments in
X.I italics.
XEscape sequences are provided at the start and end of each highlighted
Xsection. The output escape sequences must then be further processed
Xinto Postscript.
X.sp
X.nf
XThese options are used:
X\fB-i\fR   don't place comments in italics.
X\fB-s\fR   output will go to a screen. Implies -i.
X\fB-t\fInn\fR expand tabs to \fInn\fR spaces. Default is 4.
X\fB-a\fR   output ANSI sequences instead of Postscript
X\fB-A\fR   output ANSI color sequences instead of Postscript
X.SH EXAMPLES
X.nf
Xcgrind -t8 main.c part1.c | lpr
Xcgrind -A rotate.c | more
X.SH LIMITATIONS
XRequires a Postscript printer or ANSI display.
X.SH AUTHOR
XOriginal author Joe Larson (joe@dayton.dhdsc.mn.org), man page and minor
Xfixes by Bill Davidsen (davidsen@crdos1.crd.ge.com).
X'\" For more details, see man(7), as well as man(1), manroff(1), and mmt(1)
SHAR_EOF
chmod 0666 cgrind.1 || echo "restore of cgrind.1 fails"
echo "x - extracting cgrind.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > cgrind.c &&
X#include <stdio.h>
X#include <ctype.h>
X#if	0
X#include <dayton/stdtyp.h>
X#endif	/* non-portable */
X#include "cgrind.h"
X
X#define		START_ITALICS	0
X#define		END_ITALICS	1
X#define		START_BOLD	2
X#define		END_BOLD	3
X
X/* Postscript processor escape sequences */
Xchar *ES_postscr[] = {
X	"\033I", "\033i", "\033B", "\033b"
X};
X
X/* ANSI display escape sequences */
Xchar *ES_ansi_clr[] = {
X	"\033[31m", "\033[37m",
X	"\033[1m",  "\033[0m"
X};
Xchar *ES_ansi[] = {
X	"\033[7m", "\033[0m",
X	"\033[1m", "\033[0m"
X};
X
X/* escape pointer */
Xchar **EP = ES_postscr;
X#define add_ctrl(string) add_control(oline+olen, EP[string])
X
X/*
X * cgrind -- take c programs and pretty them up with bolding and
X *			 such.
X *
X * cgrind [-s] [-i] [-tnn] [filelist]
X *
X *		-s -- output will go to a screen devices rather than one
X *				of our printers.  Implies -i.
X *		-i -- don't italics comments.
X *		-t -- tabstops.  -t0 to not perform tabbing.  Default is -t4.
X *		-a -- use ANSI monochrome escape sequences
X *		-A -- use ANSI color escape sequences
X *
X * Revision History:
X *		Jun 6 1989
X *			Converted to use strings for control sequences
X *			and added the ANSI control stuff for screen viewing.
X *			davidsen@crdos1.crd.ge.com
X *
X *		Sometime in 1987:
X *			Written by Joe Larson, DHDSC.  joe@dayton.dhdsc.mn.org
X */
X
Xextern int errno;
X
X/* the following section was guessed by hand, since the non-portable
X   include file was not distributed.
X*/
Xtypedef int bool;
X#ifndef	TRUE
X#define TRUE	1
X#define	FALSE	0
X#endif
X/* end of guessing games */
X
Xbool italics = TRUE;
Xbool screen_device = FALSE;
Xshort	tabstops = 4;
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	register short	i;
X	FILE			*file;
X	bool			did_file = FALSE;
X
X	for (i = 1; i < argc; i++)
X	{
X		if (*argv[i] == '-')
X		{
X			if (argv[i][1] == 's')
X			{
X				screen_device = TRUE;
X				italics = FALSE;
X			}
X			else if (argv[i][1] == 'i')
X				italics = FALSE;
X			else if (argv[i][1] == 't')
X				tabstops = atoi(&argv[i][2]);
X			else if (argv[i][1] == 'a')
X				EP = ES_ansi;
X			else if (argv[i][1] == 'A')
X				EP = ES_ansi_clr;
X			else
X			{
X				usage(argv[0]);
X				exit(0);
X			}
X		}
X		else
X		{
X			if ((file = fopen(argv[i], "r")) == NULL)
X			{
X				perror(argv[i]);
X				exit(errno);
X			}
X			dofile(file);
X			fclose(file);
X			did_file = TRUE;
X		}
X	}
X	if (!did_file)
X		dofile(stdin);
X}
X
Xdofile(file)
XFILE *file;
X{
X	register short	i, j, olen;
X	register char	quoting = 0, comment = 0;
X	short			oloc;
X	char			line[256], oline[256];
X
X	while (fgets(line, 255, file) > 0)
X	{
X		quoting = 0;
X		olen = 0;
X		oloc = 0;
X		for (i = 0; line[i]; )
X		{
X			if (isspace(line[i]))
X			{
X				if (tabstops && (line[i] == '\t'))
X				{
X					i++;
X					oline[olen++] = ' ';
X					for ( ; (++oloc) % tabstops; )
X						oline[olen++] = ' ';
X				}
X				else
X				{
X					oline[olen++] = line[i++];
X					oloc++;
X				}
X				continue;
X			}
X			if (!comment && ((line[i] == 0x27) || (line[i] == 0x22)))
X			{
X				if (quoting == line[i])
X					quoting = 0;
X				else if (!quoting)
X					quoting = line[i];
X			}
X			else if (!quoting)
X			{
X				if (!comment && !strncmp(&line[i], "\057\052", 2))
X				{
X					comment = TRUE;
X					if (italics)
X						olen += add_ctrl(START_ITALICS);
X					oline[olen++] = line[i++];
X					oline[olen++] = line[i++];
X					oloc += 2;
X					continue;
X				}
X
X				else if (comment && !strncmp(&line[i], "\052\057", 2))
X				{
X					comment = 0;
X					oline[olen++] = line[i++];
X					oline[olen++] = line[i++];
X					oloc += 2;
X					if (italics)
X						olen += add_ctrl(END_ITALICS);
X					continue;
X				}
X			}
X			if (!quoting && !comment &&
X					(isalpha(line[i]) || (line[i] == '#')))
X			{
X				for (j = i+1; isalpha(line[j]) || isdigit(line[j]) ||
X						(line[j] == '_') || (line[j] == '$'); j++);
X				if (isreserved(&line[i], j - i))
X				{
X					if (!screen_device)
X					{
X						olen += add_ctrl(START_BOLD);
X						for ( ; i < j; )
X						{
X							oline[olen++] = line[i++];
X							oloc++;
X						}
X						olen += add_ctrl(END_BOLD);
X					}
X					else
X						for ( ; i < j; )
X						{
X							oline[olen++] = line[i];
X							oline[olen++] = '\b';
X							oline[olen++] = line[i++];
X							oloc++;
X						}
X					continue;
X				}
X			}
X			oline[olen++] = line[i++];
X			oloc++;
X			if (isalpha(line[i-1]) || (line[i-1] == '_'))
X			{
X				while(isalpha(line[i]) || isdigit(line[i]) ||
X						(line[i] == '_') || (line[i] == '$'))
X				{
X					oline[olen++] = line[i++];
X					oloc++;
X				}
X			}
X		}
X		oline[olen] = 0;
X		printf("%s", oline);
X	}
X	return(0);
X}
X
X/* see if this is a reserved token */
X
Xisreserved(c, l)
Xchar *c;
Xshort l;
X{
X	register short i;
X
X	for (i = 0; reslist[i] != NULL; i++)
X	{
X		if (!strncmp(reslist[i], c, l))
X			if (!reslist[i][l])
X				return(1);
X	}
X	return(0);
X}
X
X/* describe usage */
X
Xusage(arg)
Xchar *arg;
X{
X	fprintf(stderr, "Usage: %s [-s] [-i] [-tnn] [filelist]\n", arg);
X        fprintf(stderr, "       -s -- send output to a screen device.\n");
X        fprintf(stderr, "       -i -- do not italicize comments.  Implied by -s.\n");
X        fprintf(stderr, "       -t -- set tab stops. -t0 turns off detabbing.\n");
X        fprintf(stderr, "             Default is -t4.\n");
X        fprintf(stderr, "       -a -- use ANSI escapes\n");
X        fprintf(stderr, "       -A -- use ANSI color escapes\n");
X}
X
X/* add control sequences for attributes */
X
Xadd_control(line, string)
Xchar *line, *string;
X{
X	int len = 0;
X	while (*string) {
X		*(line++) = *(string++);
X		len++;
X	}
X	return len;
X}
SHAR_EOF
chmod 0644 cgrind.c || echo "restore of cgrind.c fails"
echo "x - extracting cgrind.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > cgrind.h &&
Xchar *reslist[] =
X{
X/*
X * Compiler reserved words
X */
X	"asm",
X	"auto",
X	"break",
X	"case",
X	"char",
X	"continue",
X	"default",
X	"do",
X	"double",
X	"else",
X	"enum",
X	"extern",
X	"float",
X	"for",
X	"fortran",
X	"goto",
X	"if",
X	"int",
X	"long",
X	"register",
X	"return",
X	"short",
X	"sizeof",
X	"static",
X	"struct",
X	"switch",
X	"typedef",
X	"union",
X	"unsigned",
X	"void",
X	"while",
X
X/*
X * precompiler statements
X */
X	"#define",
X	"#undef",
X	"#include",
X	"#if",
X	"define",
X	"#ifdef",
X	"#ifndef",
X	"#else",
X	"#endif",
X	"#line",
X
X	NULL
X};
SHAR_EOF
chmod 0644 cgrind.h || echo "restore of cgrind.h fails"
exit 0

	bill davidsen		(davidsen@crdos1.crd.GE.COM)
  {uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me