Message ID | 4C27A929.8010702@verizon.net |
---|---|
State | New |
Headers | show |
Jerry DeLisle wrote: > This attached patch adds code to read these special cases. The code is > self explanatory. This added feature is for formatted READ. Can you also add as follow up support for the parentheses to list directed read (parse_real)? Your patch only handles "read_f". Example (only tested with an unpatched gfortran as bootstrapping takes a while): !------------------------------ character(len=200) :: str real :: r str = 'NAN' read(str,*) r ! OK before your patch print *, 'Result: ',r read(str,'(g10.5)') r ! OK with your patch print *, 'Result: ',r str = 'NAN(0x34)' read(str,*) r ! FAILS (independent of your patch) print *, 'Result: ',r read(str,'(g10.5)') r ! OK with your patch print *, 'Result: ',r end !------------------------------ > As a follow-up patch we can consider the contents of the parenthesis > with NAN() and explicitly set the result. I will also be looking at > how to handle signs. I personally do not care much about the sign of NaN or the "payload" (i.e. the bits are non-zero in the trailing significand field of the NaN) . However, I really miss support for negative infinity. (For list-directed I/O, it works.) Regarding NAN("payload"): Can't we simply put the whole string to "strtod" - including sign and parentheses? At least POSIX (IEEE Std 1003.1:2003) has for strtod/stdtof/strtold: "The expected form of the subject sequence is an optional plus or minus sign, then one of the following: [...] * One of INF or INFINITY, ignoring case * One of NAN or NAN(n-char-sequence_opt), ignoring case in the NAN part, where: n-char-sequence: digit nondigit n-char-sequence digit n-char-sequence nondigit" I have no idea whether all libc handle it - if not, one could add a configure check and truncate NAN conditionally. But may first assume that all support it and and - if not - one can still add the check. Regarding your patch: I wonder whether one should check your patch to disallow spaces in the parentheses. The standard has (cf. comment 3 in PR43298): "an optional sign, followed by the string ’NAN’, optionally followed by zero or more alphanumeric characters enclosed in parentheses," A space is not an alphanumeric character. Currently, you explicitly allow spaces in parentheses How about checking for the parentheses also for INF - and rejecting them if present? For instance by using a three-state seen_paren; that way one might also reject "NAN(a)(b)" - though we should try to be fast as INF and NAN can be common while NAN(string) or invalid INF/NAN constructs are probably the exception. Note: The test case needs to use ! { dg-add-options ieee } Tobias
Index: read.c =================================================================== --- read.c (revision 161472) +++ read.c (working copy) @@ -810,6 +810,60 @@ read_f (st_parameter_dt *dtp, const fnode *f, char if (w == 0) goto zero; + + /* Check for Infinity or NaN. */ + if (unlikely ((w >= 3 && (*p == 'i' || *p == 'I' || *p == 'n' || *p == 'N')))) + { + int i; + int seen_space = 0; + int seen_paren = 0; + + /* Scan through the buffer keeping track of spaces and parenthesis. We + null terminate the string as soon as we see a left paren or if we are + BLANK_NULL mode. Leading spaces have already been skipped above, + trailing spaces spaces are ignored by converrting to '\0'. A space + between "NaN" and the optional perenthesis is not permitted. */ + for (i = 0; i < w; i++) + { + buffer[i] = tolower (p[i]); + if (!seen_paren && seen_space && buffer[i] != ' ') + goto bad_float; + if (buffer[i] == '(') + { + seen_paren = 1; + buffer[i] = '\0'; + } + if (buffer[i] == ')') + { + if (!seen_paren) + goto bad_float; + else + seen_paren = 0; + } + if (buffer[i] == ' ' && !seen_paren) + { + seen_space = 1; + if (dtp->u.p.blank_status == BLANK_ZERO) + buffer[i] = '0'; + else /* Ignore leading and trailing blanks. */ + buffer[i] = '\0'; + } + } + + buffer[w] = '\0'; + + /* If we did not see a closing parenthesis, we have a bad float. */ + if (seen_paren) + goto bad_float; + if (strcmp (buffer, "inf") != 0 + && strcmp (buffer, "nan") != 0 + && strcmp (buffer, "infinity") != 0) + goto bad_float; + + convert_real (dtp, dest, buffer, length); + return; + } + /* Process the mantissa string. */ while (w > 0) {