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