h28994
s 00494/00000/00000
d D 1.1 82/08/02 15:26:26 cecily 1 0
e
u
U
t
T
I 1
char *xxxvers = "\nDeroff Version 1.02    24 July 1978\n";


#include <stdio.h>

/* Deroff command -- strip troff, eqn, and Tbl sequences from
a file.  Has one flag argument, -w, to cause output one word per line
rather than in the original format.
Deroff follows .so and .nx commands, removes contents of macro
definitions, equations (both .EQ ... .EN and $...$),
Tbl command sequences, and Troff backslash constructions.

All input is through the C macro; the most recently read character is in c.
*/

#define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
#define C1 ( (c=getc(infile)) == EOF ? eof() :  c)
#define SKIP while(C != '\n') 

#define YES 1
#define NO 0

#define NOCHAR -2
#define SPECIAL 0
#define APOS 1
#define DIGIT 2
#define LETTER 3

int wordflag = NO;
int inmacro = NO;
int intable = NO;

char chars[128];  /* SPECIAL, APOS, DIGIT, or LETTER */

char line[512];
char *lp;

int c;
int ldelim	= NOCHAR;
int rdelim	= NOCHAR;


int argc;
char **argv;

char fname[50];
FILE *files[15];
FILE **filesp;
FILE *infile;

char *calloc();



main(ac, av)
int ac;
char **av;
{
register int i;
register char *p;
static char onechar[2] = "X";
FILE *opn();

argc = ac - 1;
argv = av + 1;

while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') 
	{
	for(p=argv[0]+1; *p; ++p) switch(*p)
		{
		case 'w':
			wordflag = YES;
			break;
		default:
			onechar[0] = *p;
			fatal("Invalid flag %s\n", onechar);
		}
	--argc;
	++argv;
	}

if(argc == 0)
	infile = stdin;
else	{
	infile = opn(argv[0]);
	--argc;
	++argv;
	}

files[0] = infile;
filesp = &files[0];

for(i='a'; i<='z' ; ++i)
	chars[i] = LETTER;
for(i='A'; i<='Z'; ++i)
	chars[i] = LETTER;
for(i='0'; i<='9'; ++i)
	chars[i] = DIGIT;
chars['\''] = APOS;
chars['&'] = APOS;

work();
}



skeqn()
{
while((c = getc(infile)) != rdelim)
	if(c == EOF)
		c = eof();
	else if(c == '"')
		while( (c = getc(infile)) != '"')
			if(c == EOF)
				c = eof();
			else if(c == '\\')
				if((c = getc(infile)) == EOF)
					c = eof();
return(c = ' ');
}


FILE *opn(p)
register char *p;
{
FILE *fd;

if(p[0]=='-' && p[1]=='\0')
	fd = stdin;
else if( (fd = fopen(p, "r")) == NULL)
	fatal("Cannot open file %s\n", p);

return(fd);
}



eof()
{
if(infile != stdin)
	fclose(infile);
if(filesp > files)
	infile = *--filesp;
else if(argc > 0)
	{
	infile = opn(argv[0]);
	--argc;
	++argv;
	}
else
	exit(0);

return(C);
}



getfname()
{
register char *p;
struct chain { struct chain *nextp; char *datap; } *chainblock;
register struct chain *q;
static struct chain *namechain	= NULL;
char *copys();

while(C == ' ') ;

for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
	C;
*p = '\0';
while(c != '\n')
	C;

/* see if this name has already been used */

for(q = namechain ; q; q = q->nextp)
	if( ! strcmp(fname, q->datap))
		{
		fname[0] = '\0';
		return;
		}

q = (struct chain *) calloc(1, sizeof(*chainblock));
q->nextp = namechain;
q->datap = copys(fname);
namechain = q;
}




fatal(s,p)
char *s, *p;
{
fprintf(stderr, "Deroff: ");
fprintf(stderr, s, p);
exit(1);
}

work()
{

for( ;; )
	{
	if(C == '.'  ||  c == '\'')
		comline();
	else
		regline(NO);
	}
}




regline(macline)
int macline;
{
line[0] = c;
lp = line;
for( ; ; )
	{
	if(c == '\\')
		{
		*lp = ' ';
		backsl();
		}
	if(c == '\n') break;
	if(intable && c=='T')
		{
		*++lp = C;
		if(c=='{' || c=='}')
			{
			lp[-1] = ' ';
			*lp = C;
			}
		}
	else	*++lp = C;
	}

*lp = '\0';

if(line[0] != '\0')
	if(wordflag)
		putwords(macline);
	else if(macline)
		putmac(line);
	else
		puts(line);
}




putmac(s)
register char *s;
{
register char *t;

while(*s)
	{
	while(*s==' ' || *s=='\t')
		putchar(*s++);
	for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
		;
	if(t>s+2 && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER)
		while(s < t)
			putchar(*s++);
	else
		s = t;
	}
putchar('\n');
}



putwords(macline)	/* break into words for -w option */
int macline;
{
register char *p, *p1;
int i, nlet;


for(p1 = line ; ;)
	{
	/* skip initial specials ampersandsct line *ai;
	register struct line *aim;
	int k;
	for(j=1;j<=n;j*= 2)
		m = 2*j - 1;
	for(m/=2;m!=0;m/=2) {
		k = n-m;
		for(j=1;j<=k;j++) {
			for(ai = &a[j]; ai > a; ai -= m) {
				aim = &ai[m];
				if(aim < ai)
					break;	/*wraparound*/
				if(aim->value > ai[0].value ||
				   aim->value == ai[0].value &&
				   aim->serial > ai[0].serial)
					break;
				w.value = ai[0].value;
				ai[0].value = aim->value;
				aim->value = w.value;
				w.serial = ai[0].serial;
				ai[0].serial = aim->serial;
				aim->serial = w.serial;
			}
		}
	}
}

unsort(f, l, b)
struct line *f;
int *b;
{
	register int *a;
	register int i;
	a = (int *)talloc((l+1)*sizeof(int));
	for(i=1;i<=l;i++)
		a[f[i].serial] = f[i].value;
	for(i=1;i<=l;i++)
		b[i] = a[i];
	free((char *)a);
}

filename(pa1, pa2)
char **pa1, **pa2;
{
	register char *a1, *b1, *a2;
	char buf[512];
	struct stat stbuf;
	int i, f;
	a1 = *pa1;
	a2 = *pa2;
	if(stat(a1,&stbuf)!=-1 && ((stbuf.st_mode&S_IFMT)==S_IFDIR)) {
		b1 = *pa1 = malloc(100);
		while(*b1++ = *a1++) ;
		b1[-1] = '/';
		a1 = b1;
		while(*a1++ = *a2++)
			if(*a2 && *a2!='/' && a2[-1]=='/')
				a1 = b1;
	}
	else if(a1[0]=='-'&&a1[1]==0&&tempfile==0) {
		signal(SIGHUP,done);
		signal(SIGINT,done);
		signal(SIGPIPE,done);
		signal(SIGTERM,done);
		*pa1 = tempfile = mktemp("/tmp/dXXXXX");
		if((f=creat(tempfile,0600)) < 0) {
			mesg("cannot create ",tempfile);
			done();
		}
		while((i=read(0,buf,512))>0)
			write(f,buf,i);
		close(f);
	}
}

prepare(i, arg)
char *arg;
{
	register struct line *p;
	register j,h;
	if((input[i] = fopen(arg,"r")) == NULL){
		mesg("cannot open ", arg);
		done();
	}
	p = (struct line *)talloc(3*sizeof(line));
	for(j=0; h=readhash(input[i]);) {
		p = (struct line *)ralloc((char *)p,(++j+3)*sizeof(line));
		p[j].value = h;
	}
	len[i] = j;
	file[i] = p;
	fclose(input[i]);
}

prune()
{
	register i,j;
	for(pref=0;pref<len[0]&&pref<len[1]&&
		file[0][pref+1].value==file[1][pref+1].value;
		pref++ ) ;
	for(suff=0;suff<len[0]-pref&&suff<len[1]-pref&&
		file[0][len[0]-suff].value==file[1][len[1]-suff].value;
		suff++) ;
	for(j=0;j<2;j++) {
		sfile[j] = file[j]+pref;
		slen[j] = len[j]-pref-suff;
		for(i=0;i<=slen[j];i++)
			sfile[j][i].serial = i;
	}
}

equiv(a,n,b,m,c)
struct line *a, *b;
int *c;
{
	register int i, j;
	i = j = 1;
	while(i<=n && j<=m) {
		if(a[i].value <b[j].value)
			a[i++].value = 0;
		else if(a[i].value == b[j].value)
			a[i++].value = j;
		else
			j++;
	}
	while(i <= n)
		a[i++].value = 0;
	b[m+1].value = 0;
	j = 0;
	while(++j <= m) {
		c[j] = -b[j].serial;
		while(b[j+1].value == b[j].value) {
			j++;
			c[j] = b[j].serial;
		}
	}
	c[j] = -1;
}

main(argc, argv)
char **argv;
{
	register int k;
	char **args;

	args = argv;
	if(argc>3 && *argv[1]=='-') {
		argc--;
		argv++;
		for(k=1;argv[0][k];k++) {
			switch(argv[0][k]) {
			case 'e':
				opt = -1;
				break;
			case 'f':
				opt = 1;
				break;
			case 'b':
