1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini tr implementation for busybox 4 * 5 * 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. 9 * 10 * 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. 25 */ 26 27#include <stdio.h> 28#include <string.h> 29#include <stdlib.h> 30#include <unistd.h> 31#include <sys/types.h> 32#include "busybox.h" 33 34/* This must be a #define, since when DODEBUG and BUFFERS_GO_IN_BSS are 35 * enabled, we otherwise get a "storage size isn't constant error. */ 36#define ASCII 0377 37 38/* some "globals" shared across this file */ 39static char com_fl, del_fl, sq_fl; 40static short in_index, out_index; 41/* these last are pointers to static buffers declared in tr_main */ 42static unsigned char *poutput, *pinput; 43static unsigned char *pvector; 44static char *pinvec, *poutvec; 45 46 47static void convert() 48{ 49 short read_chars = 0; 50 short c, coded; 51 short last = -1; 52 53 for (;;) { 54 if (in_index == read_chars) { 55 if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) { 56 if (write(1, (char *) poutput, out_index) != out_index) 57 error_msg("%s", write_error); 58 exit(0); 59 } 60 in_index = 0; 61 } 62 c = pinput[in_index++]; 63 coded = pvector[c]; 64 if (del_fl && pinvec[c]) 65 continue; 66 if (sq_fl && last == coded && (pinvec[c] || poutvec[coded])) 67 continue; 68 poutput[out_index++] = last = coded; 69 if (out_index == BUFSIZ) { 70 if (write(1, (char *) poutput, out_index) != out_index) 71 error_msg_and_die("%s", write_error); 72 out_index = 0; 73 } 74 } 75 76 /* NOTREACHED */ 77} 78 79static void map(register unsigned char *string1, unsigned int string1_len, 80 register unsigned char *string2, unsigned int string2_len) 81{ 82 unsigned char last = '0'; 83 unsigned int i, j; 84 85 for (j = 0, i = 0; i < string1_len; i++) { 86 if (string2_len <= j) 87 pvector[string1[i]] = last; 88 else 89 pvector[string1[i]] = last = string2[j++]; 90 } 91} 92 93/* supported constructs: 94 * Ranges, e.g., [0-9] ==> 0123456789 95 * Escapes, e.g., \a ==> Control-G 96 */ 97static unsigned int expand(const char *arg, register unsigned char *buffer) 98{ 99 unsigned char *buffer_start = buffer; 100 int i, ac; 101 102 while (*arg) { 103 if (*arg == '\\') { 104 arg++; 105 *buffer++ = process_escape_sequence(&arg); 106 } else if (*(arg+1) == '-') { 107 ac = *(arg+2); 108 if(ac == 0) { 109 *buffer++ = *arg++; 110 continue; 111 } 112 i = *arg; 113 while (i <= ac) 114 *buffer++ = i++; 115 arg += 3; /* Skip the assumed a-z */ 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 the assumed ']' */ 128 } else 129 *buffer++ = *arg++; 130 } 131 132 return (buffer - buffer_start); 133} 134 135static int complement(unsigned char *buffer, int buffer_len) 136{ 137 register short i, j, ix; 138 char conv[ASCII + 2]; 139 140 ix = 0; 141 for (i = 0; i <= ASCII; i++) { 142 for (j = 0; j < buffer_len; j++) 143 if (buffer[j] == i) 144 break; 145 if (j == buffer_len) 146 conv[ix++] = i & ASCII; 147 } 148 memcpy(buffer, conv, ix); 149 return ix; 150} 151 152extern int tr_main(int argc, char **argv) 153{ 154 register unsigned char *ptr; 155 int output_length=0, input_length; 156 int idx = 1; 157 int i; 158 RESERVE_BB_BUFFER(output, BUFSIZ); 159 RESERVE_BB_BUFFER(input, BUFSIZ); 160 RESERVE_BB_UBUFFER(vector, ASCII+1); 161 RESERVE_BB_BUFFER(invec, ASCII+1); 162 RESERVE_BB_BUFFER(outvec, ASCII+1); 163 164 /* ... but make them available globally */ 165 poutput = output; 166 pinput = input; 167 pvector = vector; 168 pinvec = invec; 169 poutvec = outvec; 170 171 if (argc > 1 && argv[idx][0] == '-') { 172 for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) { 173 switch (*ptr) { 174 case 'c': 175 com_fl = TRUE; 176 break; 177 case 'd': 178 del_fl = TRUE; 179 break; 180 case 's': 181 sq_fl = TRUE; 182 break; 183 default: 184 show_usage(); 185 } 186 } 187 idx++; 188 } 189 for (i = 0; i <= ASCII; i++) { 190 vector[i] = i; 191 invec[i] = outvec[i] = FALSE; 192 } 193 194 if (argv[idx] != NULL) { 195 input_length = expand(argv[idx++], input); 196 if (com_fl) 197 input_length = complement(input, input_length); 198 if (argv[idx] != NULL) { 199 if (*argv[idx] == '\0') 200 error_msg_and_die("STRING2 cannot be empty"); 201 output_length = expand(argv[idx], output); 202 map(input, input_length, output, output_length); 203 } 204 for (i = 0; i < input_length; i++) 205 invec[(int)input[i]] = TRUE; 206 for (i = 0; i < output_length; i++) 207 outvec[(int)output[i]] = TRUE; 208 } 209 convert(); 210 return (0); 211} 212 213/* 214 * Copyright (c) 1987,1997, Prentice Hall 215 * All rights reserved. 216 * 217 * Redistribution and use of the MINIX operating system in source and 218 * binary forms, with or without modification, are permitted provided 219 * that the following conditions are met: 220 * 221 * Redistributions of source code must retain the above copyright 222 * notice, this list of conditions and the following disclaimer. 223 * 224 * Redistributions in binary form must reproduce the above 225 * copyright notice, this list of conditions and the following 226 * disclaimer in the documentation and/or other materials provided 227 * with the distribution. 228 * 229 * Neither the name of Prentice Hall nor the names of the software 230 * authors or contributors may be used to endorse or promote 231 * products derived from this software without specific prior 232 * written permission. 233 * 234 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND 235 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 236 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 237 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 238 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE 239 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 242 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 243 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 244 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 245 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 246 * 247 */ 248 249