4.4BSD/usr/src/contrib/sun.sharedlib/lang/ld/verscmp.c
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify this source code without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
* SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
* OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
* EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS
* ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
* NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
*
* This source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
* SOURCE CODE OR ANY PART THEREOF.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* @(#)verscmp.c 1.4 69/12/31 */
/*
* Copyright (c) 1987, 1991 by Sun Microsystems, Inc.
*/
#define SKIP_DOT(str) ((*str == '.') ? ++str : str)
#define EMPTY(str) ((str == NULL) || (*str == '\0'))
#define NULL 0
#define isdigit(c) (((c) >= '0') && ((c) <= '9') ? 1:0)
int stol();
/*
* Test whether the string is of digit[.digit]* format
*/
rest_ok(str)
char *str; /* input string */
{
int dummy; /* integer place holder */
int legal = 1; /* return flag */
while (!EMPTY(str)) {
if (!stol(str, '.', &str, &dummy)) {
legal = 0;
break;
};
if (EMPTY(str))
break;
else SKIP_DOT(str);
};
return(legal);
};
/*
* Compare 2 strings and test whether they are of the form digit[.digit]*.
* It will return -1, 0, or 1 depending on whether c1p is less, equal or
* greater than c2p
*/
verscmp(c1p, c2p)
char *c1p; /* input string */
char *c2p; /* input string */
{
char *l_c1p = c1p; /* working copy of c1p */
char *l_c2p = c2p; /* working copy of c2p */
int l_c1p_ok = 0; /* is c1p a legal string */
int c2p_dig = 0; /* int that c1p currently represents */
int c1p_dig = 0; /* int that c2p currently represents */
int result = 0;
while ((l_c1p_ok = stol(l_c1p,'.', &l_c1p, &c1p_dig)) &&
stol(l_c2p,'.', &l_c2p, &c2p_dig) && (c2p_dig == c1p_dig)) {
if (EMPTY(l_c1p) && EMPTY(l_c2p))
return(0);
else if (EMPTY(l_c1p) && !EMPTY(l_c2p) && rest_ok(SKIP_DOT(l_c2p)))
return(-1);
else if (EMPTY(l_c2p) && !EMPTY(l_c1p) && rest_ok(SKIP_DOT(l_c1p)))
return(1);
l_c1p++; l_c2p++;
};
if (!l_c1p_ok)
return(-1);
else if (c1p_dig < c2p_dig)
return(-1);
else if ((c1p_dig > c2p_dig) && rest_ok(SKIP_DOT(l_c1p)))
return(1);
else return(-1);
}
/*
* "stol" attempts to interpret a collection of characters between delimiters
* as a decimal digit. It stops interpreting when it reaches a delimiter or
* when character does not represent a digit. In the first case it returns
* success and the latter failure.
*/
int
stol(cp, delimit, ptr, i)
char *cp; /* ptr to input string */
char delimit; /* delimiter */
char **ptr; /* left pointing to next del. or illegal
character */
int *i; /* digit that the string represents */
{
int c = 0; /* current char */
int n = 0; /* working copy of i */
int neg = 0; /* is number negative */
if (ptr != (char **)0)
*ptr = cp; /* in case no number is formed */
if (EMPTY(cp))
return(0);
if (!isdigit(c = *cp) && (c == '-')) {
neg++;
c = *++cp;
};
if (EMPTY(cp) || !isdigit(c))
return(0);
while (isdigit(c = *cp) && (*cp++ != '\0')) {
n *= 10;
n += c - '0';
};
if (ptr != (char **)0)
*ptr = cp;
if ((*cp == '\0') || (*cp == delimit)) {
*i = neg ? -n : n;
return (1);
};
return (0);
}