tr.c revision 1.1.1.3 1 1.1 cgd /*
2 1.1.1.2 jtc * Copyright (c) 1988, 1993
3 1.1.1.2 jtc * The Regents of the University of California. All rights reserved.
4 1.1 cgd *
5 1.1 cgd * Redistribution and use in source and binary forms, with or without
6 1.1 cgd * modification, are permitted provided that the following conditions
7 1.1 cgd * are met:
8 1.1 cgd * 1. Redistributions of source code must retain the above copyright
9 1.1 cgd * notice, this list of conditions and the following disclaimer.
10 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer in the
12 1.1 cgd * documentation and/or other materials provided with the distribution.
13 1.1 cgd * 3. All advertising materials mentioning features or use of this software
14 1.1 cgd * must display the following acknowledgement:
15 1.1 cgd * This product includes software developed by the University of
16 1.1 cgd * California, Berkeley and its contributors.
17 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
18 1.1 cgd * may be used to endorse or promote products derived from this software
19 1.1 cgd * without specific prior written permission.
20 1.1 cgd *
21 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 cgd * SUCH DAMAGE.
32 1.1 cgd */
33 1.1 cgd
34 1.1 cgd #ifndef lint
35 1.1.1.2 jtc static char copyright[] =
36 1.1.1.2 jtc "@(#) Copyright (c) 1988, 1993\n\
37 1.1.1.2 jtc The Regents of the University of California. All rights reserved.\n";
38 1.1 cgd #endif /* not lint */
39 1.1 cgd
40 1.1 cgd #ifndef lint
41 1.1.1.3 jtc static char sccsid[] = "@(#)tr.c 8.2 (Berkeley) 5/4/95";
42 1.1 cgd #endif /* not lint */
43 1.1 cgd
44 1.1 cgd #include <sys/types.h>
45 1.1.1.3 jtc
46 1.1 cgd #include <stdio.h>
47 1.1.1.2 jtc #include <stdlib.h>
48 1.1.1.2 jtc #include <string.h>
49 1.1.1.3 jtc #include <unistd.h>
50 1.1.1.3 jtc
51 1.1.1.2 jtc #include "extern.h"
52 1.1.1.2 jtc
53 1.1.1.2 jtc static int string1[NCHARS] = {
54 1.1.1.2 jtc 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ASCII */
55 1.1.1.2 jtc 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
56 1.1.1.2 jtc 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
57 1.1.1.2 jtc 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
58 1.1.1.2 jtc 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
59 1.1.1.2 jtc 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
60 1.1.1.2 jtc 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
61 1.1.1.2 jtc 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
62 1.1.1.2 jtc 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
63 1.1.1.2 jtc 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
64 1.1.1.2 jtc 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
65 1.1.1.2 jtc 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
66 1.1.1.2 jtc 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
67 1.1.1.2 jtc 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
68 1.1.1.2 jtc 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
69 1.1.1.2 jtc 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
70 1.1.1.2 jtc 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
71 1.1.1.2 jtc 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
72 1.1.1.2 jtc 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
73 1.1.1.2 jtc 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
74 1.1.1.2 jtc 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
75 1.1.1.2 jtc 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
76 1.1.1.2 jtc 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
77 1.1.1.2 jtc 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
78 1.1.1.2 jtc 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
79 1.1.1.2 jtc 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
80 1.1.1.2 jtc 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
81 1.1.1.2 jtc 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
82 1.1.1.2 jtc 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
83 1.1.1.2 jtc 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
84 1.1.1.2 jtc 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
85 1.1.1.2 jtc 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
86 1.1.1.2 jtc }, string2[NCHARS];
87 1.1 cgd
88 1.1.1.2 jtc STR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
89 1.1.1.2 jtc STR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
90 1.1 cgd
91 1.1.1.2 jtc static void setup __P((int *, char *, STR *, int));
92 1.1.1.2 jtc static void usage __P((void));
93 1.1 cgd
94 1.1.1.2 jtc int
95 1.1 cgd main(argc, argv)
96 1.1 cgd int argc;
97 1.1 cgd char **argv;
98 1.1 cgd {
99 1.1.1.2 jtc register int ch, cnt, lastch, *p;
100 1.1.1.2 jtc int cflag, dflag, sflag, isstring2;
101 1.1 cgd
102 1.1 cgd cflag = dflag = sflag = 0;
103 1.1 cgd while ((ch = getopt(argc, argv, "cds")) != EOF)
104 1.1 cgd switch((char)ch) {
105 1.1 cgd case 'c':
106 1.1 cgd cflag = 1;
107 1.1 cgd break;
108 1.1 cgd case 'd':
109 1.1 cgd dflag = 1;
110 1.1 cgd break;
111 1.1 cgd case 's':
112 1.1 cgd sflag = 1;
113 1.1 cgd break;
114 1.1 cgd case '?':
115 1.1 cgd default:
116 1.1.1.2 jtc usage();
117 1.1 cgd }
118 1.1 cgd argc -= optind;
119 1.1 cgd argv += optind;
120 1.1 cgd
121 1.1.1.2 jtc switch(argc) {
122 1.1.1.2 jtc case 0:
123 1.1.1.2 jtc default:
124 1.1.1.2 jtc usage();
125 1.1.1.2 jtc /* NOTREACHED */
126 1.1.1.2 jtc case 1:
127 1.1.1.2 jtc isstring2 = 0;
128 1.1.1.2 jtc break;
129 1.1.1.2 jtc case 2:
130 1.1.1.2 jtc isstring2 = 1;
131 1.1.1.2 jtc break;
132 1.1.1.2 jtc }
133 1.1.1.2 jtc
134 1.1 cgd /*
135 1.1.1.2 jtc * tr -ds [-c] string1 string2
136 1.1.1.2 jtc * Delete all characters (or complemented characters) in string1.
137 1.1.1.2 jtc * Squeeze all characters in string2.
138 1.1 cgd */
139 1.1.1.2 jtc if (dflag && sflag) {
140 1.1.1.2 jtc if (!isstring2)
141 1.1.1.2 jtc usage();
142 1.1.1.2 jtc
143 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
144 1.1.1.2 jtc setup(string2, argv[1], &s2, 0);
145 1.1.1.2 jtc
146 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;)
147 1.1.1.2 jtc if (!string1[ch] && (!string2[ch] || lastch != ch)) {
148 1.1.1.2 jtc lastch = ch;
149 1.1.1.2 jtc (void)putchar(ch);
150 1.1.1.2 jtc }
151 1.1 cgd exit(0);
152 1.1 cgd }
153 1.1 cgd
154 1.1.1.2 jtc /*
155 1.1.1.2 jtc * tr -d [-c] string1
156 1.1.1.2 jtc * Delete all characters (or complemented characters) in string1.
157 1.1.1.2 jtc */
158 1.1 cgd if (dflag) {
159 1.1.1.2 jtc if (isstring2)
160 1.1.1.2 jtc usage();
161 1.1.1.2 jtc
162 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
163 1.1.1.2 jtc
164 1.1.1.2 jtc while ((ch = getchar()) != EOF)
165 1.1.1.2 jtc if (!string1[ch])
166 1.1.1.2 jtc (void)putchar(ch);
167 1.1.1.2 jtc exit(0);
168 1.1.1.2 jtc }
169 1.1.1.2 jtc
170 1.1.1.2 jtc /*
171 1.1.1.2 jtc * tr -s [-c] string1
172 1.1.1.2 jtc * Squeeze all characters (or complemented characters) in string1.
173 1.1.1.2 jtc */
174 1.1.1.2 jtc if (sflag && !isstring2) {
175 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
176 1.1.1.2 jtc
177 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;)
178 1.1.1.2 jtc if (!string1[ch] || lastch != ch) {
179 1.1 cgd lastch = ch;
180 1.1.1.2 jtc (void)putchar(ch);
181 1.1 cgd }
182 1.1.1.2 jtc exit(0);
183 1.1.1.2 jtc }
184 1.1.1.2 jtc
185 1.1.1.2 jtc /*
186 1.1.1.2 jtc * tr [-cs] string1 string2
187 1.1.1.2 jtc * Replace all characters (or complemented characters) in string1 with
188 1.1.1.2 jtc * the character in the same position in string2. If the -s option is
189 1.1.1.2 jtc * specified, squeeze all the characters in string2.
190 1.1.1.2 jtc */
191 1.1.1.2 jtc if (!isstring2)
192 1.1.1.2 jtc usage();
193 1.1.1.2 jtc
194 1.1.1.2 jtc s1.str = argv[0];
195 1.1.1.2 jtc s2.str = argv[1];
196 1.1.1.2 jtc
197 1.1.1.2 jtc if (cflag)
198 1.1.1.2 jtc for (cnt = NCHARS, p = string1; cnt--;)
199 1.1.1.2 jtc *p++ = OOBCH;
200 1.1.1.2 jtc
201 1.1.1.2 jtc if (!next(&s2))
202 1.1.1.2 jtc err("empty string2");
203 1.1.1.2 jtc
204 1.1.1.2 jtc /* If string2 runs out of characters, use the last one specified. */
205 1.1.1.2 jtc if (sflag)
206 1.1.1.2 jtc while (next(&s1)) {
207 1.1.1.2 jtc string1[s1.lastch] = ch = s2.lastch;
208 1.1.1.2 jtc string2[ch] = 1;
209 1.1.1.2 jtc (void)next(&s2);
210 1.1 cgd }
211 1.1.1.2 jtc else
212 1.1.1.2 jtc while (next(&s1)) {
213 1.1.1.2 jtc string1[s1.lastch] = ch = s2.lastch;
214 1.1.1.2 jtc (void)next(&s2);
215 1.1.1.2 jtc }
216 1.1.1.2 jtc
217 1.1.1.2 jtc if (cflag)
218 1.1.1.2 jtc for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt)
219 1.1.1.2 jtc *p = *p == OOBCH ? ch : cnt;
220 1.1.1.2 jtc
221 1.1.1.2 jtc if (sflag)
222 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;) {
223 1.1.1.2 jtc ch = string1[ch];
224 1.1.1.2 jtc if (!string2[ch] || lastch != ch) {
225 1.1 cgd lastch = ch;
226 1.1.1.2 jtc (void)putchar(ch);
227 1.1 cgd }
228 1.1.1.2 jtc }
229 1.1.1.2 jtc else
230 1.1.1.2 jtc while ((ch = getchar()) != EOF)
231 1.1.1.2 jtc (void)putchar(string1[ch]);
232 1.1.1.2 jtc exit (0);
233 1.1 cgd }
234 1.1 cgd
235 1.1.1.2 jtc static void
236 1.1.1.2 jtc setup(string, arg, str, cflag)
237 1.1.1.2 jtc int *string;
238 1.1.1.2 jtc char *arg;
239 1.1.1.2 jtc STR *str;
240 1.1.1.2 jtc int cflag;
241 1.1 cgd {
242 1.1.1.2 jtc register int cnt, *p;
243 1.1 cgd
244 1.1.1.2 jtc str->str = arg;
245 1.1.1.2 jtc bzero(string, NCHARS * sizeof(int));
246 1.1.1.2 jtc while (next(str))
247 1.1.1.2 jtc string[str->lastch] = 1;
248 1.1.1.2 jtc if (cflag)
249 1.1.1.2 jtc for (p = string, cnt = NCHARS; cnt--; ++p)
250 1.1.1.2 jtc *p = !*p;
251 1.1 cgd }
252 1.1 cgd
253 1.1.1.2 jtc static void
254 1.1.1.2 jtc usage()
255 1.1 cgd {
256 1.1.1.2 jtc (void)fprintf(stderr, "usage: tr [-cs] string1 string2\n");
257 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -d string1\n");
258 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -s string1\n");
259 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -ds string1 string2\n");
260 1.1.1.2 jtc exit(1);
261 1.1.1.2 jtc }
262 1.1 cgd
263 1.1.1.2 jtc #if __STDC__
264 1.1.1.2 jtc #include <stdarg.h>
265 1.1.1.2 jtc #else
266 1.1.1.2 jtc #include <varargs.h>
267 1.1.1.2 jtc #endif
268 1.1.1.2 jtc
269 1.1.1.2 jtc void
270 1.1.1.2 jtc #if __STDC__
271 1.1.1.2 jtc err(const char *fmt, ...)
272 1.1.1.2 jtc #else
273 1.1.1.2 jtc err(fmt, va_alist)
274 1.1.1.2 jtc char *fmt;
275 1.1.1.2 jtc va_dcl
276 1.1.1.2 jtc #endif
277 1.1.1.2 jtc {
278 1.1.1.2 jtc va_list ap;
279 1.1.1.2 jtc #if __STDC__
280 1.1.1.2 jtc va_start(ap, fmt);
281 1.1.1.2 jtc #else
282 1.1.1.2 jtc va_start(ap);
283 1.1.1.2 jtc #endif
284 1.1.1.2 jtc (void)fprintf(stderr, "tr: ");
285 1.1.1.2 jtc (void)vfprintf(stderr, fmt, ap);
286 1.1.1.2 jtc va_end(ap);
287 1.1.1.2 jtc (void)fprintf(stderr, "\n");
288 1.1.1.2 jtc exit(1);
289 1.1.1.2 jtc /* NOTREACHED */
290 1.1 cgd }
291