[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
sort --compare-version
From: |
Bruce Korb |
Subject: |
sort --compare-version |
Date: |
Thu, 31 Jan 2008 08:02:45 -0800 |
User-agent: |
Thunderbird 2.0.0.6 (X11/20070801) |
This works for me :)
Either ``-V'' or ``--compare-version'' will trigger the use of
strverscmp in lieu of memcmp as the comparison function.
--- coreutils-6.10-ori/src/sort.c 2007-11-25 05:23:31.000000000 -0800
+++ coreutils-6.10/src/sort.c 2008-01-31 07:55:10.000000000 -0800
@@ -172,6 +172,7 @@ struct keyfield
Handle numbers in exponential notation. */
bool month; /* Flag for comparison by month name. */
bool reverse; /* Reverse the sense of comparison. */
+ bool version; /* Version number comparison. */
struct keyfield *next; /* Next keyfield to try. */
};
@@ -353,6 +354,7 @@ Other options:\n\
multiple options specify multiple directories\n\
-u, --unique with -c, check for strict ordering;\n\
without -c, output only the first of an equal
run\n\
+ -V, --compare-version compare embedded numbers as version numbers\n\
"), DEFAULT_TMPDIR);
fputs (_("\
-z, --zero-terminated end lines with 0 byte, not newline\n\
@@ -394,7 +396,7 @@ enum
RANDOM_SOURCE_OPTION
};
-static char const short_options[] = "-bcCdfgik:mMno:rRsS:t:T:uy:z";
+static char const short_options[] = "-bcCdfgik:mMno:rRsS:t:T:uVy:z";
static struct option const long_options[] =
{
@@ -418,6 +420,7 @@ static struct option const long_options[
{"field-separator", required_argument, NULL, 't'},
{"temporary-directory", required_argument, NULL, 'T'},
{"unique", no_argument, NULL, 'u'},
+ {"compare-version", no_argument, NULL, 'V'},
{"zero-terminated", no_argument, NULL, 'z'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -1543,6 +1546,26 @@ general_numcompare (const char *sa, cons
: memcmp ((char *) &a, (char *) &b, sizeof a));
}
+/* Compare the keys TEXTA (of length LENA) and TEXTB (of length LENB)
+ using strverscmp. */
+
+static int
+compare_version (char *restrict texta, size_t lena,
+ char *restrict textb, size_t lenb)
+{
+ int diff;
+ char sv_a = texta[lena];
+ char sv_b = textb[lenb];
+
+ texta[lena] = textb[lenb] = '\0';
+ diff = strverscmp (texta, textb);
+
+ texta[lena] = sv_a;
+ textb[lenb] = sv_b;
+
+ return diff;
+}
+
/* Return an integer in 1..12 of the month name MONTH with length LEN.
Return 0 if the name in S is not recognized. */
@@ -1741,8 +1764,13 @@ keycompare (const struct line *a, const
(texta, textb));
*lima = savea, *limb = saveb;
}
+
+ else if (key->version)
+ diff = compare_version (texta, lena, textb, lenb);
+
else if (key->month)
diff = getmonth (texta, lena) - getmonth (textb, lenb);
+
/* Sorting like this may become slow, so in a simple locale the user
can select a faster sort that is similar to ascii sort. */
else if (hard_LC_COLLATE)
@@ -2587,10 +2615,10 @@ check_ordering_compatibility (void)
for (key = keylist; key; key = key->next)
if ((1 < (key->random + key->numeric + key->general_numeric + key->month
- + !!key->ignore))
+ + key->version + !!key->ignore))
|| (key->random && key->translate))
{
- char opts[7];
+ char opts[sizeof short_options];
char *p = opts;
if (key->ignore == nondictionary)
*p++ = 'd';
@@ -2604,6 +2632,8 @@ check_ordering_compatibility (void)
*p++ = 'M';
if (key->numeric)
*p++ = 'n';
+ if (key->version)
+ *p++ = 'V';
if (key->random)
*p++ = 'R';
*p = '\0';
@@ -2705,6 +2735,9 @@ set_ordering (const char *s, struct keyf
case 'r':
key->reverse = true;
break;
+ case 'V':
+ key->version = true;
+ break;
default:
return (char *) s;
}
@@ -2830,7 +2863,7 @@ main (int argc, char **argv)
gkey.sword = gkey.eword = SIZE_MAX;
gkey.ignore = NULL;
gkey.translate = NULL;
- gkey.numeric = gkey.general_numeric = gkey.random = false;
+ gkey.numeric = gkey.general_numeric = gkey.random = gkey.version = false;
gkey.month = gkey.reverse = false;
gkey.skipsblanks = gkey.skipeblanks = false;
@@ -2911,6 +2944,7 @@ main (int argc, char **argv)
case 'n':
case 'r':
case 'R':
+ case 'V':
{
char str[2];
str[0] = c;
@@ -3084,9 +3118,14 @@ main (int argc, char **argv)
/* Inheritance of global options to individual keys. */
for (key = keylist; key; key = key->next)
{
- if (! (key->ignore || key->translate
- || (key->skipsblanks | key->reverse
- | key->skipeblanks | key->month | key->numeric
+ if (! (key->ignore
+ || key->translate
+ || (key->skipsblanks
+ | key->reverse
+ | key->skipeblanks
+ | key->month
+ | key->numeric
+ | key->version
| key->general_numeric
| key->random)))
{
@@ -3099,6 +3138,7 @@ main (int argc, char **argv)
key->general_numeric = gkey.general_numeric;
key->random = gkey.random;
key->reverse = gkey.reverse;
+ key->version = gkey.version;
}
need_random |= key->random;
@@ -3107,7 +3147,7 @@ main (int argc, char **argv)
if (!keylist && (gkey.ignore || gkey.translate
|| (gkey.skipsblanks | gkey.skipeblanks | gkey.month
| gkey.numeric | gkey.general_numeric
- | gkey.random)))
+ | gkey.random | gkey.version)))
{
insertkey (&gkey);
need_random |= gkey.random;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- sort --compare-version,
Bruce Korb <=