diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-13 22:22:29 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-13 22:22:29 +0000 |
| commit | 3d461676a90eecf584dc07317cdb52eba96aa2d9 (patch) | |
| tree | 7e2a706b4d19a27312be5f036dd557ea518a7790 /coreutils | |
| parent | a89d50fb9addfe0060f697a7e1d31a7b3010b2bb (diff) | |
| download | busybox-w32-3d461676a90eecf584dc07317cdb52eba96aa2d9.tar.gz busybox-w32-3d461676a90eecf584dc07317cdb52eba96aa2d9.tar.bz2 busybox-w32-3d461676a90eecf584dc07317cdb52eba96aa2d9.zip | |
tr: better comments, small code shrink
function old new delta
expand 2232 2230 -2
tr_main 677 655 -22
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/tr.c | 107 |
1 files changed, 60 insertions, 47 deletions
diff --git a/coreutils/tr.c b/coreutils/tr.c index e60e08b25..f6f458bf0 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c | |||
| @@ -42,19 +42,46 @@ static void map(char *pvector, | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | /* supported constructs: | 44 | /* supported constructs: |
| 45 | * Ranges, e.g., [0-9] ==> 0123456789 | 45 | * Ranges, e.g., 0-9 ==> 0123456789 |
| 46 | * Escapes, e.g., \a ==> Control-G | 46 | * Ranges, e.g., [0-9] ==> 0123456789 |
| 47 | * Character classes, e.g. [:upper:] ==> A ... Z | 47 | * Escapes, e.g., \a ==> Control-G |
| 48 | * Character classes, e.g. [:upper:] ==> A...Z | ||
| 49 | * Equiv classess, e.g. [=A=] ==> A (hmmmmmmm?) | ||
| 48 | */ | 50 | */ |
| 49 | static unsigned int expand(const char *arg, char *buffer) | 51 | static unsigned int expand(const char *arg, char *buffer) |
| 50 | { | 52 | { |
| 51 | char *buffer_start = buffer; | 53 | char *buffer_start = buffer; |
| 52 | unsigned i; /* XXX: FIXME: use unsigned char? */ | 54 | unsigned i; /* can't be unsigned char: must be able to hold 256 */ |
| 53 | unsigned char ac; | 55 | unsigned char ac; |
| 56 | |||
| 57 | while (*arg) { | ||
| 58 | if (*arg == '\\') { | ||
| 59 | arg++; | ||
| 60 | *buffer++ = bb_process_escape_sequence(&arg); | ||
| 61 | continue; | ||
| 62 | } | ||
| 63 | if (arg[1] == '-') { /* "0-9..." */ | ||
| 64 | ac = arg[2]; | ||
| 65 | if (ac == '\0') { /* "0-": copy verbatim */ | ||
| 66 | *buffer++ = *arg++; /* copy '0' */ | ||
| 67 | continue; /* next iter will copy '-' and stop */ | ||
| 68 | } | ||
| 69 | i = *arg; | ||
| 70 | while (i <= ac) /* ok: i is unsigned _int_ */ | ||
| 71 | *buffer++ = i++; | ||
| 72 | arg += 3; /* skip 0-9 */ | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | if (*arg == '[') { /* "[xyz..." */ | ||
| 76 | arg++; | ||
| 77 | i = *arg++; | ||
| 78 | /* "[xyz...", i=x, arg points to y */ | ||
| 79 | if (ENABLE_FEATURE_TR_CLASSES && i == ':') { | ||
| 54 | #define CLO ":]\0" | 80 | #define CLO ":]\0" |
| 55 | static const char classes[] ALIGN1 = | 81 | static const char classes[] ALIGN1 = |
| 56 | "alpha"CLO "alnum"CLO "digit"CLO "lower"CLO "upper"CLO "space"CLO | 82 | "alpha"CLO "alnum"CLO "digit"CLO |
| 57 | "blank"CLO "punct"CLO "cntrl"CLO; | 83 | "lower"CLO "upper"CLO "space"CLO |
| 84 | "blank"CLO "punct"CLO "cntrl"CLO; | ||
| 58 | #define CLASS_invalid 0 /* we increment the retval */ | 85 | #define CLASS_invalid 0 /* we increment the retval */ |
| 59 | #define CLASS_alpha 1 | 86 | #define CLASS_alpha 1 |
| 60 | #define CLASS_alnum 2 | 87 | #define CLASS_alnum 2 |
| @@ -68,27 +95,9 @@ static unsigned int expand(const char *arg, char *buffer) | |||
| 68 | //#define CLASS_xdigit 10 | 95 | //#define CLASS_xdigit 10 |
| 69 | //#define CLASS_graph 11 | 96 | //#define CLASS_graph 11 |
| 70 | //#define CLASS_print 12 | 97 | //#define CLASS_print 12 |
| 71 | while (*arg) { | ||
| 72 | if (*arg == '\\') { | ||
| 73 | arg++; | ||
| 74 | *buffer++ = bb_process_escape_sequence(&arg); | ||
| 75 | } else if (*(arg+1) == '-') { | ||
| 76 | ac = *(arg+2); | ||
| 77 | if (ac == 0) { | ||
| 78 | *buffer++ = *arg++; | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | i = *arg; | ||
| 82 | while (i <= ac) | ||
| 83 | *buffer++ = i++; | ||
| 84 | arg += 3; /* Skip the assumed a-z */ | ||
| 85 | } else if (*arg == '[') { | ||
| 86 | arg++; | ||
| 87 | i = *arg++; | ||
| 88 | if (ENABLE_FEATURE_TR_CLASSES && i == ':') { | ||
| 89 | smalluint j; | 98 | smalluint j; |
| 90 | { /* not really pretty.. */ | 99 | { /* not really pretty.. */ |
| 91 | char *tmp = xstrndup(arg, 7); // warning: xdigit needs 8, not 7 | 100 | char *tmp = xstrndup(arg, 7); // warning: xdigit would need 8, not 7 |
| 92 | j = index_in_strings(classes, tmp) + 1; | 101 | j = index_in_strings(classes, tmp) + 1; |
| 93 | free(tmp); | 102 | free(tmp); |
| 94 | } | 103 | } |
| @@ -115,10 +124,9 @@ static unsigned int expand(const char *arg, char *buffer) | |||
| 115 | *buffer++ = ' '; | 124 | *buffer++ = ' '; |
| 116 | } | 125 | } |
| 117 | if (j == CLASS_punct || j == CLASS_cntrl) { | 126 | if (j == CLASS_punct || j == CLASS_cntrl) { |
| 118 | for (i = 0; i <= ASCII; i++) | 127 | for (i = '\0'; i <= ASCII; i++) |
| 119 | if ((j == CLASS_punct && | 128 | if ((j == CLASS_punct && isprint(i) && !isalnum(i) && !isspace(i)) |
| 120 | isprint(i) && (!isalnum(i)) && (!isspace(i))) || | 129 | || (j == CLASS_cntrl && iscntrl(i))) |
| 121 | (j == CLASS_cntrl && iscntrl(i))) | ||
| 122 | *buffer++ = i; | 130 | *buffer++ = i; |
| 123 | } | 131 | } |
| 124 | if (j == CLASS_invalid) { | 132 | if (j == CLASS_invalid) { |
| @@ -128,22 +136,26 @@ static unsigned int expand(const char *arg, char *buffer) | |||
| 128 | } | 136 | } |
| 129 | break; | 137 | break; |
| 130 | } | 138 | } |
| 131 | if (ENABLE_FEATURE_TR_EQUIV && i == '=') { | 139 | /* "[xyz...", i=x, arg points to y */ |
| 132 | *buffer++ = *arg; | 140 | if (ENABLE_FEATURE_TR_EQUIV && i == '=') { /* [=CHAR=] */ |
| 133 | arg += 3; /* Skip the closing =] */ | 141 | *buffer++ = *arg; /* copy CHAR */ |
| 142 | arg += 3; /* skip CHAR=] */ | ||
| 134 | continue; | 143 | continue; |
| 135 | } | 144 | } |
| 136 | if (*arg++ != '-') { | 145 | if (*arg != '-') { /* not [x-...] - copy verbatim */ |
| 137 | *buffer++ = '['; | 146 | *buffer++ = '['; |
| 138 | arg -= 2; | 147 | arg--; /* points to x */ |
| 139 | continue; | 148 | continue; /* copy all, including eventual ']' */ |
| 140 | } | 149 | } |
| 150 | /* [x-y...] */ | ||
| 151 | arg++; | ||
| 141 | ac = *arg++; | 152 | ac = *arg++; |
| 142 | while (i <= ac) | 153 | while (i <= ac) |
| 143 | *buffer++ = i++; | 154 | *buffer++ = i++; |
| 144 | arg++; /* Skip the assumed ']' */ | 155 | arg++; /* skip the assumed ']' */ |
| 145 | } else | 156 | continue; |
| 146 | *buffer++ = *arg++; | 157 | } |
| 158 | *buffer++ = *arg++; | ||
| 147 | } | 159 | } |
| 148 | return (buffer - buffer_start); | 160 | return (buffer - buffer_start); |
| 149 | } | 161 | } |
| @@ -154,7 +166,7 @@ static int complement(char *buffer, int buffer_len) | |||
| 154 | char conv[ASCII + 2]; | 166 | char conv[ASCII + 2]; |
| 155 | 167 | ||
| 156 | ix = 0; | 168 | ix = 0; |
| 157 | for (i = 0; i <= ASCII; i++) { | 169 | for (i = '\0'; i <= ASCII; i++) { |
| 158 | for (j = 0; j < buffer_len; j++) | 170 | for (j = 0; j < buffer_len; j++) |
| 159 | if (buffer[j] == i) | 171 | if (buffer[j] == i) |
| 160 | break; | 172 | break; |
| @@ -174,7 +186,9 @@ int tr_main(int argc, char **argv) | |||
| 174 | int i; | 186 | int i; |
| 175 | smalluint flags = 0; | 187 | smalluint flags = 0; |
| 176 | ssize_t read_chars = 0; | 188 | ssize_t read_chars = 0; |
| 177 | size_t in_index = 0, out_index = 0, c, coded, last = -1; | 189 | size_t in_index = 0, out_index = 0; |
| 190 | unsigned last = UCHAR_MAX + 1; /* not equal to any char */ | ||
| 191 | unsigned char coded, c; | ||
| 178 | RESERVE_CONFIG_UBUFFER(output, BUFSIZ); | 192 | RESERVE_CONFIG_UBUFFER(output, BUFSIZ); |
| 179 | RESERVE_CONFIG_BUFFER(vector, ASCII+1); | 193 | RESERVE_CONFIG_BUFFER(vector, ASCII+1); |
| 180 | RESERVE_CONFIG_BUFFER(invec, ASCII+1); | 194 | RESERVE_CONFIG_BUFFER(invec, ASCII+1); |
| @@ -203,8 +217,8 @@ int tr_main(int argc, char **argv) | |||
| 203 | input_length = expand(argv[idx++], tr_buf); | 217 | input_length = expand(argv[idx++], tr_buf); |
| 204 | if (flags & TR_OPT_complement) | 218 | if (flags & TR_OPT_complement) |
| 205 | input_length = complement(tr_buf, input_length); | 219 | input_length = complement(tr_buf, input_length); |
| 206 | if (argv[idx] != NULL) { | 220 | if (argv[idx]) { |
| 207 | if (*argv[idx] == '\0') | 221 | if (argv[idx][0] == '\0') |
| 208 | bb_error_msg_and_die("STRING2 cannot be empty"); | 222 | bb_error_msg_and_die("STRING2 cannot be empty"); |
| 209 | output_length = expand(argv[idx], output); | 223 | output_length = expand(argv[idx], output); |
| 210 | map(vector, tr_buf, input_length, output, output_length); | 224 | map(vector, tr_buf, input_length, output, output_length); |
| @@ -222,9 +236,8 @@ int tr_main(int argc, char **argv) | |||
| 222 | xwrite(STDOUT_FILENO, (char *)output, out_index); | 236 | xwrite(STDOUT_FILENO, (char *)output, out_index); |
| 223 | out_index = 0; | 237 | out_index = 0; |
| 224 | } | 238 | } |
| 225 | read_chars = read(STDIN_FILENO, tr_buf, BUFSIZ); | 239 | read_chars = safe_read(STDIN_FILENO, tr_buf, BUFSIZ); |
| 226 | if (read_chars <= 0) { | 240 | if (read_chars <= 0) { |
| 227 | xwrite(STDOUT_FILENO, (char *)output, out_index); | ||
| 228 | if (read_chars < 0) | 241 | if (read_chars < 0) |
| 229 | bb_perror_msg_and_die(bb_msg_read_error); | 242 | bb_perror_msg_and_die(bb_msg_read_error); |
| 230 | exit(EXIT_SUCCESS); | 243 | exit(EXIT_SUCCESS); |
| @@ -235,8 +248,8 @@ int tr_main(int argc, char **argv) | |||
| 235 | coded = vector[c]; | 248 | coded = vector[c]; |
| 236 | if ((flags & TR_OPT_delete) && invec[c]) | 249 | if ((flags & TR_OPT_delete) && invec[c]) |
| 237 | continue; | 250 | continue; |
| 238 | if ((flags & TR_OPT_squeeze_reps) && last == coded && | 251 | if ((flags & TR_OPT_squeeze_reps) && last == coded |
| 239 | (invec[c] || outvec[coded])) | 252 | && (invec[c] || outvec[coded])) |
| 240 | continue; | 253 | continue; |
| 241 | output[out_index++] = last = coded; | 254 | output[out_index++] = last = coded; |
| 242 | } | 255 | } |
