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
|