tr.c revision 1590
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 351590Srgrimesstatic 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 411590Srgrimesstatic char sccsid[] = "@(#)tr.c 8.1 (Berkeley) 6/6/93"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 441590Srgrimes#include <sys/types.h> 451590Srgrimes#include <stdio.h> 461590Srgrimes#include <stdlib.h> 471590Srgrimes#include <string.h> 481590Srgrimes#include "extern.h" 491590Srgrimes 501590Srgrimesstatic int string1[NCHARS] = { 511590Srgrimes 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ASCII */ 521590Srgrimes 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 531590Srgrimes 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 541590Srgrimes 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 551590Srgrimes 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 561590Srgrimes 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 571590Srgrimes 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 581590Srgrimes 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 591590Srgrimes 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 601590Srgrimes 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 611590Srgrimes 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 621590Srgrimes 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 631590Srgrimes 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 641590Srgrimes 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 651590Srgrimes 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 661590Srgrimes 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 671590Srgrimes 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 681590Srgrimes 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 691590Srgrimes 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 701590Srgrimes 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 711590Srgrimes 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 721590Srgrimes 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 731590Srgrimes 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 741590Srgrimes 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 751590Srgrimes 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 761590Srgrimes 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 771590Srgrimes 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 781590Srgrimes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 791590Srgrimes 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 801590Srgrimes 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 811590Srgrimes 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 821590Srgrimes 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 831590Srgrimes}, string2[NCHARS]; 841590Srgrimes 851590SrgrimesSTR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL }; 861590SrgrimesSTR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL }; 871590Srgrimes 881590Srgrimesstatic void setup __P((int *, char *, STR *, int)); 891590Srgrimesstatic void usage __P((void)); 901590Srgrimes 911590Srgrimesint 921590Srgrimesmain(argc, argv) 931590Srgrimes int argc; 941590Srgrimes char **argv; 951590Srgrimes{ 961590Srgrimes register int ch, cnt, lastch, *p; 971590Srgrimes int cflag, dflag, sflag, isstring2; 981590Srgrimes 991590Srgrimes cflag = dflag = sflag = 0; 1001590Srgrimes while ((ch = getopt(argc, argv, "cds")) != EOF) 1011590Srgrimes switch((char)ch) { 1021590Srgrimes case 'c': 1031590Srgrimes cflag = 1; 1041590Srgrimes break; 1051590Srgrimes case 'd': 1061590Srgrimes dflag = 1; 1071590Srgrimes break; 1081590Srgrimes case 's': 1091590Srgrimes sflag = 1; 1101590Srgrimes break; 1111590Srgrimes case '?': 1121590Srgrimes default: 1131590Srgrimes usage(); 1141590Srgrimes } 1151590Srgrimes argc -= optind; 1161590Srgrimes argv += optind; 1171590Srgrimes 1181590Srgrimes switch(argc) { 1191590Srgrimes case 0: 1201590Srgrimes default: 1211590Srgrimes usage(); 1221590Srgrimes /* NOTREACHED */ 1231590Srgrimes case 1: 1241590Srgrimes isstring2 = 0; 1251590Srgrimes break; 1261590Srgrimes case 2: 1271590Srgrimes isstring2 = 1; 1281590Srgrimes break; 1291590Srgrimes } 1301590Srgrimes 1311590Srgrimes /* 1321590Srgrimes * tr -ds [-c] string1 string2 1331590Srgrimes * Delete all characters (or complemented characters) in string1. 1341590Srgrimes * Squeeze all characters in string2. 1351590Srgrimes */ 1361590Srgrimes if (dflag && sflag) { 1371590Srgrimes if (!isstring2) 1381590Srgrimes usage(); 1391590Srgrimes 1401590Srgrimes setup(string1, argv[0], &s1, cflag); 1411590Srgrimes setup(string2, argv[1], &s2, 0); 1421590Srgrimes 1431590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) 1441590Srgrimes if (!string1[ch] && (!string2[ch] || lastch != ch)) { 1451590Srgrimes lastch = ch; 1461590Srgrimes (void)putchar(ch); 1471590Srgrimes } 1481590Srgrimes exit(0); 1491590Srgrimes } 1501590Srgrimes 1511590Srgrimes /* 1521590Srgrimes * tr -d [-c] string1 1531590Srgrimes * Delete all characters (or complemented characters) in string1. 1541590Srgrimes */ 1551590Srgrimes if (dflag) { 1561590Srgrimes if (isstring2) 1571590Srgrimes usage(); 1581590Srgrimes 1591590Srgrimes setup(string1, argv[0], &s1, cflag); 1601590Srgrimes 1611590Srgrimes while ((ch = getchar()) != EOF) 1621590Srgrimes if (!string1[ch]) 1631590Srgrimes (void)putchar(ch); 1641590Srgrimes exit(0); 1651590Srgrimes } 1661590Srgrimes 1671590Srgrimes /* 1681590Srgrimes * tr -s [-c] string1 1691590Srgrimes * Squeeze all characters (or complemented characters) in string1. 1701590Srgrimes */ 1711590Srgrimes if (sflag && !isstring2) { 1721590Srgrimes setup(string1, argv[0], &s1, cflag); 1731590Srgrimes 1741590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) 1751590Srgrimes if (!string1[ch] || lastch != ch) { 1761590Srgrimes lastch = ch; 1771590Srgrimes (void)putchar(ch); 1781590Srgrimes } 1791590Srgrimes exit(0); 1801590Srgrimes } 1811590Srgrimes 1821590Srgrimes /* 1831590Srgrimes * tr [-cs] string1 string2 1841590Srgrimes * Replace all characters (or complemented characters) in string1 with 1851590Srgrimes * the character in the same position in string2. If the -s option is 1861590Srgrimes * specified, squeeze all the characters in string2. 1871590Srgrimes */ 1881590Srgrimes if (!isstring2) 1891590Srgrimes usage(); 1901590Srgrimes 1911590Srgrimes s1.str = argv[0]; 1921590Srgrimes s2.str = argv[1]; 1931590Srgrimes 1941590Srgrimes if (cflag) 1951590Srgrimes for (cnt = NCHARS, p = string1; cnt--;) 1961590Srgrimes *p++ = OOBCH; 1971590Srgrimes 1981590Srgrimes if (!next(&s2)) 1991590Srgrimes err("empty string2"); 2001590Srgrimes 2011590Srgrimes /* If string2 runs out of characters, use the last one specified. */ 2021590Srgrimes if (sflag) 2031590Srgrimes while (next(&s1)) { 2041590Srgrimes string1[s1.lastch] = ch = s2.lastch; 2051590Srgrimes string2[ch] = 1; 2061590Srgrimes (void)next(&s2); 2071590Srgrimes } 2081590Srgrimes else 2091590Srgrimes while (next(&s1)) { 2101590Srgrimes string1[s1.lastch] = ch = s2.lastch; 2111590Srgrimes (void)next(&s2); 2121590Srgrimes } 2131590Srgrimes 2141590Srgrimes if (cflag) 2151590Srgrimes for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt) 2161590Srgrimes *p = *p == OOBCH ? ch : cnt; 2171590Srgrimes 2181590Srgrimes if (sflag) 2191590Srgrimes for (lastch = OOBCH; (ch = getchar()) != EOF;) { 2201590Srgrimes ch = string1[ch]; 2211590Srgrimes if (!string2[ch] || lastch != ch) { 2221590Srgrimes lastch = ch; 2231590Srgrimes (void)putchar(ch); 2241590Srgrimes } 2251590Srgrimes } 2261590Srgrimes else 2271590Srgrimes while ((ch = getchar()) != EOF) 2281590Srgrimes (void)putchar(string1[ch]); 2291590Srgrimes exit (0); 2301590Srgrimes} 2311590Srgrimes 2321590Srgrimesstatic void 2331590Srgrimessetup(string, arg, str, cflag) 2341590Srgrimes int *string; 2351590Srgrimes char *arg; 2361590Srgrimes STR *str; 2371590Srgrimes int cflag; 2381590Srgrimes{ 2391590Srgrimes register int cnt, *p; 2401590Srgrimes 2411590Srgrimes str->str = arg; 2421590Srgrimes bzero(string, NCHARS * sizeof(int)); 2431590Srgrimes while (next(str)) 2441590Srgrimes string[str->lastch] = 1; 2451590Srgrimes if (cflag) 2461590Srgrimes for (p = string, cnt = NCHARS; cnt--; ++p) 2471590Srgrimes *p = !*p; 2481590Srgrimes} 2491590Srgrimes 2501590Srgrimesstatic void 2511590Srgrimesusage() 2521590Srgrimes{ 2531590Srgrimes (void)fprintf(stderr, "usage: tr [-cs] string1 string2\n"); 2541590Srgrimes (void)fprintf(stderr, " tr [-c] -d string1\n"); 2551590Srgrimes (void)fprintf(stderr, " tr [-c] -s string1\n"); 2561590Srgrimes (void)fprintf(stderr, " tr [-c] -ds string1 string2\n"); 2571590Srgrimes exit(1); 2581590Srgrimes} 2591590Srgrimes 2601590Srgrimes#if __STDC__ 2611590Srgrimes#include <stdarg.h> 2621590Srgrimes#else 2631590Srgrimes#include <varargs.h> 2641590Srgrimes#endif 2651590Srgrimes 2661590Srgrimesvoid 2671590Srgrimes#if __STDC__ 2681590Srgrimeserr(const char *fmt, ...) 2691590Srgrimes#else 2701590Srgrimeserr(fmt, va_alist) 2711590Srgrimes char *fmt; 2721590Srgrimes va_dcl 2731590Srgrimes#endif 2741590Srgrimes{ 2751590Srgrimes va_list ap; 2761590Srgrimes#if __STDC__ 2771590Srgrimes va_start(ap, fmt); 2781590Srgrimes#else 2791590Srgrimes va_start(ap); 2801590Srgrimes#endif 2811590Srgrimes (void)fprintf(stderr, "tr: "); 2821590Srgrimes (void)vfprintf(stderr, fmt, ap); 2831590Srgrimes va_end(ap); 2841590Srgrimes (void)fprintf(stderr, "\n"); 2851590Srgrimes exit(1); 2861590Srgrimes /* NOTREACHED */ 2871590Srgrimes} 288