xref: /illumos-gate/usr/src/ucbcmd/tr/tr.c (revision dd72704bd9e794056c558153663c739e2012d721)
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
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
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
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