1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #include <stdio.h>
41
42 /* tr - transliterate data stream */
43 int dflag = 0;
44 int sflag = 0;
45 int cflag = 0;
46 int save = 0;
47 char code[256];
48 char squeez[256];
49 char vect[256];
50 struct string { int last, max; char *p; } string1, string2;
51
52 int
main(int argc,char ** argv)53 main(int argc, char **argv)
54 {
55 int i;
56 int j;
57 int c, d;
58 char *compl;
59 int lastd;
60
61 string1.last = string2.last = 0;
62 string1.max = string2.max = 0;
63 string1.p = string2.p = "";
64
65 if(--argc>0) {
66 argv++;
67 if(*argv[0]=='-'&&argv[0][1]!=0) {
68 while(*++argv[0])
69 switch(*argv[0]) {
70 case 'c':
71 cflag++;
72 continue;
73 case 'd':
74 dflag++;
75 continue;
76 case 's':
77 sflag++;
78 continue;
79 }
80 argc--;
81 argv++;
82 }
83 }
84 if(argc>0) string1.p = argv[0];
85 if(argc>1) string2.p = argv[1];
86 for(i=0; i<256; i++)
87 code[i] = vect[i] = 0;
88 if(cflag) {
89 while(c = next(&string1))
90 vect[c&0377] = 1;
91 j = 0;
92 for(i=1; i<256; i++)
93 if(vect[i]==0) vect[j++] = i;
94 vect[j] = 0;
95 compl = vect;
96 }
97 for(i=0; i<256; i++)
98 squeez[i] = 0;
99 lastd = 0;
100 for(;;){
101 if(cflag) c = *compl++;
102 else c = next(&string1);
103 if(c==0) break;
104 d = next(&string2);
105 if(d==0) d = lastd;
106 else lastd = d;
107 squeez[d&0377] = 1;
108 code[c&0377] = dflag?1:d;
109 }
110 while(d = next(&string2))
111 squeez[d&0377] = 1;
112 squeez[0] = 1;
113 for(i=0;i<256;i++) {
114 if(code[i]==0) code[i] = i;
115 else if(dflag) code[i] = 0;
116 }
117
118 clearerr(stdout);
119 while((c=getc(stdin)) != EOF ) {
120 if(c == 0) continue;
121 if(c = code[c&0377]&0377)
122 if(!sflag || c!=save || !squeez[c&0377]) {
123 (void)putchar(save = c);
124 if(ferror(stdout))
125 exit(1);
126 }
127 }
128 return (0);
129 }
130
131 int
next(struct string * s)132 next(struct string *s)
133 {
134
135 again:
136 if(s->max) {
137 if(s->last++ < s->max)
138 return(s->last);
139 s->max = s->last = 0;
140 }
141 if(s->last && *s->p=='-') {
142 (void)nextc(s);
143 s->max = nextc(s);
144 if(s->max==0) {
145 s->p--;
146 return('-');
147 }
148 if(s->max < s->last) {
149 s->last = s->max-1;
150 return('-');
151 }
152 goto again;
153 }
154 return(s->last = nextc(s));
155 }
156
157 int
nextc(struct string * s)158 nextc(struct string *s)
159 {
160 int c, i, n;
161
162 c = *s->p++;
163 if(c=='\\') {
164 i = n = 0;
165 while(i<3 && (c = *s->p)>='0' && c<='7') {
166 n = n*8 + c - '0';
167 i++;
168 s->p++;
169 }
170 if(i>0) c = n;
171 else c = *s->p++;
172 }
173 if(c==0) *--s->p = 0;
174 return(c&0377);
175 }
176