tr.c revision 1.1.1.2 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.2 jtc static char sccsid[] = "@(#)tr.c 8.1 (Berkeley) 6/6/93";
42 1.1 cgd #endif /* not lint */
43 1.1 cgd
44 1.1 cgd #include <sys/types.h>
45 1.1 cgd #include <stdio.h>
46 1.1.1.2 jtc #include <stdlib.h>
47 1.1.1.2 jtc #include <string.h>
48 1.1.1.2 jtc #include "extern.h"
49 1.1.1.2 jtc
50 1.1.1.2 jtc static int string1[NCHARS] = {
51 1.1.1.2 jtc 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ASCII */
52 1.1.1.2 jtc 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
53 1.1.1.2 jtc 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
54 1.1.1.2 jtc 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
55 1.1.1.2 jtc 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
56 1.1.1.2 jtc 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
57 1.1.1.2 jtc 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
58 1.1.1.2 jtc 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
59 1.1.1.2 jtc 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
60 1.1.1.2 jtc 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
61 1.1.1.2 jtc 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
62 1.1.1.2 jtc 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
63 1.1.1.2 jtc 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
64 1.1.1.2 jtc 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
65 1.1.1.2 jtc 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
66 1.1.1.2 jtc 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
67 1.1.1.2 jtc 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
68 1.1.1.2 jtc 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
69 1.1.1.2 jtc 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
70 1.1.1.2 jtc 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
71 1.1.1.2 jtc 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
72 1.1.1.2 jtc 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
73 1.1.1.2 jtc 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
74 1.1.1.2 jtc 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
75 1.1.1.2 jtc 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
76 1.1.1.2 jtc 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
77 1.1.1.2 jtc 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
78 1.1.1.2 jtc 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
79 1.1.1.2 jtc 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
80 1.1.1.2 jtc 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
81 1.1.1.2 jtc 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
82 1.1.1.2 jtc 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
83 1.1.1.2 jtc }, string2[NCHARS];
84 1.1 cgd
85 1.1.1.2 jtc STR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
86 1.1.1.2 jtc STR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
87 1.1 cgd
88 1.1.1.2 jtc static void setup __P((int *, char *, STR *, int));
89 1.1.1.2 jtc static void usage __P((void));
90 1.1 cgd
91 1.1.1.2 jtc int
92 1.1 cgd main(argc, argv)
93 1.1 cgd int argc;
94 1.1 cgd char **argv;
95 1.1 cgd {
96 1.1.1.2 jtc register int ch, cnt, lastch, *p;
97 1.1.1.2 jtc int cflag, dflag, sflag, isstring2;
98 1.1 cgd
99 1.1 cgd cflag = dflag = sflag = 0;
100 1.1 cgd while ((ch = getopt(argc, argv, "cds")) != EOF)
101 1.1 cgd switch((char)ch) {
102 1.1 cgd case 'c':
103 1.1 cgd cflag = 1;
104 1.1 cgd break;
105 1.1 cgd case 'd':
106 1.1 cgd dflag = 1;
107 1.1 cgd break;
108 1.1 cgd case 's':
109 1.1 cgd sflag = 1;
110 1.1 cgd break;
111 1.1 cgd case '?':
112 1.1 cgd default:
113 1.1.1.2 jtc usage();
114 1.1 cgd }
115 1.1 cgd argc -= optind;
116 1.1 cgd argv += optind;
117 1.1 cgd
118 1.1.1.2 jtc switch(argc) {
119 1.1.1.2 jtc case 0:
120 1.1.1.2 jtc default:
121 1.1.1.2 jtc usage();
122 1.1.1.2 jtc /* NOTREACHED */
123 1.1.1.2 jtc case 1:
124 1.1.1.2 jtc isstring2 = 0;
125 1.1.1.2 jtc break;
126 1.1.1.2 jtc case 2:
127 1.1.1.2 jtc isstring2 = 1;
128 1.1.1.2 jtc break;
129 1.1.1.2 jtc }
130 1.1.1.2 jtc
131 1.1 cgd /*
132 1.1.1.2 jtc * tr -ds [-c] string1 string2
133 1.1.1.2 jtc * Delete all characters (or complemented characters) in string1.
134 1.1.1.2 jtc * Squeeze all characters in string2.
135 1.1 cgd */
136 1.1.1.2 jtc if (dflag && sflag) {
137 1.1.1.2 jtc if (!isstring2)
138 1.1.1.2 jtc usage();
139 1.1.1.2 jtc
140 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
141 1.1.1.2 jtc setup(string2, argv[1], &s2, 0);
142 1.1.1.2 jtc
143 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;)
144 1.1.1.2 jtc if (!string1[ch] && (!string2[ch] || lastch != ch)) {
145 1.1.1.2 jtc lastch = ch;
146 1.1.1.2 jtc (void)putchar(ch);
147 1.1.1.2 jtc }
148 1.1 cgd exit(0);
149 1.1 cgd }
150 1.1 cgd
151 1.1.1.2 jtc /*
152 1.1.1.2 jtc * tr -d [-c] string1
153 1.1.1.2 jtc * Delete all characters (or complemented characters) in string1.
154 1.1.1.2 jtc */
155 1.1 cgd if (dflag) {
156 1.1.1.2 jtc if (isstring2)
157 1.1.1.2 jtc usage();
158 1.1.1.2 jtc
159 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
160 1.1.1.2 jtc
161 1.1.1.2 jtc while ((ch = getchar()) != EOF)
162 1.1.1.2 jtc if (!string1[ch])
163 1.1.1.2 jtc (void)putchar(ch);
164 1.1.1.2 jtc exit(0);
165 1.1.1.2 jtc }
166 1.1.1.2 jtc
167 1.1.1.2 jtc /*
168 1.1.1.2 jtc * tr -s [-c] string1
169 1.1.1.2 jtc * Squeeze all characters (or complemented characters) in string1.
170 1.1.1.2 jtc */
171 1.1.1.2 jtc if (sflag && !isstring2) {
172 1.1.1.2 jtc setup(string1, argv[0], &s1, cflag);
173 1.1.1.2 jtc
174 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;)
175 1.1.1.2 jtc if (!string1[ch] || lastch != ch) {
176 1.1 cgd lastch = ch;
177 1.1.1.2 jtc (void)putchar(ch);
178 1.1 cgd }
179 1.1.1.2 jtc exit(0);
180 1.1.1.2 jtc }
181 1.1.1.2 jtc
182 1.1.1.2 jtc /*
183 1.1.1.2 jtc * tr [-cs] string1 string2
184 1.1.1.2 jtc * Replace all characters (or complemented characters) in string1 with
185 1.1.1.2 jtc * the character in the same position in string2. If the -s option is
186 1.1.1.2 jtc * specified, squeeze all the characters in string2.
187 1.1.1.2 jtc */
188 1.1.1.2 jtc if (!isstring2)
189 1.1.1.2 jtc usage();
190 1.1.1.2 jtc
191 1.1.1.2 jtc s1.str = argv[0];
192 1.1.1.2 jtc s2.str = argv[1];
193 1.1.1.2 jtc
194 1.1.1.2 jtc if (cflag)
195 1.1.1.2 jtc for (cnt = NCHARS, p = string1; cnt--;)
196 1.1.1.2 jtc *p++ = OOBCH;
197 1.1.1.2 jtc
198 1.1.1.2 jtc if (!next(&s2))
199 1.1.1.2 jtc err("empty string2");
200 1.1.1.2 jtc
201 1.1.1.2 jtc /* If string2 runs out of characters, use the last one specified. */
202 1.1.1.2 jtc if (sflag)
203 1.1.1.2 jtc while (next(&s1)) {
204 1.1.1.2 jtc string1[s1.lastch] = ch = s2.lastch;
205 1.1.1.2 jtc string2[ch] = 1;
206 1.1.1.2 jtc (void)next(&s2);
207 1.1 cgd }
208 1.1.1.2 jtc else
209 1.1.1.2 jtc while (next(&s1)) {
210 1.1.1.2 jtc string1[s1.lastch] = ch = s2.lastch;
211 1.1.1.2 jtc (void)next(&s2);
212 1.1.1.2 jtc }
213 1.1.1.2 jtc
214 1.1.1.2 jtc if (cflag)
215 1.1.1.2 jtc for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt)
216 1.1.1.2 jtc *p = *p == OOBCH ? ch : cnt;
217 1.1.1.2 jtc
218 1.1.1.2 jtc if (sflag)
219 1.1.1.2 jtc for (lastch = OOBCH; (ch = getchar()) != EOF;) {
220 1.1.1.2 jtc ch = string1[ch];
221 1.1.1.2 jtc if (!string2[ch] || lastch != ch) {
222 1.1 cgd lastch = ch;
223 1.1.1.2 jtc (void)putchar(ch);
224 1.1 cgd }
225 1.1.1.2 jtc }
226 1.1.1.2 jtc else
227 1.1.1.2 jtc while ((ch = getchar()) != EOF)
228 1.1.1.2 jtc (void)putchar(string1[ch]);
229 1.1.1.2 jtc exit (0);
230 1.1 cgd }
231 1.1 cgd
232 1.1.1.2 jtc static void
233 1.1.1.2 jtc setup(string, arg, str, cflag)
234 1.1.1.2 jtc int *string;
235 1.1.1.2 jtc char *arg;
236 1.1.1.2 jtc STR *str;
237 1.1.1.2 jtc int cflag;
238 1.1 cgd {
239 1.1.1.2 jtc register int cnt, *p;
240 1.1 cgd
241 1.1.1.2 jtc str->str = arg;
242 1.1.1.2 jtc bzero(string, NCHARS * sizeof(int));
243 1.1.1.2 jtc while (next(str))
244 1.1.1.2 jtc string[str->lastch] = 1;
245 1.1.1.2 jtc if (cflag)
246 1.1.1.2 jtc for (p = string, cnt = NCHARS; cnt--; ++p)
247 1.1.1.2 jtc *p = !*p;
248 1.1 cgd }
249 1.1 cgd
250 1.1.1.2 jtc static void
251 1.1.1.2 jtc usage()
252 1.1 cgd {
253 1.1.1.2 jtc (void)fprintf(stderr, "usage: tr [-cs] string1 string2\n");
254 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -d string1\n");
255 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -s string1\n");
256 1.1.1.2 jtc (void)fprintf(stderr, " tr [-c] -ds string1 string2\n");
257 1.1.1.2 jtc exit(1);
258 1.1.1.2 jtc }
259 1.1 cgd
260 1.1.1.2 jtc #if __STDC__
261 1.1.1.2 jtc #include <stdarg.h>
262 1.1.1.2 jtc #else
263 1.1.1.2 jtc #include <varargs.h>
264 1.1.1.2 jtc #endif
265 1.1.1.2 jtc
266 1.1.1.2 jtc void
267 1.1.1.2 jtc #if __STDC__
268 1.1.1.2 jtc err(const char *fmt, ...)
269 1.1.1.2 jtc #else
270 1.1.1.2 jtc err(fmt, va_alist)
271 1.1.1.2 jtc char *fmt;
272 1.1.1.2 jtc va_dcl
273 1.1.1.2 jtc #endif
274 1.1.1.2 jtc {
275 1.1.1.2 jtc va_list ap;
276 1.1.1.2 jtc #if __STDC__
277 1.1.1.2 jtc va_start(ap, fmt);
278 1.1.1.2 jtc #else
279 1.1.1.2 jtc va_start(ap);
280 1.1.1.2 jtc #endif
281 1.1.1.2 jtc (void)fprintf(stderr, "tr: ");
282 1.1.1.2 jtc (void)vfprintf(stderr, fmt, ap);
283 1.1.1.2 jtc va_end(ap);
284 1.1.1.2 jtc (void)fprintf(stderr, "\n");
285 1.1.1.2 jtc exit(1);
286 1.1.1.2 jtc /* NOTREACHED */
287 1.1 cgd }
288