|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: char copyright[] = ! 22: "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ ! 23: All rights reserved.\n"; ! 24: #endif /* not lint */ ! 25: ! 26: #ifndef lint ! 27: static char sccsid[] = "@(#)tr.c 4.7 (Berkeley) 7/23/90"; ! 28: #endif /* not lint */ ! 29: ! 30: #include <sys/types.h> ! 31: #include <stdio.h> ! 32: #include <ctype.h> ! 33: ! 34: #define NCHARS 256 /* size of u_char */ ! 35: #define OOBCH 257 /* out of band value */ ! 36: ! 37: typedef struct { ! 38: char *str; ! 39: int lastch, endrange; ! 40: enum { NORM, INRANGE, EOS } state; ! 41: } STR; ! 42: ! 43: main(argc, argv) ! 44: int argc; ! 45: char **argv; ! 46: { ! 47: extern int optind; ! 48: STR s1, s2; ! 49: register int ch, indx, lastch; ! 50: int cflag, dflag, sflag; ! 51: u_char *tp, tab[NCHARS], squeeze[NCHARS]; ! 52: ! 53: cflag = dflag = sflag = 0; ! 54: while ((ch = getopt(argc, argv, "cds")) != EOF) ! 55: switch((char)ch) { ! 56: case 'c': ! 57: cflag = 1; ! 58: break; ! 59: case 'd': ! 60: dflag = 1; ! 61: break; ! 62: case 's': ! 63: sflag = 1; ! 64: break; ! 65: case '?': ! 66: default: ! 67: fprintf(stderr, ! 68: "usage: tr [-cds] [string1 [string2]]\n"); ! 69: exit(1); ! 70: } ! 71: argc -= optind; ! 72: argv += optind; ! 73: ! 74: /* ! 75: * the original tr was amazingly tolerant of the command line. ! 76: * Neither -c or -s have any effect unless there are two strings. ! 77: * Extra arguments are silently ignored. Bag this noise, they ! 78: * should all be errors. ! 79: */ ! 80: if (argc < 2 && !dflag) { ! 81: while ((ch = getchar()) != EOF) ! 82: putchar(ch); ! 83: exit(0); ! 84: } ! 85: ! 86: bzero(tab, NCHARS); ! 87: if (sflag) { ! 88: s1.str = argv[1]; ! 89: s1.state = NORM; ! 90: s1.lastch = OOBCH; ! 91: while (next(&s1)) ! 92: squeeze[s1.lastch] = 1; ! 93: } ! 94: if (dflag) { ! 95: s1.str = argv[0]; ! 96: s1.state = NORM; ! 97: s1.lastch = OOBCH; ! 98: while (next(&s1)) ! 99: tab[s1.lastch] = 1; ! 100: if (cflag) ! 101: for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx) ! 102: *tp = !*tp; ! 103: if (sflag) ! 104: for (lastch = OOBCH; (ch = getchar()) != EOF;) { ! 105: if (tab[ch] || (squeeze[ch] && lastch == ch)) ! 106: continue; ! 107: lastch = ch; ! 108: putchar(ch); ! 109: } ! 110: else ! 111: while ((ch = getchar()) != EOF) ! 112: if (!tab[ch]) ! 113: putchar(ch); ! 114: } else { ! 115: s1.str = argv[0]; ! 116: s2.str = argv[1]; ! 117: s1.state = s2.state = NORM; ! 118: s1.lastch = s2.lastch = OOBCH; ! 119: if (cflag) { ! 120: /* ! 121: * if cflag is set, tr just pretends it only got one ! 122: * character in string2. As reasonable as anything ! 123: * else. Should really be an error. ! 124: */ ! 125: while (next(&s2)); ! 126: lastch = s2.lastch; ! 127: for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx) ! 128: *tp = lastch; ! 129: while (next(&s1)) ! 130: tab[s1.lastch] = s1.lastch; ! 131: } else { ! 132: for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx) ! 133: *tp = indx; ! 134: while (next(&s1)) { ! 135: (void)next(&s2); ! 136: tab[s1.lastch] = s2.lastch; ! 137: } ! 138: } ! 139: if (sflag) ! 140: for (lastch = OOBCH; (ch = getchar()) != EOF;) { ! 141: ch = tab[ch]; ! 142: if (squeeze[ch] && lastch == ch) ! 143: continue; ! 144: lastch = ch; ! 145: putchar(ch); ! 146: } ! 147: else ! 148: while ((ch = getchar()) != EOF) ! 149: putchar((int)tab[ch]); ! 150: } ! 151: exit(0); ! 152: } ! 153: ! 154: next(s) ! 155: register STR *s; ! 156: { ! 157: register int ch; ! 158: ! 159: if (s->state == EOS) ! 160: return(0); ! 161: if (s->state == INRANGE) { ! 162: if (++s->lastch == s->endrange) ! 163: s->state = NORM; ! 164: return(1); ! 165: } ! 166: if (!(ch = *s->str++)) { ! 167: s->state = EOS; ! 168: return(0); ! 169: } ! 170: if (ch == '\\') { /* \### */ ! 171: s->lastch = tran(s); ! 172: return(1); ! 173: } ! 174: if (ch == '-') { /* ranges */ ! 175: if (s->lastch == OOBCH) /* "-a" */ ! 176: goto fail2; ! 177: if (!(ch = *s->str++)) /* "a-" */ ! 178: goto fail1; ! 179: if (ch == '\\') /* \### */ ! 180: ch = tran(s); ! 181: if (s->lastch > ch) { /* "z-a" */ ! 182: fail1: --s->str; ! 183: fail2: s->lastch = '-'; ! 184: return(1); ! 185: } ! 186: if (s->lastch == ch) /* "a-a" */ ! 187: return(next(s)); ! 188: s->state = INRANGE; /* "a-z" */ ! 189: s->endrange = ch; ! 190: return(1); ! 191: } ! 192: s->lastch = ch; ! 193: return(1); ! 194: } ! 195: ! 196: /* ! 197: * Translate \-escapes. Up to 3 octal digits => char; no digits => literal. ! 198: * Unadorned backslash "\" is like \000. ! 199: */ ! 200: tran(s) ! 201: register STR *s; ! 202: { ! 203: register int ch, cnt = 0, val = 0; ! 204: ! 205: for (;;) { ! 206: ch = *s->str++; ! 207: if (!isascii(ch) || !isdigit(ch) || ++cnt > 3) ! 208: break; ! 209: val = val * 8 + ch - '0'; ! 210: } ! 211: if (cnt || ch == 0) ! 212: s->str--; ! 213: return (cnt ? val : ch); ! 214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.