[net.sources] headings: print headings outline of troff input file

perlman@wanginst.UUCP (Gary Perlman) (10/16/85)

By popular demand, here is my headings outline generator.
Please send me notes about problems or suggestions for improvements.
The punctutation graph printer will follow in a few days when I
get a chance to clean it up for the net.

#! /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 the files:
#	headings.1
#	makefile
#	headings.c
#	filter.c
#	getopt.c
#	headings.test
# This archive created: Tue Oct 15 18:58:02 1985
# By:	Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'headings.1'" '(2118 characters)'
if test -f 'headings.1'
then
	echo shar: "will not over-write existing file 'headings.1'"
else
sed 's/^	X//' << \SHAR_EOF > 'headings.1'
	X.TH HEADINGS 1 "October 1985" "Wang Institute" "UNIX User's Manual"
	X.SH NAME
	Xheadings \- show headings from nroff source file
	X.SH SYNOPSIS
	X.B headings
	X.nf
	XUsage: headings [-cflns] [-h header] [-p para] [-P mark]
	X	[-m min] [-M max] [-] [file]
	X.fi
	X.SH DESCRIPTION
	X.P
	X.I Headings
	Xis used to create tables of contents and outlines of papers
	Xbased on the \fI nroff\fR headings macros in the text.
	XSubheadings are indented below their superheadings
	Xto show the structure of the paper.
	X.SH OPTIONS
	X.de OP
	X.TP
	X.B -\\$1 \\$2
	X..
	X.OP n
	XNumber sections according to their order and depth.
	X.OP l
	XLine numbers from the input are printed along with the headings.
	X.OP c
	XCharacters read from the input are printed along with the headings.
	X.OP m N
	XThe minimum section level is taken to be \fIN\fR.
	XSections of level less than \fIN\fR will be shown,
	Xbut not indented nor numbered.
	X.OP M N
	XThe maximum section level is taken to be \fIN\fR.
	XSections of level greater than \fIN\fR will not appear in the output.
	X.OP h XX
	XThe "next" heading macro is taken to be XX,
	Xwhere XX is a one or two letter macro name.
	XIt is assumed that the level of each successive heading macro
	Xis one greater than the previous
	X(see the macros example below).
	XIf no macros are specified, the \fB-me\fR standard of ".sh" is assumed.
	XIf only one macro is supplied, a numerical argument indicating the
	Xsection level is assumed to follow the call to the macro.
	XThis is used as an index of how much to indent the headings.
	XThis option must be the last in a sequence started with a flag.
	XIf different section macros are used for different levels,
	Xa new flag argument must be added.
	X.SH EXAMPLES
	XThe -mcsl macros at the UCSD Cognitive Science Lab are based on
	Xthe APA standard headings: hh (high), mh (main), lh (left), and ph (paragraph).
	XThe call to \fIheadings\fR for these macros would look like:
	X.ce
	Xheadings -h hh  -h mh  -h lh  -h ph  file...
	X
	XTo get a standard memorandum macro (\fB-mm\fR) table of contents
	X(this includes numbering and headings for level 1 and 2 only), use:
	X.ce
	Xheadings -n -M 2 -h H file...
	X.SH SEE\ ALSO
	Xwwb(1), org(1)
	X.SH AUTHOR
	XGary Perlman
SHAR_EOF
if test 2118 -ne "`wc -c < 'headings.1'`"
then
	echo shar: "error transmitting 'headings.1'" '(should have been 2118 characters)'
fi
fi
echo shar: "extracting 'makefile'" '(946 characters)'
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'makefile'
	XMAIN=headings
	XHDRS=
	XSRCS=filter.c getopt.c
	XOBJS=filter.o getopt.o
	XDOCS=headings.1
	XLIBS=
	XDESTDIR=.
	XCFLAGS=-O
	XTEXT=$(HDRS) $(MAIN).c $(SRCS) headings.test
	X
	XLINT  =/usr/bin/lint -hp
	XPR    =cpr
	XSPELL =sp
	XSHAR  =shar -a
	XRCS   =ci -l
	XCC    =/bin/cc
	X
	X$(MAIN): $(MAIN).o $(OBJS)
	X	$(CC) $(CFLAGS) -o $(MAIN) $(MAIN).o $(OBJS)
	X
	Xinstall: $(MAIN)
	X	cp -i $(MAIN) $(DESTDIR)/$(MAIN)
	X
	Xprint:
	X	@$(PR) $(MAIN).c
	X
	Xlint:
	X	$(LINT) $(MAIN).c
	X
	Xspell:
	X	seec -cqe $(MAIN).c | $(SPELL)
	X
	Xtest:
	X	$(MAIN).test
	X
	Xarchive:
	X	@$(SHAR) $(DOCS) [Mm]akefile $(TEXT) 
	X
	Xclean:
	X	rm -f *.o core a.out mon.out gmon.out scmon.out
	X
	Xgprof:
	X	make CFLAGS="$(CFLAGS) -pg"
	Xscprof:
	X	make CFLAGS="$(CFLAGS) -p" CC=sc
	X
	Xxref: cscope.out
	X	ccall -dr > xref.r
	X	ccall -a > xref.a
	X	touch xref
	Xcscope.out: $(TEXT)
	X	cscope $(TEXT)
	X
	Xstyle: style.out
	Xstyle.out:
	X	cstyle $(TEXT) > style.out
	X
	Xrcs: RCS
	X
	XRCS: $(TEXT)
	X	$(RCS) $(TEXT)
	X
	X$(MAIN).1: $(MAIN).c
	X	@seec -t MANUAL $(MAIN).c
	X
	X.PRECIOUS: $(TEXT) $(DOCS)
SHAR_EOF
if test 946 -ne "`wc -c < 'makefile'`"
then
	echo shar: "error transmitting 'makefile'" '(should have been 946 characters)'
fi
fi
echo shar: "extracting 'headings.c'" '(5042 characters)'
if test -f 'headings.c'
then
	echo shar: "will not over-write existing file 'headings.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'headings.c'
	X/* headings.c prettyprints section headings from the user's nroff macros */
	X#include <stdio.h>
	X#include <ctype.h>
	X
	X#define	MACROS_LIB "/usr/lib"  /* do not follow .so (include) commands here */
	X#define MAXHEADERS 20          /* maximum number of section headings */
	X
	Xchar	*Header[MAXHEADERS];   /* section heading names */
	Xint 	Nheaders = 0;          /* number of section headings */
	Xint 	Mindent = 0;           /* lowest section number to indent */
	Xint 	Section[MAXHEADERS];   /* section numbers */
	Xint 	Countlines = 0;        /* should lines be counted and printed? */
	Xint 	Linecount = 0;         /* count of number of lines */
	Xint 	Countchars = 0;        /* should characters be counted and printed? */
	Xint 	Charcount = 0;         /* count of number of characters */
	Xint 	Numbersections = 0;    /* should sections be numbered? */
	Xint 	Maxheaders = (MAXHEADERS-1); /* only print sections to this depth */
	Xint 	Followso = 0;          /* should .so (include) macros be followed? */
	Xchar	*Paragraph;            /* paragraph macro */
	Xchar	*Parashow;             /* how should paragraphs be shown? */
	Xint 	Lastindent;            /* indentation (depth) of previous macro */
	Xchar	*Argv0;                /* name of the program */
	X
	Xinitial (argc, argv) char **argv;
	X	{
	X	extern	int 	optind;
	X	extern	char	*optarg;
	X	int 	C;
	X	int 	errflg = 0;
	X	char	*usage =
	X		"[-cflns] [-h header] [-p para] [-P mark]\n\t[-m min] [-M max] [-] [files]";
	X	Argv0 = argv[0];
	X	while ((C = getopt (argc, argv, "M:m:P:p:lcnsh:f")) != EOF)
	X		switch (C)
	X			{
	X			case 'f': Followso = 1; break;
	X			case 'h':
	X				Header[Nheaders] = optarg;
	X				Nheaders++;
	X				break;
	X			case 's':
	X			case 'n': Numbersections = 1; break;
	X			case 'c': Countchars = 1; break;
	X			case 'l': Countlines = 1; break;
	X			case 'p': Paragraph = optarg; break;
	X			case 'P': Parashow = optarg; break;
	X			case 'm': Mindent = atoi (optarg); break;
	X			case 'M': Maxheaders = atoi (optarg); break;
	X			case '?': errflg++; break;
	X			}
	X	if (errflg)
	X		{
	X		fprintf (stderr, "Usage: %s %s\n", Argv0, usage);
	X		exit (1);
	X		}
	X	if (Nheaders < 1) /* assume -me macros for no particular reason */
	X		{
	X		Header[0] = "sh";
	X		Nheaders = 1;
	X		if (Mindent == 0)
	X			Mindent = 1;
	X		}
	X	return (optind);
	X	}
	X
	Xmain (argc, argv) char **argv;
	X	{
	X	int  	head ();
	X	exit (filter (argc, argv, initial (argc, argv), head));
	X	}
	X
	Xint
	Xhead (filename, infile)
	Xchar	*filename;
	XFILE	*infile;
	X	{
	X	char	line[BUFSIZ];  /* input lines read here */
	X	char	*ptr;          /* work pointer in line */
	X	int 	i;
	X
	X	Linecount = 0;
	X	printf ("Headings for %s\n", filename);
	X
	X	while (fgets (line, BUFSIZ, infile))
	X		{
	X		Linecount++;
	X		Charcount += strlen (line);
	X		if (*line != '.') /* ignore any lines that are not breaking macros */
	X			continue;
	X		trimend (line);
	X		for (ptr = line+1; isspace (*ptr); ptr++); /* skip optional space */
	X		if (Followso && begins ("so", ptr)) /* nroff source file */
	X			{
	X			if (!begins (MACROS_LIB, ptr))
	X				head (ptr, infile);
	X			}
	X		else if (Paragraph && *Paragraph && begins (Paragraph, ptr))
	X			{
	X			output (Lastindent, Parashow ? Parashow : ptr, 0);
	X			}
	X		else for (i = 0; i < Nheaders; i++)
	X			if (begins (Header[i], ptr))
	X				{
	X				ptr += strlen (Header[i]);
	X				if ((Nheaders == 1) && (i = atoi (ptr))) /* numbered section */
	X					{
	X					while (isspace (*ptr)) ptr++;
	X					while (!isspace (*ptr)) ptr++;
	X					}
	X				while (*ptr == '"' || isspace (*ptr)) ptr++;
	X				if (*ptr == NULL) /* section heading is on next line */
	X					{
	X					if (fgets (line, BUFSIZ, infile))
	X						{
	X						Linecount++;
	X						Charcount += strlen (line);
	X						trimend (line);
	X						ptr = line;
	X						}
	X					}
	X				output (i, ptr, 1);
	X				break;
	X				}
	X		}
	X	}
	X
	X/* trim off spaces and "'s from end of line */
	Xtrimend (line)
	Xchar	*line;
	X	{
	X	char	*ptr = line;
	X	while (*ptr)
	X		ptr++;
	X	while (ptr > line && (ptr[-1] == '"' || isspace (ptr[-1])))
	X		ptr--;
	X	*ptr = '\0';
	X	}
	X
	X/* indent the line to the standard output */
	Xoutput (indent, line, header)
	Xint 	indent;    /* amount to indent the line */
	Xchar	*line;     /* heading or paragraph text to be printed */
	Xint 	header;    /* is the line a section heading? */
	X	{
	X	int 	loop;
	X	Lastindent = indent;
	X	if (!header)
	X		indent++; /* non-headers are less important */
	X	if (header && indent > Maxheaders)
	X		return;
	X	if (Countlines)
	X		printf ("%4d\t", Linecount);
	X	if (Countchars)
	X		printf ("%6d\t", Charcount);
	X	for (loop = 0; loop < indent-Mindent; loop++)
	X		putchar ('\t');
	X	if (header && Numbersections)
	X		{
	X		Section[indent]++;
	X		for (loop = indent+1; loop < Maxheaders; loop++)
	X			Section[loop] = 0;
	X		printsection ();
	X		putchar (' ');
	X		}
	X	puts (line);
	X	}
	X	
	X/* print the section number in #.#.# format */
	Xprintsection ()
	X	{
	X	int 	loop;
	X	int 	max;
	X	for (loop = Maxheaders; loop >= 0; loop--)
	X		if (Section[loop]) break;
	X	max = loop;
	X	for (loop = Mindent; loop <= max; loop++)
	X		{
	X		printf ("%d", Section[loop]);
	X		if (loop < max)
	X			putchar ('.');
	X		}
	X	}
	X
	Xbegins (string1, string2)
	Xregister	char *string1;
	Xregister	char *string2;
	X	{
	X	while (*string1)
	X		if (*string1++ != *string2++) return (0);
	X	return (1);
	X	}
SHAR_EOF
if test 5042 -ne "`wc -c < 'headings.c'`"
then
	echo shar: "error transmitting 'headings.c'" '(should have been 5042 characters)'
fi
fi
echo shar: "extracting 'filter.c'" '(4306 characters)'
if test -f 'filter.c'
then
	echo shar: "will not over-write existing file 'filter.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'filter.c'
	X/*
	X	Function:    filter "Filter Command Line Files In Classic UNIX Style"
	X	Created:     Sat Aug 10 21:57:12 EDT 1985
	X	By:          Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
	X	Compilation: nothing unusual
	X	Tester:      $Compile: cc -DSTANDALONE -o filter %f
	X	Preconditions:
	X		The index of the first file operand has been determined.
	X	Postconditions:
	X		All files have been opened, processed, and closed.
	X	Returns:
	X		The return status (non-zero is bad) depends on the accessibility
	X		of files, the ability to open them, and the return statuses of
	X		the called function.
	X	Exceptions:
	X		If any file cannot be accessed, then none will be processed.
	X		During processing, if something goes wrong (a file that could
	X		be accessed cannot be opened, or the file processor returns a
	X		non-zero status), processing continues.
	X	Notes:
	X		"-" is the conventional name for the standard input.
	X			It can only be read once.
	X		Fputs and putc are used to print error messages to avoid
	X			loading fat fprintf just because filter used it.
	X*/
	X
	X
	X#include <stdio.h>
	X
	X#ifdef STANDALONE
	X
	Xint
	Xcat (file, ioptr)
	Xchar	*file;
	Xregister	FILE	*ioptr;
	X	{
	X	register	int 	C;
	X	while ((C = getc (ioptr)) != EOF)
	X		putchar (C);
	X	return (0);
	X	}
	X
	Xmain (argc, argv) char **argv;
	X	{
	X	int 	cat ();
	X
	X	if (filter (argc, argv, 1, cat))
	X		{
	X		putc ('\007', stderr); /* UNIX friendly error message */
	X		exit (1);
	X		}
	X	exit (0);
	X	}
	X
	X#endif STANDALONE
	X
	X
	X/* LINTLIBRARY */
	Xstatic
	Xvoid
	Xerrmsg (pgm, file, errorno, dflt)
	Xchar	*pgm;       /* name of the program running */
	Xchar	*file;      /* file operand to be mentioned (if any) */
	Xint 	errorno;    /* system errno or some bad value */
	Xchar	*dflt;      /* default message for bad error numbers */
	X	{
	X	extern	char *sys_errlist[];  /* list of error messages */
	X	extern	int sys_nerr;         /* number of error messages */
	X
	X	fputs (pgm, stderr);
	X	putc (':', stderr);
	X	putc (' ', stderr);
	X	if (errorno > 0 && errorno < sys_nerr)
	X		fputs (sys_errlist[errorno], stderr);
	X	else
	X		fputs (dflt, stderr);
	X	if (file)
	X		{
	X		putc (' ', stderr);
	X		putc ('\'', stderr);
	X		fputs (file, stderr);
	X		putc ('\'', stderr);
	X		}
	X	putc ('\n', stderr);
	X	}
	X
	X
	X#define	isstdin(file) (file[0] == '-' && file[1] == '\0')
	X
	Xint
	Xfilter (argc, argv, curarg, process)
	Xint 	argc;          /* real number of command line args */
	Xchar	**argv;        /* command line argument pointer */
	Xint 	curarg;        /* first argv to filter */
	Xint 	(*process) (); /* status process (char *name, FILE *ioptr) */
	X	{
	X	int 	status = 0;         /* return status of this function */
	X	int 	arg;                /* loop index variable */
	X	char	*file;              /* name of the current file */
	X	char	*pgm = argv[0];     /* name of the program */
	X	FILE	*ioptr;             /* file pointer for opening */
	X	int 	countstdin = 0;     /* number of times stdin is processed */
	X	extern	int errno;          /* system error number */
	X
	X	if (curarg == argc)
	X		status += ((*process) ("-", stdin));
	X	else
	X		{
	X		/* first check to make sure all files can be opened to read */
	X		for (arg = curarg; arg < argc; arg++)
	X			{
	X			file = argv[arg];
	X			if (isstdin (file))
	X				countstdin++;
	X			else if (access (file, 4))
	X				{
	X				errmsg (pgm, file, errno, "Can't access file");
	X				status++;
	X				}
	X			}
	X		if (countstdin > 1)
	X			{
	X			errmsg (pgm, NULL, -1, "Can only read standard input once");
	X			status++;
	X			}
	X		if (status == 0)
	X			for (arg = curarg; arg < argc; arg++)
	X				{
	X				file = argv[arg];
	X				if (isstdin (file))
	X					status += ((*process) (file, stdin) != 0);
	X				else if (ioptr = fopen (file, "r"))
	X					{
	X					status += ((*process) (file, ioptr) != 0);
	X					(void) fclose (ioptr);
	X					}
	X				else
	X					{
	X					errmsg (pgm, file, errno, "Can't open file");
	X					status++;
	X					}
	X				}
	X		}
	X	return (status);
	X	}
	X
	X/*NOTES
	X	Some modifications might be useful but unpopular:
	X		If there is piped input (!isatty (fileno (stdin))),
	X		and the standard input is not read,
	X		then some information may be ignored,
	X		so a warning should be printed.
	X		Unfortunately, this would break things like vi filters.
	X
	X		If there is not piped input,
	X		and the standard input is being read from the keyboard,
	X		then prompt the user for input with something like:
	X			pgm: reading input from terminal
	X		This would avoid the problem of people forgetting to supply
	X		an input redirection.
	X*/
SHAR_EOF
if test 4306 -ne "`wc -c < 'filter.c'`"
then
	echo shar: "error transmitting 'filter.c'" '(should have been 4306 characters)'
fi
fi
echo shar: "extracting 'getopt.c'" '(3008 characters)'
if test -f 'getopt.c'
then
	echo shar: "will not over-write existing file 'getopt.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'getopt.c'
	X/*
	X	I got this off net.sources from Henry Spencer.
	X	It is a public domain getopt(3) like in System V.
	X	I have made the following modifications:
	X
	X	index(s,c) was added because too many people could
	X	not compile getopt without it.
	X
	X	A test main program was added, ifdeffed by STANDALONE.
	X	This main program is a public domain implementation
	X	of the getopt(1) program like in System V.  The getopt
	X	program can be used to standardize shell option handling.
	X		e.g.  cc -DSTANDALONE getopt.c -o getopt
	X*/
	X#include <stdio.h>
	X
	X#ifndef lint
	Xstatic	char	sccsfid[] = "@(#) getopt.c 5.0 (UTZoo) 1985";
	X#endif
	X
	X#define	ARGCH    (int)':'
	X#define BADCH	 (int)'?'
	X#define EMSG	 ""
	X#define	ENDARGS  "--"
	X
	X/* this is included because index is not on some UNIX systems */
	Xstatic
	Xchar *
	Xindex (s, c)
	Xregister	char	*s;
	Xregister	int 	c;
	X	{
	X	while (*s)
	X		if (c == *s) return (s);
	X		else s++;
	X	return (NULL);
	X	}
	X
	X/*
	X * get option letter from argument vector
	X */
	Xint	opterr = 1,		/* useless, never set or used */
	X	optind = 1,		/* index into parent argv vector */
	X	optopt;			/* character checked for validity */
	Xchar	*optarg;		/* argument associated with option */
	X
	X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
	X		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
	X
	X
	Xgetopt(nargc,nargv,ostr)
	Xint	nargc;
	Xchar	**nargv,
	X	*ostr;
	X{
	X	static char	*place = EMSG;	/* option letter processing */
	X	register char	*oli;		/* option letter list index */
	X	char	*index();
	X
	X	if(!*place) {			/* update scanning pointer */
	X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
	X		if (*place == '-') {	/* found "--" */
	X			++optind;
	X			return(EOF);
	X		}
	X	}				/* option letter okay? */
	X	if ((optopt = (int)*place++) == ARGCH || !(oli = index(ostr,optopt))) {
	X		if(!*place) ++optind;
	X		tell(": illegal option -- ");
	X	}
	X	if (*++oli != ARGCH) {		/* don't need argument */
	X		optarg = NULL;
	X		if (!*place) ++optind;
	X	}
	X	else {				/* need an argument */
	X		if (*place) optarg = place;	/* no white space */
	X		else if (nargc <= ++optind) {	/* no arg */
	X			place = EMSG;
	X			tell(": option requires an argument -- ");
	X		}
	X	 	else optarg = nargv[optind];	/* white space */
	X		place = EMSG;
	X		++optind;
	X	}
	X	return(optopt);			/* dump back option letter */
	X}
	X
	X
	X#ifdef STANDALONE
	X
	X#ifndef lint
	Xstatic	char	sccspid[] = "@(#) getopt.c 5.1 (WangInst) 6/15/85";
	X#endif
	X
	Xmain (argc, argv) char **argv;
	X	{
	X	char	*optstring = argv[1];
	X	char	*argv0 = argv[0];
	X	extern	int 	optind;
	X	extern	char	*optarg;
	X	int 	opterr = 0;
	X	int 	C;
	X	char	*opi;
	X	if (argc == 1)
	X		{
	X		fprintf (stderr, "Usage: %s optstring args\n", argv0);
	X		exit (1);
	X		}
	X	argv++;
	X	argc--;
	X	argv[0] = argv0;
	X	while ((C = getopt (argc, argv, optstring)) != EOF)
	X		{
	X		if (C == BADCH) opterr++;
	X		printf ("-%c ", C);
	X		opi = index (optstring, C);
	X		if (opi && opi[1] == ARGCH)
	X			if (optarg)
	X				printf ("\"%s\" ", optarg);
	X			else opterr++;
	X		}
	X	printf ("%s", ENDARGS);
	X	while (optind < argc)
	X		printf (" \"%s\"", argv[optind++]);
	X	putchar ('\n');
	X	exit (opterr);
	X	}
	X
	X#endif
SHAR_EOF
if test 3008 -ne "`wc -c < 'getopt.c'`"
then
	echo shar: "error transmitting 'getopt.c'" '(should have been 3008 characters)'
fi
fi
echo shar: "extracting 'headings.test'" '(1028 characters)'
if test -f 'headings.test'
then
	echo shar: "will not over-write existing file 'headings.test'"
else
sed 's/^	X//' << \SHAR_EOF > 'headings.test'
	X#! /bin/sh
	X
	Xecho "Test script for the headings program"
	X
	Xecho "		Testing -me macros"
	Xheadings -n << \EOF
	X.sh 1 "The Headings Program"
	X.sh 2 "Options"
	XThere are many options.
	X.sh 2 "Implementation"
	XSee the source code.
	X.sh 1 "The Punctuation Graph Program"
	X.sh 2      "Options"
	XThere are many options.
	X.sh 2		"Implementation
	XSee the source code.
	XEOF
	X
	Xecho ""
	Xecho "		Testing -mm macros"
	Xheadings -m 1 -h H -n << \EOF
	X.H 1 "Introduction
	X.H 1 "Method
	X.	H 2 "Materials
	X.	H 2 "Subjects
	X.	H 2 "Procedure
	X.H 1 "Results
	X.H 1 "Discussion
	X.H 1 "References
	XEOF
	X
	Xecho ""
	Xecho "		Testing -ms macros"
	Xheadings -h SH -h SS << \EOF
	X.SH NAME
	X.SH USAGE
	X.SH OPTIONS
	X.SH DESCRIPTION
	X.SS Input
	X.SS Output
	X.SH EXAMPLES
	X.SH VARIABLES
	X.SH FILES
	X.SH
	XDIAGNOSTICS
	X.SH "SEE ALSO"
	X.SH
	XAUTHOR(S)
	X.SH STATUS
	X.SH
	XWARNINGS
	XEOF
	X
	Xecho ""
	Xecho "		Testing paragraph options"
	Xheadings -n -p pp -P ========== << \EOF
	X.sh 1 "Introduction
	X.pp
	XThis is the introduction.
	X.sh 1 "Body"
	X.pp
	XThis is the body.
	X.pp
	XThis is more of the body.
	X.sh 1 "Conclusion
	X.pp
	XThe end.
	XEOF
SHAR_EOF
if test 1028 -ne "`wc -c < 'headings.test'`"
then
	echo shar: "error transmitting 'headings.test'" '(should have been 1028 characters)'
fi
chmod +x 'headings.test'
fi
exit 0
#	End of shell archive
-- 
Gary Perlman  Wang Institute  Tyngsboro, MA 01879  (617) 649-9731
UUCP: decvax!wanginst!perlman             CSNET: perlman@wanginst