xref: /original-bsd/usr.bin/tr/tr.c (revision 6386612b)
1 static char *sccsid = "@(#)tr.c	4.2 (Berkeley) 04/22/85";
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 	clearerr(stdout);
81 	while((c=getc(stdin)) != EOF ) {
82 		if(c == 0) continue;
83 		if(c = code[c&0377]&0377)
84 			if(!sflag || c!=save || !squeez[c&0377]) {
85 				putchar(save = c);
86 				if(ferror(stdout))
87 					exit(1);
88 			}
89 	}
90 	exit(0);
91 }
92 
93 next(s)
94 struct string *s;
95 {
96 
97 again:
98 	if(s->max) {
99 		if(s->last++ < s->max)
100 			return(s->last);
101 		s->max = s->last = 0;
102 	}
103 	if(s->last && *s->p=='-') {
104 		nextc(s);
105 		s->max = nextc(s);
106 		if(s->max==0) {
107 			s->p--;
108 			return('-');
109 		}
110 		if(s->max < s->last)  {
111 			s->last = s->max-1;
112 			return('-');
113 		}
114 		goto again;
115 	}
116 	return(s->last = nextc(s));
117 }
118 
119 nextc(s)
120 struct string *s;
121 {
122 	register c, i, n;
123 
124 	c = *s->p++;
125 	if(c=='\\') {
126 		i = n = 0;
127 		while(i<3 && (c = *s->p)>='0' && c<='7') {
128 			n = n*8 + c - '0';
129 			i++;
130 			s->p++;
131 		}
132 		if(i>0) c = n;
133 		else c = *s->p++;
134 	}
135 	if(c==0) *--s->p = 0;
136 	return(c&0377);
137 }
138