diff options
Diffstat (limited to 'coreutils/sort.c')
-rw-r--r-- | coreutils/sort.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/coreutils/sort.c b/coreutils/sort.c index 36f02543b..07d903388 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -106,7 +106,9 @@ static struct sort_key { | |||
106 | 106 | ||
107 | static char *get_key(char *str, struct sort_key *key, int flags) | 107 | static char *get_key(char *str, struct sort_key *key, int flags) |
108 | { | 108 | { |
109 | int start = 0, end = 0, len, j; | 109 | int start = start; /* for compiler */ |
110 | int end; | ||
111 | int len, j; | ||
110 | unsigned i; | 112 | unsigned i; |
111 | 113 | ||
112 | /* Special case whole string, so we don't have to make a copy */ | 114 | /* Special case whole string, so we don't have to make a copy */ |
@@ -123,12 +125,15 @@ static char *get_key(char *str, struct sort_key *key, int flags) | |||
123 | end = len; | 125 | end = len; |
124 | /* Loop through fields */ | 126 | /* Loop through fields */ |
125 | else { | 127 | else { |
128 | unsigned char ch = 0; | ||
129 | |||
126 | end = 0; | 130 | end = 0; |
127 | for (i = 1; i < key->range[2*j] + j; i++) { | 131 | for (i = 1; i < key->range[2*j] + j; i++) { |
128 | if (key_separator) { | 132 | if (key_separator) { |
129 | /* Skip body of key and separator */ | 133 | /* Skip body of key and separator */ |
130 | while (str[end]) { | 134 | while ((ch = str[end]) != '\0') { |
131 | if (str[end++] == key_separator) | 135 | end++; |
136 | if (ch == key_separator) | ||
132 | break; | 137 | break; |
133 | } | 138 | } |
134 | } else { | 139 | } else { |
@@ -136,7 +141,7 @@ static char *get_key(char *str, struct sort_key *key, int flags) | |||
136 | while (isspace(str[end])) | 141 | while (isspace(str[end])) |
137 | end++; | 142 | end++; |
138 | /* Skip body of key */ | 143 | /* Skip body of key */ |
139 | while (str[end]) { | 144 | while (str[end] != '\0') { |
140 | if (isspace(str[end])) | 145 | if (isspace(str[end])) |
141 | break; | 146 | break; |
142 | end++; | 147 | end++; |
@@ -144,23 +149,29 @@ static char *get_key(char *str, struct sort_key *key, int flags) | |||
144 | } | 149 | } |
145 | } | 150 | } |
146 | /* Remove last delim: "abc:def:" => "abc:def" */ | 151 | /* Remove last delim: "abc:def:" => "abc:def" */ |
147 | if (key_separator && j && end != 0) | 152 | if (j && ch) { |
153 | //if (str[end-1] != key_separator) | ||
154 | // bb_error_msg(_and_die("BUG! " | ||
155 | // "str[start:%d,end:%d]:'%.*s'", | ||
156 | // start, end, (int)(end-start), &str[start]); | ||
148 | end--; | 157 | end--; |
158 | } | ||
149 | } | 159 | } |
150 | if (!j) start = end; | 160 | if (!j) start = end; |
151 | } | 161 | } |
152 | /* Strip leading whitespace if necessary */ | 162 | /* Strip leading whitespace if necessary */ |
153 | //XXX: skip_whitespace() | ||
154 | if (flags & FLAG_b) | 163 | if (flags & FLAG_b) |
164 | /* not using skip_whitespace() for speed */ | ||
155 | while (isspace(str[start])) start++; | 165 | while (isspace(str[start])) start++; |
156 | /* Strip trailing whitespace if necessary */ | 166 | /* Strip trailing whitespace if necessary */ |
157 | if (flags & FLAG_bb) | 167 | if (flags & FLAG_bb) |
158 | while (end > start && isspace(str[end-1])) end--; | 168 | while (end > start && isspace(str[end-1])) end--; |
159 | /* Handle offsets on start and end */ | 169 | /* -kSTART,N.ENDCHAR: honor ENDCHAR (1-based) */ |
160 | if (key->range[3]) { | 170 | if (key->range[3]) { |
161 | end += key->range[3] - 1; | 171 | end = key->range[3]; |
162 | if (end > len) end = len; | 172 | if (end > len) end = len; |
163 | } | 173 | } |
174 | /* -kN.STARTCHAR[,...]: honor STARTCHAR (1-based) */ | ||
164 | if (key->range[1]) { | 175 | if (key->range[1]) { |
165 | start += key->range[1] - 1; | 176 | start += key->range[1] - 1; |
166 | if (start > len) start = len; | 177 | if (start > len) start = len; |
@@ -281,7 +292,7 @@ static int compare_keys(const void *xarg, const void *yarg) | |||
281 | else if (!yy) | 292 | else if (!yy) |
282 | retval = 1; | 293 | retval = 1; |
283 | else | 294 | else |
284 | retval = (dx == thyme.tm_mon) ? 0 : dx - thyme.tm_mon; | 295 | retval = dx - thyme.tm_mon; |
285 | break; | 296 | break; |
286 | } | 297 | } |
287 | /* Full floating point version of -n */ | 298 | /* Full floating point version of -n */ |
@@ -307,8 +318,8 @@ static int compare_keys(const void *xarg, const void *yarg) | |||
307 | 318 | ||
308 | /* Perform fallback sort if necessary */ | 319 | /* Perform fallback sort if necessary */ |
309 | if (!retval && !(option_mask32 & FLAG_s)) { | 320 | if (!retval && !(option_mask32 & FLAG_s)) { |
310 | retval = strcmp(*(char **)xarg, *(char **)yarg); | ||
311 | flags = option_mask32; | 321 | flags = option_mask32; |
322 | retval = strcmp(*(char **)xarg, *(char **)yarg); | ||
312 | } | 323 | } |
313 | 324 | ||
314 | if (flags & FLAG_r) | 325 | if (flags & FLAG_r) |
@@ -336,7 +347,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
336 | char *line, **lines; | 347 | char *line, **lines; |
337 | char *str_ignored, *str_o, *str_t; | 348 | char *str_ignored, *str_o, *str_t; |
338 | llist_t *lst_k = NULL; | 349 | llist_t *lst_k = NULL; |
339 | int i, flag; | 350 | int i; |
340 | int linecount; | 351 | int linecount; |
341 | unsigned opts; | 352 | unsigned opts; |
342 | 353 | ||
@@ -359,7 +370,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
359 | /* note: below this point we use option_mask32, not opts, | 370 | /* note: below this point we use option_mask32, not opts, |
360 | * since that reduces register pressure and makes code smaller */ | 371 | * since that reduces register pressure and makes code smaller */ |
361 | 372 | ||
362 | /* parse sort key */ | 373 | /* Parse sort key */ |
363 | while (lst_k) { | 374 | while (lst_k) { |
364 | enum { | 375 | enum { |
365 | FLAG_allowed_for_k = | 376 | FLAG_allowed_for_k = |
@@ -386,17 +397,18 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
386 | key->range[2*i+1] = str2u(&str_k); | 397 | key->range[2*i+1] = str2u(&str_k); |
387 | } | 398 | } |
388 | while (*str_k) { | 399 | while (*str_k) { |
389 | const char *temp2; | 400 | int flag; |
401 | const char *idx; | ||
390 | 402 | ||
391 | if (*str_k == ',' && !i++) { | 403 | if (*str_k == ',' && !i++) { |
392 | str_k++; | 404 | str_k++; |
393 | break; | 405 | break; |
394 | } /* no else needed: fall through to syntax error | 406 | } /* no else needed: fall through to syntax error |
395 | because comma isn't in OPT_STR */ | 407 | because comma isn't in OPT_STR */ |
396 | temp2 = strchr(OPT_STR, *str_k); | 408 | idx = strchr(OPT_STR, *str_k); |
397 | if (!temp2) | 409 | if (!idx) |
398 | bb_error_msg_and_die("unknown key option"); | 410 | bb_error_msg_and_die("unknown key option"); |
399 | flag = 1 << (temp2 - OPT_STR); | 411 | flag = 1 << (idx - OPT_STR); |
400 | if (flag & ~FLAG_allowed_for_k) | 412 | if (flag & ~FLAG_allowed_for_k) |
401 | bb_error_msg_and_die("unknown sort type"); | 413 | bb_error_msg_and_die("unknown sort type"); |
402 | /* b after ',' means strip _trailing_ space */ | 414 | /* b after ',' means strip _trailing_ space */ |
@@ -430,10 +442,10 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
430 | } while (*++argv); | 442 | } while (*++argv); |
431 | 443 | ||
432 | #if ENABLE_FEATURE_SORT_BIG | 444 | #if ENABLE_FEATURE_SORT_BIG |
433 | /* if no key, perform alphabetic sort */ | 445 | /* If no key, perform alphabetic sort */ |
434 | if (!key_list) | 446 | if (!key_list) |
435 | add_key()->range[0] = 1; | 447 | add_key()->range[0] = 1; |
436 | /* handle -c */ | 448 | /* Handle -c */ |
437 | if (option_mask32 & FLAG_c) { | 449 | if (option_mask32 & FLAG_c) { |
438 | int j = (option_mask32 & FLAG_u) ? -1 : 0; | 450 | int j = (option_mask32 & FLAG_u) ? -1 : 0; |
439 | for (i = 1; i < linecount; i++) { | 451 | for (i = 1; i < linecount; i++) { |
@@ -447,20 +459,21 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
447 | #endif | 459 | #endif |
448 | /* Perform the actual sort */ | 460 | /* Perform the actual sort */ |
449 | qsort(lines, linecount, sizeof(lines[0]), compare_keys); | 461 | qsort(lines, linecount, sizeof(lines[0]), compare_keys); |
450 | /* handle -u */ | 462 | |
463 | /* Handle -u */ | ||
451 | if (option_mask32 & FLAG_u) { | 464 | if (option_mask32 & FLAG_u) { |
452 | flag = 0; | 465 | int j = 0; |
453 | /* coreutils 6.3 drop lines for which only key is the same */ | 466 | /* coreutils 6.3 drop lines for which only key is the same */ |
454 | /* -- disabling last-resort compare... */ | 467 | /* -- disabling last-resort compare... */ |
455 | option_mask32 |= FLAG_s; | 468 | option_mask32 |= FLAG_s; |
456 | for (i = 1; i < linecount; i++) { | 469 | for (i = 1; i < linecount; i++) { |
457 | if (compare_keys(&lines[flag], &lines[i]) == 0) | 470 | if (compare_keys(&lines[j], &lines[i]) == 0) |
458 | free(lines[i]); | 471 | free(lines[i]); |
459 | else | 472 | else |
460 | lines[++flag] = lines[i]; | 473 | lines[++j] = lines[i]; |
461 | } | 474 | } |
462 | if (linecount) | 475 | if (linecount) |
463 | linecount = flag+1; | 476 | linecount = j+1; |
464 | } | 477 | } |
465 | 478 | ||
466 | /* Print it */ | 479 | /* Print it */ |
@@ -469,9 +482,11 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
469 | if (option_mask32 & FLAG_o) | 482 | if (option_mask32 & FLAG_o) |
470 | xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); | 483 | xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); |
471 | #endif | 484 | #endif |
472 | flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; | 485 | { |
473 | for (i = 0; i < linecount; i++) | 486 | int ch = (option_mask32 & FLAG_z) ? '\0' : '\n'; |
474 | printf("%s%c", lines[i], flag); | 487 | for (i = 0; i < linecount; i++) |
488 | printf("%s%c", lines[i], ch); | ||
489 | } | ||
475 | 490 | ||
476 | fflush_stdout_and_exit(EXIT_SUCCESS); | 491 | fflush_stdout_and_exit(EXIT_SUCCESS); |
477 | } | 492 | } |