This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
scanf conflict with conclusions of WG 14 Defect Report 017 Question 29
- From: mjn3 at codepoet dot org (Manuel Novoa III)
- To: libc-alpha at sources dot redhat dot com
- Date: Tue, 16 Sep 2003 17:01:27 -0600
- Subject: scanf conflict with conclusions of WG 14 Defect Report 017 Question 29
Sigh... One more attempt to convince Ulrich Drepper that scanf is broken.
Manuel
/* glibc scanf violates the behavior specified in Defect Report #022 Question 29.
From http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_017.html
Question 29
Conversion failure and longest matches
Consider 1.2e+4 with field width of 5. Is it input item 1.2e+ that gives a
conversion failure? What is the ordering between building input items and
converting them? Do they run in parallel, or sequential?
Refer to subclause 7.9.6.2 The fscanf function, page 135, lines 31-33
concerning the longest matching sequence, and subclause 7.9.6.2, page 137,
lines 15-16 concerning a conflicting input character.
For 1.2e-x, is 1.2 or 1.2e- read?
The above questions all come about because of page 137, line 15: ``If
conversion terminates ...'' In this context the use of the word
``conversion'' could be referring to the process of turning a sequence
of characters into numeric form. I believe what was intended was ``If
a conversion specifier terminates ...''
Response
The relevant citations are subclause 7.9.6.2, page 137, lines 15-16:
If conversion terminates on a conflicting input character, the offending
input character is left unread in the input stream.
and subclause 7.9.6.2, page 135, lines 31-33:
An input item is defined as the longest matching sequence of input
characters, unless that exceeds a specified field width, in which case
it is the initial subsequence of that length in the sequence.
and subclause 7.9.6.2, page 135, lines 38-40:
If the input item is not a matching sequence, the execution of the
directive fails: this condition is a matching failure.
The ``conversion'' in the first quoted passage is the process of both
forming an input item and converting it as specified by the conversion
specifier.
About your example: If the characters available for input are `` 1.2e+4''
and input is performed using a ``%5e,'' then the input item is ``1.2e+''
as defined by the second passage quoted above. That input item is not a
matching sequence, but only an initial subsequence that fails to be a
matching sequence in its own right. Under the rules of the third quoted
passage, this is a matching failure.
Note that in this case, no characters were pushed back onto the input stream.
There was no ``conflicting input character'' that terminated the field, and
so the first quoted passage does not apply.
See the Correction made in response to Defect Report #022, Question 1,
for additional clarification.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
float x;
FILE *fp;
int n;
int c;
if (!(fp = fmemopen("1.2e+4", 6, "r"))) {
printf("fmemopen failed!\n");
return EXIT_FAILURE;
}
n = fscanf(fp, "%5g", &x);
printf("fscanf returned %d, ferror=%d, feof=%d, and the next fgetc returned ",
n, ferror(fp), feof(fp));
if ((c = fgetc(fp)) < 0) {
printf("EOF!\n");
return EXIT_FAILURE;
}
if (isprint(c)) {
printf("'%c'\n", c);
} else {
printf("'\\x%.2x'\n", c);
}
if (n == 0) {
printf("ok\n");
} else {
printf("Error: By the response to Defect Report #022 Question 29,\n"
" scanf should have returned 0 due to a matching failure!\n");
return EXIT_FAILURE;
}
if (c != '4') {
printf("Error: By the response to Defect Report #022 Question 29,\n"
" the fgetc following fscanf should have returned '4'!\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}