Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
kcc-4/lib/atoi.c
There are 8 other files named atoi.c in the archive. Click here to see a list.
/*
* ATOI - convert strings to numbers
*
* Copyright (C) 1987 by Ian Macky, SRI International
*/
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
double atof(str)
char *str;
{
return strtod(str, (char **) NULL);
}
int atoi(str)
char *str;
{
return (int) strtol(str, (char **) NULL, 10);
}
long atol(str)
char *str;
{
return strtol(str, (char **) NULL, 10);
}
/*
* STRTOD - turn a string double into the real thing
*/
double strtod(str, ptr)
char *str, **ptr;
{
double value = 0.0; /* the actual value */
int negative = 0; /* negative number? */
int exponent = 0; /* exponent... */
double multiplier;
while (isspace(*str)) str++; /* skip leading whitespace */
switch (*str) {
case '-': negative = 1; /* leading - means negative # */
case '+': str++; /* - falls into. skip the sign */
}
while (isdigit(*str)) /* slurp the left-of-dot mantissa */
value = value * 10.0 + toint(*str++);
if (*str == '.') { /* if there's a decimal point */
multiplier = 1.0;
while (isdigit(*++str))
value += (toint(*str) / (multiplier *= 10.0));
}
if (*str == 'e' || *str == 'E') { /* there's an exponent */
multiplier = 10.0; /* assume positive exponent */
switch (*++str) {
case '-': multiplier = 0.1; /* negative, so 1/10th */
case '+': str++;
}
while (isdigit(*str)) /* accumulate the exponent */
exponent = exponent * 10 + toint(*str++);
while (--exponent >= 0) /* calculate out the exponent now */
value *= multiplier;
}
if (ptr) *ptr = str; /* save pointer to after number */
return (negative) ? -value : value; /* return the double value */
}
/*
* STRTOL - turn a string long into the real thing
*/
long strtol(str, ptr, base)
char *str, **ptr;
int base;
{
long value = 0; /* the accumulated value */
int negative = 0; /* this a negative number? */
long _strtoc(); /* numeric constant reader */
char c;
if (base && (base < 2 || base > 36)) /* range check the base. */
return 0; /* base 0 means a const */
while (isspace(*str)) str++; /* skip leading whitespace */
if (!base) /* if base = 0, */
return _strtoc(str, ptr); /* read & return a constant */
switch (*str) { /* check for leading sign char */
case '-': negative = 1; /* yes, negative #. fall into '+' */
case '+': str++; /* skip the sign character */
}
if (base == 16 && *str == '0' && toupper(*(str + 1)) == 'X')
str += 2; /* allow hex prefix "0x" */
for (;;++str) {
c = toupper(*str); /* get a char of the number */
if (isdigit(c)) /* if a digit, */
c = toint(c); /* convert to a number */
else if (isalpha(c)) /* if a letter, convert it; */
c = c - 'A' + 10; /* A=10, B=11, etc */
else break; /* else no way it's a digit */
if (c >= base) break; /* digit out of range for base? */
value = value * base + c; /* accumulate the digit */
} /* loop until non-numeric char */
if (ptr) *ptr = str; /* save users ptr to after number */
return (negative) ? -value : value; /* negate number if needed */
}
/*
* STRTOUL - read unsigned number
*/
unsigned long strtoul(str, ptr, base)
char *str, **ptr;
int base;
{
unsigned long value = 0; /* the accumulated value */
long _strtoc(); /* numeric constant reader */
char c;
if (base && (base < 2 || base > 36)) /* range check the base. */
return 0; /* base 0 means a const */
while (isspace(*str)) str++; /* skip leading whitespace */
if (!base) /* if base = 0, read&ret constant */
return (unsigned long) _strtoc(str, ptr);
if (base == 16 && *str == '0' && toupper(*(str + 1)) == 'X')
str += 2; /* allow hex prefix "0x" */
for (;;++str) {
c = toupper(*str); /* get a char of the number */
if (isdigit(c)) /* if a digit, */
c = toint(c); /* convert to a number */
else if (isalpha(c)) /* if a letter, convert it; */
c = c - 'A' + 10; /* A=10, B=11, etc */
else break; /* else no way it's a digit */
if (c >= base) break; /* digit out of range for base? */
value = value * base + c; /* accumulate the digit */
} /* loop until non-numeric char */
if (ptr) *ptr = str; /* save users ptr to after number */
return value;
}
/*
* _STRTOC - read a numeric constant.
*/
static long _strtoc(str, ptr)
char *str, **ptr;
{
long value = 0; /* the accumulated value */
int negative; /* negative number? */
int base; /* number base - assumed from format */
int ok; /* true while valid chars for number */
if (*str == '-') { /* integer constants are allowed a */
negative = 1; /* leading unary minus, but not */
str++; /* unary plus. */
} else negative = 0;
if (*str == '0') { /* if it starts with 0, its either */
if (toupper(*++str) == 'X') { /* 0X, which marks a hex constant, */
str++; /* skip the X */
base = 16; /* base is hex 16 */
} else base = 8; /* leading 0 means octal number */
} else base = 10; /* otherwise, decimal. */
do {
switch (base) { /* char has to be valid for base */
case 8: ok = isodigit(*str); break; /* this digit ok? */
case 10: ok = isdigit(*str); break;
case 16: ok = isxdigit(*str); break;
}
if (ok) /* if valid char, accumulate */
value = value * base + toint(*str++);
} while (ok);
if (toupper(*str) == 'L') /* if ends in 'l' or 'L' marker */
str++; /* to indicate long, just ignore it */
if (ptr) *ptr = str; /* set user pointer to after num */
return (negative) ? -value : value;
}