/********************************************************/
/*							*/
/*		    ROFF4, Version 1.60			*/
/*							*/
/*(C) 1983,4 by Ernest E. Bergmann			*/
/*		Physics, Building #16			*/
/*		Lehigh Univerisity			*/
/*		Bethlehem, Pa. 18015			*/
/*							*/
/* Permission is hereby granted for all commercial and	*/
/* non-commercial reproduction and distribution of this	*/
/* material provided this notice is included.		*/
/*							*/
/********************************************************/
/*feb 19, 1984*/
/*Jan 14, 1984*/
/********************************************************/
/* March 1984  DeSmet C version */
/* Henry Harpending*/
/* Anthropology Department*/
/* University of New Mexico*/
/* Albuquerque, NM  87131*/
/*   no restrictions */
/*********************************************************/
#include "a:roff4.h"

insert()	/*takes a command line in LINE and adds its
		entry to the table; no space check is made of
		TRTBL*/
{int *pw;
char *pc,*s2,*s3,*fnd;
pw=TREND;
*pw=SLINK;
pc=pw+1;
gettl3(LINE,pc,&s2,&s3);
if(fnd=find2(pc,SLINK))
	{fprintf(stderr,"%cWarning: <%s> was defined to be <%s>\n",BELL,pc,fnd);
	fprintf(stderr,"...now it is defined to be <%s>\n",s2);
	}
SLINK=TREND;
TREND=s3;
}
/****************************************/
showit()	/* displays the list of entries in the string
		substitution table pointed to by HEAD. */
{int *pw;
char *pc;
fprintf(stderr,"ENTRIES:\n");
pw=SLINK;
while(pw)
	{fprintf(stderr,"%u: ",pw);
	pc=pw+1;
	fprintf(stderr,"<%s>",pc);
	pc += strlen(pc); pc++;
	if(*pc) fprintf(stderr," <%s>\n",pc);
	else fprintf(stderr," <>\n"); /*'C' bug*/
	pw=*pw;
	}
dashes();
}
/****************************************/
putback(c)	/*cf K & P, p256*/
char c;
{if(++BINP >= BACKSIZE)
	{printf(stderr,"Too many characters pushed back\n");
	exit();
	}
BACKBUF[BINP]=c;
}
/****************************************/
int ngetc(iobuf)	/*cf K & P p256*/
FILE iobuf;	/*filters \r followed by \n,msb*/
{int kgetc(), c;
if(BINP) c=BACKBUF[BINP];
else	{if(KEYBD){
	 c=kgetc();
      if (c==EOF) return(EOF);
}      
else if (((c=getc(iobuf)) == EOF) ||(c== CPMEOF)){
	BACKBUF[BINP=1]=CPMEOF;
	return EOF;
}
	else c&=0x7f;
	BACKBUF[BINP=1]=c;
	}
if((c!=CPMEOF)&&c!=EOF) BINP--;
if (c==CPMEOF) c=EOF;
if(c=='\r')
	{c=ngetc(iobuf);
	if(c!='\n')
		{putback(c);
		return('\r');
		}
	}
return(c);
}
/****************************************/
kgetc()	/*like getc(),from keyboard, line-buffered*/
{int i;
if(!*KPTR)
	{fprintf(stderr,"%c",KEYBD);
	if((gets(KLINE)) == NULL) return EOF;
	i=strlen(KLINE);
	KLINE[i++]='\n';
	KLINE[i]='\0';
	KPTR=KLINE;
	}
return(*(KPTR++));
}
/****************************************/
pbstr(s)	/*put back string on input;cf K&P,p257*/
char s[LSZ];
{int i;
for(i=strlen(s);i>0;) putback(s[--i]);
}
/****************************************/
minsert()	/*takes a .DM and following lines and places
		the information in the table;  no macro
		definition nesting permitted*/
{char c, *pc,*pc2;
int *pw1;
/*pass over command and following white space*/
for(pc=LINE,c=*pc; (c!=' ')&&(c!='\n')&&(c!='\t'); pc++)
	c=*pc;
for(; (c==' ')||(c=='\t'); pc++) c=*pc;
start();
if(c=='\n') {fprintf(stderr,".DM is UNnamed\n"); }
else	{pw1=TREND;
	*(pw1++)=MLINK;
	MLINK=TREND;
	TREND=pw1;
	while(class(c)==BLACK)
		{*(TREND++)=c;
		c=*(pc++);
		}
	}
*(TREND++)='\0';
while(fgets2(LINE,ifp))	/*until EOF or CPMEOF*/
	{pw1=LINE;
	if((*LINE==COMMAND)&&(comtyp(LINE)==EM)) break;
	else	{transfer(&pw1,&TREND,0);
		*(TREND-1)='\n';
		}
	}
*(TREND++)='\0';
complete();
}
/****************************************/
showm()	/*lists macro definitions*/
{int *pw;
char *pc;
fprintf(stderr,"MACROS DEFINED:\n");
pw=MLINK;
while(pw)
	{pc = pw+1;
	fprintf(stderr,"%u  .%s\n",pw,pc);
	pc +=strlen(pc); pc++;
	fprintf(stderr,"%s\n",pc);
	pw=*pw;
	}
dashes();
}
/****************************************/
char *macq(line)	/*looks up name to see if it is a macro
			definition.  If it is, returns the
			corresponding string, else returns
			FALSE.
			*/
char *line;
{char c,*pc,wb[LSZ],*find2();
pc=wb;
while(class(c=*(++line))==BLACK) *(pc++)=c;
*pc='\0';
return(find2(wb,MLINK));
}
/****************************************/
char *find2(s,link)	/*finds or doesn't find s in table
			of substitutions pointed to by link*/
char *s;
int *link;
{char *pc;
while(link)
	{if(!strcmp(s,link+1))
		{pc=link+1;
		pc += strlen(pc);
		pc++;
		return(pc);
		}
	link=*link;
	}
return(FALSE);
}
in