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/tr.c | |
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/tr.c')
-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 | } |