[net.sources] New NRO file 2 of 3

ron@trsvax.UUCP (09/16/83)

#N:trsvax:66500003:000:26321
trsvax!ron    Sep  9 00:37:00 1983

--------------------------------------------------------------------------------
: Run this shell script with "sh" not "csh"
#! /bin/sh
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting nro.c'
sed 's/^X//' <<'//go.sysin dd *' >nro.c
X/*
X *	Word Processor
X *	similar to Unix NROFF or RSX-11M RNO -
X *	adaptation of text processor given in
X *	"Software Tools", Kernighan and Plauger.
X *
X *	Stephen L. Browning
X *	5723 North Parker Avenue
X *	Indianapolis, Indiana 46220
X *
X *	Modified and enhanced by:
X *		Ron Light
X *		6016 Croftway Ct.
X *		Ft. Worth, Tx. 76131
X */
X
X#include <stdio.h>
X#include "nro.h"
X
X
X
X
Xstruct docctl	dc = 0;
Xstruct page	pg = 0;
XFILE   		*pout = 0;
Xstruct cout	co = 0;
Xstruct macros	mac = 0;
Xstruct file	file[NFILES] = 0;
Xunsigned char	newext[200] = 0;
Xunsigned char	disk = 0;
Xunsigned char	diskx = 0;
Xunsigned char	raw = 0;
Xunsigned char	*divertbuf = 0;
Xunsigned char	*divpnt = 0;
X
X
X
X
Xmain(argc, argv)
Xunsigned int		argc;
Xregister unsigned char	*argv[];
X{
X	register unsigned int	i;
X		 unsigned int	ifp, ofp;
X		 unsigned char	x;
X
X
X	pout = stdout;
X	ifp = ofp = 0;
X	init();
X
X	for (i = 1; i < argc; ++i) 
X	{
X		if (*argv[i] == '-' || *argv[i] == '+') 
X			pswitch(argv[i]);
X	}
X
X	for (i = 1; i < argc; ++i) 
X	{
X		if (*argv[i] != '-' && *argv[i] != '+')
X		{
X			if(diskx)
X			{
X				addext(argv[i], newext, "lis", 1);
X				pout = fopen(newext, "w+");
X				co.lpr =
X				diskx = 0;
X			}
X
X			addext(argv[i], newext, "txt", 0);
X
X			if ((file[0].fle = fopen(newext, "r")) == NULL) 
X				error("unable to open file %s\n", newext);
X			else
X			{
X				strcpy(file[0].fname, newext);
X				file[0].fline = 0;
X				profile();
X				fclose(file[0].fle);
X			}
X		}
X	}
X
X	if (argc == 1) 
X	{
X		fprintf (stderr, "Usage: nro [-n] [+n] [-pxx] [-l] [-d] [-mmacfile] infile ...\n");
X		exit(1);
X	}
X
X	br();
X
X	if (pg.lineno > 0)
X		 space(HUGE);
X
X	fflush(pout);
X	fclose(pout);
X}
X
X
X
X/*
X *	retrieve one line of input text
X */
X
Xgetlin(p, in_buf)
Xregister unsigned char	*p;
Xregister FILE		*in_buf;
X{
X	register unsigned int	i, c;
X	register unsigned char	*q;
X
X	q = p;
X
X	for (i = 0; i < MAXLINE - 1; ++i) 
X	{
X		if((c = ngetc(in_buf)) == EOF)
X		{
X			*q = EOS;
X			c = strlen(p);
X			return (c == 0 ? EOF : c);
X		}
X
X		*q++ = c;
X
X		if (c == '\n')
X			 break;
X	}
X
X	*q = EOS;
X
X	if(*p == '|')
X		return(getlin(p, in_buf));
X	else
X		return (strlen(p));
X}
X
X
X
X
X/*
X *	initialize parameters for nro word processor
X */
X
Xinit()
X{
X	register int	i;
X
X	dc.rmval = PAGEWIDTH - 1;
X	dc.mauto =
X	dc.lsval = 1;
X	pg.m1val =
X	pg.m2val =
X	pg.m3val =
X	pg.m4val = 2;
X	dc.fill =
X	dc.juval = YES;
X	dc.pgchr = '#';
X	dc.ichr =
X	dc.cmdchr = '.';
X	dc.prflg = TRUE;
X	pg.newpag = 1;
X	pg.plval = PAGELEN;
X	setbot();
X	pg.lastpg = 30000;
X	pg.ehead = malloc(MAXLINE);
X	pg.ohead = malloc(MAXLINE);
X	pg.efoot = malloc(MAXLINE);
X	pg.ofoot = malloc(MAXLINE);
X	pg.thead = malloc(MAXLINE);
X	strcpy(pg.ehead, "\n");
X	strcpy(pg.ohead, "\n");
X	strcpy(pg.efoot, "\n");
X	strcpy(pg.ofoot, "\n");
X	pg.ehlim[RIGHT] =
X	pg.ohlim[RIGHT] =
X	pg.eflim[RIGHT] =
X	pg.oflim[RIGHT] =
X	dc.tmval = dc.rmval;
X	co.lpr = FALSE;
X	mac.pbb = malloc(PUSHBUF);
X	mac.mb = malloc(MACBUF);
X	mac.emb = mac.mb;
X}
X
X
X
X/*
X *	get character from input file or push back buffer
X */
X
Xngetc(infp)
Xregister FILE	*infp;
X{
X	register int	c;
X
X
X	if (mac.ppb >= mac.pbb) 
X		c = *mac.ppb--;
X	else if((c = getc(infp)) == '\n')
X		++file[dc.flevel].fline;
X
X	return (c);
X}
X
X
X
X/*
X *	process input files from command line
X */
X
Xprofile()
X{
X	unsigned char	ibuf[MAXLINE];
X
X	for (dc.flevel = 0; dc.flevel >= 0; --dc.flevel) 
X	{
X		while (getlin(ibuf, file[dc.flevel].fle) != EOF) 
X		{
X			if (ibuf[0] == dc.cmdchr)
X				comand(ibuf);
X			else
X				text(ibuf);
X		}
X
X		if (dc.flevel > 0)
X			 fclose(file[dc.flevel].fle);
X	}
X}
X
X
X
X/*
X *	process switch values from command line
X */
X
Xpswitch(p)
Xregister unsigned char	*p;
X{
X	unsigned int	swgood = TRUE;
X	unsigned char	tempbuf[150];
X
X
X	if (*p == '-') 
X	{
X		++p;
X
X		switch (tolower(*p)) 
X		{
X		case 'r':
X			raw = TRUE;
X			break;
X
X		case 'm':
X			addext(++p, newext, "nro", 0);
X
X			if ((file[0].fle = fopen(newext, "r")) == NULL) 
X			{
X				sprintf(tempbuf, "/usr/lib/tmac/tmac.%s", newext);
X				strcpy(newext, tempbuf);
X
X				if((file[0].fle = fopen(tempbuf, "r")) == NULL)
X					error("unable to open macro file %s\n", newext);
X			}
X
X			strcpy(file[0].fname, newext);
X			file[0].fline = 0;
X			profile();
X			fclose(file[0].fle);
X			break;
X
X		case 'p':
X			set(&pg.offset, ctod(++p), '1', 0, 0, HUGE);
X			pg.tofset = pg.offset;
X			break;
X
X		case 'l':
X			co.lpr = TRUE;
X			break;
X
X		case 'd':
X			diskx =
X			disk = TRUE;
X			break;
X
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X			pg.lastpg = ctod(p);
X			break;
X
X		default:
X			swgood = FALSE;
X			break;
X		}
X	}
X	else if (*p == '+') 
X		pg.frstpg = ctod(++p);
X	else
X		fprintf (stderr, "illegal switch %s\n", p);
X
X	return(OK);
X}
X
X
X
Xerror(f, a)
Xchar	*f, *a;
X{
X	trouble("FATAL ERROR ");
X	fprintf(stderr, f, a);
X	exit(1);
X}
X
X
X
Xtrouble(f, a)
Xregister unsigned char	*f, *a;
X{
X	fprintf(stderr, "nro: [%d %s] ", file[dc.flevel].fline, file[dc.flevel].fname);
X	fprintf(stderr, f, a);
X}
X
X
Xtolower(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = byte & 0x7f;
X
X	if(x >= 'A' && x <= 'Z')
X		return(byte + ' ');
X	else
X		return(byte);
X}
X
X
X
Xisdigit(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = byte & 0x7f;
X
X	if(x >= '0' && x <= '9')
X		return(1);
X	else
X		return(0);
X}
X
X
X
Xisalpha(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = tolower(byte) & 0x7f;
X
X	if(x >= 'a' && x <= 'z')
X		return(1);
X	else
X		return(0);
X}
X
X
X
X
Xiswhite(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = byte & 0x7f;
X
X	if(x == ' ' || x == '\t')
X		return(1);
X	else
X		return(0);
X}
X
X
Xislower(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = byte & 0x7f;
X
X	if(x >= 'a' && x <= 'z')
X		return(1);
X	else
X		return(0);
X}
X
X
Xisspace(byte)
Xregister unsigned char	byte;
X{
X	register unsigned char	x;
X
X	x = byte & 0x7f;
X
X	if(x == ' ')
X		return(1);
X	else
X		return(0);
X}
X
X
X
Xisterm(byte)
Xregister unsigned char	byte;
X{
X	if(byte == EOS)
X		return(1);
X
X	return(iscr(byte));
X}
X
X
Xiscr(byte)
Xregister unsigned char	byte;
X{
X	if(byte == '\n')
X		return(1);
X	else
X		return(0);
X}
X
X
X
X
X/*	"addext" - add an extension to a file spec/name.  If the	*/
X/*		   filespec already has an extension, then the		*/
X/*		   condition of 'flag' determines if a new extension	*/
X/*		   will be forced.  On entry:				*/
X/*			from	points to filespec/name			*/
X/*			to	points to where you want the new one	*/
X/*			ext	points to the extension to add		*/
X/*			flag	1 = force new extension			*/
X/*				0 = add extension ONLY if one is needed	*/
X/*									*/
X
X
Xaddext(from, to, ext, flag)
Xregister unsigned char	*to, *from;
Xunsigned char	*ext;
Xunsigned char	flag;
X{
X	register	unsigned char	*pnt;
X			unsigned char	name[100];
X			unsigned char	extension[5];
X			unsigned char	c;
X
X
X	name[0] = 0;
X	extension[0] = 0;
X
X
X	pnt = move(from, name);
X	c = *pnt++;
X
X	if(c == '.')
X	{
X		pnt = move(pnt, extension);
X		c = *pnt++;
X	}
X
X	if(c != 0)
X		return(1);
X
X
X	strcpy(to, name);
X	strcat(to, ".");
X
X	if(flag || (extension[0] == 0))
X		strcat(to, ext);
X	else
X		strcat(to, extension);
X}
X
X
X
X
Xstatic move(from, to)
Xregister unsigned char	*from, *to;
X{
X	while(*from)
X	{
X		if(*from == '.')
X			break;
X
X		*to++ = *from++;
X	}
X
X	*to = 0;
X	return(from);
X}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 664 nro.c
	/bin/echo -n '	'; /bin/ls -ld nro.c
fi
/bin/echo 'Extracting nrocmd.c'
sed 's/^X//' <<'//go.sysin dd *' >nrocmd.c
X/*
X *	Command processor for NRO text processor
X *
X *	Stephen L. Browning
X *	5723 North Parker Avenue
X *	Indianapolis, Indiana 46220
X *
X *	Modified and enhanced by:
X *		Ron Light
X *		6016 Croftway Ct.
X *		Ft. Worth, Tx. 76131
X */
X
X#include <stdio.h>
X#include "nro.h"
X
X
Xextern	struct docctl	dc;
Xextern	struct page	pg;
Xextern	FILE   		*pout;
Xextern	struct cout	co;
Xextern	struct macros	mac;
Xextern	struct file	file[];
Xextern	unsigned char	newext[];
Xextern	unsigned char	*divertbuf;
Xextern	unsigned char	*divpnt;
Xextern	unsigned char	inbuf[];
X
X
X/*	for diversion routines	*/
Xint	xoutp = 0;
Xint	xoutw = 0;
Xint	xoutwds = 0;
Xint	tline = 0;
Xchar	xoutbuf[MAXLINE] = 0;
X
X
Xcomand(p)
Xunsigned char	*p;
X{
X	unsigned int	ct, val;
X	unsigned int	spval;
X	unsigned int	index;
X	unsigned char	argtyp;
X	unsigned char	*x;
X	unsigned char	name[MAXLINE];
X	unsigned char	macexp[MXMLEN];
X
X	ct = comtyp(p, macexp);
X
X	if (ct == UNKNOWN) 
X	{
X		trouble("unrecognized command %s\n", p);
X		return;
X	}
X
X	expesc(p, name);
X	val = getval(p, &argtyp);
X
X	switch (ct) 
X	{
X	case CB: /* continuous bold */
X		dc.cbold = TRUE;	/* NO break */
X
X	case BO: /* bold face */
X		set(&dc.boval, val, argtyp, 1, 0, HUGE);
X		dc.cuval = dc.ulval = 0;
X		break;
X
X	case BP: /* begin page */
X		if (pg.lineno > 0)
X			 space(HUGE);
X
X		set(&pg.curpag, val, argtyp, pg.curpag + 1, -HUGE, HUGE);
X		pg.newpag = pg.curpag;
X		pg.lineno = 0;
X		break;
X
X	case BR: /* break */
X		br();
X		break;
X
X	case CC: /* command character */
X		if (argtyp == '\n')
X			dc.cmdchr = '.';
X		else
X			dc.cmdchr = argtyp;
X
X		break;
X
X	case CE: /* center */
X		br();
X		set(&dc.ceval, val, argtyp, 1, 0, HUGE);
X		break;
X
X	case CU: /* continuous underline */
X		set(&dc.cuval, val, argtyp, 1, 0, HUGE);
X		dc.ulval = dc.boval = 0;
X		break;
X
X	case DE: /* define macro */
X		defmac(p, file[dc.flevel].fle);
X		break;
X
X	case EF: /* even footer */
X		gettl(p, pg.efoot, &pg.eflim[0]);
X		break;
X
X	case EH: /* even header */
X		gettl(p, pg.ehead, &pg.ehlim[0]);
X		break;
X
X	case EN: /* end macro definition */
X		trouble("missing .de command\n");
X		break;
X
X	case FI: /* fill */
X		br();
X		dc.fill = YES;
X		break;
X
X	case FO: /* footer */
X		gettl(p, pg.efoot, &pg.eflim[0]);
X		gettl(p, pg.ofoot, &pg.oflim[0]);
X		break;
X
X	case HE: /* header */
X		gettl(p, pg.ehead, &pg.ehlim[0]);
X		gettl(p, pg.ohead, &pg.ohlim[0]);
X		break;
X
X	case IN: /* indenting */
X		set(&dc.inval, val, argtyp, 0, 0, dc.rmval - 1);
X		dc.tival = dc.inval;
X		break;
X
X	case JU: /* justify */
X		dc.juval = YES;
X		break;
X
X	case LS: /* line spacing */
X		set(&dc.lsval, val, argtyp, 1, 1, HUGE);
X		break;
X
X	case M1: /* set topmost margin */
X		set(&pg.m1val, val, argtyp, 2, 0, HUGE);
X		setbot();
X		break;
X
X	case M2: /* set second top margin */
X		set(&pg.m2val, val, argtyp, 2, 0, HUGE);
X		setbot();
X		break;
X
X	case M3: /* set first bottom margin */
X		set(&pg.m3val, val, argtyp, 2, 0, HUGE);
X		setbot();
X		break;
X
X	case M4: /* set bottom-most margin */
X		set(&pg.m4val, val, argtyp, 2, 0, HUGE);
X		setbot();
X		break;
X
X	case MACRO: /* macro expansion */
X		maceval(p, macexp);
X		break;
X
X	case NE: /* need n lines */
X		br();
X
X		if (pg.bottom - pg.lineno + 1 < val * dc.lsval) 
X			space(HUGE);
X
X		break;
X
X	case NF: /* no fill */
X		br();
X		dc.fill = NO;
X		break;
X
X	case NJ: /* no justify */
X		dc.juval = NO;
X		break;
X
X	case NR: /* set number register */
X		p = skipbl(skipwd(p));
X
X		if (!isalpha(*p)) 
X			trouble("invalid or missing number register name\n");
X		else
X		{
X			index = tolower(*p) - 'a';
X			p = skipwd(p);
X			val = getval(p, &argtyp);
X			set(&dc.nr[index], val, argtyp, 0, -HUGE, HUGE);
X		}
X
X		break;
X
X	case OF: /* odd footer */
X		gettl(p, pg.ofoot, &pg.oflim[0]);
X		break;
X
X	case OH: /* odd header */
X		gettl(p, pg.ohead, &pg.ohlim[0]);
X		break;
X
X	case PC: /* page number character */
X		if (argtyp == '\n')
X			dc.pgchr = EOS;
X		else
X			dc.pgchr = argtyp;
X
X		break;
X
X	case PL: /* page length */
X		set(&pg.plval, val, argtyp, PAGELEN, 
X		pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1, HUGE);
X		setbot();
X		break;
X
X	case PO: /* page offset */
X		set(&pg.offset, val, argtyp, 0, 0, HUGE);
X		pg.tofset = pg.offset;
X		break;
X
X	case EP: /* even page offset */
X		set(&pg.eofset, val, argtyp, 0, 0, HUGE);
X		break;
X
X	case OP: /* odd page offset */
X		set(&pg.oofset, val, argtyp, 0 , 0, HUGE);
X		break;
X
X	case RM: /* right margin */
X		set(&dc.rmval, val, argtyp, PAGEWIDTH, dc.tival + 1, HUGE);
X		dc.tmval = dc.rmval;
X		break;
X
X	case SO: /* source file */
X		p = skipbl(skipwd(p));
X
X		if (getwrd(p, name) == 0)
X			 break;
X
X		if (dc.flevel + 1 >= NFILES) 
X			error(".so commands nested too deeply\n");
X
X		addext(name, newext, "txt", 0);
X
X		if ((file[dc.flevel + 1].fle = fopen(newext, "r")) == NULL) 
X		{
X			trouble("unable to open %s\n", name);
X			break;
X		}
X
X		++dc.flevel;
X		strcpy(file[dc.flevel].fname, newext);
X		file[dc.flevel].fline = 0;
X		break;
X
X	case SP: /* space */
X		set(&spval, val, argtyp, 1, 0, HUGE);
X		space(spval);
X		break;
X
X	case TI: /* temporary indent */
X		br();
X		set(&dc.tival, val, argtyp, 0, 0, dc.rmval);
X		break;
X
X	case UL: /* underline */
X		set(&dc.ulval, val, argtyp, 0, 1, HUGE);
X		dc.cuval = dc.boval = 0;
X		break;
X
X	case TL: /* temp title */
X		br();
X		gettl(p, pg.thead, &pg.tlim[0]);
X		title(pg.thead, pg.tlim, pg.curpag);
X		break;
X
X	case PI: /* put inside of indention field */
X		br();
X		putin(p);
X		break;
X
X	case AR: /* set (normal) aribic numbers */
X		dc.roman =
X		dc.rlower = FALSE;
X		break;
X
X	case CR: /* set capital roman numerials */
X		dc.roman = TRUE;
X		dc.rlower = FALSE;
X		break;
X
X	case LR: /* set lower case roman numerials */
X		dc.roman =
X		dc.rlower = TRUE;
X		break;
X
X	case DA: /* add current date to text */
X		getdate(1);
X		break;
X
X	case PN: /* new page number */
X		set(&pg.curpag, val, argtyp, 0, -HUGE, HUGE);
X
Xbp:
X		if(pg.lineno)
X			pg.newpag = pg.curpag+1;
X		else
X			pg.newpag = pg.curpag;
X
X		break;
X
X	case AI: /* auto increment for registers */
X		set(&dc.rauto, val, argtyp, 1, -HUGE, HUGE);
X		break;
X
X	case DV: /* set divert buffer on */
X		if(!divertbuf)
X		{
X			divertbuf = malloc(2000);
X			divpnt = divertbuf;
X		}
X
X		save();
X		dc.divert = TRUE;
X		break;
X
X	case ED: /* end divert */
X		if(dc.divert)
X		{
X			br();
X			dc.divert = FALSE;
X			*divpnt = EOS;
X
X			if (pg.bottom - pg.lineno < dc.divlin)
X			{
X				dc.divsav = dc.divlin;
X				dc.divlin = 0;
X			}
X
X			restore();
X			setbot();
X		}
X
X		break;
X
X	case RV: /* recall diverted text */
X		br();
X
X		if(dc.divsav && !dc.divlin)
X			dc.divlin = dc.divsav;
X
X		dumpdivert();
X		break;
X
X	case LI: /* output in literal mode */
X		br();
X		set(&dc.literal, val, argtyp, 1, -HUGE, HUGE);
X		break;
X
X	case AX: /* set auto index mode */
X		dc.aindex = TRUE;
X		val = AUTO;
X		goto mindex;
X
X	case IX: /* set manual index mode */
X		val = MANUAL;
Xmindex:
X		p = skipbl((x = skipwd(p)));
X
X		if(isspace(*x))
X			++x;
X
X		if(!isterm(*p))
X		{
X			dc.indexx = TRUE;
X			addsym(p, val, 1);
X			text(dc.literal ? x : p);
X		}
X
X		break;
X
X	case EX: /* add word to index, but don't output as text */
X		p = skipbl(skipwd(p));
X
X		if(!isterm(*p))
X		{
X			dc.aindex =
X			dc.indexx = TRUE;
X			addsym(p, AUTO, 0);
X		}
X
X		break;
X
X	case SX: /* set index fill character */
X		p = skipbl(skipwd(p));
X
X		if(*p == '\'')
X			dc.ichr = *++p;
X
X		break;
X
X	case PX: /* print index page */
X		pindex();
X		break;
X
X	case AU: /* set manual increment value */
X		set(&dc.mauto, val, argtyp, 0, -HUGE, HUGE);
X		break;
X
X	case ST: /* stop processor */
X		br();
X		fprintf(stderr, "...[stoped]... ");
X		fflush(stderr);
X
X		val = getc(stdin);
X
X		if(tolower(val) == 's')
X			exit(1);
X	}
X}
X
X
X
X/*
X *	convert ascii character to decimal.
X */
X
Xatod(c)
Xunsigned char	c;
X{
X	return (((c < '0') || (c > '9')) ? -1 : c-'0');
X}
X
X
X
X/*
X *	end current filled line
X */
X
Xbr()
X{
X	if (co.outp) 
X	{
X		co.outbuf[co.outp] = '\n';
X		co.outbuf[co.outp + 1] = EOS;
X		put(co.outbuf);
X	}
X	else if(inbuf[0])
X	{
X		both();
X		prchar('\n');
X	}
X
X	reset();
X	co.outp =
X	co.outw =
X	co.outwds = 0;
X}
X
X
X
X/*
X *	Save text in buffer so we can divert
X */
X
X
Xsave()
X{
X	if (co.outp) 
X	{
X		co.outbuf[co.outp] = EOS;
X		strcpy(xoutbuf, co.outbuf);
X		xoutp = co.outp;
X		xoutw = co.outw;
X		xoutwds = co.outwds;
X	}
X
X	co.outp =
X	co.outw =
X	co.outwds =
X	co.outbuf[0] = 0;
X	tline = pg.lineno;
X	pg.lineno = 7;
X}
X
X
X
X
X/*
X *	restore the text we saved from diversion
X */
X
Xrestore()
X{
X	if (xoutp) 
X	{
X		strcpy(co.outbuf, xoutbuf);
X		co.outp = xoutp;
X		co.outw = xoutw;
X		co.outwds = xoutwds;
X	}
X
X	xoutp =
X	xoutw =
X	xoutwds = 0;
X	pg.lineno = tline;
X}
X
X
X
X
X/*
X *	Collect macro definition from input stream
X */
X
Xcolmac(p, d, i)
Xregister unsigned char	*p, d[];
Xregister	  int	i;
X{
X	while (*p != EOS) 
X	{
X		if (i >= MXMLEN - 1) 
X		{
X			d[i - 1] = EOS;
X			return (ERR);
X		}
X
X		d[i++] = *p++;
X	}
X
X	d[i] = EOS;
X	return(i);
X}
X
X
X
X
X/*
X *	decodes nro command and returns its associated
X *	value.
X */
X
X
Xstruct comm	comtab[] = 
X{
X	".",	EN, 
X	"ai",	AI,
X	"ar",	AR,
X	"au",	AU,
X	"ax",	AX,
X	"bo",	BO, 
X	"bp",	BP, 
X	"br",	BR, 
X	"cb",	CB,
X	"cc",	CC, 
X	"ce",	CE, 
X	"cr",	CR,
X	"cu",	CU, 
X	"da",	DA,
X	"de",	DE, 
X	"dv",	DV,
X	"ed",	ED,
X	"ef",	EF, 
X	"eh",	EH, 
X	"en",	EN, 
X	"ep",	EP,
X	"ex",	EX,
X	"fi",	FI, 
X	"fo",	FO, 
X	"he",	HE, 
X	"in",	IN, 
X	"ix",	IX,
X	"ju",	JU, 
X	"li",	LI,
X	"lr",	LR,
X	"ls",	LS, 
X	"m1",	M1, 
X	"m2",	M2, 
X	"m3",	M3, 
X	"m4",	M4, 
X	"ne",	NE, 
X	"nf",	NF, 
X	"nj",	NJ, 
X	"nr",	NR, 
X	"of",	OF, 
X	"oh",	OH, 
X	"op",	OP,
X	"pc",	PC, 
X	"pi",	PI, 
X	"pl",	PL, 
X	"pn",	PN,
X	"po",	PO,
X	"px",	PX,
X	"rm",	RM, 
X	"rv",	RV,
X	"so",	SO, 
X	"sp",	SP, 
X	"st",	ST,
X	"sx",	SX,
X	"ti",	TI, 
X	"tl",	TL, 
X	"ul",	UL, 
X	0,	0
X};
X
X
X
Xcomtyp(p, m)
Xregister unsigned char	*p, *m;
X{
X		 unsigned char	macnam[MNLEN];
X	register unsigned char	*s;
X
X	p++;
X
X	/*
X	 *	 First check to see if the command is a macro.
X	 *	 If it is, truncate to two characters and return
X	 *	 expansion in m.  Note that upper and lower case
X	 *	 characters are handled differently for macro names, 
X	 *	 but not for normal command names.
X	 */
X	gettok(p, macnam);
X	macnam[2] = EOS;
X
X	if ((s = getmac(macnam)) != NULL) 
X	{
X		strcpy(m, s);
X		return (MACRO);
X	}
X
X	return(findcomm(p));
X}
X
X
Xfindcomm(p)
Xregister unsigned char	*p;
X{
X		 unsigned char	xbuff[4];
X	register unsigned int	i;
X
X	xbuff[0] = tolower(*p);
X	p++;
X
X	if(*p > ' ')
X	{
X		xbuff[1] = tolower(*p);
X		xbuff[2] = 0;
X	}
X	else
X		xbuff[1] = 0;
X
X	for(i = 0; ; i++)
X	{
X		if(!(comtab[i].c1))
X			return(UNKNOWN);
X
X		if(strcmp(comtab[i].c1, xbuff))
X			continue;
X
X		return(comtab[i].c2);
X	}
X}
X
X
X
X/*
X *	convert string to decimal.
X *	processes only positive values.
X */
X
Xctod(p)
Xregister unsigned char	*p;
X{
X	register unsigned int	val, d;
X
X
X	val = 0;
X
X	while(*p != EOS) 
X	{
X		d = atod(*p++);
X
X		if (d == -1)
X			 return (val);
X
X		val = 10 * val + d;
X	}
X
X	return (val);
X}
X
X
X/*
X *	Define a macro
X */
X
Xdefmac(p, infp)
Xregister unsigned char	*p;
Xregister FILE *infp;
X{
X	register unsigned int	i;
X	register unsigned char	*q;
X		 unsigned char	name[MNLEN];
X		 unsigned char	defn[MXMLEN];
X
X	q = skipbl(skipwd(p));
X	i = getwrd(q, name);
X
X	if (!isalpha(*name)) 
X		error("missing or illegal macro definition name\n");
X
X	if (i > 2)
X		 name[2] = EOS;
X
X	i = 0;
X
X	while (getlin(p, infp) != EOF) 
X	{
X		if(*p == '|')
X			continue;
X
X		if((*p == '.') && (findcomm(p+1) == EN))
X			break;
X
X		if ((i = colmac(p, defn, i)) == ERR) 
X			error("macro definition too long\n");
X	}
X
X	if (putmac(name, defn) == ERR) 
X		error("macro definition table full\n");
X}
X
X
X/*
X *	Expand escape sequences
X */
X
Xexpesc(p, q)
Xregister unsigned char	*p, *q;
X{
X	register unsigned char	*s, *t, *r;
X	register unsigned char	byte;
X		 unsigned char	buff[30];
X
X
X	s = p;
X	t = q;
X
X	while (*s != EOS) 
X	{
X		/* look for "don't touch" characters */
X		if (*s == '\\') 
X		{
X			++s;
X			byte = *s++;
X			byte |= (unsigned) 0x80;
X			*t = byte;
X			++t;
X		}
X		/* look for date substitution */
X		else if(*s == '^')
X		{
X			++s;
X			strcpy(buff, getdate(0));
X			r = buff;
X
X			while(*r)
X				*t++ = *r++;
X		}
X		/* look for quoted strings and don't touch */
X		else if(*s == '"')
X		{
X			*t++ = *s++;	/* store the 1st one */
X
X			while(*s && *s != '"')
X				*t++ = *s++;
X
X			if(*s)
X				*t++ = *s++;	/* store the 2nd one */
X		}
X		/* look for number register */
X		else if (*s == '@') 
X		{
X			if (s[1] == '@') 
X			{
X				*t++ = *s++;
X				++s;
X			}
X			else if (tolower(s[1]) == 'n')
X			{
X				if(s[2] == '+' && isalpha(s[3]))
X				{
X					s += 3;
X					byte = tolower(*s) - 'a';
X					dc.nr[byte] += dc.mauto;
X					goto figure;
X				}
X				else if(isalpha(s[2])) 
X				{
X					s += 2;
X					byte = tolower(*s) - 'a';
X
X					if(dc.rauto)
X						dc.nr[byte] += dc.rauto;
X
Xfigure:
X					t += itoda(dc.nr[byte], t, 6) - 1;
X					++s;
X				}
X			}
X		}
X		else
X			*t++ = *s++;
X	}
X
X	*t = EOS;
X	strcpy(p, q);
X}
X
X
X
X/*
X *	Get macro definition from table
X */
X
Xgetmac(name)
Xregister unsigned char	*name;
X{
X	register	  int	i, j;
X
X	if(!strcmp(".", name))
X		return(NULL);
X
X	for (i = mac.lastp; i >= 0; --i) 
X		if (!strcmp(name, mac.mnames[i])) 
X			return (mac.mnames[i] + 3);
X
X	return(NULL);
X}
X
X
X
X
X/*
X *	get header or footer title
X */
X
Xgettl(p, q, limit)
Xregister unsigned char	*p, *q;
Xregister unsigned int	limit[];
X{
X	p = skipbl(skipwd(p));
X	strcpy(q, p);
X	limit[LEFT] = dc.inval;
X	limit[RIGHT] = dc.rmval;
X}
X
X
X
X
X/*
X *	retrieves optional argument following nro command.
X *	returns positive integer value with sign (if any)
X *	saved in character addressed by p_argt.
X */
X
Xgetval(p, p_argt)
Xregister unsigned char	*p;
Xregister unsigned char	*p_argt;
X{
X	p = skipbl(skipwd(p));
X	*p_argt = *p;
X
X	if ((*p == '+') || (*p == '-'))
X		++p;
X
X	return (ctod(p));
X}
X
X
X/*
X *	Evaluate macro expansion
X */
X
Xmaceval(p, m)
Xregister unsigned char	*p;
Xregister unsigned char	m[];
X{
X	register unsigned int	j;
X	register	  int	i;
X	register unsigned char	hold[200];
X	register unsigned char	*xx;
X		 unsigned char	*argp[10];
X		 unsigned char	c;
X
X
X	*p++ = EOS;		/* replace command char with EOS */
X
X	/*
X	 *	 initialize argp array to substitute command
X	 *	 string for any undefined argument
X	 */
X	for (i = 0; i < 10; ++i)
X		argp[i] = EOS;		/* was "p" */
X
X	p = skiptok(p);
X	xx = skipbl(p);
X
X	if(*xx == '.')
X		sprintf(hold, "\\%s", xx);
X	else
X		sprintf(hold, "%s", xx);
X
X	xx = &hold[strlen(hold) -2];
X
X	while(*xx)
X		if(iscr(*xx))
X			break;
X		else
X			++xx;
X
X	*xx = ' ';
X	*xx = EOS;
X	*p++ = EOS;
X
X	for (i = 0; i < 10; ++i) 
X	{
X		p = skipbl(p);
X
X		if (isterm(*p))
X			 break;
X
X		if (*p == '\'' || *p == '"') 
X		{
X			c = *p++;
X			argp[i] = p;
X
X			while (*p != c && !isterm(*p))
X				++p;
X
X			*p++ = EOS;
X		}
X		else
X		{
X			argp[i] = p;
X			p = skipwd(p);
X			*p++ = EOS;
X		}
X	}
X
X	for (i = strlen(m) - 1; i >= 0; --i) 
X	{
X		if (i > 0 && m[i - 1] == '$') 
X		{
X			if(m[i] == '$')
X			{
X				pbstr(hold);
X				--i;
X			}
X			else if (!isdigit(m[i])) 
X				putbak(m[i]);
X			else
X			{
X				pbstr(argp[m[i]-'0']);
X				--i;
X			}
X		}
X		else
X			putbak(m[i]);
X	}
X}
X
X
X/*
X *	Push back string into input stream
X */
X
Xpbstr(p)
Xregister unsigned char	p[];
X{
X	register int	i;
X
X	for (i = strlen(p) - 1; i >= 0; --i) 
X		putbak(p[i]);
X}
X
X
X
X/*
X *	Push character back into input stream
X */
X
Xputbak(c)
Xunsigned char	c;
X{
X	if (mac.ppb < mac.pbb) 
X	{
X		mac.ppb = mac.pbb;
X		*mac.ppb = c;
X	}
X	else
X	{
X		if (mac.ppb >= (mac.pbb+PUSHBUF) - 1) 
X			error("push back buffer overflow\n");
X
X		*++mac.ppb = c;
X	}
X}
X
X
X
X
X/*
X *	Put macro definition into table
X */
X
Xputmac(name, p)
Xregister unsigned char	*name, *p;
X{
X	if (mac.lastp >= MXMDEF)
X		 return (ERR);
X
X	if (mac.emb + strlen(name) + strlen(p) + 1 > mac.mb+MACBUF) 
X		return(ERR);
X
X	++mac.lastp;
X	mac.mnames[mac.lastp] = mac.emb;
X	strcpy(mac.emb, name);
X	strcpy(mac.emb + 3, p);
X	mac.emb += 3 + strlen(p) + 2;
X	return (OK);
X}
X
X
X
X
X/*
X *	set parameter and check range
X */
X
Xset(param, val, type, defval, minval, maxval)
Xregister unsigned int	*param;
Xregister unsigned int	val, defval, minval, maxval;
Xregister unsigned char	type;
X{
X	switch (type) 
X	{
X	case '\n':
X		*param = defval;
X		break;
X
X	case '+':
X		*param += val;
X		break;
X
X	case '-':
X		*param -= val;
X		break;
X
X	default:
X		*param = val;
X		break;
X	}
X
X	*param = min(*param, maxval);
X	*param = max(*param, minval);
X}
X
X
X
X/*
X *	skip blanks and tabs in character buffer.
X *	return number of characters skipped.
X */
X
Xskipbl(p)
Xregister unsigned char	*p;
X{
X	while (iswhite(*p))
X		++p;
X
X	return (p);
X}
X
X
X/*
X *	skip over word and punctuation
X */
X
Xskipwd(p)
Xregister unsigned char	*p;
X{
X	while (!iswhite(*p) && !isterm(*p))
X		++p;
X
X	return (p);
X}
X
X
X
X/*
X *	skip over token
X */
X
Xskiptok(p)
Xregister unsigned char	*p;
X{
X	register	int	i;
X
X	for(i = 0; i < 2; i++)
X		if(iswhite(*p))
X			break;
X		else
X			++p;
X
X	return(p);
X}
X
X
X
X/*
X *	get next token
X */
X
Xgettok(from, to)
Xregister unsigned char	*from, *to;
X{
X	register	int	i;
X
X	for(i = 0; i < 2; i++)
X		if(iswhite(*from))
X			break;
X		else
X			*to++ = *from++;
X
X	*to = EOS;
X	return(i);
X}
X
X
X
X/*
X *	space vertically n lines
X */
X
Xspace(n)
Xregister unsigned int	n;
X{
X	register unsigned int	i;
X
X
X	br();
X	setbot();
X
X	if (pg.lineno > pg.bottom)
X	{
X		if(!(pg.m1val+pg.m2val+pg.m3val+pg.m4val))
X			skip(n * dc.lsval);
X
X		 return;
X	}
X
X	if (pg.lineno == 0)
X		 phead();
X
X	skip(min(n, pg.bottom + 1 - pg.lineno));
X	chkbot();
X}
X
X
X
Xsetbot()
X{
X	if(!dc.divert)
X		pg.bottom = pg.plval - (pg.m4val + pg.m3val + dc.divlin + 1);
X}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 664 nrocmd.c
	/bin/echo -n '	'; /bin/ls -ld nrocmd.c
fi
--