[comp.sources.misc] v03i011: Creating index listings with [nt]roff

davidsen@crdos1.UUCP (Wm E. Davidsen) (05/03/88)

comp.sources.misc: Volume 3, Issue 11
Submitted-By: "Wm E. Davidsen" <davidsen@crdos1.UUCP>
Archive-Name: indexmac

  There was a request for a way to generate an index using ?roff. Here
is the code. At the beginning of the roff input place an
        .so index.mac
to include the index macro. At each place in the text where you want
an index entry, place a line of the form
        .IX "subject"

  When running ?roff, save the error output in a file:
	# create the file with the index data
        nroff -mm -Tljc.12 myfile.n >/dev/null 2>myfile.idx
	# sort the data and create the complete document
	sort myfile.idx | indexfmt | cat myfile.n - |
		nroff -man -Tljc.12 > myfile.prn

  You will have to use tbl, eqn, etc as needed.  If you can use a
standard format for the index, you can run it off as a separate
document. I actually do something else with named pipes, bit it's not
portable.

  You will probably want to hack this a little, but it does work as is.

BUGS: if you mess up your input or command options the error messages
are sent to the index file. The index should be created from a known good
input.

#!/bin/sh
# shar:	Shell Archiver  (v1.20)
#
#	Run the following text with /bin/sh to create:
#	  index.mac
#	  indexfmt.c
#
echo "x - extracting index.mac (Text)"
sed 's/^X//' << 'SHAR_EOF' > index.mac &&
X.de IX
X.tm \\$1;\\nP
X..
SHAR_EOF
chmod 0644 index.mac || echo "restore of index.mac fails"
echo "x - extracting indexfmt.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > indexfmt.c &&
X/*
X *  ixformat - format an index file for output
X *
X *  Bill Davidsen, June 1986
X *
X *  This program is a filter which accepts the list of subjects
X *  for an index, and the page on which they occur. It then emits
X *  output in xroff format with all refs to a single subject on
X *  one line.
X */
X
X#include <stdio.h>
X#define MAXLINE 80		/* longest subject */
X#define MAXREFS 10		/* refs to any one subject */
X
Xchar  current[MAXLINE];		/* current subject */
Xint  refs[MAXREFS];		/* current refs */
Xint  nref = 0;			/* # of refs to current subj */
X
Xmain ()
X{
X    char  line[MAXLINE];	/* next subject */
X    int  page;			/* page of current ref */
X
X    while (scanf ("%[^;];%d", line, &page) == 2)
X    { /* see if this is a new subject */
X	while (getchar () != '\n'); /* skip to EOL */
X
X	if (nref == 0)
X	{ /* this is the first one in */
X	    strcpy (current, line);
X	    refs[nref++] = page;
X	/* get the proper footer on it */
X	    printf (".PH \"\"\n.PF \"//- index %% -//\"\n.nf\n");
X	    continue;
X	}
X
X	if (strcmp (line, current))
X	{ /* starting a new subject, output this one */
X	    flushref (0);
X
X	/* copy the new subject and page in */
X	    strcpy (current, line);
X	    refs[0] = page;
X	    nref = 1;
X	}
X	else
X	{ /* add a reference to this subject */
X	    if (nref == MAXREFS)
X		flushref (1);
X	    refs[nref++] = page;
X	}
X    }
X
X /* if there are references left, flush them */
X    if (nref)
X	flushref (0);
X    exit (0);
X}
X
XX/*
X *  flushref - output a subject and all current references to it.
X */
X
Xflushref (flag)
X    int  flag;
X{
X    int  ix;			/* loop index */
X
X    printf ("%s  ", current);
X    for (ix = 0; ix < nref;)
X    { /* output a reference, and comma if more */
X	printf ("%d", refs[ix++]);
X	if (ix < nref)
X	    putchar (',');
X    }
X    if (flag)
X	putchar (',');
X    putchar ('\n');
X}
SHAR_EOF
chmod 0644 indexfmt.c || echo "restore of indexfmt.c fails"
exit 0

bill davidsen		(wedu@ge-crd.ARPA -or- davidsen@crdos1.uucp)
			{uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me