[net.sources] Tpr

ken@rochester.UUCP (Ken Yap) (01/01/85)

#--------CUT---------CUT---------CUT---------CUT--------#
#########################################################
#                                                       #
# This is a shell archive file.  To extract files:      #
#                                                       #
#    1) Make a directory for the files.                 #
#    2) Write a file, such as "file.shar", containing   #
#       this archive file into the directory.           #
#    3) Type "sh file.shar".  Do not use csh.           #
#                                                       #
#########################################################
#
#
echo Extracting Read_This:
sed 's/^Z//' >Read_This <<\STUNKYFLUFF
ZThese are the sources and manual page for tpr, a text formatter based
Zon roff and translated into C from the version in "Software Tools"
Z(Kernighan and Plaugher, Addison-Wesley). I have not provided a
Zmakefile as there are only a few files.
Z
Z	cc -O -o tpr tpr0.c tpr1.c itoeng.c
Z
Zshould work.
Z
ZUnfortunately, I have neither the time nor the inclination these days
Zto do any more work on this program so you are on your own. But I would
Zappreciate hearing from you if you do anything interesting with the
Zsources. Do the net a favour too and post any bug fixes or interesting
Zmodifications you make.
Z
ZEnjoy. Cheers.
Z
Z	Ken Yap
Z
ZUUCP: (..!{allegra, decvax, seismo}!rochester!ken) ARPA: ken@rochester.arpa
ZUSnail:	Dept. of Comp. Sci., U. of Rochester, NY 14627. Voice: Ken!
STUNKYFLUFF
set `sum Read_This`
if test 15411 != $1
then
echo Read_This: Checksum error. Is: $1, should be: 15411.
fi
#
#
echo Extracting tpr.h:
sed 's/^Z//' >tpr.h <<\STUNKYFLUFF
Z#include	<stdio.h>
Z#include	<ctype.h>
Z
Z#define	min(a,b)	(a<b?a:b)
Z#define	max(a,b)	(a>b?a:b)
Z#define	skipbl(p)	{while(*p == ' ' || *p == '\t')p++;}
Z#define	skipnbl(p)	{while(*p != ' ' && *p != '\t' && *p != '\n')p++;}
Z#define	CHARNULL	((char *)NULL)
Z#define	NO		0
Z#define	YES		1
Z#define	COMMAND		'.'
Z#define	PAGENUM		'%'
Z#define	HUGE		10000
Z#define	MAXIN		256
Z#define	MAXOUT		256
Z#define	MAXFN		64	/* length of included filename */
Z#define	MAXCHARS	14
Z#define	MAXMAC		50
Z#define	MAXPB		50
Z#define	MAXTABS		20
Z#define	PAGLEN		66
Z#define	PAPERSIZE	65
Z#define	M1DEF		3
Z#define	M2DEF		1
Z#define	M3DEF		1
Z#define	M4DEF		3
Z#define	PAGEWIDTH	60
Z#define	ARABIC		0
Z#define	ROMAN		1
Z#define	ENGLISH		2
Z
Zstruct linelink{
Z	char *lineptr;
Z	struct linelink *lastline;
Z	};
Zstruct	macro{
Z	char macnam[3];
Z	struct linelink *macend;
Z	} macros[MAXMAC];
Zstruct	envir{
Z	short plval;
Z	short m1val;
Z	short m2val;
Z	short m3val;
Z	short m4val;
Z	short bottom;
Z	char *evenhdr,*oddhdr;
Z	char *evenftr,*oddftr;
Z	char comchr;
Z	char tabchr;
Z	char ubchr;
Z	short fill;
Z	short adjust;
Z	short numtyp;
Z	short lsval;
Z	short llval;
Z	short inval;
Z	short tival;
Z	short poval;
Z	short ceval;
Z	short ulval;
Z	short bdval;
Z	short litval;
Z	short blval;
Z	short skpval;
Z	short tabpos[MAXTABS];
Z	struct envir *lastenv;
Z	};
Zstruct cmdents{
Z	char cmdname[3];
Z	short notredefd;
Z	};
Zenum cmdnum	{ADJ, ARA, BLD, BLN, BPG, BRE, CMC, CEN, DFN, EFO, ENG, EHD,
Z		FIL, FOT, HED, IND, INX, LIT, LNL, LNS, M1, M2, M3, M4, NAD,
Z		NED, NFL, OFO, OHD, PGL, POF, PGT, RNV, REF, ROM, RPG, SNV, SKP,
Z		SOU, SPA, TCL, TCH, TMI, UBC, UDL, MAC, UNKNOWN};
Zextern	struct macro macros[MAXMAC];
Zextern	short maccnt;
Zextern	char *pbptr[MAXMAC];
Zextern	short pblev;
Zextern	char outbuf[MAXOUT];
Zextern	char *outp;
Zextern	short outw;
Zextern	short outwds;
Zextern	short pages;
Zextern	short pausecount;
Zextern	short curpag;
Zextern	short newpag;
Zextern	short lineno;
Zextern	short peekno;
Zextern	short indline;
Zextern	short respage;
Zextern	char trapmac[];
Zextern	char blnkhdr[];
Zextern	struct envir env;
Zextern	struct envir *curenv;
Zextern	struct cmdents builtins[];
Zextern	short echodir;
Zextern	char *progname;
Zextern	char *filename;
Zextern	short fileline;
Zextern	short ttyfd;
Zextern	FILE *indfp;
Zextern	char *nomem;
STUNKYFLUFF
set `sum tpr.h`
if test 61190 != $1
then
echo tpr.h: Checksum error. Is: $1, should be: 61190.
fi
#
#
echo Extracting tpr0.c:
sed 's/^Z//' >tpr0.c <<\STUNKYFLUFF
Z/*
Z**	tpr - text formatter
Z**		Ken Yap, June 1981
Z*/
Z#include	"tpr.h"
Z
Zstruct macro macros[MAXMAC];
Zshort maccnt	= 0;		/* counter for current macro */
Zchar *pbptr[MAXMAC];		/* pointers to pushed back lines */
Zshort pblev	= 0;		/* indicates level of macro nesting during collection */
Z
Zchar outbuf[MAXOUT];	/* lines to be filled collect here */
Zchar *outp	= outbuf;	/* last char position in outbuf; init = 0 */
Zshort outw	= 0;	/* width of text currenty in outbuf; init = 0 */
Zshort outwds	= 0;	/* number of words in outbuf; init = 0 */
Z
Zshort pages	= 1;	/* pages between pauses with -s option */
Zshort pausecount= 0;	/* decremented every page */
Zshort curpag	= 0;
Zshort newpag	= 1;
Zshort lineno	= 0;
Zshort peekno	= 1;
Zshort indline	= 0;
Zshort respage	= 0;
Zchar trapmac[2]	= "";
Zchar blnkhdr[]	= "\n";
Zstruct envir env	= {
Z	PAGLEN, M1DEF, M2DEF, M3DEF, M4DEF, (PAGLEN-M3DEF-M4DEF),
Z	blnkhdr, blnkhdr,
Z	blnkhdr, blnkhdr,
Z	'.', '\t', ' ',
Z	YES, YES, ARABIC, 1, PAGEWIDTH, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Z	{ 8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,0 },
Z	NULL
Z	};
Zstruct envir *curenv	= NULL;
Zstruct cmdents builtins[] ={
Z	{ "ad",YES },
Z	{ "ar",YES },
Z	{ "bd",YES },
Z	{ "bl",YES },
Z	{ "bp",YES },
Z	{ "br",YES },
Z	{ "cc",YES },
Z	{ "ce",YES },
Z	{ "de",YES },
Z	{ "ef",YES },
Z	{ "eg",YES },
Z	{ "eh",YES },
Z	{ "fi",YES },
Z	{ "fo",YES },
Z	{ "he",YES },
Z	{ "in",YES },
Z	{ "ix",YES },
Z	{ "li",YES },
Z	{ "ll",YES },
Z	{ "ls",YES },
Z	{ "m1",YES },
Z	{ "m2",YES },
Z	{ "m3",YES },
Z	{ "m4",YES },
Z	{ "na",YES },
Z	{ "ne",YES },
Z	{ "nf",YES },
Z	{ "of",YES },
Z	{ "oh",YES },
Z	{ "pl",YES },
Z	{ "po",YES },
Z	{ "pt",YES },
Z	{ "re",YES },
Z	{ "rf",YES },
Z	{ "ro",YES },
Z	{ "rp",YES },
Z	{ "se",YES },
Z	{ "sk",YES },
Z	{ "so",YES },
Z	{ "sp",YES },
Z	{ "ta",YES },
Z	{ "tc",YES },
Z	{ "ti",YES },
Z	{ "ub",YES },
Z	{ "ul",YES }
Z	};
Z
Zshort echodir	= 0;
Zchar *progname;
Zchar *filename	= "stdin";
Zshort fileline	= 0;
Zshort ttyfd	= -1;	/* for pause between pages */
ZFILE *indfp	= NULL;
Zchar *nomem	= "Out of dynamic memory\n";	/* canned message */
Z
Z/*
Z**	main
Z*/
Zmain(argc,argv)
Z	short argc;
Z	char **argv;{
Z	FILE *file;
Z	extern char _sobuf[];
Z	
Z	progname = *argv;
Z	for(argc--, argv++; argc > 0 && **argv == '-' && (*argv)[1] != '\0'; argc--, argv++)
Z		setoptions(*argv);
Z	setbuf(stdout,_sobuf);
Z	if(argc == 0)
Z		tpr(stdin,"stdin");
Z	else
Z		for( ; argc > 0; argc--, argv++){
Z			if(**argv == '-' && (*argv)[1] == '\0')
Z				tpr(stdin,"stdin");
Z			else{
Z				if((file = fopen(*argv,"r")) == NULL){
Z					perror(*argv);
Z					continue;
Z					}
Z				tpr(file,*argv);
Z				fclose(file);
Z				}
Z			}
Z	if(lineno > 0)
Z		spc(HUGE);		/* flush last output */
Z	if(indfp != NULL)
Z		fclose(indfp);
Z	fflush(stdout);
Z}
Z
Zsetoptions(arg)
Z	char *arg;{
Z	register char c;
Z	int isatty(),open();
Z	FILE *fopen();
Z
Z	while((c = *++arg) != '\0')
Z		switch(c){
Z			case 'd':	/* echo directives */
Z				echodir++;
Z				break;
Z			case 'e':	/* divert errors */
Z				close(2);
Z				if(creat(++arg,0600) < 0){
Z					open("/dev/tty",1);
Z					perror(arg);
Z					exit(1);
Z					}
Z				return;
Z			case 'i':	/* open index file */
Z				if((indfp = fopen(arg[1] == '\0' ? "index" : ++arg, "w")) == NULL)
Z					perror(arg);
Z				return;
Z			case 'n':	/* set initial page number */
Z				curpag = atoi(++arg);
Z				if(curpag < 0)
Z					curpag = 0;
Z				newpag = curpag;
Z				return;
Z			case 's':	/* pause every n pages */
Z				pages = atoi(++arg);
Z				if(pages <= 0)
Z					pages = 1;
Z				pausecount = pages;
Z				if(isatty(fileno(stdout)))
Z					ttyfd = open("/dev/tty",0);
Z				return;
Z			default:
Z				fprintf(stderr,"Usage: %s [-d] [-efile] [-iindex] [-nN] [-sN] files\n",progname);
Z				exit(1);
Z			}
Z}
Z
Z/*
Z**	tpr - here is the main routine for each file
Z**	the name is passed along so that the 'include' directive
Z**	can call 'tpr' recursively
Z*/
Ztpr(file,name)
Z	FILE *file;
Z	char *name;{
Z	register char *savename;
Z	register short saveline;
Z	char inbuf[MAXIN];
Z	char *ngetl();
Z
Z	savename = filename;	/* save old name */
Z	filename = name;	/* make new one available for error routine */
Z	saveline = fileline;	/* and line number */
Z	fileline = 0;
Z	while(ngetl(inbuf,file) != CHARNULL){
Z		++fileline;
Z		if(*inbuf == env.comchr)	/* it's a command */
Z			cmd(inbuf,file);
Z		else			/* it's text */
Z			text(inbuf);
Z		}
Z	filename = savename;	/* restore name and linenumber */
Z	fileline = saveline;
Z}
Z
Z/*
Z**	error - prints filename and linenumber
Z*/
Zerror(msg,arg)
Z	char *msg,*arg;{
Z
Z	fprintf(stderr,"At line %d in file %s: ",fileline,filename);
Z	fprintf(stderr,msg,arg);
Z}
Z
Z/*
Z**	bold - bolden a line
Z*/
Zbold(buf,tbuf,tend)
Z	char *buf,*tbuf,*tend;{
Z	register char c;
Z	register char *p,*q;
Z	char *strcpy();
Z	
Z	p = buf;
Z	q = tbuf;
Z	while(*p != '\n' && q < tend){
Z		if(isprint(c = *p++)){
Z			*q++ = c;
Z			*q++ = '\b';
Z			}
Z		*q++ = c;
Z		}
Z	*q++ = '\n';
Z	*q = '\0';
Z	strcpy(buf,tbuf);	/* copy it back to buf */
Z}
Z
Z/*
Z**	blnk - space n lines (to new page if necessary, cf spc)
Z*/
Zblnk(n)
Z	short n;{
Z	register short i;
Z	short nextline();
Z	
Z	linebreak();
Z	while(n > 0){
Z		if(lineno > env.bottom){
Z			pfoot();
Z			lineno = 0;
Z			peekno = nextline(lineno);
Z			}
Z		if(lineno == 0)
Z			newpage();
Z		i = min(n,env.bottom + 1 - lineno);
Z		skip(i);
Z		n -= i;
Z		lineno += i;
Z		peekno = nextline(lineno);
Z		}
Z	if(lineno > env.bottom)
Z		pfoot();
Z}
Z
Z/*
Z**	linebreak - end current filled line
Z*/
Zlinebreak(){
Z	
Z	if(outp != outbuf){
Z		*outp++ = '\n';
Z		*outp = '\0';
Z		put(outbuf);
Z		}
Z	outp = outbuf;
Z	outw = 0;
Z	outwds = 0;
Z}
Z
Z/*
Z**	centre - centre a line by setting tival
Z*/
Zcenter(buf)
Z	char *buf;{
Z	short width();
Z	
Z	env.tival = max((env.llval + env.tival - width(buf))/2,0);
Z}
Z
Z/*
Z**	cmd - perform formatting command
Z*/
Zcmd(buf,file)
Z	char *buf;
Z	FILE *file;{
Z	enum cmdnum comtyp(),ct;
Z	register short spval,val;
Z	register char *p;
Z	short macnum;
Z	char argtyp;
Z	char fn[MAXFN];
Z	FILE *fp;
Z	int strlen();
Z	short getval(),set();
Z	char *gettl();
Z	
Z	if(echodir)
Z		putdir(buf);
Z	ct = comtyp(buf,&macnum);
Z	val = 0;
Z	val = getval(buf,&argtyp);
Z	switch(ct){
Z		case SPA:
Z			spval = set(0,val,argtyp,1,0,HUGE);
Z			spc(spval);
Z			break;
Z		case IND:
Z		case INX:
Z			if(ct == IND)
Z				linebreak();
Z			env.inval = set(env.inval,val,argtyp,0,0,env.llval - 1);
Z			env.tival = env.inval;
Z			break;
Z		case TMI:
Z			linebreak();
Z			env.tival = set(env.tival,val,argtyp,0,0,env.llval);
Z			break;
Z		case CEN:
Z			linebreak();
Z			env.ceval = set(env.ceval,val,argtyp,1,0,HUGE);
Z			break;
Z		case UDL:
Z			env.ulval = set(env.ulval,val,argtyp,0,1,HUGE);
Z			break;
Z		case BLD:
Z			env.bdval = set(env.bdval,val,argtyp,0,1,HUGE);
Z			break;
Z		case FIL:
Z			linebreak();
Z			env.fill = YES;
Z			break;
Z		case NFL:
Z			linebreak();
Z			env.fill = NO;
Z			break;
Z		case BRE:
Z			linebreak();
Z			break;
Z		case BLN:
Z			env.blval = set(env.blval,val,argtyp,1,0,HUGE);
Z			blnk(env.blval);
Z			env.blval = 0;
Z			break;
Z		case NED:
Z			if(val > env.bottom - peekno + 1)
Z				spc(HUGE);
Z			break;
Z		case LNS:
Z			env.lsval = set(env.lsval,val,argtyp,1,1,HUGE);
Z			break;
Z		case LNL:
Z			env.llval = set(env.llval,val,argtyp,PAGEWIDTH,env.tival + 1,HUGE);
Z			break;
Z		case PGL:
Z			env.plval = set(env.plval,val,argtyp,PAGLEN,
Z				env.m1val + env.m2val + env.m3val + env.m4val + 1,HUGE);
Z			env.bottom = env.plval - env.m3val - env.m4val;
Z			break;
Z		case BPG:
Z			if(lineno > 0)
Z				spc(HUGE);
Z			curpag = set(curpag,val,argtyp,curpag + 1, - HUGE,HUGE);
Z			newpag = curpag;
Z			break;
Z		case HED:
Z			env.evenhdr = env.oddhdr = gettl(buf);
Z			break;
Z		case FOT:
Z			env.evenftr = env.oddftr = gettl(buf);
Z			break;
Z		case EHD:
Z			env.evenhdr = gettl(buf);
Z			break;
Z		case EFO:
Z			env.evenftr = gettl(buf);
Z			break;
Z		case OHD:
Z			env.oddhdr = gettl(buf);
Z			break;
Z		case OFO:
Z			env.oddftr = gettl(buf);
Z			break;
Z		case NAD:
Z			env.adjust = NO;
Z			break;
Z		case ADJ:
Z			env.adjust = YES;
Z			break;
Z		case ROM:
Z			env.numtyp = ROMAN;
Z			break;
Z		case ARA:
Z			env.numtyp = ARABIC;
Z			break;
Z		case ENG:
Z			env.numtyp = ENGLISH;
Z			break;
Z		case LIT:
Z			env.litval = set(env.litval,val,argtyp,1,0,HUGE);
Z			break;
Z		case M1:
Z			env.m1val = set(env.m1val,val,argtyp,M1DEF,
Z				0,env.plval - (env.m2val + env.m3val + env.m4val + 1));
Z			break;
Z		case M2:
Z			env.m2val = set(env.m2val,val,argtyp,M2DEF,
Z				0,env.plval - (env.m1val + env.m3val + env.m4val + 1));
Z			break;
Z		case M3:
Z			env.m3val = set(env.m3val,val,argtyp,M3DEF,
Z				0,env.plval - (env.m1val + env.m2val + env.m4val + 1));
Z			env.bottom = env.plval - env.m3val - env.m4val;
Z			break;
Z		case M4:
Z			env.m4val = set(env.m4val,val,argtyp,M4DEF,
Z				0,env.plval - (env.m1val + env.m2val + env.m3val + 1));
Z			env.bottom = env.plval - env.m3val - env.m4val;
Z			break;
Z		case CMC:
Z			if(argtyp != '\n')
Z				env.comchr = argtyp;
Z			else
Z				env.comchr = COMMAND;
Z			break;
Z		case POF:
Z			env.poval = set(env.poval,val,argtyp,0,0,PAPERSIZE);
Z			break;
Z		case SKP:
Z			env.skpval = set(env.skpval,val,argtyp,1,0,HUGE);
Z			break;
Z		case DFN:
Z			getmac(buf,file);
Z			break;
Z		case TCH:
Z			if(argtyp != '\n')
Z				env.tabchr = argtyp;
Z			else
Z				env.tabchr = '\t';
Z			break;
Z		case TCL:
Z			tabcol(buf);
Z			break;
Z		case UBC:
Z			if(argtyp != '\n')
Z				env.ubchr = argtyp;
Z			else
Z				env.ubchr = ' ';
Z			break;
Z		case REF:
Z			if(indfp != NULL)
Z				indline = set(indline,val,argtyp,1,0,HUGE);
Z			break;
Z		case RPG:
Z			respage += set(0,val,argtyp,1,0,HUGE);
Z			break;
Z		case PGT:
Z			settrap(buf);
Z			break;
Z		case RNV:
Z			if(val <= 0)
Z				val = 1;
Z			resenv(val);
Z			break;
Z		case SNV:
Z			savenv();
Z			break;
Z		case MAC:
Z			expand(macnum);
Z			break;
Z		case SOU:
Z			skipnbl(buf);
Z			skipbl(buf);
Z			for(p = fn; p < &fn[MAXFN - 1] && *buf != '\n'; )
Z				*p++ = *buf++;
Z			*p = '\0';
Z			if((fp = fopen(fn,"r")) == NULL)
Z				error("Cannot open %s\n",fn);
Z			else{
Z				tpr(fp,fn);
Z				fclose(fp);
Z				}
Z			break;
Z		case UNKNOWN:
Z			error("Unrecognised directive:\n%s",buf);
Z			return;
Z		}
Z}
Z
Z/*
Z**	comtyp - decode command type
Z*/
Zenum cmdnum comtyp(buf,macnum)
Z	char *buf;
Z	short *macnum;{
Z	register char a,b;
Z	register struct cmdents *p;
Z	register char *q;
Z	register short l,h,m;
Z	
Z	a = buf[1];
Z	b = buf[2];
Z	for(l = 0, h = (sizeof(builtins)/sizeof(builtins[0])) - 1; l <= h; ){
Z		p = &builtins[m = (l + h) / 2];
Z		if(a < p->cmdname[0] || a <= p->cmdname[0] && b < p->cmdname[1])
Z			h = m - 1;
Z		else if(a > p->cmdname[0] || a <= p->cmdname[0] && b > p->cmdname[1])
Z			l = m + 1;
Z		else
Z			break;
Z		}
Z	if(l <= h && p->notredefd)
Z		return((enum cmdnum)m);
Z	for(l = maccnt - 1; l >= 0; l--){
Z		q = macros[l].macnam;
Z		if(a == *q++ && b == *q){
Z			*macnum = l;
Z			return(MAC);
Z			}
Z		}
Z	return(UNKNOWN);
Z}
STUNKYFLUFF
set `sum tpr0.c`
if test 40408 != $1
then
echo tpr0.c: Checksum error. Is: $1, should be: 40408.
fi
#
#
echo Extracting tpr1.c:
sed 's/^Z//' >tpr1.c <<\STUNKYFLUFF
Z#include	"tpr.h"
Z
Z/*
Z**	expand - pushback macro definition onto input
Z*/
Zexpand(macnum)
Z	short macnum;{
Z	register struct linelink *lp;
Z	
Z	for(lp = macros[macnum].macend; lp != NULL; lp = lp->lastline)
Z		pushback(lp->lineptr);
Z}
Z
Z/*
Z**	getmac - collect macro
Z*/
Zgetmac(buf,file)
Z	char *buf;
Z	FILE *file;{
Z	register char *p;
Z	register struct macro *mp;
Z	register struct linelink *lp;
Z	register short dotlev;
Z	enum cmdnum ct;
Z	short macnum;
Z	char line[MAXIN];
Z	enum cmdnum comtyp();
Z	char *strcpy();
Z	char *malloc();
Z	char *ngetl();
Z	
Z	skipnbl(buf);
Z	skipbl(buf);
Z	if(*buf == '\n'){
Z		error("Missing macro name\n",CHARNULL);
Z		return;
Z		}
Z	if(maccnt >= MAXMAC){
Z		error("Too many macro definitions",CHARNULL);
Z		return;
Z		}
Z	mp = &macros[maccnt];
Z	p = mp->macnam;
Z	if((ct = comtyp(buf - 1,&macnum)) != UNKNOWN && ct != MAC)
Z		builtins[(int)ct].notredefd = NO;
Z	*p++ = *buf++;	/* record name */
Z	*p++ = *buf++;
Z	*p = '\0';
Z	for(lp = mp->macend; lp != NULL; lp = lp->lastline, free(lp))
Z		free(lp->lineptr);
Z	mp->macend = NULL;
Z	dotlev = 1;
Z	do{
Z		if((p = ngetl(line,file)) == CHARNULL)
Z			break;	/* unexpected EOF */
Z		++fileline;
Z		if(*p++ == env.comchr){
Z			if(*p == '.')
Z				dotlev--;
Z			else if(comtyp(line,&macnum) == DFN)
Z				dotlev++;	/* included .de */
Z			}
Z		if(dotlev > 0){
Z			if((lp = (struct linelink *)malloc(sizeof(struct linelink))) == NULL){
Z				error(nomem,CHARNULL);
Z				break;
Z				}
Z			lp->lastline = mp->macend;
Z			mp->macend = lp;
Z			if((lp->lineptr = malloc((unsigned)(strlen(line) + 1))) == NULL){
Z				error(nomem,CHARNULL);
Z				break;
Z				}
Z			strcpy(lp->lineptr,line);
Z			}
Z		}while(dotlev > 0);
Z	maccnt++;
Z}
Z
Z/*
Z**	getseg - puts out part of header
Z*/
Zchar *getseg(buf,copy,copyend,term,pageno)
Z	char *buf,*copy,*copyend,term;
Z	short pageno;{
Z	register short i;
Z	register char *p;
Z	short itorom(),itoeng();
Z	
Z	p = buf;
Z	for( ;copy != copyend && *p != term && *p != '\0' && *p != '\n'; p++){
Z		if(*p == PAGENUM){
Z			switch(env.numtyp){
Z			    case ARABIC:
Z				sprintf(copy, "%d", pageno);
Z				i = strlen(copy);
Z				break;
Z			    case ROMAN:
Z				i = itorom(pageno,copy,min(MAXCHARS,(short)(copyend - copy)));
Z				break;
Z			    case ENGLISH:
Z				i = itoeng(pageno,copy,copyend);
Z				break;
Z				}
Z			copy += i;
Z			}
Z		else
Z			*copy++ = *p;
Z		}
Z	if(*p == term)
Z		p++;
Z	*copy = '\0';
Z	return(p);
Z}
Z
Z/*
Z**	gettl - copy title from buf to ttl
Z*/
Zchar *gettl(buf)
Z	char *buf;{
Z	register char *p,*q;
Z	char *strcpy();
Z	char *malloc();
Z	
Z	p = buf;
Z	skipnbl(p);
Z	skipbl(p);	/* find argument */
Z	if((q = malloc((unsigned)(strlen(p) + 1))) == NULL){
Z		error(nomem,CHARNULL);
Z		return(q);
Z		}
Z	strcpy(q,p);
Z	return(q);
Z}
Z
Z/*
Z**	getval - evaluate optional numeric argument
Z*/
Zshort getval(buf,argtyp)
Z	char *buf;
Z	char *argtyp;{
Z	int atoi();
Z	
Z	skipnbl(buf);
Z	skipbl(buf);	/* find argument */
Z	*argtyp = *buf;
Z	if(!isdigit(*buf))
Z		buf++;
Z	return(atoi(buf));
Z}
Z
Z/*
Z**	getwrd - get a non - blank word from instr(i) to out, increment i
Z*/
Zchar *getwrd(instr,out)
Z	char *instr,*out;{
Z	register char c;
Z	register char *p,*q;
Z	
Z	p = instr;
Z	q = out;
Z	while((*p == ' ' || *p == '\t') && *p != env.tabchr)
Z		p++;
Z	instr = p;
Z	if(*p == env.tabchr)
Z		*q++ = *p;
Z	else{
Z		while((c = *p) != '\0' && c != ' ' && c != '\t'
Z			&& c != '\n' && c != env.tabchr){
Z			*q++ = *p++;
Z			}
Z		}
Z	*q = '\0';
Z	return(p == instr ? NULL : p);
Z}
Z
Z/*
Z**	itorom - converts integer to roman numerals
Z*/
Zshort itorom(num,str,flen)
Z	char *str;
Z	short num,flen;{
Z	register short i,j;
Z	char *p;
Z	static short romval[]	= { 1000,500,100,50,10,5,1,0 };
Z	static short reltab[]	= { 2,1,2,1,2,1,1,0 };
Z	static char romlet[]	= "mdclxvi0";
Z	
Z	p = str;
Z	if(num < 0 && flen > 1){
Z		num = -num;
Z		*p++ = '-';
Z		}
Z	for(i = 0; num > 0; i++){
Z		while(num >= romval[i]){
Z			num -= romval[i];
Z			*p++ = romlet[i];
Z			}
Z		j = i + reltab[i];
Z		if(num >= (romval[i] - romval[j])){
Z			num -= (romval[i] - romval[j]);
Z			*p++ = romlet[j];
Z			*p++ = romlet[i];
Z			}
Z		}
Z	*p = '\0';
Z	return((short)(p - str));
Z}
Z
Z/*
Z**	leadbl - delete leading blanks, set tival
Z*/
Zleadbl(buf)
Z	char *buf;{
Z	register char *p;
Z	
Z	linebreak();
Z	p = buf;
Z	skipnbl(buf);
Z	if(*buf != '\n')
Z		env.tival = (buf - p);
Z	while(*buf != '\0')		/* move line to left */
Z		*p++ = *buf++;
Z	*p = '\0';
Z}
Z
Z/*
Z**	newpage - put out as many blank pages as necessary to satisfy
Z**	reserved page count 'respage'
Z*/
Znewpage(){
Z
Z	phead();
Z	for( ; respage > 0; respage--){
Z		skip(env.bottom + 1 - lineno);
Z		pfoot();
Z		phead();
Z		}
Z}
Z
Z/*
Z**	nextline - predicts the next line after n
Z*/
Zshort nextline(n)
Z	register short n;{
Z	register short i;
Z
Z	i = n + 1;
Z	if(i > env.bottom)
Z		i = env.m1val + env.m2val + 1;
Z	return(i);
Z}
Z
Z/*
Z**	nextab - returns position of next tab stop
Z*/
Zshort nextab(pos)
Z	short pos;{
Z	register short i,k;
Z	
Z	for(i =  0; i < MAXTABS; i++){
Z	       if(env.tabpos[i] == 0)
Z			break;
Z	       if(env.tabpos[i] > pos){
Z	               k = env.tabpos[i];
Z	               return(k);
Z	               }
Z	       }
Z	k = pos + 1;
Z	return(k);
Z}
Z
Z/*
Z**	ngetl - gets line from input or pushback buffer
Z*/
Zchar *ngetl(buf,file)
Z	char *buf;
Z	FILE *file;{
Z	char *fgets();
Z	char *strcpy();
Z	
Z	if(pblev <= 0)
Z		return(fgets(buf,MAXIN,file));
Z	else{
Z		pblev--;
Z		strcpy(buf,pbptr[pblev]);
Z		}
Z	return(buf);
Z}
Z
Z/*
Z**	pfoot - put out page footer
Z*/
Zpfoot(){
Z	
Z	skip(env.m3val);
Z	if(env.m4val > 0){
Z		puttl(curpag % 2 ? env.oddftr : env.evenftr, curpag);
Z		skip(env.m4val - 1);
Z		}
Z}
Z
Z/*
Z**	phead - put out page header
Z*/
Zphead(){
Z	short nextline();
Z	
Z	curpag = newpag;
Z	newpag++;
Z	if(ttyfd >= 0 && pausecount-- <= 0){
Z		fflush(stdout);
Z		waitfornl();
Z		pausecount = pages - 1;
Z		}
Z	if(trapmac[0] != '\0')
Z		springtrap();
Z	if(env.m1val > 0){
Z		skip(env.m1val - 1);
Z		puttl(curpag % 2 ? env.oddhdr : env.evenhdr, curpag);
Z		}
Z	skip(env.m2val);
Z	lineno = env.m1val + env.m2val + 1;
Z	peekno = nextline(lineno);
Z}
Z
Z/*
Z**	pushback - pushback line onto input
Z*/
Zpushback(buf)
Z	char *buf;{
Z
Z	if(pblev > MAXPB){
Z		error("Not enough pushback space\n",CHARNULL);
Z		return;	/* to catch stack overflow */
Z		}
Z	pbptr[pblev] = buf;
Z	pblev++;
Z}
Z
Z/*
Z**	put - put out line with proper spacing and indenting
Z*/
Zput(buf)
Z	char *buf;{
Z	short nextab();
Z	register char c;
Z	register short col,i;
Z	short nextline();
Z	
Z	if(lineno == 0 || lineno > env.bottom)
Z		newpage();
Z	for(i = (env.tival + env.poval); i--; )
Z		putchar(' ');
Z	col = env.tival;
Z	env.tival = env.inval;
Z	for(; (c = *buf) != '\0'; buf++){
Z		if(c == env.ubchr)
Z			c = ' ';	/* put blanks instead of blank replacement */
Z		if(c == env.tabchr){
Z			i = nextab(col);	/* nextab wants last used column */
Z			for(; col < i; col++)
Z				putchar(' ');
Z			continue;
Z			}
Z		else if(c == '\b')
Z			col--;
Z		else
Z			col++;
Z		putchar(c);
Z		}
Z	skip(min(env.lsval - 1,env.bottom - lineno));
Z	lineno += env.lsval;
Z	peekno = nextline(lineno);
Z	if(lineno > env.bottom){
Z		pfoot();
Z		if(env.skpval > 0){
Z			skpage(env.skpval);
Z			env.skpval = 0;
Z			}
Z		}
Z}
Z
Z/*
Z**	putdir - output a directive
Z*/
Zputdir(buf)
Z	char *buf;{
Z
Z	fprintf(stderr,"%.10s",buf);	/* first 10 chars */
Z}
Z
Z/*
Z**	puttl - put out title line with optional page number
Z*/
Zputtl(buf,pageno)
Z	char *buf;
Z	short pageno;{
Z	register char *p,*q;
Z	register short col,newcol;
Z	char copy[MAXOUT],term;
Z	short width();
Z	char *getseg();
Z	
Z	for(col = env.poval; col-- > 0; )
Z		tputc(' ');
Z	term = *buf;
Z	if(term == '\n'){
Z		tputc('\n');
Z		return;
Z		}
Z	col = 0;
Z	p = buf + 1;
Z	p = getseg(p,copy,&copy[MAXOUT],term,pageno);
Z	col += width(copy);
Z	for(q = copy; *q != '\0'; q++)
Z		tputc(*q);
Z	p = getseg(p,copy,&copy[MAXOUT],term,pageno);
Z	newcol = (env.llval - strlen(copy))/2;	/* start of centre */
Z	for(; col < newcol; col++)
Z		tputc(' ');
Z	col += width(copy);
Z	for(q = copy; *q != '\0'; q++)
Z		tputc(*q);
Z	p = getseg(p,copy,&copy[MAXOUT],term,pageno);
Z	newcol = env.llval - strlen(copy);	/* start of right */
Z	for(; col < newcol; col++)
Z		tputc(' ');
Z	for(q = copy; *q != '\0'; q++)
Z		tputc(*q);
Z	tputc('\n');
Z}
Z
Z/*
Z**	putwrd - put a word in outbuf; includes margin justification
Z*/
Zputwrd(wrdbuf)
Z	char *wrdbuf;{
Z	char *strcpy();
Z	register short l,w,lnval,nextra;
Z	short width(), nextab();
Z	int strlen();
Z	
Z	lnval = env.llval - env.tival;
Z	if(*wrdbuf == env.tabchr){
Z		outw = nextab(outw + env.tival) - env.tival;
Z		/* because outw floats from the indent */
Z		/* and nextab is absolute */
Z		if(outp  != outbuf && outw > lnval){
Z			linebreak();
Z			outw = nextab(outw + env.tival) - env.tival;
Z			}
Z		*++outp = env.tabchr;
Z		outwds = 0;		/* adjust from next word */
Z		}
Z	else{
Z		w = width(wrdbuf);
Z		l = strlen(wrdbuf);
Z		if(outp != outbuf && (outw + w > lnval ||	/* too big */
Z			(char *)(outp + l) >= &outbuf[MAXOUT])){
Z			--outp;	/* we put in a blank earlier */
Z			if(env.adjust == YES){
Z				nextra = lnval - outw + 1;
Z				spread(outp,nextra,outwds);
Z				outp += nextra;
Z				}
Z			linebreak();		/* flush previous line */
Z			}
Z		strcpy(outp,wrdbuf);
Z		outp += l;
Z		*outp++ = ' ';		/* blank between words */
Z		outw += w + 1;			/* 1 for blank */
Z		outwds++;
Z		}
Z}
Z
Z/*
Z**	resenv - restore environment n levels back
Z*/
Zresenv(n)
Z	short n;{
Z	register struct envir *ep,*tp;
Z	
Z	linebreak();		/* to flush any latent output */
Z	for(ep = curenv; ep != NULL && --n > 0; free(tp))
Z		ep = (tp = ep)->lastenv;
Z	if(ep != NULL){
Z		env = *ep;
Z		curenv = ep->lastenv;
Z		free(ep);
Z		}
Z}
Z
Z/*
Z**	savenv - keep environment for later restoration
Z*/
Zsavenv(){
Z	register struct envir *ep;
Z	char *malloc();
Z	
Z	if((ep = (struct envir *)malloc(sizeof(env))) == NULL){
Z		error(nomem,CHARNULL);
Z		return;
Z		}
Z	*ep = env;	/* structure copy */
Z	ep->lastenv = curenv;
Z	curenv = ep;
Z}
Z
Z/*
Z**	set - set parameter and check range
Z*/
Zshort set(param,val,argtyp,defval,minval,maxval)
Z	short param,val,defval,minval,maxval;
Z	char argtyp;{
Z	
Z	switch(argtyp){
Z		case '\n':
Z			param = defval;
Z			break;
Z		case '+':
Z			param = param + val;
Z			break;
Z		case '-':
Z			param = param - val;
Z			break;
Z		default:
Z			param = val;
Z		}
Z	param = min(param,maxval);
Z	param = max(param,minval);
Z	return(param);
Z}
Z
Z/*
Z**	settrap - record macro name to be invoked on page crossing
Z*/
Zsettrap(buf)
Z	char *buf;{
Z	register char *p;
Z
Z	p = buf;
Z	skipnbl(p);
Z	skipbl(p);
Z	if(*p == '\n'){
Z		trapmac[0] = '\0';
Z		return;
Z		}
Z	trapmac[0] = *p++;
Z	trapmac[1] = *p;
Z}
Z
Z/*
Z**	skip - output n blank lines
Z*/
Zskip(n)
Z	short n;{
Z	
Z	while(n-- > 0)
Z		putchar('\n');
Z}
Z
Z/*
Z**	skpage - skip n pages
Z*/
Zskpage(n)
Z	short n;{
Z	short nextline();
Z	
Z	while(n-- > 0){
Z		newpage();
Z		skip(env.bottom + 1 - lineno);
Z		lineno = env.bottom + 1;
Z		peekno = nextline(lineno);
Z		pfoot();
Z		}
Z}
Z
Z/*
Z**	spc - space n lines or to bottom of page (cf blnk)
Z*/
Zspc(n)
Z	short n;{
Z	short nextline();
Z	
Z	linebreak();
Z	if(lineno > env.bottom)
Z		return;
Z	if(lineno == 0)
Z		newpage();
Z	skip(min(n,env.bottom + 1 - lineno));
Z	lineno += n;
Z	peekno = nextline(lineno);
Z	if(lineno > env.bottom){
Z		pfoot();
Z		if(env.skpval > 0){
Z			skpage(env.skpval);
Z			env.skpval = 0;
Z			}
Z		}
Z}
Z
Z/*
Z**	spread - spread words to justify right margin
Z*/
Zspread(ptr,nextra,nwrds)
Z	char *ptr;
Z	short nextra,nwrds;{
Z	register char *p,*q;
Z	register short nb,nholes;
Z	static short dir	= 0;
Z	
Z	if(nextra <= 0 || nwrds <= 1)
Z		return;
Z	dir = !dir;		/* reverse previous direction */
Z	nholes = nwrds - 1;
Z	p = ptr - 1;
Z	q = ptr + nextra;
Z	*q-- = '\0';
Z	while(p < q){
Z		if((*q = *p) == ' '){
Z			nb = dir ? (nextra - 1) / nholes + 1 :
Z				nextra / nholes;
Z			nextra -= nb;
Z			nholes--;
Z			while(nb-- > 0){
Z				*--q = ' ';
Z				}
Z			}
Z		p--;
Z		q--;
Z		}
Z}
Z
Z/*
Z**	springtrap - invoke macro on page crossing
Z*/
Zspringtrap(){
Z	static char mac[5]	= ".xx\n";
Z
Z	mac[1] = trapmac[0];
Z	mac[2] = trapmac[1];
Z	trapmac[0] = '\0';	/* deactivate trap */
Z	pushback(mac);
Z}
Z
Z/*
Z**	tabcol - enters pseudotab stops, checking validity
Z*/
Ztabcol(buf)
Z	char *buf;{
Z	int atoi();
Z	register short tp,incr,val;
Z	
Z	for(tp = 0; tp < MAXTABS - 1; tp++){
Z		skipnbl(buf);
Z		skipbl(buf);
Z		if(*buf == '\n')
Z			break;	/* end of list */
Z		incr = *buf++ == '+' ? YES : NO;
Z		val = atoi(buf);
Z		if(incr == YES && tp > 1)	/* relative tab */
Z			val = env.tabpos[tp - 1] + val;
Z		env.tabpos[tp] = val;
Z		if(val < 0 || (tp > 1 && val < env.tabpos[tp - 1]))
Z			tp--;
Z		}
Z	env.tabpos[tp] = 0;	/* end of list */
Z}
Z
Z/*
Z**	text - process text lines
Z*/
Ztext(inbuf)
Z	char *inbuf;{
Z	register char *p;
Z	char wrdbuf[MAXIN];
Z	char *getwrd();
Z	
Z	if(indline > 0){
Z		fprintf(indfp,"%d. %s",curpag,inbuf);
Z		indline--;
Z		}
Z	if(env.litval > 0){
Z		put(inbuf);
Z		env.litval--;
Z		return;
Z		}
Z	if(*inbuf == ' ' || *inbuf == '\n')
Z		leadbl(inbuf);	/* move left, set tival */
Z	if(env.ulval > 0){			/* underlining */
Z		underl(inbuf,wrdbuf,&wrdbuf[MAXIN]);
Z		env.ulval--;
Z		}
Z	if(env.bdval > 0){
Z		bold(inbuf,wrdbuf,&wrdbuf[MAXIN]);
Z		env.bdval--;
Z		}
Z	if(env.ceval > 0){			/* centering */
Z		center(inbuf);
Z		put(inbuf);
Z		env.ceval--;
Z		}
Z	else if(*inbuf == '\n')	/* all blank line */
Z		put(inbuf);
Z	else if(env.fill == NO)		/* unfilled text */
Z		put(inbuf);
Z	else
Z		for(p = inbuf; (p = getwrd(p,wrdbuf)) != NULL;)
Z			putwrd(wrdbuf);
Z}
Z
Z/*
Z**	tputc  - intelligent filter routine to eliminate unnecessary blanks
Z*/
Ztputc(c)
Z	register char c;{
Z	static short curcol	= 0;
Z	static short lastcol	= 0;
Z
Z	switch(c){
Z	    case ' ':
Z		curcol++;
Z		break;
Z	    case '\n':
Z		curcol = lastcol = 0;
Z		putchar(c);
Z		break;
Z	    default:
Z		while(lastcol++ < curcol)
Z			putchar(' ');
Z		putchar(c);
Z		curcol++;
Z		break;
Z		}
Z}
Z
Z/*
Z**	underl - underline a line
Z*/
Zunderl(buf,tbuf,tend)
Z	char *buf,*tbuf,*tend;{
Z	register char c;
Z	register char *p,*q;
Z	char *strcpy();
Z	
Z	p = buf;
Z	q = tbuf;
Z	while(*p != '\n' && q < tend){
Z		if(isalnum(c = *p++)){
Z			*q++ = '_';
Z			*q++ = '\b';
Z			}
Z		*q++ = c;
Z		}
Z	*q++ = '\n';
Z	*q = '\0';
Z	strcpy(buf,tbuf);	/* copy it back to buf */
Z}
Z
Z/*
Z**	waitfornl - crude version to get newline from terminal
Z*/
Zwaitfornl(){
Z	char c;
Z	int read();
Z
Z	while(read(ttyfd,&c,1) > 0)
Z		if(c == '\n')
Z			break;
Z}
Z
Z
Z/*
Z**	width - compute width of character string
Z*/
Zshort width(buf)
Z	char *buf;{
Z	register short i;
Z	register char c;
Z	
Z	for(i = 0; (c = *buf) != '\0'; buf++){
Z		if(c == '\b')
Z			i--;
Z		else if(c != '\n')
Z			i++;
Z		}
Z	return(i);
Z}
STUNKYFLUFF
set `sum tpr1.c`
if test 65239 != $1
then
echo tpr1.c: Checksum error. Is: $1, should be: 65239.
fi
#
#
echo Extracting itoeng.c:
sed 's/^Z//' >itoeng.c <<\STUNKYFLUFF
Zstatic char *units[]	= {
Z	"", "one", "two", "three", "four", "five",
Z	"six", "seven", "eight", "nine" };
Z
Zstatic char *tens[]	= {
Z	"", "", "twenty", "thirty", "forty", "fifty",
Z	"sixty", "seventy", "eighty", "ninety" };
Z
Zstatic char *teens[]	= {
Z	"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
Z	"sixteen", "seventeen", "eighteen", "nineteen" };
Z
Zshort itoeng(n,s,e)
Z	register short n;
Z	register char *s,*e;{
Z	char *itoe();
Z	register char *p;
Z
Z	p = s;
Z	e--;
Z	s = itoe(n,s,e);
Z	if(s[-1] == ' ')
Z		s--;
Z	*s++ = '\0';
Z	return((short)(s - p));
Z}
Z
Zchar *itoe(n,s,e)
Z	register short n;
Z	register char *s,*e;{
Z	short flag;
Z	char *copy(),*prword();
Z
Z	flag = 0;
Z	if(n < 0){
Z		s = copy("minus ",s,e);
Z		n = -n;
Z		}
Z	if(n == 0)
Z		return(copy("zero",s,e));
Z	if(n >= 1000){
Z		s = itoe(n / 1000,s,e);
Z		s = copy("thousand ",s,e);
Z		n %= 1000;
Z		flag++;
Z		}
Z	if(n >= 100){
Z		s = prword(units,n / 100,s,e);
Z		s = copy("hundred ",s,e);
Z		n %= 100;
Z		flag++;
Z		}
Z	if(n > 0 && flag)
Z		s = copy("and ",s,e);
Z	if(n >= 20){
Z		s = prword(tens,n / 10,s,e);
Z		n %= 10;
Z		}
Z	else if(10 <= n && n < 20)
Z		return(prword(teens,n - 10,s,e));
Z	return(prword(units,n,s,e));
Z}
Z
Zchar *prword(tab,n,s,e)
Z	char *tab[];
Z	register short n;
Z	register char *s,*e;{
Z	char *copy();
Z
Z	s = copy(tab[n],s,e);
Z	return(copy(" ",s,e));
Z}
Z
Zchar *copy(p,s,e)
Z	register char *p,*s,*e;{
Z
Z	while(*p != '\0' && s != e)
Z		*s++ = *p++;
Z	return(s);
Z}
Z
Z#ifdef	DEBUG
Z#include	<stdio.h>
Z
Zmain(){
Z	char line[128];
Z	short i,n;
Z	short itoeng();
Z
Z	for(;;){
Z		scanf("%d",&n);
Z		i = itoeng(n,line,&line[128]);
Z		printf("itoeng returns %d, %d = %s\n",i,n,line);
Z		}
Z}
Z#endif
STUNKYFLUFF
set `sum itoeng.c`
if test 20714 != $1
then
echo itoeng.c: Checksum error. Is: $1, should be: 20714.
fi
#
#
echo Extracting tpr.1:
sed 's/^Z//' >tpr.1 <<\STUNKYFLUFF
Z.TH TPR 1 4/82
Z.SH NAME
Ztpr \- text processor
Z.SH SYNOPSIS
Z.B tpr
Z[
Z.B options
Z]
Z.B file ...
Z.SH DESCRIPTION
Z.B Tpr
Zformats text according to control lines embedded
Zin the text in the given files or standard input if none
Zis specified.
ZInput consists of intermixed
Z.I text lines,
Zwhich contain information to be formatted, and
Z.I request lines,
Zwhich contain instructions about how to format
Zit.
ZRequest lines begin with a distinguished
Z.I control character,
Znormally a period.
ZOutput lines may be
Z.I filled
Zas nearly as possible with words without regard to
Zinput lineation.
ZLine
Z.I breaks
Zmay be caused at specified places by
Zcertain commands, or by the appearance of an
Zempty input line or an input line beginning with a space.
Z.PP
ZThe capabilities of
Z.B tpr
Zare specified in the attached Request Summary.
ZNumerical values are denoted there by n or +n,
Ztitles by t, and single characters by c.
ZNumbers denoted +n may be signed + or \-,
Zin which case they signify relative changes to
Za quantity, otherwise they signify
Zan absolute resetting.
ZMissing n fields are ordinarily taken to be 1,
Zmissing t fields to be empty, and c fields to shut off
Zthe appropriate special interpretation.
Z.PP
ZRunning titles usually appear at top and bottom of every
Zpage.
ZThey are set by requests like
Z.sp
Z.in +10
Z.if t \&.he \(fmpart1\(fmpart2\(fmpart3\(fm
Z.if n \&.he 'part1'part2'part3'
Z.in -10
Z.sp
ZPart1 is left justified, part2 is centered,
Zand part3 is right justified on the page.
ZAny % sign in a title is replaced by the current
Zpage number.
ZAny nonblank may serve as a quote.
Z.PP
ZThe options currently available are:
Z.TP 10
Z.B d
Zprint directives encountered in input on diagnostic output
Z(debugging only).
Z.TP 10
Z.B efile
Zdivert error messages to \*(lqfile\*(rq.
Z.TP 10
Z.B i[index]
Zopen the index file (see .rf directive), default name is \*(lqindex\*(rq.
Z.TP 10
Z.B nN
Znumber first page N (default 0).
Z.TP 10
Z.B sN
Zstop after every N pages (default 1)
Zand wait for newline from terminal
Ziff output is to terminal device.
ZThere is no initial pause.
Z.PP
ZIn addition, \*(lq-\*(rq in the input file list indicates that
Zstandard input is to be opened and read.
Z.SH DIAGNOSTICS
ZOf course!
Z.SH "SEE ALSO"
Znroff(1), troff(1)
Z.SH AUTHOR
ZMany people have worked on the ancestors of
Z.B tpr,
Zknown by names such as runoff, roff, etc.
ZKen Yap (\ University of Sydney\ ) can only
Zclaim credit for rewriting it in C.
Z.SH BUGS
Z.B Tpr
Zmay produce output too rapidly for people used to
Zslower formatters.
Z.PP
ZAlthough
Z.B tpr
Zis written in C,
Zit will probably be utterly frozen
Zbecause of the archaic convention of
Zcontrol lines and text lines
Zand paucity of structured directives.
Z.bp
Z.tc |
Z.tr |
Z.if t .ta .75i 1.5i 2.25i
Z.if n .ta 11 18 26 33
Z.in 0
Z.na
Z.ce
ZREQUEST SUMMARY
Z.sp
Z.ul
ZRequest	Break	Initial	Meaning
Z.if t .in 2.25i
Z.if n .in 26
Z.ti 0
Z\&.ad	yes	yes	Begin adjusting right margins.
Z.ti 0
Z\&.ar	no	arabic	Arabic page numbers.
Z.ti 0
Z\&.br	yes	-	Causes a line break \- the filling of
Zthe current line is stopped.
Z.ti 0
Z\&.bd|n	no	-	Bold the printable characters in the next n lines.
Z.ti 0
Z\&.bl|n	yes	-	Insert of n blank lines, on new page if necessary.
Z.ti 0
Z\&.bp|+n	yes	n=1	Begin new page and number it n; no n means \*(lq+1\*(rq.
Z.ti 0
Z\&.cc|c	no	c=.	Control character becomes \*(lqc\*(rq.
Z.ti 0
Z\&.ce|n	yes	-	Center the next n input lines,
Zwithout filling.
Z.ti 0
Z\&.de|xx	no	-	Define parameterless macro 
Zto be invoked by request \*(lq.xx\*(rq
Z(definition ends on line beginning \*(lq\fB..\fR\*(rq).
Z.ti 0
Z\&.ef|t	no	t=\*a\*a\*a\*a	Even foot title becomes t.
Z.ti 0
Z\&.eg	no	arabic	English page numbers.
Z.ti 0
Z\&.eh|t	no	t=\*a\*a\*a\*a	Even head title becomes t.
Z.ti 0
Z\&.fi	yes	yes	Begin filling output lines.
Z.ti 0
Z\&.fo|t	no	t=\*a\*a\*a\*a	All foot titles are t.
Z.ti 0
Z\&.he|t	no	t=\*a\*a\*a\*a	All head titles are t.
Z.ti 0
Z\&.in|+n	yes	-	Indent n spaces from left margin.
Z.ti 0
Z\&.ix +n	no	-	Same as \*(lq.in\*(rq but without break.
Z.ti 0
Z\&.li|n	no	-	Literal, treat next n lines as text.
Z.ti 0
Z\&.ll|+n	no	n=65	Line length including indent is n characters.
Z.ti 0
Z\&.ls|+n	yes	n=1	Line spacing set to n lines per output line.
Z.ti 0
Z\&.m1|n	no	n=3	n-1 blank lines put between the top
Zof page and head title.
Z.ti 0
Z\&.m2|n	no	n=1	n blank lines put between head title
Zand beginning of text on page.
Z.ti 0
Z\&.m3|n	no	n=1	n blank lines put between end of
Ztext and foot title.
Z.ti 0
Z\&.m4|n	no	n=3	n-1 blank lines put between the foot title
Zand the bottom of page.
Z.ti 0
Z\&.na	yes	no	Stop adjusting the right margin.
Z.ti 0
Z\&.ne|n	no	-	Begin new page, if n output lines
Zcannot fit on present page.
Z.ti 0
Z\&.nf	yes	no	Stop filling output lines.
Z.ti 0
Z\&.of|t	no	t=\*a\*a\*a\*a	Odd foot title becomes t.
Z.ti 0
Z\&.oh|t	no	t=\*a\*a\*a\*a	Odd head title becomes t.
Z.ti 0
Z\&.pl|+n	no	n=66	Total paper length taken to be n lines.
Z.ti 0
Z\&.po|+n	no	n=0	Page offset.
ZAll lines are preceded by n spaces.
Z.ti 0
Z\&.re|+n	no	-	Restore environment n levels back.
Z.ti 0
Z\&.rf|+n	no	n=1	Save the next n following lines in the index file with page number.
Z.ti 0
Z\&.ro	no	arabic	Roman page numbers.
Z.ti 0
Z\&.rp|n	no	n=1	Output n blank pages at the next page break.
ZPage reservations are cumulative.
Z.ti 0
Z.ne 8
Z\&.se	yes	-	Save environment.
ZThe \*(lqenvironment\*(rq consists of all current settings
Zaffected by the following directives:
Z\&.ad, .ar, .bd, .bl, .cc, .ce, .ef, .eh, .fi, .fo,
Z\&.he, .in, .ix, .li, .ll, .ls, .m1, .m2, .m3,
Z\&.m4, .na, .ne, .nf, .of, .oh, .pl, .po, .ro, .sk,
Z\&.sp, .ta, .tc, .ti, .ub, .ul.
Z.ti 0
Z\&.sk|n	no	-	Produce n blank pages starting next page.
Z.ti 0
Z\&.so|file	no	-	Include file \*(lqfile\*(rq.
Z.ti 0
Z\&.sp|n	yes	-	Insert block of n blank lines,
Zexcept at top of page.
Z.ti 0
Z\&.ta|n|n..		9,17,..	Pseudotab settings.
ZInitial tab settings are columns 9 17 25 ...
Z.ti 0
Z\&.tc|c	no	space	Tab replacement character becomes \*(lqc\*(rq.
Z.ti 0
Z\&.ti|+n	yes	-	Temporarily indent next output
Zline n spaces.
Z.ti 0
Z\&.ub|c	no	' '	Unpaddable blank is \*(lqc\*(rq.
Z.ti 0
Z\&.ul|n	no	-	Underline the letters and numbers
Zin the next n input lines.
STUNKYFLUFF
set `sum tpr.1`
if test 30025 != $1
then
echo tpr.1: Checksum error. Is: $1, should be: 30025.
fi
#
#
echo Extracting Test_Text:
sed 's/^Z//' >Test_Text <<\STUNKYFLUFF
Z.nf
Z.ul
ZL'homme seul
Z.sp
ZAragon
Z.sp 2
ZL'homme seul est un escalier
ZNulle part l'homme qui ne m`ene
ZEt lui demeurent inhumaines
ZToutes les portes des palais
Z.sp 2
ZL'homme seul a les bras obliques
ZL'oeil impair le souffle ray'e
ZIl n'a qu'aileurs pour oreiller
ZSon sommeil est fille publique
Z.sp 2
ZL'homme seul a des doigts de vent
ZCe qu'on lui donne se fait cendre
ZPlaisir m^eme il ne peut rien prendre
ZQue poussi`ere le retrouvant
Z.sp 2
ZL'homme seul n'a pas de visage
ZIl n'est que vitre pour la pluie
ZEt les pleur que l'on voit sur lui
ZAppartiennent au paysage
Z.sp 2
ZIl est une lettre 'egar'ee
ZPortait-il une fausse adresse
ZA qui disait-elle Tendresses
ZQuelles mains l'auraient dechir'e
Z.sp 4
Z.ul
ZThe man alone
Z.sp
ZAragon
Z.sp 2
ZThe man alone: a stair that goes
ZNowhere for anyone. All the gates
ZOf the palaces remain
ZInhuman to his single state.
Z.sp 2
ZThe man alone has crooked limbs,
ZOne eye, a life which does not count;
ZElsewhere is his only pillow;
ZHis sleep a girl of easy virtue.
Z.sp 2
ZThe man alone: fingers of air;
ZWhatever he's given turns to ash;
ZWhen he takes it, even pleasure
ZIs, so he discovers, dust.
Z.sp 2
ZThe man alone: he has no face;
ZLike window glass, he takes the rain;
ZThe tears one sees upon him are
ZWhat the countryside has wept.
Z.sp 2
ZHe's a letter gone astray.
ZDid he carry a wrong address?
ZTo whom did it say 'tenderly'?
ZWhose hands should have torn it open?
STUNKYFLUFF
set `sum Test_Text`
if test 25603 != $1
then
echo Test_Text: Checksum error. Is: $1, should be: 25603.
fi
echo ALL DONE BUNKY!
exit 0
-- 
	Ken Yap

UUCP: (..!{allegra, decvax, seismo}!rochester!ken) ARPA: ken@rochester.arpa
USnail:	Dept. of Comp. Sci., U. of Rochester, NY 14627. Voice: Ken!