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;
_______________________________________________
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to