xref: /original-bsd/usr.bin/tr/tr.c (revision d25e1985)
1 static char *sccsid = "@(#)tr.c	4.1 (Berkeley) 10/01/80";
2 #include <stdio.h>
3 
4 /* tr - transliterate data stream */
5 int	dflag	= 0;
6 int	sflag	= 0;
7 int	cflag = 0;
8 int	save	= 0;
9 char	code[256];
10 char	squeez[256];
11 char	vect[256];
12 struct string { int last, max; char *p; } string1, string2;
13 
14 main(argc,argv)
15 char **argv;
16 {
17 	register i;
18 	int j;
19 	register c, d;
20 	char *compl;
21 	int lastd;
22 
23 	string1.last = string2.last = 0;
24 	string1.max = string2.max = 0;
25 	string1.p = string2.p = "";
26 
27 	if(--argc>0) {
28 		argv++;
29 		if(*argv[0]=='-'&&argv[0][1]!=0) {
30 			while(*++argv[0])
31 				switch(*argv[0]) {
32 				case 'c':
33 					cflag++;
34 					continue;
35 				case 'd':
36 					dflag++;
37 					continue;
38 				case 's':
39 					sflag++;
40 					continue;
41 				}
42 			argc--;
43 			argv++;
44 		}
45 	}
46 	if(argc>0) string1.p = argv[0];
47 	if(argc>1) string2.p = argv[1];
48 	for(i=0; i<256; i++)
49 		code[i] = vect[i] = 0;
50 	if(cflag) {
51 		while(c = next(&string1))
52 			vect[c&0377] = 1;
53 		j = 0;
54 		for(i=1; i<256; i++)
55 			if(vect[i]==0) vect[j++] = i;
56 		vect[j] = 0;
57 		compl = vect;
58 	}
59 	for(i=0; i<256; i++)
60 		squeez[i] = 0;
61 	lastd = 0;
62 	for(;;){
63 		if(cflag) c = *compl++;
64 		else c = next(&string1);
65 		if(c==0) break;
66 		d = next(&string2);
67 		if(d==0) d = lastd;
68 		else lastd = d;
69 		squeez[d&0377] = 1;
70 		code[c&0377] = dflag?1:d;
71 	}
72 	while(d = next(&string2))
73 		squeez[d&0377] = 1;
74 	squeez[0] = 1;
75 	for(i=0;i<256;i++) {
76 		if(code[i]==0) code[i] = i;
77 		else if(dflag) code[i] = 0;
78 	}
79 
80 	while((c=getc(stdin)) != EOF ) {
81 		if(c == 0) continue;
82 		if(c = code[c&0377]&0377)
83 			if(!sflag || c!=save || !squeez[c&0377])
84 				putchar(save = c);
85 	}
86 	exit(0);
87 }
88 
89 next(s)
90 struct string *s;
91 {
92 
93 again:
94 	if(s->max) {
95 		if(s->last++ < s->max)
96 			return(s->last);
97 		s->max = s->last = 0;
98 	}
99 	if(s->last && *s->p=='-') {
100 		nextc(s);
101 		s->max = nextc(s);
102 		if(s->max==0) {
103 			s->p--;
104 			return('-');
105 		}
106 		if(s->max < s->last)  {
107 			s->last = s->max-1;
108 			return('-');
109 		}
110 		goto again;
111 	}
112 	return(s->last = nextc(s));
113 }
114 
115 nextc(s)
116 struct string *s;
117 {
118 	register c, i, n;
119 
120 	c = *s->p++;
121 	if(c=='\\') {
122 		i = n = 0;
123 		while(i<3 && (c = *s->p)>='0' && c<='7') {
124 			n = n*8 + c - '0';
125 			i++;
126 			s->p++;
127 		}
128 		if(i>0) c = n;
129 		else c = *s->p++;
130 	}
131 	if(c==0) *--s->p = 0;
132 	return(c&0377);
133 }
134