sort: fix -s. Closes 10671
function old new delta sort_main 786 862 +76 compare_keys 720 794 +74 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 150/0) Total: 150 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e789c3bea1
commit
7d285c78a3
@ -62,9 +62,9 @@
|
|||||||
//usage: "\n -u Suppress duplicate lines"
|
//usage: "\n -u Suppress duplicate lines"
|
||||||
//usage: IF_FEATURE_SORT_BIG(
|
//usage: IF_FEATURE_SORT_BIG(
|
||||||
//usage: "\n -z Lines are terminated by NUL, not newline"
|
//usage: "\n -z Lines are terminated by NUL, not newline"
|
||||||
////usage: "\n -m Ignored for GNU compatibility"
|
///////: "\n -m Ignored for GNU compatibility"
|
||||||
////usage: "\n -S BUFSZ Ignored for GNU compatibility"
|
///////: "\n -S BUFSZ Ignored for GNU compatibility"
|
||||||
////usage: "\n -T TMPDIR Ignored for GNU compatibility"
|
///////: "\n -T TMPDIR Ignored for GNU compatibility"
|
||||||
//usage: )
|
//usage: )
|
||||||
//usage:
|
//usage:
|
||||||
//usage:#define sort_example_usage
|
//usage:#define sort_example_usage
|
||||||
@ -117,6 +117,7 @@ enum {
|
|||||||
FLAG_k = 0x10000,
|
FLAG_k = 0x10000,
|
||||||
FLAG_t = 0x20000,
|
FLAG_t = 0x20000,
|
||||||
FLAG_bb = 0x80000000, /* Ignore trailing blanks */
|
FLAG_bb = 0x80000000, /* Ignore trailing blanks */
|
||||||
|
FLAG_no_tie_break = 0x40000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SORT_BIG
|
#if ENABLE_FEATURE_SORT_BIG
|
||||||
@ -340,10 +341,34 @@ static int compare_keys(const void *xarg, const void *yarg)
|
|||||||
#endif
|
#endif
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
/* Perform fallback sort if necessary */
|
if (retval == 0) {
|
||||||
if (!retval && !(option_mask32 & FLAG_s)) {
|
/* So far lines are "the same" */
|
||||||
flags = option_mask32;
|
|
||||||
retval = strcmp(*(char **)xarg, *(char **)yarg);
|
if (option_mask32 & FLAG_s) {
|
||||||
|
/* "Stable sort": later line is "smaller",
|
||||||
|
* IOW: do not allow qsort() to swap equal lines.
|
||||||
|
*/
|
||||||
|
uint32_t *p32;
|
||||||
|
uint32_t x32, y32;
|
||||||
|
char *line;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
line = *(char**)xarg;
|
||||||
|
len = (strlen(line) + 4) & (~3u);
|
||||||
|
p32 = (void*)(line + len);
|
||||||
|
x32 = *p32;
|
||||||
|
line = *(char**)yarg;
|
||||||
|
len = (strlen(line) + 4) & (~3u);
|
||||||
|
p32 = (void*)(line + len);
|
||||||
|
y32 = *p32;
|
||||||
|
|
||||||
|
retval = x32 > y32;
|
||||||
|
} else
|
||||||
|
if (!(option_mask32 & FLAG_no_tie_break)) {
|
||||||
|
/* fallback sort */
|
||||||
|
flags = option_mask32;
|
||||||
|
retval = strcmp(*(char **)xarg, *(char **)yarg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & FLAG_r)
|
if (flags & FLAG_r)
|
||||||
@ -368,7 +393,7 @@ static unsigned str2u(char **str)
|
|||||||
int sort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int sort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int sort_main(int argc UNUSED_PARAM, char **argv)
|
int sort_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
char *line, **lines;
|
char **lines;
|
||||||
char *str_ignored, *str_o, *str_t;
|
char *str_ignored, *str_o, *str_t;
|
||||||
llist_t *lst_k = NULL;
|
llist_t *lst_k = NULL;
|
||||||
int i;
|
int i;
|
||||||
@ -457,7 +482,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
* do not continue to next file: */
|
* do not continue to next file: */
|
||||||
FILE *fp = xfopen_stdin(*argv);
|
FILE *fp = xfopen_stdin(*argv);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
line = GET_LINE(fp);
|
char *line = GET_LINE(fp);
|
||||||
if (!line)
|
if (!line)
|
||||||
break;
|
break;
|
||||||
lines = xrealloc_vector(lines, 6, linecount);
|
lines = xrealloc_vector(lines, 6, linecount);
|
||||||
@ -482,15 +507,35 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* For stable sort, store original line position beyond terminating NUL */
|
||||||
|
if (option_mask32 & FLAG_s) {
|
||||||
|
for (i = 0; i < linecount; i++) {
|
||||||
|
uint32_t *p32;
|
||||||
|
char *line;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
line = lines[i];
|
||||||
|
len = (strlen(line) + 4) & (~3u);
|
||||||
|
lines[i] = line = xrealloc(line, len + 4);
|
||||||
|
p32 = (void*)(line + len);
|
||||||
|
*p32 = i;
|
||||||
|
}
|
||||||
|
/*option_mask32 |= FLAG_no_tie_break;*/
|
||||||
|
/* ^^^redundant: if FLAG_s, compare_keys() does no tie break */
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform the actual sort */
|
/* Perform the actual sort */
|
||||||
qsort(lines, linecount, sizeof(lines[0]), compare_keys);
|
qsort(lines, linecount, sizeof(lines[0]), compare_keys);
|
||||||
|
|
||||||
/* Handle -u */
|
/* Handle -u */
|
||||||
if (option_mask32 & FLAG_u) {
|
if (option_mask32 & FLAG_u) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
/* coreutils 6.3 drop lines for which only key is the same */
|
/* coreutils 6.3 drop lines for which only key is the same
|
||||||
/* -- disabling last-resort compare... */
|
* -- disabling last-resort compare, or else compare_keys()
|
||||||
option_mask32 |= FLAG_s;
|
* will be the same only for completely identical lines.
|
||||||
|
*/
|
||||||
|
option_mask32 |= FLAG_no_tie_break;
|
||||||
for (i = 1; i < linecount; i++) {
|
for (i = 1; i < linecount; i++) {
|
||||||
if (compare_keys(&lines[j], &lines[i]) == 0)
|
if (compare_keys(&lines[j], &lines[i]) == 0)
|
||||||
free(lines[i]);
|
free(lines[i]);
|
||||||
|
Loading…
Reference in New Issue
Block a user