Annotation of 43BSDReno/usr.bin/tr/tr.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.