[comp.sources.misc] v02i086: Determine Troff document type

gry@IDA.LiU.SE.UUCP (Goran Rydquist) (04/01/88)

Submitted-By: "Goran Rydquist" <gry@IDA.LiU.SE.UUCP>

Archive-Name: tdp


comp.sources.misc: Volume 2, Issue 86
Submitted-By: "Goran Rydquist" <gry@IDA.LiU.SE.UUCP>
Archive-Name: tdp

[Sent on April 1; it looks legitimate, but caveat programmer....  ++bsa]

The following C code determines the troff document type of its parameters, and
if requested to, executes it. The code is a fast hack (< 6 hours), but has
been found to work quite reliably here for a couple of months. 

---
Goran Rydqvist			gorry@majestix.liu.se
Troskareg. 69:22		seismo!enea!liuida!majestix!gorry
583 30  Linkoping		Linkoping Institute of Technology
Sweden				Int +46-13213696 / +46-13282494
---------

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README dtp.c dtp.man hash.c hash.h makefile tool.h
# Wrapped by gorry@smidefix on Thu Feb 18 14:36:45 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(97 characters\)
sed "s/^X//" >README <<'END_OF_README'
XSimple instruction on modification of the system can be found
Xat the beginning of the file dtp.c
END_OF_README
if test 97 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dtp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dtp.c\"
else
echo shar: Extracting \"dtp.c\" \(14184 characters\)
sed "s/^X//" >dtp.c <<'END_OF_dtp.c'
X/*
X  dtp.c
X
X  Dtp tries to decide the troff document type of the file specified by the
X  file argument. The program recognizes:
X
X  Changes:
X
X  To change the output of the program, change the strcat's in all_done().
X
X  To modify the set of commands that invokes a filter, alter the lists
X  in build_assoc().
X
X  To add a filter:
X  	Add a constant XX below.
X	Add a boolean global variable xx below and set it initially to FALSE.
X	Add a char *xx_opt below and update set_filter_opt() appropriately.
X	Add the recognizers in build_assoc() - addassoc("yy", XX);.
X	Add a case XX: xx = TRUE; break; to the switch in getcom().
X	Add a recognizer in all_done() of the form:
X	    if (xx) {
X	        ADD_PIPE(command, fnameflag);
X		strcat(command, " | xx");
X		add_opt_and_fname(command, xx_opt, &fnameflag);
X	    }
X	in the correct position.
X  	Recompile.
X
X  Written by:	
X
X  Goran Rydqvist <gorry@majestix.liu.se>
X  */
X
X
X#include <stdio.h>
X#include "tool.h"
X#include "hash.h"
X
X#define STREQ(s1, s2) (!strcmp(s1, s2))
X
X#define EOLN '\n'
X
X#define REFER 1
X#define PIC 2
X#define TBL 3
X#define EQN 4
X#define MS 5
X#define MAN 6
X#define AMBIG 7
X#define ME 8
X#define SWE 9
X#define PSTROFF 10
X#define PLAIN 11		/* Plain troff - no macros */
X
X
XFILE *fp;
X
XBOOL refer	= FALSE;
XBOOL pic	= FALSE;
XBOOL tbl	= FALSE;
XBOOL eqn	= FALSE;
XBOOL ms		= FALSE;
XBOOL me		= FALSE;
XBOOL man	= FALSE;
XBOOL ambig	= FALSE;
XBOOL a_ms	= FALSE;
XBOOL a_me	= FALSE;
XBOOL a_man	= FALSE;
XBOOL iptroff	= FALSE;
XBOOL ditroff	= TRUE;
XBOOL swe	= FALSE;
XBOOL pstroff    = FALSE;
XBOOL plain	= FALSE;
X
XBOOL execute	= FALSE;
X
Xchar *refer_opt	  = "";
Xchar *pic_opt	  = "";
Xchar *tbl_opt	  = "";
Xchar *eqn_opt	  = "";
Xchar *troff_opt = "";
Xchar *swe_opt	  = "";
X
Xchar *self;
Xchar *fnames = (char *) 0;
Xchar suffix[40];
X
XHASH *assoc;			/* Global hash table object */
X
X
X#define ADD_PIPE(command, flag) if (flag) strcat(command, " | ");
X
Xvoid add_opt_and_fname(command, opt, flag)
Xchar *command, *opt;
Xint *flag;
X{
X    if (opt[0]) {
X	strcat(command, " ");
X	strcat(command, opt);
X    }
X    if (!(*flag)) {
X	strcat(command, " ");
X	strcat(command, fnames);
X	*flag = 1;
X   }
X}
X
X
X/* AI - part of dtp (ha ha). */
Xvoid all_done()
X{
X    char command[100];
X    int fnamesflag;
X    
X    strcpy(command, "");
X    fnamesflag = FALSE;
X    
X    if (!strcmp(suffix, "ms")) {
X	if (man || me)
X	    fprintf(stderr, "%s: strange suffix .%s\n", self, suffix);
X	else
X	    ms = TRUE;
X    }
X    if (!strcmp(suffix, "me")) {
X	if (man || ms)
X	    fprintf(stderr, "%s: strange suffix .%s\n", self, suffix);
X	else
X	    me = TRUE;
X    }
X    if (!strcmp(suffix, "man")) {
X	if (ms || me)
X	    fprintf(stderr, "%s: strange suffix .%s\n", self, suffix);
X	else
X	    man = TRUE;
X    }
X
X    if (a_ms) {
X	ms = a_ms; me = FALSE; man = FALSE;
X    }
X    if (a_me) {
X	me = a_me; ms = FALSE; man = FALSE;
X    }
X    if (a_man) {
X	man = a_man; ms = FALSE; me = FALSE;
X    }
X
X    if (!(ms || me || man) && ambig)
X	fprintf(stderr, "%s: ambigous - use propper suffix .ms, .me, .man\n"
X		, self), exit(1);
X
X    if (swe) {
X	if (pstroff)
X	    strcat(command, "swede -Tps");
X	else
X	    strcat(command, "swede");
X	add_opt_and_fname(command, swe_opt, &fnamesflag);
X    }
X
X    if (refer) {
X	ADD_PIPE(command, fnamesflag);
X	strcat(command, "refer -e");
X	add_opt_and_fname(command, refer_opt, &fnamesflag);
X    }
X
X    if (pic) {
X	ADD_PIPE(command, fnamesflag);
X	strcat(command, "pic");
X	if (pstroff)
X	    strcat(command, " -Tps");
X	strcat(command, " -D");
X	add_opt_and_fname(command, pic_opt, &fnamesflag);
X    }
X
X    if (tbl) {
X	ADD_PIPE(command, fnamesflag);
X	strcat(command, "tbl");
X	add_opt_and_fname(command, tbl_opt, &fnamesflag);	
X    }
X
X    if (eqn) {
X	ADD_PIPE(command, fnamesflag);
X	if (pstroff)
X	    strcat(command, "eqn -Tps");
X	else
X	    strcat(command, "eqn");
X	add_opt_and_fname(command, eqn_opt, &fnamesflag);	
X    }
X    
X    if (pstroff) {
X	ADD_PIPE(command, fnamesflag);	
X	strcat(command, "pstroff");
X	iptroff = FALSE;
X	ditroff = FALSE;
X    } else if (iptroff) {
X	ADD_PIPE(command, fnamesflag);
X	strcat(command, "iptroff");
X	ditroff = FALSE;
X    }
X    else if (ditroff) {
X	ADD_PIPE(command, fnamesflag);
X	strcat(command, "ditroff");
X    }
X
X    if (ms)
X	strcat(command, " -ms");
X    else if (me)
X	strcat(command, " -me");
X    else if (man)
X	strcat(command, " -man");
X    add_opt_and_fname(command, troff_opt, &fnamesflag);
X
X    if (ditroff) {
X	strcat(command, " > ");
X	strcat(command, self);
X	strcat(command, ".out");
X    }
X    
X    printf("%s\n", command);
X    if (execute)
X	system(command);
X
X    exit(0);
X}
X
X
Xvoid addassoc(key, value)
Xchar *key;
Xint value;
X{
X    inserthentry(assoc, (int) key[0]*256 + (int) key[1], &value, sizeof(int));
X}
X
X
X/* The two-char combinations below are inserted in a hash table. If a line
Xbegins with a '.', the following two characters are checked against these. */
Xvoid build_assoc()
X{
X    /* For refer */
X    addassoc("[ ", REFER);
X    addassoc("] ", REFER);
X
X    /* For pic */
X    addassoc("PS", PIC);
X    addassoc("PE", PIC);
X
X    /* For tbl */
X    addassoc("TS", TBL);
X    addassoc("TE", TBL);
X    
X    /* For eqn */
X    addassoc("EQ", EQN);
X    addassoc("EN", EQN);
X
X    /* For ms */
X    addassoc("1C", MS);
X    addassoc("2C", MS);
X    addassoc("AB", MS);
X    addassoc("AE", MS);
X    addassoc("AI", MS);
X    addassoc("AM", MS);
X    addassoc("AT", MS);
X    addassoc("AU", MS);
X    addassoc("B1", MS);
X    addassoc("B2", MS);
X    addassoc("BX", MS);
X    addassoc("CM", MS);
X    addassoc("CT", MS);
X    addassoc("DA", MS);
X    addassoc("DE", MS);
X    addassoc("DS", MS);
X    addassoc("EF", MS);
X    /* EN, EQ - eqn */
X    addassoc("FE", MS);
X    addassoc("FS", MS);
X    addassoc("KE", MS);
X    addassoc("KF", MS);
X    addassoc("KS", MS);
X    addassoc("LG", MS);
X    addassoc("ND", MS);
X    addassoc("NH", MS);
X    addassoc("NL", MS);
X    addassoc("OF", MS);
X    addassoc("OH", MS);
X    addassoc("P1", MS);
X    addassoc("PT", MS);
X    addassoc("PX", MS);
X    addassoc("QP", MS);
X    addassoc("R ", MS);
X    addassoc("RP", MS);
X    addassoc("TA", MS);
X    /* TE - tbl */
X    addassoc("TL", MS);
X    addassoc("TM", MS);
X    /* TS - tbl */
X    addassoc("UL", MS);
X    addassoc("XA", MS);
X    addassoc("XE", MS);
X    addassoc("XS", MS);
X    addassoc("UL", MS);
X
X    /* For man */
X    /* B ambigous */
X    addassoc("BI", MAN);
X    addassoc("BR", MAN);
X    addassoc("DT", MAN);
X    addassoc("HP", MAN);
X    /* I ambigous */
X    addassoc("IB", MAN);
X    /* IP ambigous */
X    addassoc("IR", MAN);
X    /* LP ambigous */
X    addassoc("PD", MAN);
X    /* PP ambigous */
X    /* RE ambigous */
X    addassoc("RB", MAN);
X    addassoc("RI", MAN);
X    /* RS ambigous */
X    /* SH ambigous */
X    /* SM ambigous */
X    /* TH ambigous */
X    addassoc("TP", MAN);
X
X    /* For me */
X    addassoc("(c", ME);
X    addassoc("(d", ME);
X    addassoc("(f", ME);
X    addassoc("(l", ME);
X    addassoc("(q", ME);
X    addassoc("(x", ME);
X    addassoc("(z", ME);
X    addassoc(")c", ME);
X    addassoc(")d", ME);
X    addassoc(")f", ME);
X    addassoc(")l", ME);
X    addassoc(")q", ME);
X    addassoc(")x", ME);
X    addassoc(")z", ME);
X    addassoc("++", ME);
X    addassoc("+c", ME);
X    addassoc("1c", ME);
X    addassoc("2c", ME);
X    /* EN, EQ - eqn */
X    /* TE, TH, TS - tbl*/
X    addassoc("ac", ME);
X    addassoc("b ", ME);
X    addassoc("ba", ME);
X    addassoc("bc", ME);
X    addassoc("bi", ME);
X    addassoc("bx", ME);
X    addassoc("ef", ME);
X    addassoc("eh", ME);
X    addassoc("fo", ME);
X    addassoc("he", ME);
X    addassoc("hl", ME);
X    addassoc("hx", ME);
X    addassoc("i ", ME);
X    addassoc("ip", ME);
X    addassoc("lp", ME);
X    addassoc("lo", ME);
X    addassoc("np", ME);
X    addassoc("of", ME);
X    addassoc("oh", ME);
X    addassoc("pd", ME);
X    addassoc("pp", ME);
X    addassoc("r ", ME);
X    addassoc("re", ME);
X    addassoc("sc", ME);
X    addassoc("sh", ME);
X    addassoc("sk", ME);
X    addassoc("sz", ME);
X    addassoc("th", ME);
X    addassoc("tp", ME);
X    addassoc("u ", ME);
X    addassoc("uh", ME);
X    addassoc("xp", ME);
X
X    /* For swede */
X    addassoc("SW", SWE);
X    addassoc("SE", SWE);
X
X    /* Ambigous - recognized, but not used */
X    addassoc("B ", AMBIG);
X    addassoc("I ", AMBIG);
X    addassoc("IP", AMBIG);
X    addassoc("LP", AMBIG);
X    addassoc("IX", AMBIG);
X    addassoc("PP", AMBIG);
X    addassoc("RE", AMBIG);
X    addassoc("RS", AMBIG);
X    addassoc("SH", AMBIG);
X    addassoc("SM", AMBIG);
X    addassoc("TH", AMBIG);
X
X    /* For troff */
X    addassoc("ab", PLAIN);
X    addassoc("ad", PLAIN);
X    addassoc("af", PLAIN);
X    addassoc("am", PLAIN);
X    addassoc("as", PLAIN);
X    addassoc("bd", PLAIN);
X    addassoc("bd", PLAIN);
X    addassoc("bp", PLAIN);
X    addassoc("br", PLAIN);
X    addassoc("c2", PLAIN);
X    addassoc("cc", PLAIN);
X    addassoc("ce", PLAIN);
X    addassoc("ch", PLAIN);
X    addassoc("cs", PLAIN);
X    addassoc("cu", PLAIN);
X    addassoc("da", PLAIN);
X    addassoc("de", PLAIN);
X    addassoc("di", PLAIN);
X    addassoc("ds", PLAIN);
X    addassoc("dt", PLAIN);
X    addassoc("ec", PLAIN);
X    addassoc("el", PLAIN);
X    addassoc("em", PLAIN);
X    addassoc("eo", PLAIN);
X    addassoc("ev", PLAIN);
X    addassoc("ex", PLAIN);
X    addassoc("fc", PLAIN);
X    addassoc("fi", PLAIN);
X    addassoc("fl", PLAIN);
X    addassoc("fp", PLAIN);
X    addassoc("ft", PLAIN);
X    addassoc("fz", PLAIN);
X    addassoc("hc", PLAIN);
X    addassoc("hw", PLAIN);
X    addassoc("hy", PLAIN);
X    addassoc("ie", PLAIN);
X    addassoc("if", PLAIN);
X    addassoc("ig", PLAIN);
X    addassoc("in", PLAIN);
X    addassoc("it", PLAIN);
X    addassoc("lc", PLAIN);
X    addassoc("lg", PLAIN);
X    addassoc("ll", PLAIN);
X    addassoc("ls", PLAIN);
X    addassoc("lt", PLAIN);
X    addassoc("mc", PLAIN);
X    addassoc("mk", PLAIN);
X    addassoc("na", PLAIN);
X    addassoc("ne", PLAIN);
X    addassoc("nf", PLAIN);
X    addassoc("nh", PLAIN);
X    addassoc("nm", PLAIN);
X    addassoc("nn", PLAIN);
X    addassoc("nr", PLAIN);
X    addassoc("ns", PLAIN);
X    addassoc("nx", PLAIN);
X    addassoc("os", PLAIN);
X    addassoc("pc", PLAIN);
X    addassoc("pi", PLAIN);
X    addassoc("pm", PLAIN);
X    addassoc("ps", PLAIN);
X    addassoc("pl", PLAIN);
X    addassoc("pn", PLAIN);
X    addassoc("po", PLAIN);
X    addassoc("rd", PLAIN);
X    addassoc("rn", PLAIN);
X    addassoc("rm", PLAIN);
X    addassoc("rr", PLAIN);
X    addassoc("rs", PLAIN);
X    addassoc("rt", PLAIN);
X    addassoc("so", PLAIN);
X    addassoc("sp", PLAIN);
X    addassoc("ss", PLAIN);
X    addassoc("sv", PLAIN);
X    addassoc("ta", PLAIN);
X    addassoc("tc", PLAIN);
X    addassoc("ti", PLAIN);
X    addassoc("tl", PLAIN);
X    addassoc("tm", PLAIN);
X    addassoc("tr", PLAIN);
X    addassoc("uf", PLAIN);
X    addassoc("ul", PLAIN);
X    addassoc("vs", PLAIN);
X    addassoc("wh", PLAIN);
X}
X
X
Xint getcom()
X{
X    register int i;
X    register int *res;
X    register char c1, c2;
X
X    if ((c1 = getc(fp)) != '.')
X	return c1;
X
X    if ((c1 = getc(fp)) == EOF)
X	return EOF;
X    if (c1 == EOLN)
X	return c1;
X
X    if ((c2 = getc(fp)) == EOF)
X	return EOF;
X    if (c2 == EOLN)
X	c2 = ' ';
X
X    i = (int) c1*256 + (int) c2;
X    if (!(res = (int *) lookuphentry(assoc, i)))
X	return;			/* Unknown */
X    
X    switch (*res) {
X      case REFER:
X	refer = TRUE;
X	break;
X      case PIC:
X	pic = TRUE;
X	break;
X      case TBL:
X	tbl = TRUE;
X	break;
X      case EQN:
X	eqn = TRUE;
X	break;
X      case MS:
X	ms = TRUE;
X	break;
X      case ME:
X	me = TRUE;
X	break;
X      case MAN:
X	man = TRUE;
X	break;
X      case AMBIG:
X	ambig = TRUE;
X	break;
X      case SWE:
X	swe = TRUE;
X	break;
X      case PLAIN:
X	plain = TRUE;
X	break;
X      default:
X	printf("getcom: can't happen\n");
X	abort();
X    }
X    return 1;
X}
X
X
X#define FILL(s, argvp) \
X{ \
X    if (STREQ(s, "")) { \
X	s = (char *) malloc(240); \
X	strcpy(s, *++(*argvp)); \
X    } \
X    else { \
X	strcat(s, " "); \
X        strcat(s, *++(*argvp)); \
X    } \
X} \
X
Xvoid set_filter_opt(argcp, argvp)
Xint *argcp;
Xchar ***argvp;
X{
X    (*argvp)++;			/* Step to the filter parameter */
X    (*argcp)--;
X
X    if (STREQ(**argvp, "refer"))
X	FILL(refer_opt, argvp)
X    else if (STREQ(**argvp, "pic"))
X	FILL(pic_opt, argvp)
X    else if (STREQ(**argvp, "tbl"))
X	FILL(tbl_opt, argvp)
X    else if (STREQ(**argvp, "eqn"))
X	FILL(eqn_opt, argvp)
X    else if (STREQ(**argvp, "troff"))
X	FILL(troff_opt, argvp)
X    else if (STREQ(**argvp, "swede"))
X	FILL(swe_opt, argvp)
X    else
X	usage();
X    (*argcp)--;
X}
X
X
Xusage()
X{
X    fprintf(stderr, "Usage: %s [ -aipx -ms -me -man] files\n", self);
X    exit(1);
X}
X
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    int i;
X
X    fnames = (char *) malloc(800);
X    strcpy(fnames, "");
X    
X    assoc = newhash(273);
X    build_assoc();
X
X    self = argv[0];
X
X    argv++;
X    argc--;
X
X    for(; argc-- > 0; argv++)
X	if( argv[0][0] == '-' ) {
X	    if (STREQ(argv[0], "-ms")) {
X		a_ms = TRUE; a_me = FALSE; a_man = FALSE;
X	    } else if (STREQ(argv[0], "-me")) {
X		a_me = TRUE; a_ms = FALSE; a_man = FALSE; 
X	    } else if (STREQ(argv[0], "-man")) {
X		a_man = TRUE; a_ms = FALSE; a_me = FALSE;
X	    } else if (STREQ(argv[0], "-a")) {
X		set_filter_opt(&argc, &argv);
X	    } else for(i = strlen(argv[0]) - 1; i > 0; i--)
X		switch( argv[0][i] ) {
X		  case 'i':
X		    iptroff = TRUE;
X		    pstroff = FALSE;
X		    ditroff = FALSE;
X		    break;
X		  case 'p':
X		    pstroff = TRUE;
X		    iptroff = FALSE;
X		    ditroff = FALSE;
X		    break;
X		  case 'x':
X		    execute = TRUE;
X		    break;
X		  default:
X		    usage();
X		}
X	}
X	else {
X	    if (!STREQ(fnames, ""))
X		strcat(fnames, " ");
X	    strcat(fnames, argv[0]);
X	    troff_scan(argv[0]);
X	}
X
X    all_done();
X}
X
X
Xtroff_scan(fname)
Xchar *fname;
X{
X    register char c;
X
X    if (fname == (char *) 0)
X	usage();
X	
X    if ((fp = fopen(fname, "r")) == (FILE *) 0) {
X	fprintf(stderr, "%s: %s not found\n", self, fname);
X	exit(1);
X    }
X    
X    sscanf(fname, "%[^.] %1s %s", suffix, suffix, suffix);
X
X    for(;;) {
X	if (getcom() == EOF) break; /* Get a troff command */
X
X	/* Skip to next eoln */
X	for(c = getc(fp); (c != EOLN) && (c != EOF); c = getc(fp));
X	if (c == EOF) break;
X
X	/* Skip eolns */
X	for(c = getc(fp); (c == EOLN) && (c != EOF); c = getc(fp));
X	if (c == EOF) break;
X	ungetc(c, fp);
X    }
X    fclose(fp);
X
X    if ( !(refer || pic || tbl || eqn || ms || man || me || ambig || plain) ) {
X	fprintf(stderr, "%s: %s not troff file\n", self, fname);
X	exit(1);
X    }
X}
END_OF_dtp.c
if test 14184 -ne `wc -c <dtp.c`; then
    echo shar: \"dtp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dtp.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dtp.man\"
else
echo shar: Extracting \"dtp.man\" \(3073 characters\)
sed "s/^X//" >dtp.man <<'END_OF_dtp.man'
X.TH DTP 1 "27 April 1987"
X.SH NAME
Xdtp \- decide troff document type
X.SH SYNOPSIS
X.B dtp
X[
X.B \-ipxq \-ms \-me \-man
X] [
X.B \-a
X.I "filter argument"
X] \fIfiles
X.SH DESCRIPTION
XDtp tries to decide the troff document type of \fIfiles\fP. A resulting
Xcommand is printed to standard output, including only the filters needed,
Xand possibly a macro package. This is decided from recognized unambigous 
Xcommands/macros in \fIfiles\fP. If nothing in \fIfiles\fP indicates
Xthe macro package, the file suffix is checked \- .ms, .me, .man are recognized.
X.LP
XThe default troff processor is ditroff. When ditroff is used, the
Xoutput is redirected to the file dtp.out. The \-i option changes the troff
Xprocessor to iptroff, and the \-p option changes it to pstroff.
X.SH OPTIONS
X.TP 1i
X.B \-i
XUse iptroff as troff processor instead of ditroff.
X.TP
X.B \-p
XUse pstroff as troff processor.
X.TP
X.B \-x
XExecute the resulting command.
X.TP
X.B \-ms
XForce \-ms as macro package.
X.TP
X.B \-me
XForce \-me.
X.TP
X.B \-man
XForce \-man.
X.TP
X.B \-a \fIfilter argument\fP
XAdd \fIargument\fP to \fIfilter\fP. The refer, swede, pic, tbl, eqn and
Xtroff filters are recognized.
X.SH WHAT IS RECOGNIZED
X.TP 1i
X.B refer \-e 
XThe \-e mode is recognized from .[ and .]
X.TP
X.B swede 
XSwede is a special filter that replaces the special characters {, }, |, [, ], \
X\\ with the Swedish equivalents between .SW and .SE. \-Tps is added 
Xautomatically if pstroff is used as troff processor.
X.TP
X.B pic \-D
XThe undocumented feature of pic \-D is always issued. Pic is recognized
Xfrom .PS and .PE
X.TP
X.B tbl
XTbl is recognized from .TS and .TE
X.TP
X.B eqn
XEqn is recognized from .EQ and .EN
X.TP
X.B \-ms
X .1C .2C .AB .AE .AI .AM .AT .AU .B1 \
X .B2 .BX .CM .CT .DA .DE .DS .EF .FE .FS .KE .KF .KS .LG .ND .NH .NL \
X .OF .OH .P1 .PT .PX .QP .R  .RP .TA .TL .TM .UL .XA .XS .UL
X.TP
X.B \-man
X .BI .BR .DT .HP .IB .IR .PD .RB .RI .TP
X.TP
X.B \-me
X .(c .(d .(f .(l .(q .(x .(z .)c .)d .)f .)l .)q .)x \
X .)z .++ .1c .2c .ac .b  .ba .bc .bi .bx .ef .eh .fo \
X .he .hl .hx .i  .ip .lp .lo .np .of .oh .pd .pp .r \
X .re .sc .sh .sk .sz .th .tp .u  .uh .xp 
X.TP
X.B Ambiguous
X .B .I .IP .LP .IX .PP .RE .RS .SH .SM .TH. \
XThese are not unique to any specific macro package or filter, and causes no
Xselection.
X.TP
X.B Plain Troff
X .ab .ad .af .am .as .bd .bp .br .c2 .cc .ce .ch .cs .cu .da .de .di .ds .dt \
X .ec .el .em .eo .ev .ex .fc .fi .fl .fp .ft .fz .hc .hw .hy .ie .if .ig .in \
X .it .lc .lg .ll .ls .lt .mc .mk .na .ne .nf .nh .nm .nn .nr .ns .nx .os .pc \
X .pi .pm .ps .pl .pn .po .rd .rn .rm .rr .rs .rt .so .sp .ss .sv .ta .tc .ti \
X .tl .tm .tr .uf .ul .vs .wh
X.LP
XIf no filter selection, macro requests or plain troff commands are found, dtp
Xassumes that the formatting request was a mistake, and exits.
X.SH AUTHOR
XG\o"o\(um"ran Rydqvist <gorry@majestix.liu.se>
X.br
XDepartement of Computer and Information Science, Link\o"o\(um"ping, Sweden.
X.SH SEE ALSO
X.I "Formatting Documents on the Sun Workstation"
X.br
Xtroff(1), tbl(1), eqn(1), pic(1), ms(7)
X.SH BUGS
XThe program was written in about six hours \- don't expect to much.
END_OF_dtp.man
if test 3073 -ne `wc -c <dtp.man`; then
    echo shar: \"dtp.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hash.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hash.c\"
else
echo shar: Extracting \"hash.c\" \(3693 characters\)
sed "s/^X//" >hash.c <<'END_OF_hash.c'
X/*
X  hash.c
X
X  Handles bucket hash objects of warying size. Each keyed item consists of
X  an invariant and an arbitrary part.
X
X  Interface:
X
X  A HASH object is declared by: HASH *object;
X
X  HASH *newhash(size)
X  int size;
X  Retrurn a pointer to a new HASH object of size.
X
X  void rmhash(object)
X  HASH *object;
X  Free memory occupied by a HASH object.
X
X  char *lookuphentry(object, key)
X  HASH *object;
X  KEY key;
X  Return a pointer to the data part of a hash entry. Return NIL if no such key.
X
X  BOOL inserthentry(object, key, data, datasize)
X  HASH *object;
X  KEY key;
X  char *data;
X  int datasize;
X  Insert key and data into hash table object. No insertion is performed if key
X  already exists. Returns true if insertion done.
X
X  BOOL rmhentry(object, key)
X  HASH *object;
X  KEY key;
X  Remove a hash entry matching key. Returns true if entry removed.
X
X  HENTRY firsthentry(object)
X  HASH *object;
X  Return the data part of the first key in the hash table object.
X
X  HENTRY nexthentry(object)
X  HASH *object;
X  Return the data part of the ensuing key in the hash table object.
X
X  OBS! A firsthentry() call must precede nexthentry() calls between
X  hashtable manipulation (rmhentry() och inserthentry()).
X
X  */
X
X#include <stdio.h>
X#include <malloc.h>
X#include "tool.h"
X#include "hash.h"
X
X
XHASH *newhash(size)
Xint size;
X{
X    HASH *ht;
X
X    CHKMEM(ht = (HASH *) malloc(sizeof(HASH)), "newhash");
X    ht -> no_buckets = size;
X    ht -> no_inhab = 0;
X    ht -> cur_bucket = 0;
X    ht -> cur_cell = 0;
X    CHKMEM(ht -> thetbl = (HENTRY *) calloc(size, sizeof(HENTRY)), "newhash");
X
X    return ht;
X}
X
X
Xvoid rmhash(object)
XHASH *object;
X{
X    register HENTRY *p, hp, prev;
X
X    for(p = object -> thetbl; object -> no_inhab > 0; p++)
X	for(hp = *p; hp; hp = prev -> next) {
X	    prev = hp;
X	    free(hp);
X	    object -> no_inhab--;
X	}
X
X    free(object -> thetbl);
X    free(object);
X}
X
X
Xchar *lookuphentry(object, key)
XHASH *object;
XKEY key;
X{
X    register HENTRY *p, hp;
X
X    p = object -> thetbl + h(object, key); /* Hash the key */
X    for(hp = *p; hp; hp = hp -> next) /* Follow bucket */
X	if (hp -> key == key)
X	    return (hp -> data);
X    return (char *) 0;
X}
X
X
Xvoid mvbytes(p1, p2, n)
Xregister char *p1, *p2;
Xregister int n;
X{
X    for(; n-- > 0; *p1++ = *p2++);
X}
X
X
XBOOL inserthentry(object, key, data, datasize)
XHASH *object;
XKEY key;
Xchar *data;
Xint datasize;
X{
X    register HENTRY *p, hp;
X
X    p = object -> thetbl + h(object, key);
X    for(hp = *p; hp; hp = hp -> next)
X	if (hp -> key == key)
X	    return FALSE;
X    CHKMEM(hp = (HENTRY) malloc(sizeof(struct h_cell) + datasize),
X	   "inserthentry");
X
X    hp -> key = key;
X    hp -> next = *p;
X    mvbytes(hp -> data, data, datasize);
X    *p = hp;
X
X    return TRUE;
X}
X
X
XBOOL rmhentry(object, key)
XHASH *object;
XKEY key;
X{
X    register HENTRY *p, hp, prev;
X
X    p = object -> thetbl + h(object, key);
X    for(hp = *p; hp; prev = hp, hp = hp -> next)
X	if (hp -> key == key) {
X	    if (hp == *p)	/* First bucket is a special case */
X		*p = hp -> next;
X	    else
X		prev -> next = hp -> next;
X	    object -> no_inhab--;
X	    free(hp);
X	    return TRUE;
X	}
X    
X    return FALSE;
X}
X
X
X
XHENTRY firsthentry(object)
XHASH *object;
X{
X    object -> cur_bucket = 0;
X    object -> cur_cell = 0;
X    return nexthentry(object);
X}
X
X
XHENTRY nexthentry(object)
Xregister HASH *object;
X{
X    register HENTRY *p, hp;
X    register int i;
X    
X    for(;;) {
X	p = object -> thetbl + object -> cur_bucket;
X	i = object -> cur_cell;
X	for(hp = *p; hp; hp = hp -> next, i--)
X	    if( i < 1 ) {
X		object -> cur_cell++;
X		return hp;
X	    }
X	
X	if (!hp) {
X	    object -> cur_cell = 0;
X	    if (++object -> cur_bucket >= object -> no_buckets)
X		return (HENTRY) 0;
X	}
X    }
X}
X
END_OF_hash.c
if test 3693 -ne `wc -c <hash.c`; then
    echo shar: \"hash.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hash.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hash.h\"
else
echo shar: Extracting \"hash.h\" \(866 characters\)
sed "s/^X//" >hash.h <<'END_OF_hash.h'
X/*
X  hash.h
X
X  Include file for hash.c
X
X  Synopsis:
X
X  #include <stdio.h>
X  #include "tool.h"
X  #include "hash.h"
X  */
X
Xtypedef struct {
X    int no_buckets;		/* Number of buckets */
X    int no_inhab;		/* Number of inhabitants */
X    int cur_bucket;		/* Used by first&nexthentry() */
X    int cur_cell;		/* As for cur_bucket */
X    struct h_cell **thetbl;	/* The table itself */
X} HASH;				/* A HASH object */
X
Xtypedef int KEY;
X
Xtypedef struct h_cell {
X    KEY key;			/* Hash key */
X    struct h_cell *next;	/* Next bucket pointer */
X    char data[1];		/* Data starts here - variable size struct */
X} *HENTRY;			/* A Hash entry (invariant) */
X
X/* Hash function */
X#define h(object, key) (key % object -> no_buckets)
X
X/* Functions */
XHASH *newhash();
Xvoid rmhash();
Xchar *lookuphentry();
XBOOL inserthentry();
XBOOL rmhentry();
XHENTRY firsthentry();
XHENTRY nexthentry();
END_OF_hash.h
if test 866 -ne `wc -c <hash.h`; then
    echo shar: \"hash.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile\"
else
echo shar: Extracting \"makefile\" \(422 characters\)
sed "s/^X//" >makefile <<'END_OF_makefile'
X
XCFLAGS = -O -pipe
X
Xdtp: hash.o dtp.o
X	cc -o dtp hash.o dtp.o
X
Xhash.o: hash.c hash.h tool.h
Xdtp.o: dtp.c hash.h tool.h
X
Xinstall:
X	strip dtp
X	cp dtp /usr/local/bin/.
X	cp dtp.man /usr/man/manl/dtp.l
X	cp dtp.c /usr/local/src/dtp/.
X	cp hash.c /usr/local/src/dtp/.
X	cp hash.h /usr/local/src/dtp/.
X	cp tool.h /usr/local/src/dtp/.
X	cp makefile /usr/local/src/dtp/.
X
Xclean:
X	rm dtp *.o #*
X	mv *~ /usr/majestix/exjobb/gorry/back
X	
END_OF_makefile
if test 422 -ne `wc -c <makefile`; then
    echo shar: \"makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tool.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tool.h\"
else
echo shar: Extracting \"tool.h\" \(503 characters\)
sed "s/^X//" >tool.h <<'END_OF_tool.h'
X/*
X  tool.h
X
X  Describes system wide conventions, like pointers and general datatypes etc.
X
X  OBS! stdio.h must be included before tool.h if system_failure isn't defined.
X  */
X
X#ifndef system_failure
X#define system_failure(p) fprintf(stderr, "%s\n", p), abort();
X#endif
X
X#define CHKMEM(p, x) if ( !(p) ) { \
X			  char s[40]; \
X			  strcpy(s, x); \
X			  strcat(s, ": out of memory"); \
X			  system_failure(s); \
X		     }
X
X/* Boolean datatype */
X
Xtypedef short BOOL;
X#define FALSE 0
X#define TRUE (!FALSE)
END_OF_tool.h
if test 503 -ne `wc -c <tool.h`; then
    echo shar: \"tool.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0