aboutsummaryrefslogtreecommitdiff
path: root/coreutils/sort.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/sort.c')
-rw-r--r--coreutils/sort.c67
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
107static char *get_key(char *str, struct sort_key *key, int flags) 107static 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}