blob: ebb64799f4f42bd34a39f3013d22661d7d2659c0 [file] [log] [blame]
Erik Andersenfb002d02000-03-05 08:07:00 +00001/* vi: set sw=4 ts=4: */
2/*
Erik Andersen8f8d6d52000-05-01 22:30:37 +00003 * Mini tr implementation for busybox
Erik Andersenfb002d02000-03-05 08:07:00 +00004 *
Erik Andersen5afc8642000-05-02 00:07:56 +00005 * Copyright (c) Michiel Huisjes
6 *
7 * This version of tr is adapted from Minix tr and was modified
8 * by Erik Andersen <andersee@debian.org> to be used in busybox.
Erik Andersenfb002d02000-03-05 08:07:00 +00009 *
Erik Andersen8f8d6d52000-05-01 22:30:37 +000010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Original copyright notice is retained at the end of this file.
Erik Andersenfb002d02000-03-05 08:07:00 +000025 */
26
Erik Andersenfb002d02000-03-05 08:07:00 +000027#include "internal.h"
Erik Andersenfb002d02000-03-05 08:07:00 +000028#include <stdio.h>
Erik Andersenfb002d02000-03-05 08:07:00 +000029#include <string.h>
Erik Andersen8f8d6d52000-05-01 22:30:37 +000030#include <stdlib.h>
Erik Andersenfb002d02000-03-05 08:07:00 +000031#include <unistd.h>
Erik Andersen8f8d6d52000-05-01 22:30:37 +000032#include <sys/types.h>
Erik Andersenfb002d02000-03-05 08:07:00 +000033
Erik Andersenfb002d02000-03-05 08:07:00 +000034
Erik Andersenfb002d02000-03-05 08:07:00 +000035
Erik Andersen8f8d6d52000-05-01 22:30:37 +000036#ifdef TRUE
37#undef TRUE
38#undef FALSE
39#define TRUE 1
40#define FALSE 0
41#endif
Erik Andersenfb002d02000-03-05 08:07:00 +000042
Erik Andersen8f8d6d52000-05-01 22:30:37 +000043#define ASCII 0377
Erik Andersenfb002d02000-03-05 08:07:00 +000044
Erik Andersen8f8d6d52000-05-01 22:30:37 +000045/* some glabals shared across this file */
46static char com_fl, del_fl, sq_fl;
47static unsigned char output[BUFSIZ], input[BUFSIZ];
48static unsigned char vector[ASCII + 1];
49static char invec[ASCII + 1], outvec[ASCII + 1];
50static short in_index, out_index;
Erik Andersenfb002d02000-03-05 08:07:00 +000051
Erik Andersenfb002d02000-03-05 08:07:00 +000052
Erik Andersen8f8d6d52000-05-01 22:30:37 +000053static void convert()
Erik Andersenfb002d02000-03-05 08:07:00 +000054{
Erik Andersen8f8d6d52000-05-01 22:30:37 +000055 short read_chars = 0;
56 short c, coded;
57 short last = -1;
Erik Andersenfb002d02000-03-05 08:07:00 +000058
Erik Andersen8f8d6d52000-05-01 22:30:37 +000059 for (;;) {
60 if (in_index == read_chars) {
61 if ((read_chars = read(0, (char *) input, BUFSIZ)) <= 0) {
62 if (write(1, (char *) output, out_index) != out_index)
63 write(2, "Bad write\n", 10);
64 exit(0);
Erik Andersenfb002d02000-03-05 08:07:00 +000065 }
Erik Andersen8f8d6d52000-05-01 22:30:37 +000066 in_index = 0;
67 }
68 c = input[in_index++];
69 coded = vector[c];
70 if (del_fl && invec[c])
71 continue;
72 if (sq_fl && last == coded && outvec[coded])
73 continue;
74 output[out_index++] = last = coded;
75 if (out_index == BUFSIZ) {
76 if (write(1, (char *) output, out_index) != out_index) {
77 write(2, "Bad write\n", 10);
78 exit(1);
Erik Andersenfb002d02000-03-05 08:07:00 +000079 }
Erik Andersen8f8d6d52000-05-01 22:30:37 +000080 out_index = 0;
81 }
Erik Andersenfb002d02000-03-05 08:07:00 +000082 }
83
Erik Andersenfb002d02000-03-05 08:07:00 +000084 /* NOTREACHED */
Erik Andersen8f8d6d52000-05-01 22:30:37 +000085}
86
87static void map(register unsigned char *string1, register unsigned char *string2)
88{
89 unsigned char last = '0';
90
91 while (*string1) {
92 if (*string2 == '\0')
93 vector[*string1] = last;
94 else
95 vector[*string1] = last = *string2++;
96 string1++;
97 }
98}
99
100static void expand(register char *arg, register unsigned char *buffer)
101{
102 int i, ac;
103
104 while (*arg) {
105 if (*arg == '\\') {
106 arg++;
107 i = ac = 0;
108 if (*arg >= '0' && *arg <= '7') {
109 do {
110 ac = (ac << 3) + *arg++ - '0';
111 i++;
112 } while (i < 4 && *arg >= '0' && *arg <= '7');
113 *buffer++ = ac;
114 } else if (*arg != '\0')
115 *buffer++ = *arg++;
116 } else if (*arg == '[') {
117 arg++;
118 i = *arg++;
119 if (*arg++ != '-') {
120 *buffer++ = '[';
121 arg -= 2;
122 continue;
123 }
124 ac = *arg++;
125 while (i <= ac)
126 *buffer++ = i++;
127 arg++; /* Skip ']' */
128 } else
129 *buffer++ = *arg++;
130 }
131}
132
133static void complement(unsigned char *buffer)
134{
135 register unsigned char *ptr;
136 register short i, index;
137 unsigned char conv[ASCII + 2];
138
139 index = 0;
140 for (i = 1; i <= ASCII; i++) {
141 for (ptr = buffer; *ptr; ptr++)
142 if (*ptr == i)
143 break;
144 if (*ptr == '\0')
145 conv[index++] = i & ASCII;
146 }
147 conv[index] = '\0';
148 strcpy((char *) buffer, (char *) conv);
149}
150
151extern int tr_main(int argc, char **argv)
152{
153 register unsigned char *ptr;
154 int index = 1;
155 short i;
156
157 if (argc > 1 && argv[index][0] == '-') {
158 for (ptr = (unsigned char *) &argv[index][1]; *ptr; ptr++) {
159 switch (*ptr) {
160 case 'c':
161 com_fl = TRUE;
162 break;
163 case 'd':
164 del_fl = TRUE;
165 break;
166 case 's':
167 sq_fl = TRUE;
168 break;
169 default:
170 usage("tr [-cds] STRING1 [STRING2]\n"
171#ifndef BB_FEATURE_TRIVIAL_HELP
172 "\nTranslate, squeeze, and/or delete characters from\n"
173 "standard input, writing to standard output.\n\n"
174 "Options:\n"
175 "\t-c\ttake complement of STRING1\n"
176 "\t-d\tdelete input characters coded STRING1\n"
177 "\t-s\tsqueeze multiple output characters of STRING2 into one character\n"
178#endif
179 );
180 }
181 }
182 index++;
183 }
184 for (i = 0; i <= ASCII; i++) {
185 vector[i] = i;
186 invec[i] = outvec[i] = FALSE;
187 }
188
189 if (argv[index] != NULL) {
190 expand(argv[index++], input);
191 if (com_fl)
192 complement(input);
193 if (argv[index] != NULL)
194 expand(argv[index], output);
195 if (argv[index] != NULL)
196 map(input, output);
197 for (ptr = input; *ptr; ptr++)
198 invec[*ptr] = TRUE;
199 for (ptr = output; *ptr; ptr++)
200 outvec[*ptr] = TRUE;
201 }
202 convert();
Erik Andersenfb002d02000-03-05 08:07:00 +0000203 return (0);
204}
205
Erik Andersenfb002d02000-03-05 08:07:00 +0000206/*
Erik Andersen8f8d6d52000-05-01 22:30:37 +0000207 * Copyright (c) 1987,1997, Prentice Hall
208 * All rights reserved.
209 *
210 * Redistribution and use of the MINIX operating system in source and
211 * binary forms, with or without modification, are permitted provided
212 * that the following conditions are met:
213 *
214 * Redistributions of source code must retain the above copyright
215 * notice, this list of conditions and the following disclaimer.
216 *
217 * Redistributions in binary form must reproduce the above
218 * copyright notice, this list of conditions and the following
219 * disclaimer in the documentation and/or other materials provided
220 * with the distribution.
221 *
222 * Neither the name of Prentice Hall nor the names of the software
223 * authors or contributors may be used to endorse or promote
224 * products derived from this software without specific prior
225 * written permission.
226 *
227 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
228 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
229 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
230 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
231 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
232 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
233 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
235 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
236 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
237 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
238 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
239 *
Erik Andersenfb002d02000-03-05 08:07:00 +0000240 */
Erik Andersenfb002d02000-03-05 08:07:00 +0000241