Group :: Sistema/Configurações/Rede
RPM: net-tools
Main Changelog Spec Patches Sources Download Gear Bugs e FR Repocop
Patch: net-tools-1.60-alt-nstrcmp.patch
Download
Download
--- net-tools-1.60/lib/nstrcmp.c~ 1999-01-09 18:55:20 +0300
+++ net-tools-1.60/lib/nstrcmp.c 2002-07-03 01:35:04 +0400
@@ -1,34 +1,157 @@
-/* Copyright 1998 by Andi Kleen. Subject to the GPL. */
-/* $Id: nstrcmp.c,v 1.2 1998/11/15 20:11:38 freitag Exp $ */
+/*
+ compare alpha and numeric segments of two strings.
+
+ Copyright (c) 1998 by Red Hat Software, Inc.
+ Copyright (c) 2002 by Dmitry V. Levin <ldv@altlinux.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <string.h>
#include <ctype.h>
#include <stdlib.h>
-#include "util.h"
-/* like strcmp(), but knows about numbers */
-int nstrcmp(const char *astr, const char *b)
+/*
+ * compares alpha and numeric segments of two strings.
+ * returns an integer less than, equal to, or greater
+ * than zero if a is found, respectively, to be less
+ * than, to match, or be greater than b.
+*/
+int
+nstrcmp (const char *a, const char *b)
{
- const char *a = astr;
+ char *str1, *str2;
+ char *one, *two;
- while (*a == *b) {
- if (*a == '\0')
- return 0;
- a++;
- b++;
- }
- if (isdigit(*a)) {
- if (!isdigit(*b))
- return -1;
- while (a > astr) {
- a--;
- if (!isdigit(*a)) {
- a++;
- break;
- }
- if (!isdigit(*b))
- return -1;
- b--;
+ /* easy comparison to see if versions are identical */
+ if (!strcmp (a, b))
+ return 0;
+
+ str1 = alloca (strlen (a) + 1);
+ str2 = alloca (strlen (b) + 1);
+
+ strcpy (str1, a);
+ strcpy (str2, b);
+
+ one = str1;
+ two = str2;
+
+ /* loop through each version segment of str1 and str2 and compare them */
+ while (*one && *two)
+ {
+ int isalnum1 = isalnum (*one);
+ int isalnum2 = isalnum (*two);
+ int isnum, rc;
+ char oldch1, oldch2;
+
+ if (*one == *two)
+ {
+ if (!isalnum1)
+ {
+ ++one;
+ ++two;
+ continue;
+ }
+ } else
+ {
+ if (!(isalnum1 && isalnum2))
+ return *one - *two;
+ }
+
+ str1 = one;
+ str2 = two;
+
+ /* grab first completely alpha or completely numeric segment */
+ /* leave one and two pointing to the start of the alpha or numeric */
+ /* segment and walk str1 and str2 to end of segment */
+ /* Also take care of the case where the two version segments are */
+ /* different types: one numeric and one alpha */
+ if (isdigit (*str1))
+ {
+ if (isalpha (*str2))
+ return -1;
+ while (*str1 && isdigit (*str1))
+ str1++;
+ while (*str2 && isdigit (*str2))
+ str2++;
+ isnum = 1;
+ } else
+ {
+ while (*str1 && isalpha (*str1))
+ str1++;
+ while (*str2 && isalpha (*str2))
+ str2++;
+ isnum = 0;
+ }
+
+ /* Again, take care of the case where the two version segments are */
+ /* different types: one numeric and one alpha */
+ if (one == str1)
+ return -1;
+ if (two == str2)
+ return 1;
+
+ /* save character at the end of the alpha or numeric segment */
+ /* so that they can be restored after the comparison */
+ oldch1 = *str1;
+ *str1 = '\0';
+ oldch2 = *str2;
+ *str2 = '\0';
+
+ if (isnum)
+ {
+ /* this used to be done by converting the digit segments */
+ /* to ints using atoi() - it's changed because long */
+ /* digit segments can overflow an int - this should fix that. */
+
+ /* throw away any leading zeros - it's a number, right? */
+ while (*one == '0')
+ one++;
+ while (*two == '0')
+ two++;
+
+ /* whichever number has more digits wins */
+ if (strlen (one) > strlen (two))
+ return 1;
+ if (strlen (two) > strlen (one))
+ return -1;
+ }
+
+ /* strcmp will return which one is greater - even if the two */
+ /* segments are alpha or if they are numeric. don't return */
+ /* if they are equal because there might be more segments to */
+ /* compare */
+ rc = strcmp (one, two);
+ if (rc)
+ return rc;
+
+ /* restore character that was replaced by null above */
+ *str1 = oldch1;
+ one = str1;
+ *str2 = oldch2;
+ two = str2;
}
- return atoi(a) > atoi(b) ? 1 : -1;
- }
- return *a - *b;
+
+ /* this catches the case where all numeric and alpha segments have */
+ /* compared identically but the segment sepparating characters were */
+ /* different */
+ if (!*one && !*two)
+ return 0;
+
+ /* whichever version still has characters left over wins */
+ if (!*one)
+ return -1;
+ else
+ return 1;
}