V10/cmd/tr.c

Compare this file to the similar file:
Show the results in this format:

#include <stdio.h>

#define N 500

unsigned char from[N];
int nfrom;
unsigned char to[N];
int nto;
unsigned char trans[256];
unsigned char occur[256];

int cflag;
int dflag;
int sflag;

main(argc, argv)
unsigned char **argv;
{
	int c;
	for( ; argc>1 && argv[1][0]=='-'; argc--, argv++) {
		while(c = *++argv[1]) {
			switch(c) {
			case 's':
				sflag++;
				continue;
			case 'd':
				dflag++;
				continue;
			case 'c':
				cflag++;
				continue;
			default:
				fprintf(stderr,"tr: bad option\n");
				exit(1);
			}
		}
	}
	if(argc>1)
		nfrom = canon(argv[1],from);
	if(argc>2)
		nto = canon(argv[2],to);
	if(cflag)
		complement();
	if(dflag)
		delete();
	else
		translit();
	return 0;
}

delete()
{
	register i, c, last;
	for(i=0; i<nfrom; i++)
		trans[from[i]] = 1;
	if(sflag)
		for(i=0; i<nto; i++)
			occur[to[i]] = 1;
	last = -1;
	while((c=getchar()) != EOF)
		if(!trans[c] && (c!=last || !occur[c]))
			putchar(last = c);
}

translit()
{
	register i, c;
	if(nfrom>0 && nto==0) {
		fprintf(stderr,"tr: arg count\n");
		exit(1);
	}
	for(i=0; i<sizeof trans; i++)
		trans[i] = i;
	for(i=0; i<nfrom; i++)
		trans[from[i]] = to[i<nto? i: nto-1];
	if(sflag) 
		squeeze();
	else
		while((c=getchar()) != EOF)
			putchar(trans[c]);
}

squeeze()
{
	register i, c, last;
	for(i=0; i<nto; i++)
		occur[to[i]] = 1;
	last = -1;
	while((c=getchar()) != EOF)
		if((c=trans[c]) != last || !occur[c])
			putchar(last = c);
}

complement()
{
	register i;
	for(i=0; i<nfrom; i++)
		occur[from[i]] = 1;
	for(i=nfrom=0; i<sizeof occur; i++)
		if(!occur[i])
			from[nfrom++] = i;
	memset((char*)occur,0,sizeof occur);
}

getch(ps)
unsigned char **ps;
{
	unsigned char *s = *ps;
	int c = *s++;
	int n, i;
	if(c=='\\' && *s) {
		n = 0;
		for(i=0; i<3; i++)
			if(*s>='0' && *s<='7')
				n = 8*n + *s++ - '0';
			else
				break;
		if(i == 0)
			c = *s;
		else if(n <= 0377)
			c = n;
		else {
			fprintf(stderr,"tr: char>0377\n");
			exit(1);
		}
	}
	*ps = s;
	return c;
}

canon(s, t)
unsigned char *s, *t;
{
	int n = 0;
	int i, c;
	while(*s && n<N) {
		if(*s=='-' && n>0 && s[1]) {
			s++;
			c = getch(&s);
			for(i=t[n-1]; ++i<=c && n<N ; )
				t[n++] = i;
		} else
			t[n++] = getch(&s);
	}
	if(n >= N) {
		fprintf(stderr,"tr: arg string too long\n");
		exit(1);
	}
	return n;
}