2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * This file contains the common part of the functions string_to_decimal, 2N/A * func_to_decimal, and file_to_decimal. Much of this code has been dupli- 2N/A * cated in wstring_to_decimal (see wstod.c) with some simplifications and 2N/A * appropriate modifications for wide characters. DO NOT fix a bug here 2N/A * without fixing the same bug in wstring_to_decimal, if it applies. 2N/A * The code below makes the following assumptions. 2N/A * 1. The first six parameters to the function are declared with the 2N/A * following names and types: 2N/A * int fortran_conventions; 2N/A * decimal_record *pd; 2N/A * enum decimal_string_form *pform; 2N/A * 2. Before this file is #included, the following variables have been 2N/A * defined and initialized as shown: 2N/A * char *good = *ppc - 1; 2N/A * If the first character can be read successfully, then current is set 2N/A * to the value of the first character, cp is set to *ppc, (char)current 2N/A * is stored at *cp, and nread = 1. If the first character cannot be 2N/A * read successfully, then current = EOF and nread = 0. 2N/A * 3. The macro NEXT is defined to expand to code that implements 2N/A * the following logic: 2N/A * if (nread < nmax) { 2N/A * current = <next character>; 2N/A * if (current != EOF) { 2N/A * *++cp = (char)current; 2N/A * Note that nread always reflects the number of characters successfully 2N/A * read, the buffer pointed to by *ppc gets filled only with characters 2N/A * that have been successfully read, and cp always points to the location 2N/A * in the buffer that was filled by the last character successfully read. 2N/A * current == EOF if and only if we can't read any more, either because 2N/A * we've reached the end of the input file or the buffer is full (i.e., 2N/A * we've read nmax characters). 2N/A * 4. After this file is #included, the following variables may be used 2N/A * and will have the specified values: 2N/A * *ppc, *pd, *pform, and *pechar will be set as documented in the 2N/A * nmax and fortran_conventions will be unchanged; 2N/A * nread will be the number of characters actually read; 2N/A * cp will point to the last character actually read, provided at least 2N/A * one character was read successfully (in which case cp >= *ppc). 2N/A#
define UCASE(c) (((
'a' <= c) && (c <=
'z'))? c -
32 : c)
2N/A ((
'a' <= c && c <=
'f') || (
'A' <= c && c <=
'F'))))
2N/A int nzbp = 0;
/* number of zeros before point */ 2N/A int nzap = 0;
/* number of zeros after point */ 2N/A * This routine assumes that the radix point is a single 2N/A * ASCII character, so that following this assignment, the 2N/A * condition (current == decpt) will correctly detect it. 2N/A /* input is invalid until we find something */ 2N/A /* skip white space */ 2N/A * We found at least one white space character. For 2N/A * Fortran formatted input, accept this; if we don't 2N/A * find anything else, we'll interpret it as a valid zero. 2N/A /* look for optional leading sign */ 2N/A * Admissible first non-white-space, non-sign characters are 2N/A * 0-9, i, I, n, N, or the radix point. 2N/A * When fortran_conventions >= 2, treat leading 2N/A * blanks the same as leading zeroes. 2N/A * Accept the leading zero and set pd->fpclass 2N/A * accordingly, but don't set sigfound until we 2N/A * determine that this isn't a "fake" hex string 2N/A /* look for a hex fp string */ 2N/A /* assume hex fp form */ 2N/A * Only a digit or radix point can 2N/A /* not hex fp after all */ 2N/A /* skip all leading zeros */ 2N/A /* look for inf or infinity */ 2N/A /* found valid infinity */ 2N/A * Accept trailing blanks if no extra characters 2N/A /* look for nan or nan(string) */ 2N/A /* found valid NaN */ 2N/A /* accept parenthesized string */ 2N/A /* prepare for loop below */ 2N/A /* accept trailing blanks */ 2N/A * Don't accept the radix point just yet; 2N/A * we need to see at least one digit. 2N/A * Admissible characters after the first digit are a valid digit, 2N/A * an exponent delimiter (E or e for any decimal form; +, -, D, d, 2N/A * Q, or q when fortran_conventions >= 2; P or p for hex form), 2N/A * or the radix point. (Note that we can't get here unless we've 2N/A * already found a digit.) 2N/A * Found another nonzero digit. If there's enough room 2N/A * in pd->ds, store any intervening zeros we've found so far 2N/A * and then store this digit. Otherwise, stop storing 2N/A * digits in pd->ds and set pd->more. 2N/A /* don't store any more digits */ 2N/A * Use an optimized loop to grab a consecutive sequence 2N/A * of nonzero digits quickly. 2N/A /* advance good to the last accepted digit */ 2N/A * When fortran_conventions > 2, treat internal 2N/A * blanks the same as zeroes. 2N/A * Count zeros before the radix point. Later we 2N/A * will either put these zeros into pd->ds or add 2N/A * nzbp to pd->exponent to account for them. 2N/A * Only accept these as the start of the exponent 2N/A * field if fortran_conventions is positive. 2N/A /* accept the radix point */ 2N/A * Admissible characters after the radix point are a valid digit 2N/A * or an exponent delimiter. (Note that it is possible to get 2N/A * here even though we haven't found any digits yet.) 2N/A /* found a digit after the point; revise form */ 2N/A /* no significant digits found until now */ 2N/A /* significant digits have been found */ 2N/A /* don't store any more digits */ 2N/A * Use an optimized loop to grab a consecutive sequence 2N/A * of nonzero digits quickly. 2N/A /* advance good to the last accepted digit */ 2N/A * Treat a radix point followed by blanks 2N/A * but no digits as zero so we'll pass FCVS. 2N/A * when fortran_conventions > 2, treat internal 2N/A * blanks the same as zeroes 2N/A /* found a digit after the point; revise form */ 2N/A * Count zeros after the radix point. If we find 2N/A * any more nonzero digits later, we will put these 2N/A * zeros into pd->ds and decrease pd->exponent by 2N/A * Only accept these as the start of the exponent 2N/A * field if fortran_conventions is positive. 2N/A /* don't accept exponent without preceding digits */ 2N/A /* don't accept exponent without preceding digits */ 2N/A * Set *pechar to point to the character that looks like the 2N/A * beginning of the exponent field, then attempt to parse it. 2N/A /* skip the exponent character and following blanks */ 2N/A /* look for optional exponent sign */ 2N/A * Accumulate explicit exponent. Note that if we don't find at 2N/A * least one digit, good won't be updated and e will remain 0. 2N/A * Also, we keep e from getting too large so we don't overflow 2N/A * the range of int (but notice that the threshold is large 2N/A * enough that any larger e would cause the result to underflow 2N/A * or overflow anyway). 2N/A /* accept trailing blanks */ 2N/A * If we successfully parsed an exponent field, update form 2N/A * accordingly. If we didn't, don't set *pechar. 2N/A * If we found any zeros before the radix point that were not 2N/A * accounted for earlier, adjust the exponent. (This is only 2N/A * relevant when pd->fpclass == fp_normal, but it's harmless 2N/A * in all other cases.) 2N/A /* terminate pd->ds if we haven't already */ 2N/A * If we accepted any characters, advance *ppc to point to the 2N/A * first character we didn't accept; otherwise, pass back a