diff options
author | Pádraig Brady <P@draigBrady.com> | 2009-06-30 00:52:43 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2009-07-03 17:00:55 +0100 |
commit | acc01947af2e025d11016f3a4b0a26beb06dd120 (patch) | |
tree | 278d23fc40bed474e0ca30315a628e9fcf7629a7 | |
parent | d9f83f9a603a2f5ecdc13bbe65e22aba49d43d66 (diff) | |
download | coreutils-acc01947af2e025d11016f3a4b0a26beb06dd120.tar.xz |
sort: allow SI and IEC units on separate human sort fields
* src/sort.c: Store the si_present state per key rather than globally
* tests/misc/sort: Add a check that would have previously failed.
Also add a test to demonstrate that invalid IEC/SI mixtures are not
always noticed when they're not significant to the sort.
-rw-r--r-- | src/sort.c | 30 | ||||
-rwxr-xr-x | tests/misc/sort | 4 |
2 files changed, 20 insertions, 14 deletions
diff --git a/src/sort.c b/src/sort.c index 6acec070d..62ddd4993 100644 --- a/src/sort.c +++ b/src/sort.c @@ -178,6 +178,7 @@ struct keyfield Handle numbers in exponential notation. */ bool human_numeric; /* Flag for sorting by human readable units with either SI xor IEC prefixes. */ + int si_present; /* Flag for checking for mixed SI and IEC. */ bool month; /* Flag for comparison by month name. */ bool reverse; /* Reverse the sense of comparison. */ bool version; /* sort by version number */ @@ -1684,13 +1685,12 @@ numcompare (const char *a, const char *b) /* Exit with an error if a mixture of SI and IEC units detected. */ static void -check_mixed_SI_IEC (char prefix) +check_mixed_SI_IEC (char prefix, struct keyfield *key) { - static int seen_si = -1; - bool si_present = prefix == 'i'; - if (seen_si != -1 && seen_si != si_present) + int si_present = prefix == 'i'; + if (key->si_present != -1 && si_present != key->si_present) error (SORT_FAILURE, 0, _("both SI and IEC prefixes present on units")); - seen_si = si_present; + key->si_present = si_present; } /* Return an integer which represents the order of magnitude of @@ -1699,7 +1699,7 @@ check_mixed_SI_IEC (char prefix) Negative numbers return a negative unit order. */ static int -find_unit_order (const char *number) +find_unit_order (const char *number, struct keyfield *key) { static const char orders [UCHAR_LIM] = { ['K']=1, ['M']=2, ['G']=3, ['T']=4, ['P']=5, ['E']=6, ['Z']=7, ['Y']=8, @@ -1736,7 +1736,7 @@ find_unit_order (const char *number) /* For valid units check for MiB vs MB etc. */ if (order) - check_mixed_SI_IEC (*(p + 1)); + check_mixed_SI_IEC (*(p + 1), key); return sign * order; } @@ -1747,15 +1747,15 @@ find_unit_order (const char *number) i.e. input will never have both 6000K and 5M. */ static int -human_numcompare (const char *a, const char *b) +human_numcompare (const char *a, const char *b, struct keyfield *key) { while (blanks[to_uchar (*a)]) a++; while (blanks[to_uchar (*b)]) b++; - int order_a = find_unit_order (a); - int order_b = find_unit_order (b); + int order_a = find_unit_order (a, key); + int order_b = find_unit_order (b, key); return (order_a > order_b ? 1 : order_a < order_b ? -1 @@ -1982,7 +1982,7 @@ compare_version (char *restrict texta, size_t lena, static int keycompare (const struct line *a, const struct line *b) { - struct keyfield const *key = keylist; + struct keyfield *key = keylist; /* For the first iteration only, the key positions have been precomputed for us. */ @@ -2015,9 +2015,9 @@ keycompare (const struct line *a, const struct line *b) char savea = *lima, saveb = *limb; *lima = *limb = '\0'; - diff = ((key->numeric ? numcompare - : key->general_numeric ? general_numcompare - : human_numcompare) (texta, textb)); + diff = (key->numeric ? numcompare (texta, textb) + : key->general_numeric ? general_numcompare (texta, textb) + : human_numcompare (texta, textb, key)); *lima = savea, *limb = saveb; } else if (key->version) @@ -3125,6 +3125,7 @@ key_init (struct keyfield *key) { memset (key, 0, sizeof *key); key->eword = SIZE_MAX; + key->si_present = -1; return key; } @@ -3240,6 +3241,7 @@ main (int argc, char **argv) gkey.ignore = NULL; gkey.translate = NULL; gkey.numeric = gkey.general_numeric = gkey.human_numeric = false; + gkey.si_present = -1; gkey.random = gkey.version = false; gkey.month = gkey.reverse = false; gkey.skipsblanks = gkey.skipeblanks = false; diff --git a/tests/misc/sort b/tests/misc/sort index 21e7af8e9..b1f012059 100755 --- a/tests/misc/sort +++ b/tests/misc/sort @@ -71,6 +71,10 @@ my @Tests = {ERR=>"$prog: options `-hn' are incompatible\n"}], # check key processing ["h8", '-n -k2,2h', {IN=>"1 1E\n2 2M\n"}, {OUT=>"2 2M\n1 1E\n"}], +# SI and IEC prefixes on separate keys allowed +["h9", '-h -k1,1 -k2,2', {IN=>"1M 1Mi\n1M 1Mi\n"}, {OUT=>"1M 1Mi\n1M 1Mi\n"}], +# This invalid SI and IEC prefix mixture is not significant so not noticed +["h10", '-h -k1,1 -k2,2', {IN=>"1M 2M\n2M 1Mi\n"}, {OUT=>"1M 2M\n2M 1Mi\n"}], ["01a", '', {IN=>"A\nB\nC\n"}, {OUT=>"A\nB\nC\n"}], # |