1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <mach.h>
include <ctype.h>
define DECIMAL 10
.help
.nf _________________________________________________________________________
Attempt to convert a string to a number: nchar = ctod (str, ip, dval)
The index IP must be set to the first character to be scanned upon entry
to CTOD, and will be left pointing at the first untranslated character.
If the string is successfully converted, the number of characters used
is returned as the function argument. If the string (or the first few
characters of the string) cannot be interpreted as a number, zero will be
returned. Note that even if no numeric characters are encountered, the
index IP may be incremented, if leading whitespace is encountered (but the
return value N will still be zero).
The upper case string "INDEF" is a legal real number, as is "." (. == 0.0).
Sexagesimal numbers are permitted. Excess digits of precision are ignored.
Out of range exponents are detected, and result in the value INDEF being
returned (this is not considered an ERROR condition). Any number with an
exponent greater than or equal to MAX_EXPONENT is interpreted as INDEF,
regardless of the mantissa. The number need not contain a decimal point.
Lexical form of a sexagesimal number:
D :== [0-9] numeric digit
E :== [eEdD] exponent symbol
({D}*:)+{D}*(".")?{D}*({E}("+"|"-")?{D}+)?
The format for sexagesimal numbers is fairly permissive. Any number of
colon fields are permitted, with any number of digits (including zero) in
each field. An exponent may occur at the end of a sexagesimal number.
Leading zeros may be omitted in the fields.
.endhelp ____________________________________________________________________
# CTOD -- Convert a string to double precision real.
int procedure ctod (str, ip, dval)
char str[ARB] # string to be converted
int ip # pointer into str
double dval # receives binary value
bool neg
char dig[MAX_DIGITS]
int j, e, vexp, ip_start
long expon
double value, scalar
int strncmp(), gctol(), stridx()
begin
while (IS_WHITE (str[ip])) # skip whitespace
ip = ip + 1
ip_start = ip
dval = INDEFD
if (strncmp (str[ip], "INDEF", 5) == 0) { # check for "INDEF"
for (ip=ip+5; IS_ALPHA (str[ip]) || str[ip] == '_'; ip=ip+1)
;
return (ip - ip_start)
}
neg = (str[ip] == '-') # check for sign
if (neg || str[ip] == '+')
ip = ip + 1
while (str[ip] == '0') # ignore leading zeros
ip = ip + 1
dval = 0.0
scalar = 60.0
repeat { # accumulate digits
for (j=1; j <= MAX_DIGITS && IS_DIGIT(str[ip]); j=j+1) {
dig[j] = str[ip]
ip = ip + 1
}
for (e=0; IS_DIGIT(str[ip]); e=e+1) # ignore the rest
ip = ip + 1
scalar = scalar / 60.0
if (ip > 1 && stridx(str[ip], "'\":dDhHmMsS")>0) { # sexagesimal?
ip = ip + 1
dig[j] = EOS
value = 0.0 # convert digits
for (j=1; dig[j] != EOS; j=j+1)
value = value * 10.0D0 + TO_INTEG (dig[j])
dval = dval + value * scalar * (10.0 ** e)
while (str[ip] != EOS && # multiple spaces etc
stridx(str[ip]," '\":dDhHmMsS")>0)
ip = ip + 1
} else
break
}
if (str[ip] == '.') { # check for a fraction
ip = ip + 1
if (j == 1) # skip leading zeros
while (str[ip] == '0') { # if str = "0.00ddd"
ip = ip + 1
e = e - 1
}
for (; j <= MAX_DIGITS && IS_DIGIT(str[ip]); j=j+1) {
dig[j] = str[ip]
e = e - 1 # adjust scale factor
ip = ip + 1
} # discard insignificant
while (IS_DIGIT (str[ip])) # fractional digits
ip = ip + 1
}
dig[j] = EOS # no more digits
vexp = e + j - 1 # save for ovfl check
if (ip == ip_start) # not a number?
return (0)
value = 0.0 # convert the mantissa
for (j=1; dig[j] != EOS; j=j+1)
value = value * 10.0D0 + TO_INTEG (dig[j])
if (e != 0)
value = value * (10.0D0 ** e) # scale by e
# Check for exponent.
j = ip
expon = 0
if (stridx (str[ip], "eEdD") > 0) { # exponent?
ip = ip + 1
if (gctol (str, ip, expon, DECIMAL) <= 0) {
ip = j # return chars
expon = 0
}
}
if (abs(vexp+expon) > MAX_EXPONENTD) # check for overflow
return (ip - ip_start)
dval = dval + value * scalar
if (expon != 0)
dval = dval * (10.0D0 ** expon) # apply exponent
if (neg)
dval = -dval
return (ip - ip_start)
end
|