summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2009-06-30 00:52:43 +0100
committerPádraig Brady <P@draigBrady.com>2009-07-03 17:00:55 +0100
commitacc01947af2e025d11016f3a4b0a26beb06dd120 (patch)
tree278d23fc40bed474e0ca30315a628e9fcf7629a7
parentd9f83f9a603a2f5ecdc13bbe65e22aba49d43d66 (diff)
downloadcoreutils-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.c30
-rwxr-xr-xtests/misc/sort4
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"}],
#