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 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include <stdio.h>
43
44 /* tr - transliterate data stream */
45 int dflag = 0;
46 int sflag = 0;
47 int cflag = 0;
48 int save = 0;
49 char code[256];
50 char squeez[256];
51 char vect[256];
52 struct string { int last, max; char *p; } string1, string2;
53
54 int
main(int argc,char ** argv)55 main(int argc, char **argv)
56 {
57 int i;
58 int j;
59 int c, d;
60 char *compl;
61 int lastd;
62
63 string1.last = string2.last = 0;
64 string1.max = string2.max = 0;
65 string1.p = string2.p = "";
66
67 if(--argc>0) {
68 argv++;
69 if(*argv[0]=='-'&&argv[0][1]!=0) {
70 while(*++argv[0])
71 switch(*argv[0]) {
72 case 'c':
73 cflag++;
74 continue;
75 case 'd':
76 dflag++;
77 continue;
78 case 's':
79 sflag++;
80 continue;
81 }
82 argc--;
83 argv++;
84 }
85 }
86 if(argc>0) string1.p = argv[0];
87 if(argc>1) string2.p = argv[1];
88 for(i=0; i<256; i++)
89 code[i] = vect[i] = 0;
90 if(cflag) {
91 while(c = next(&string1))
92 vect[c&0377] = 1;
93 j = 0;
94 for(i=1; i<256; i++)
95 if(vect[i]==0) vect[j++] = i;
96 vect[j] = 0;
97 compl = vect;
98 }
99 for(i=0; i<256; i++)
100 squeez[i] = 0;
101 lastd = 0;
102 for(;;){
103 if(cflag) c = *compl++;
104 else c = next(&string1);
105 if(c==0) break;
106 d = next(&string2);
107 if(d==0) d = lastd;
108 else lastd = d;
109 squeez[d&0377] = 1;
110 code[c&0377] = dflag?1:d;
111 }
112 while(d = next(&string2))
113 squeez[d&0377] = 1;
114 squeez[0] = 1;
115 for(i=0;i<256;i++) {
116 if(code[i]==0) code[i] = i;
117 else if(dflag) code[i] = 0;
118 }
119
120 clearerr(stdout);
121 while((c=getc(stdin)) != EOF ) {
122 if(c == 0) continue;
123 if(c = code[c&0377]&0377)
124 if(!sflag || c!=save || !squeez[c&0377]) {
125 (void)putchar(save = c);
126 if(ferror(stdout))
127 exit(1);
128 }
129 }
130 return (0);
131 }
132
133 int
next(struct string * s)134 next(struct string *s)
135 {
136
137 again:
138 if(s->max) {
139 if(s->last++ < s->max)
140 return(s->last);
141 s->max = s->last = 0;
142 }
143 if(s->last && *s->p=='-') {
144 (void)nextc(s);
145 s->max = nextc(s);
146 if(s->max==0) {
147 s->p--;
148 return('-');
149 }
150 if(s->max < s->last) {
151 s->last = s->max-1;
152 return('-');
153 }
154 goto again;
155 }
156 return(s->last = nextc(s));
157 }
158
159 int
nextc(struct string * s)160 nextc(struct string *s)
161 {
162 int c, i, n;
163
164 c = *s->p++;
165 if(c=='\\') {
166 i = n = 0;
167 while(i<3 && (c = *s->p)>='0' && c<='7') {
168 n = n*8 + c - '0';
169 i++;
170 s->p++;
171 }
172 if(i>0) c = n;
173 else c = *s->p++;
174 }
175 if(c==0) *--s->p = 0;
176 return(c&0377);
177 }
178