trivial pathname changes
[unix-history] / usr / src / usr.bin / tr / tr.c
CommitLineData
5ad3291e
KB
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
cb956e54 5 * %sccs.include.redist.c%
5ad3291e
KB
6 */
7
8#ifndef lint
9char copyright[] =
10"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
11 All rights reserved.\n";
12#endif /* not lint */
13
14#ifndef lint
cb956e54 15static char sccsid[] = "@(#)tr.c 4.6 (Berkeley) %G%";
5ad3291e
KB
16#endif /* not lint */
17
18#include <sys/types.h>
14db73f8 19#include <stdio.h>
5ad3291e 20#include <ctype.h>
14db73f8 21
5ad3291e
KB
22#define NCHARS 256 /* size of u_char */
23#define OOBCH 257 /* out of band value */
14db73f8 24
5ad3291e
KB
25typedef struct {
26 char *str;
27 int lastch, endrange;
28 enum { NORM, INRANGE, EOS } state;
29} STR;
14db73f8 30
5ad3291e
KB
31main(argc, argv)
32 int argc;
33 char **argv;
34{
35 extern int optind;
36 STR s1, s2;
37 register int ch, indx, lastch;
38 int cflag, dflag, sflag;
39 u_char *tp, tab[NCHARS], squeeze[NCHARS];
14db73f8 40
5ad3291e
KB
41 cflag = dflag = sflag = 0;
42 while ((ch = getopt(argc, argv, "cds")) != EOF)
43 switch((char)ch) {
44 case 'c':
45 cflag = 1;
46 break;
47 case 'd':
48 dflag = 1;
49 break;
50 case 's':
51 sflag = 1;
52 break;
53 case '?':
54 default:
55 fprintf(stderr,
56 "usage: tr [-cds] [string1 [string2]]\n");
57 exit(1);
14db73f8 58 }
5ad3291e
KB
59 argc -= optind;
60 argv += optind;
61
62 /*
63 * the original tr was amazingly tolerant of the command line.
64 * Neither -c or -s have any effect unless there are two strings.
65 * Extra arguments are silently ignored. Bag this noise, they
66 * should all be errors.
67 */
68 if (argc < 2 && !dflag) {
69 while ((ch = getchar()) != EOF)
70 putchar(ch);
71 exit(0);
14db73f8
BJ
72 }
73
5ad3291e
KB
74 bzero(tab, NCHARS);
75 if (sflag) {
76 s1.str = argv[1];
77 s1.state = NORM;
78 s1.lastch = OOBCH;
79 while (next(&s1))
80 squeeze[s1.lastch] = 1;
81 }
82 if (dflag) {
83 s1.str = argv[0];
84 s1.state = NORM;
85 s1.lastch = OOBCH;
86 while (next(&s1))
87 tab[s1.lastch] = 1;
88 if (cflag)
89 for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx)
90 *tp = !*tp;
91 if (sflag)
92 for (lastch = OOBCH; (ch = getchar()) != EOF;) {
93 if (tab[ch] || (squeeze[ch] && lastch == ch))
94 continue;
95 lastch = ch;
96 putchar(ch);
97 }
98 else
99 while ((ch = getchar()) != EOF)
100 if (!tab[ch])
101 putchar(ch);
102 } else {
103 s1.str = argv[0];
104 s2.str = argv[1];
105 s1.state = s2.state = NORM;
106 s1.lastch = s2.lastch = OOBCH;
107 if (cflag) {
108 /*
109 * if cflag is set, tr just pretends it only got one
110 * character in string2. As reasonable as anything
111 * else. Should really be an error.
112 */
113 while (next(&s2));
114 lastch = s2.lastch;
115 for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx)
116 *tp = lastch;
117 while (next(&s1))
118 tab[s1.lastch] = s1.lastch;
119 } else {
120 for (tp = tab, indx = 0; indx < NCHARS; ++tp, ++indx)
121 *tp = indx;
122 while (next(&s1)) {
123 (void)next(&s2);
124 tab[s1.lastch] = s2.lastch;
125 }
126 }
127 if (sflag)
128 for (lastch = OOBCH; (ch = getchar()) != EOF;) {
129 ch = tab[ch];
130 if (squeeze[ch] && lastch == ch)
131 continue;
132 lastch = ch;
133 putchar(ch);
bbcc5e9f 134 }
5ad3291e
KB
135 else
136 while ((ch = getchar()) != EOF)
137 putchar((int)tab[ch]);
14db73f8
BJ
138 }
139 exit(0);
140}
141
142next(s)
5ad3291e 143 STR *s;
14db73f8 144{
5ad3291e 145 register int ch;
14db73f8 146
5ad3291e
KB
147 if (s->state == EOS)
148 return(0);
149 if (s->state == INRANGE) {
150 if (++s->lastch == s->endrange)
151 s->state = NORM;
152 return(1);
153 }
154 if (!(ch = *s->str++)) {
155 s->state = EOS;
156 return(0);
14db73f8 157 }
44ec1783
KB
158 if (ch == '\\') { /* \### */
159 s->lastch = tran(s);
5ad3291e
KB
160 return(1);
161 }
162 if (ch == '-') { /* ranges */
44ec1783
KB
163 if (s->lastch == OOBCH) /* "-a" */
164 goto fail2;
165 if (!(ch = *s->str++)) /* "a-" */
166 goto fail1;
167 if (ch == '\\') /* \### */
168 ch = tran(s);
5ad3291e 169 if (s->lastch > ch) { /* "z-a" */
44ec1783
KB
170fail1: --s->str;
171fail2: s->lastch = '-';
5ad3291e 172 return(1);
14db73f8 173 }
5ad3291e
KB
174 if (s->lastch == ch) /* "a-a" */
175 return(next(s));
176 s->state = INRANGE; /* "a-z" */
44ec1783 177 s->endrange = ch;
5ad3291e 178 return(1);
14db73f8 179 }
5ad3291e
KB
180 s->lastch = ch;
181 return(1);
14db73f8 182}
44ec1783
KB
183
184tran(s)
185 register STR *s;
186{
187 register int ch, cnt, val;
188
35594124
KB
189 for (val = cnt = 0; isascii(ch = *s->str++) && isdigit(ch)
190 && cnt++ < 3;)
44ec1783
KB
191 val = val * 8 + ch - '0';
192 return(cnt ? val : ch);
193}