This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]