4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1990-1995, by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This file contains the common part of string_to_decimal, func_to_decimal,
31 * and file_to_decimal. NEXT must be defined to cause CURRENT to contain the
32 * next input character. ATEOF must be defined to be == EOF if an input
33 * file is at EOF, != EOF otherwise.
40 int nzbp
= 0, nzap
= 0; /* Length of zero substring
41 * before point, after point. */
43 int nfast
, nfastlimit
;
46 *pform
= invalid_form
; /* Invalid until we find something. */
47 *pechar
= NULL
; /* No exponent field assumed. */
48 pd
->fpclass
= fp_normal
;/* Defaults. */
49 pd
->sign
= 0; /* Positive. */
51 pd
->more
= 0; /* Assume no overflow of digits on NaN
53 if (fortran_conventions
!= 0)
59 decpt
= *(localeconv()->decimal_point
);
61 while (isspace(CURRENT
)) {
63 } /* Skip white space. */
64 if (fortran_conventions
>= 2) {
66 * All white space - valid zero for Fortran formatted input.
68 *pform
= whitespace_form
;
73 if ((nread
>= nmax
) && (CURRENT
== NULL
)) { /* Used up field width. */
74 pd
->fpclass
= fp_zero
;
80 } else if (CURRENT
== '-') { /* Negative. */
84 sigfound
= -1; /* -1 = no digits found yet. */
86 if (('1' <= CURRENT
) && (CURRENT
<= '9')) {
88 *pform
= fixed_int_form
;
89 sigfound
= 1; /* 1 = significant digits found. */
90 pd
->ds
[ids
++] = CURRENT
;
96 if (fortran_conventions
< 2)
99 *pform
= fixed_int_form
;
100 while ((CURRENT
== '0') || ((fortran_conventions
>= 2) && (CURRENT
== ' '))) {
102 } /* Ignore leading zeros. */
103 if ((*cp
== '0') || ((fortran_conventions
>= 2) && (*cp
== ' ')))
107 sigfound
= 0; /* 0 = only zeros found yet. */
111 { /* Try infinity. */
112 static char *infstring
= "INFINITY";
115 #define UCASE(c) ( (('a' <= c) && (c <= 'z')) ? c - 32 : c )
120 UCASE(CURRENT
) == infstring
[is
]) {
125 if (CURRENT
!= NULL
) {
126 is
++; /* To account for infstring
127 * indexing starting at 0.
130 if (iagree
>= 3) { /* Found syntactically
132 if (iagree
< 8) { /* INFxxxx */
134 nmax
++; /* 1083219 */
135 CURRENT
= EOF
; /* 1083219 */
137 good
= cp
- (is
- 3);
139 } else { /* INFINITYxxx */
140 good
= cp
- (is
- 8);
141 *pform
= infinity_form
;
143 pd
->fpclass
= fp_infinity
;
147 nmax
++; /* 1083219 */
148 CURRENT
= EOF
; /* 1083219 */
155 static char *nanstring
= "NAN(";
161 UCASE(CURRENT
) == nanstring
[is
]) {
165 if ((is
== 3)) { /* Found syntactically
168 good
= CURRENT
== NULL
? cp
: cp
- 1;
169 pd
->fpclass
= fp_quiet
;
172 else if (is
== 4) { /* Found NaN followed by
174 good
= CURRENT
== NULL
? cp
- 1 : cp
- 2;
176 pd
->fpclass
= fp_quiet
;
178 while ((CURRENT
!= 0) && (CURRENT
!= ')') && (ids
< (DECIMAL_STRING_LENGTH
- 1))) {
179 pd
->ds
[ids
++] = CURRENT
;
182 while ((CURRENT
!= 0) && (CURRENT
!= ')') && (ATEOF
!= EOF
)) { /* Pick up rest of
187 if (CURRENT
== ')') {
190 *pform
= nanstring_form
;
193 nmax
++; /* 1083219 */
194 CURRENT
= EOF
; /* 1083219 */
198 nmax
++; /* 1083219 */
199 CURRENT
= EOF
; /* 1083219 */
204 if (CURRENT
== decpt
) {
205 NEXT
; /* Try number. */
215 if (('1' <= CURRENT
) && (CURRENT
<= '9')) {
216 if ((ids
+ nzbp
+ 2) >= DECIMAL_STRING_LENGTH
) { /* Not enough room to
219 pd
->exponent
+= nzbp
+ 1;
221 pd
->ds
[ids
] = 0; /* Actual string termination. */
222 ids
= DECIMAL_STRING_LENGTH
- 1; /* To allow end of
223 * program to terminate
226 for (i
= 0; (i
< nzbp
); i
++)
228 pd
->ds
[ids
++] = CURRENT
;
230 *pform
= fixed_int_form
;
234 nfastlimit
= DECIMAL_STRING_LENGTH
- 3 - ids
;
235 if ((0 < nfastlimit
) && ('1' <= CURRENT
) && (CURRENT
<= '9')) { /* Special handling for
238 pfast
= &(pd
->ds
[ids
]);
240 pfast
[nfast
++] = CURRENT
;
243 while (('1' <= CURRENT
) && (CURRENT
<= '9') && (nfast
< nfastlimit
));
247 goto nextnumberzero
; /* common case */
249 if (('1' > *good
) || (*good
> '9'))
250 good
--; /* look out if we fell off end */
255 if (fortran_conventions
< 2)
257 if (fortran_conventions
== 2) {
262 *pform
= fixed_int_form
;
264 while ((CURRENT
== '0') || (CURRENT
== ' ')) { /* Accumulate zero
266 if (CURRENT
== ' ') {
267 if (fortran_conventions
< 2) {
271 if (fortran_conventions
== 2) {
272 nzbp
--; /* Undo effect of
273 * following nzbp++ */
286 if (sigfound
== -1) /* exp following no digits?
290 pd
->exponent
+= nzbp
;
298 if (fortran_conventions
!= 0)
301 if (CURRENT
== decpt
) {
307 pd
->exponent
+= nzbp
;
312 if (sigfound
>= 0) { /* Better accept the point as good, but don't
313 * accept the next character after. */
314 good
= cp
- 1; /* Assume cp points past. */
315 if (*good
!= decpt
) /* If not, bump good. */
318 switch (*pform
) { /* Revise *pform now that point has been
321 case whitespace_form
:
322 *pform
= fixed_dotfrac_form
;
325 *pform
= fixed_intdot_form
;
329 if (('1' <= CURRENT
) && (CURRENT
<= '9')) {
330 if (*pform
== fixed_intdot_form
)
331 *pform
= fixed_intdotfrac_form
;
333 if (sigfound
< 1) { /* No significant digits found so
336 pd
->ds
[ids
++] = CURRENT
;
337 pd
->exponent
= -(nzap
+ 1);
338 } else { /* Significant digits have begun. */
339 if ((ids
+ nzbp
+ nzap
+ 2) >= DECIMAL_STRING_LENGTH
) { /* Not enough room to
342 pd
->exponent
+= nzbp
;
344 pd
->ds
[ids
] = 0; /* Actual string
346 ids
= DECIMAL_STRING_LENGTH
- 1; /* To allow end of
347 * program to terminate
350 for (i
= 0; (i
< (nzbp
+ nzap
)); i
++)
352 pd
->ds
[ids
++] = CURRENT
;
353 pd
->exponent
-= nzap
+ 1;
359 nfastlimit
= DECIMAL_STRING_LENGTH
- 3 - ids
;
360 if ((0 < nfastlimit
) && ('1' <= CURRENT
) && (CURRENT
<= '9')) { /* Special handling for
363 pfast
= &(pd
->ds
[ids
]);
365 pfast
[nfast
++] = CURRENT
;
368 while (('1' <= CURRENT
) && (CURRENT
<= '9') && (nfast
< nfastlimit
));
370 if (('1' > *good
) || (*good
> '9'))
371 good
--; /* look out if we fell off end */
373 pd
->exponent
-= nfast
;
377 goto switchafterpoint
;
381 if (fortran_conventions
< 2)
382 goto afterpointdefault
;
383 if (fortran_conventions
== 2) {
385 * To pass FCVS, all blanks after point must
386 * count as if zero seen.
391 goto switchafterpoint
;
394 if (*pform
== fixed_intdot_form
)
395 *pform
= fixed_intdotfrac_form
;
402 while ((CURRENT
== '0') || (CURRENT
== ' ')) {
403 if (CURRENT
== ' ') { /* Handle blanks and
405 if (fortran_conventions
< 2) {
407 goto afterpointdefault
;
409 if (fortran_conventions
== 2) {
410 nzap
--; /* Undo following nzap++ */
419 goto switchafterpoint
;
425 if (sigfound
== -1) /* exp following no digits?
429 pd
->exponent
+= nzbp
;
437 if (fortran_conventions
!= 0)
443 pd
->exponent
+= nzbp
;
448 unsigned explicitsign
= 0, explicitexponent
= 0;
450 if ((CURRENT
!= '+') && (CURRENT
!= '-')) { /* Skip EeDd and
451 * following blanks. */
452 NEXT
; /* Pass the EeDd. */
453 if (fortran_conventions
>= 2)
454 while (CURRENT
== ' ') {
458 if (CURRENT
== '+') {
460 } else if (CURRENT
== '-') { /* Negative explicit
465 while ((('0' <= CURRENT
) && (CURRENT
<= '9')) || (CURRENT
== ' ')) { /* Accumulate explicit
467 if (CURRENT
== ' ') { /* Handle blanks and Fortran. */
468 if (fortran_conventions
< 2)
470 if (fortran_conventions
== 2) {
477 if (explicitexponent
<= 400000000) {
478 explicitexponent
= 10 * explicitexponent
+ CURRENT
- '0';
482 case whitespace_form
:
484 *pform
= floating_int_form
;
486 case fixed_intdot_form
:
487 *pform
= floating_intdot_form
;
489 case fixed_dotfrac_form
:
490 *pform
= floating_dotfrac_form
;
492 case fixed_intdotfrac_form
:
493 *pform
= floating_intdotfrac_form
;
499 if (explicitsign
== 1)
500 pd
->exponent
-= explicitexponent
;
502 pd
->exponent
+= explicitexponent
;
506 if (fortran_conventions
>= 2) { /* Fill up field width with extra
508 if (good
== (cp
- 1))
509 good
= NULL
; /* Flag that whole field was good up
511 while (CURRENT
== ' ') {
515 good
= CURRENT
== NULL
? cp
: cp
- 1;
519 pd
->fpclass
= fp_zero
; /* True zero found. */
521 pd
->ds
[ids
] = 0; /* Terminate decimal string. */
522 pd
->ndigits
= ids
; /* Save string length in ndigits. */
523 if (good
>= cp0
) { /* Valid token found. */
524 *ppc
= good
+ 1;/* token found - point one past. */
525 } else { /* No valid token found. */
526 *pform
= invalid_form
;
527 *ppc
= cp0
; /* No token found - revert to original value. */
529 pd
->fpclass
= fp_signaling
; /* If anyone looks, x will be