Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/tr.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/tr.c
r821 r1770 16 16 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 17 17 */ 18 19 #include "busybox.h" 20 21 // Even with -funsigned-char, gcc still complains about char as an array index. 22 23 #define GCC4_IS_STUPID int 18 /* http://www.opengroup.org/onlinepubs/009695399/utilities/tr.html 19 * TODO: xdigit, graph, print 20 */ 21 #include "libbb.h" 24 22 25 23 #define ASCII 0377 26 24 27 /* some "globals" shared across this file */ 28 static char com_fl, del_fl, sq_fl; 29 /* these last are pointers to static buffers declared in tr_main */ 30 static char *poutput, *pvector, *pinvec, *poutvec; 31 32 static void convert(void) 33 { 34 int read_chars = 0, in_index = 0, out_index = 0, c, coded, last = -1; 35 36 for (;;) { 37 // If we're out of input, flush output and read more input. 38 39 if (in_index == read_chars) { 40 if (out_index) { 41 if (write(1, (char *) poutput, out_index) != out_index) 42 bb_error_msg_and_die(bb_msg_write_error); 43 out_index = 0; 44 } 45 46 if ((read_chars = read(0, bb_common_bufsiz1, BUFSIZ)) <= 0) { 47 if (write(1, (char *) poutput, out_index) != out_index) 48 bb_error_msg(bb_msg_write_error); 49 exit(0); 50 } 51 in_index = 0; 52 } 53 c = bb_common_bufsiz1[in_index++]; 54 coded = pvector[c]; 55 if (del_fl && pinvec[c]) 56 continue; 57 if (sq_fl && last == coded && (pinvec[c] || poutvec[coded])) 58 continue; 59 poutput[out_index++] = last = coded; 60 } 61 62 /* NOTREACHED */ 63 } 64 65 static void map(char *string1, unsigned int string1_len, 66 char *string2, unsigned int string2_len) 25 #define TR_OPT_complement (1<<0) 26 #define TR_OPT_delete (1<<1) 27 #define TR_OPT_squeeze_reps (1<<2) 28 29 static void map(char *pvector, 30 unsigned char *string1, unsigned int string1_len, 31 unsigned char *string2, unsigned int string2_len) 67 32 { 68 33 char last = '0'; … … 71 36 for (j = 0, i = 0; i < string1_len; i++) { 72 37 if (string2_len <= j) 73 pvector[ (GCC4_IS_STUPID)string1[i]] = last;38 pvector[string1[i]] = last; 74 39 else 75 pvector[ (GCC4_IS_STUPID)string1[i]] = last = string2[j++];40 pvector[string1[i]] = last = string2[j++]; 76 41 } 77 42 } … … 85 50 { 86 51 char *buffer_start = buffer; 87 int i, ac; 88 52 unsigned i; /* XXX: FIXME: use unsigned char? */ 53 unsigned char ac; 54 #define CLO ":]\0" 55 static const char classes[] ALIGN1 = 56 "alpha"CLO "alnum"CLO "digit"CLO "lower"CLO "upper"CLO "space"CLO 57 "blank"CLO "punct"CLO "cntrl"CLO; 58 #define CLASS_invalid 0 /* we increment the retval */ 59 #define CLASS_alpha 1 60 #define CLASS_alnum 2 61 #define CLASS_digit 3 62 #define CLASS_lower 4 63 #define CLASS_upper 5 64 #define CLASS_space 6 65 #define CLASS_blank 7 66 #define CLASS_punct 8 67 #define CLASS_cntrl 9 68 //#define CLASS_xdigit 10 69 //#define CLASS_graph 11 70 //#define CLASS_print 12 89 71 while (*arg) { 90 72 if (*arg == '\\') { … … 93 75 } else if (*(arg+1) == '-') { 94 76 ac = *(arg+2); 95 if (ac == 0) {77 if (ac == 0) { 96 78 *buffer++ = *arg++; 97 79 continue; … … 105 87 i = *arg++; 106 88 if (ENABLE_FEATURE_TR_CLASSES && i == ':') { 107 if (strncmp(arg, "alpha", 5) == 0) { 89 smalluint j; 90 { /* not really pretty.. */ 91 char *tmp = xstrndup(arg, 7); // warning: xdigit needs 8, not 7 92 j = index_in_strings(classes, tmp) + 1; 93 free(tmp); 94 } 95 if (j == CLASS_alnum || j == CLASS_digit) { 96 for (i = '0'; i <= '9'; i++) 97 *buffer++ = i; 98 } 99 if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_upper) { 108 100 for (i = 'A'; i <= 'Z'; i++) 109 101 *buffer++ = i; 102 } 103 if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_lower) { 110 104 for (i = 'a'; i <= 'z'; i++) 111 105 *buffer++ = i; 112 106 } 113 else if (strncmp(arg, "alnum", 5) == 0) { 114 for (i = '0'; i <= '9'; i++) 115 *buffer++ = i; 116 for (i = 'A'; i <= 'Z'; i++) 117 *buffer++ = i; 118 for (i = 'a'; i <= 'z'; i++) 119 *buffer++ = i; 120 } 121 else if (strncmp(arg, "digit", 5) == 0) 122 for (i = '0'; i <= '9'; i++) 123 *buffer++ = i; 124 else if (strncmp(arg, "lower", 5) == 0) 125 for (i = 'a'; i <= 'z'; i++) 126 *buffer++ = i; 127 else if (strncmp(arg, "upper", 5) == 0) 128 for (i = 'A'; i <= 'Z'; i++) 129 *buffer++ = i; 130 else if (strncmp(arg, "space", 5) == 0) { 131 const char s[] = "\t\n\v\f\r "; 132 strcat((char*)buffer, s); 133 buffer += sizeof(s) - 1; 134 } 135 else if (strncmp(arg, "blank", 5) == 0) { 107 if (j == CLASS_space || j == CLASS_blank) { 136 108 *buffer++ = '\t'; 109 if (j == CLASS_space) { 110 *buffer++ = '\n'; 111 *buffer++ = '\v'; 112 *buffer++ = '\f'; 113 *buffer++ = '\r'; 114 } 137 115 *buffer++ = ' '; 138 116 } 139 /* gcc gives a warning if braces aren't used here */ 140 else if (strncmp(arg, "punct", 5) == 0) { 117 if (j == CLASS_punct || j == CLASS_cntrl) { 141 118 for (i = 0; i <= ASCII; i++) 142 if (isprint(i) && (!isalnum(i)) && (!isspace(i))) 119 if ((j == CLASS_punct && 120 isprint(i) && (!isalnum(i)) && (!isspace(i))) || 121 (j == CLASS_cntrl && iscntrl(i))) 143 122 *buffer++ = i; 144 123 } 145 else if (strncmp(arg, "cntrl", 5) == 0) { 146 for (i = 0; i <= ASCII; i++) 147 if (iscntrl(i)) 148 *buffer++ = i; 149 } 150 else { 124 if (j == CLASS_invalid) { 151 125 *buffer++ = '['; 152 126 *buffer++ = ':'; … … 157 131 if (ENABLE_FEATURE_TR_EQUIV && i == '=') { 158 132 *buffer++ = *arg; 159 /* skip the closing =] */ 160 arg += 3; 133 arg += 3; /* Skip the closing =] */ 161 134 continue; 162 135 } … … 169 142 while (i <= ac) 170 143 *buffer++ = i++; 171 arg++; 144 arg++; /* Skip the assumed ']' */ 172 145 } else 173 146 *buffer++ = *arg++; 174 147 } 175 176 148 return (buffer - buffer_start); 177 149 } … … 179 151 static int complement(char *buffer, int buffer_len) 180 152 { 181 register short i, j, ix;153 int i, j, ix; 182 154 char conv[ASCII + 2]; 183 155 … … 194 166 } 195 167 168 int tr_main(int argc, char **argv); 196 169 int tr_main(int argc, char **argv) 197 170 { 198 registerunsigned char *ptr;199 int output_length =0, input_length;171 unsigned char *ptr; 172 int output_length = 0, input_length; 200 173 int idx = 1; 201 174 int i; 202 RESERVE_CONFIG_BUFFER(output, BUFSIZ); 175 smalluint flags = 0; 176 size_t read_chars = 0, in_index = 0, out_index = 0, c, coded, last = -1; 177 RESERVE_CONFIG_UBUFFER(output, BUFSIZ); 203 178 RESERVE_CONFIG_BUFFER(vector, ASCII+1); 204 179 RESERVE_CONFIG_BUFFER(invec, ASCII+1); 205 180 RESERVE_CONFIG_BUFFER(outvec, ASCII+1); 206 181 207 /* ... but make them available globally */208 poutput = output;209 pvector = vector;210 pinvec = invec;211 poutvec = outvec;212 213 182 if (argc > 1 && argv[idx][0] == '-') { 214 183 for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) { 215 switch (*ptr) { 216 case 'c': 217 com_fl = TRUE; 218 break; 219 case 'd': 220 del_fl = TRUE; 221 break; 222 case 's': 223 sq_fl = TRUE; 224 break; 225 default: 184 if (*ptr == 'c') 185 flags |= TR_OPT_complement; 186 else if (*ptr == 'd') 187 flags |= TR_OPT_delete; 188 else if (*ptr == 's') 189 flags |= TR_OPT_squeeze_reps; 190 else 226 191 bb_show_usage(); 227 }228 192 } 229 193 idx++; … … 234 198 } 235 199 200 #define tr_buf bb_common_bufsiz1 236 201 if (argv[idx] != NULL) { 237 input_length = expand(argv[idx++], bb_common_bufsiz1);238 if ( com_fl)239 input_length = complement( bb_common_bufsiz1, input_length);202 input_length = expand(argv[idx++], tr_buf); 203 if (flags & TR_OPT_complement) 204 input_length = complement(tr_buf, input_length); 240 205 if (argv[idx] != NULL) { 241 206 if (*argv[idx] == '\0') 242 207 bb_error_msg_and_die("STRING2 cannot be empty"); 243 208 output_length = expand(argv[idx], output); 244 map( bb_common_bufsiz1, input_length, output, output_length);209 map(vector, tr_buf, input_length, output, output_length); 245 210 } 246 211 for (i = 0; i < input_length; i++) 247 invec[( GCC4_IS_STUPID)bb_common_bufsiz1[i]] = TRUE;212 invec[(unsigned char)tr_buf[i]] = TRUE; 248 213 for (i = 0; i < output_length; i++) 249 outvec[(GCC4_IS_STUPID)output[i]] = TRUE; 250 } 251 convert(); 252 return (0); 253 } 214 outvec[output[i]] = TRUE; 215 } 216 217 for (;;) { 218 /* If we're out of input, flush output and read more input. */ 219 if (in_index == read_chars) { 220 if (out_index) { 221 xwrite(STDOUT_FILENO, (char *)output, out_index); 222 out_index = 0; 223 } 224 read_chars = read(STDIN_FILENO, tr_buf, BUFSIZ); 225 if (read_chars <= 0) { 226 if (write(STDOUT_FILENO, (char *)output, out_index) != out_index) 227 bb_perror_msg(bb_msg_write_error); 228 exit(EXIT_SUCCESS); 229 } 230 in_index = 0; 231 } 232 c = tr_buf[in_index++]; 233 coded = vector[c]; 234 if ((flags & TR_OPT_delete) && invec[c]) 235 continue; 236 if ((flags & TR_OPT_squeeze_reps) && last == coded && 237 (invec[c] || outvec[coded])) 238 continue; 239 output[out_index++] = last = coded; 240 } 241 /* NOTREACHED */ 242 return EXIT_SUCCESS; 243 }
Note:
See TracChangeset
for help on using the changeset viewer.