tr.c revision 28368
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1988, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3528368Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1988, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4128368Scharnier#if 0 4223693Speterstatic char sccsid[] = "@(#)tr.c 8.2 (Berkeley) 5/4/95"; 4328368Scharnier#endif 4428368Scharnierstatic const char rcsid[] = 4528368Scharnier "$Id$"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 4811895Sache#include <locale.h> 491590Srgrimes#include <sys/types.h> 5023693Speter 5128368Scharnier#include <err.h> 521590Srgrimes#include <stdio.h> 531590Srgrimes#include <stdlib.h> 541590Srgrimes#include <string.h> 5523693Speter#include <unistd.h> 5623693Speter 571590Srgrimes#include "extern.h" 581590Srgrimes 591590Srgrimesstatic int string1[NCHARS] = { 601590Srgrimes 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ASCII */ 611590Srgrimes 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 621590Srgrimes 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 631590Srgrimes 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 641590Srgrimes 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 651590Srgrimes 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 661590Srgrimes 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 671590Srgrimes 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 681590Srgrimes 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 691590Srgrimes 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 701590Srgrimes 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 711590Srgrimes 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 721590Srgrimes 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 731590Srgrimes 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 741590Srgrimes 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 751590Srgrimes 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 761590Srgrimes 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 771590Srgrimes 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 781590Srgrimes 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 791590Srgrimes 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 801590Srgrimes 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 811590Srgrimes 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 821590Srgrimes 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 831590Srgrimes 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 841590Srgrimes 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 851590Srgrimes 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 861590Srgrimes 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 871590Srgrimes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 881590Srgrimes 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 891590Srgrimes 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 901590Srgrimes 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 911590Srgrimes 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 921590Srgrimes}, string2[NCHARS]; 931590Srgrimes 941590SrgrimesSTR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL }; 951590SrgrimesSTR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL }; 961590Srgrimes 971590Srgrimesstatic void setup __P((int *, char *, STR *, int)); 981590Srgrimesstatic void usage __P((void)); 991590Srgrimes 1001590Srgrimesint 1011590Srgrimesmain(argc, argv) 1021590Srgrimes int argc; 1031590Srgrimes char **argv; 1041590Srgrimes{ 1051590Srgrimes register int ch, cnt, lastch, *p; 1061590Srgrimes int cflag, dflag, sflag, isstring2; 1071590Srgrimes 10811895Sache (void) setlocale(LC_CTYPE, ""); 10911895Sache 1101590Srgrimes cflag = dflag = sflag = 0; 11124360Simp while ((ch = getopt(argc, argv, "cds")) != -1) 1121590Srgrimes switch((char)ch) { 1131590Srgrimes case 'c': 1141590Srgrimes cflag = 1; 1151590Srgrimes break; 1161590Srgrimes case 'd': 1171590Srgrimes dflag = 1; 1181590Srgrimes break; 1191590Srgrimes case 's': 1201590Srgrimes sflag = 1; 1211590Srgrimes break; 1221590Srgrimes case '?': 1231590Srgrimes default: 1241590Srgrimes usage(); 1251590Srgrimes } 1261590Srgrimes argc -= optind; 1271590Srgrimes argv += optind; 1281590Srgrimes 1291590Srgrimes switch(argc) { 1301590Srgrimes case 0: 1311590Srgrimes default: 1321590Srgrimes usage(); 1331590Srgrimes /* NOTREACHED */ 1341590Srgrimes case 1: 1351590Srgrimes isstring2 = 0; 1361590Srgrimes break; 1371590Srgrimes case 2: 1381590Srgrimes isstring2 = 1; 1391590Srgrimes break; 1401590Srgrimes } 1411590Srgrimes 1421590Srgrimes /* 1431590Srgrimes * tr -ds [-c] string1 string2 1441590Srgrimes * Delete all characters (or complemented characters) in string1. 1451590Srgrimes * Squeeze all characters in string2. 1461590Srgrimes */ 1471590Srgrimes if (dflag && sflag) { 1481590Srgrimes if (!isstring2) 1491590Srgrimes usage(); 1501590Srgrimes 1511590Srgrimes setup(string1, argv[0], &s1, cflag); 1521590Srgrimes setup(string2, argv[1], &s2, 0); 1538874Srgrimes 1541590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) 1551590Srgrimes if (!string1[ch] && (!string2[ch] || lastch != ch)) { 1561590Srgrimes lastch = ch; 1571590Srgrimes (void)putchar(ch); 1581590Srgrimes } 1591590Srgrimes exit(0); 1601590Srgrimes } 1611590Srgrimes 1621590Srgrimes /* 1631590Srgrimes * tr -d [-c] string1 1641590Srgrimes * Delete all characters (or complemented characters) in string1. 1651590Srgrimes */ 1661590Srgrimes if (dflag) { 1671590Srgrimes if (isstring2) 1681590Srgrimes usage(); 1691590Srgrimes 1701590Srgrimes setup(string1, argv[0], &s1, cflag); 1711590Srgrimes 1721590Srgrimes while ((ch = getchar()) != EOF) 1731590Srgrimes if (!string1[ch]) 1741590Srgrimes (void)putchar(ch); 1751590Srgrimes exit(0); 1761590Srgrimes } 1771590Srgrimes 1781590Srgrimes /* 1791590Srgrimes * tr -s [-c] string1 1801590Srgrimes * Squeeze all characters (or complemented characters) in string1. 1811590Srgrimes */ 1821590Srgrimes if (sflag && !isstring2) { 1831590Srgrimes setup(string1, argv[0], &s1, cflag); 1841590Srgrimes 1851590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) 1861590Srgrimes if (!string1[ch] || lastch != ch) { 1871590Srgrimes lastch = ch; 1881590Srgrimes (void)putchar(ch); 1891590Srgrimes } 1901590Srgrimes exit(0); 1911590Srgrimes } 1921590Srgrimes 1931590Srgrimes /* 1941590Srgrimes * tr [-cs] string1 string2 1951590Srgrimes * Replace all characters (or complemented characters) in string1 with 1961590Srgrimes * the character in the same position in string2. If the -s option is 1971590Srgrimes * specified, squeeze all the characters in string2. 1981590Srgrimes */ 1991590Srgrimes if (!isstring2) 2001590Srgrimes usage(); 2011590Srgrimes 2021590Srgrimes s1.str = argv[0]; 2031590Srgrimes s2.str = argv[1]; 2041590Srgrimes 2051590Srgrimes if (cflag) 2061590Srgrimes for (cnt = NCHARS, p = string1; cnt--;) 2071590Srgrimes *p++ = OOBCH; 2081590Srgrimes 2091590Srgrimes if (!next(&s2)) 21028368Scharnier errx(1, "empty string2"); 2111590Srgrimes 2121590Srgrimes /* If string2 runs out of characters, use the last one specified. */ 2131590Srgrimes if (sflag) 2141590Srgrimes while (next(&s1)) { 2151590Srgrimes string1[s1.lastch] = ch = s2.lastch; 2161590Srgrimes string2[ch] = 1; 2171590Srgrimes (void)next(&s2); 2181590Srgrimes } 2191590Srgrimes else 2201590Srgrimes while (next(&s1)) { 2211590Srgrimes string1[s1.lastch] = ch = s2.lastch; 2221590Srgrimes (void)next(&s2); 2231590Srgrimes } 2241590Srgrimes 2251590Srgrimes if (cflag) 2261590Srgrimes for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt) 2271590Srgrimes *p = *p == OOBCH ? ch : cnt; 2281590Srgrimes 2291590Srgrimes if (sflag) 2301590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) { 2311590Srgrimes ch = string1[ch]; 2321590Srgrimes if (!string2[ch] || lastch != ch) { 2331590Srgrimes lastch = ch; 2341590Srgrimes (void)putchar(ch); 2351590Srgrimes } 2361590Srgrimes } 2371590Srgrimes else 2381590Srgrimes while ((ch = getchar()) != EOF) 2391590Srgrimes (void)putchar(string1[ch]); 2401590Srgrimes exit (0); 2411590Srgrimes} 2421590Srgrimes 2431590Srgrimesstatic void 2441590Srgrimessetup(string, arg, str, cflag) 2451590Srgrimes int *string; 2461590Srgrimes char *arg; 2471590Srgrimes STR *str; 2481590Srgrimes int cflag; 2491590Srgrimes{ 2501590Srgrimes register int cnt, *p; 2511590Srgrimes 2521590Srgrimes str->str = arg; 2531590Srgrimes bzero(string, NCHARS * sizeof(int)); 2541590Srgrimes while (next(str)) 2551590Srgrimes string[str->lastch] = 1; 2561590Srgrimes if (cflag) 2571590Srgrimes for (p = string, cnt = NCHARS; cnt--; ++p) 2581590Srgrimes *p = !*p; 2591590Srgrimes} 2601590Srgrimes 2611590Srgrimesstatic void 2621590Srgrimesusage() 2631590Srgrimes{ 26428368Scharnier (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", 26528368Scharnier "usage: tr [-cs] string1 string2", 26628368Scharnier " tr [-c] -d string1", 26728368Scharnier " tr [-c] -s string1", 26828368Scharnier " tr [-c] -ds string1 string2"); 2691590Srgrimes exit(1); 2701590Srgrimes} 271