xref: /csrg-svn/usr.bin/pascal/libpc/READ8.c (revision 15302)
11680Smckusick /* Copyright (c) 1979 Regents of the University of California */
21680Smckusick 
3*15302Smckusick static char sccsid[] = "@(#)READ8.c 1.7 10/28/83";
41680Smckusick 
51680Smckusick #include "h00vars.h"
66498Smckusick #include <errno.h>
76498Smckusick extern int errno;
81680Smckusick 
91680Smckusick double
101680Smckusick READ8(curfile)
111680Smckusick 
121680Smckusick 	register struct iorec	*curfile;
131680Smckusick {
141680Smckusick 	double			data;
152223Smckusic 	int			retval;
161680Smckusick 
171680Smckusick 	if (curfile->funit & FWRITE) {
183869Smckusic 		ERROR("%s: Attempt to read, but open for writing\n",
193869Smckusic 			curfile->pfname);
201680Smckusick 		return;
211680Smckusick 	}
221680Smckusick 	UNSYNC(curfile);
236498Smckusick 	errno = 0;
24*15302Smckusick 	retval = readreal(curfile, &data);
252223Smckusic 	if (retval == EOF) {
263869Smckusic 		ERROR("%s: Tried to read past end of file\n", curfile->pfname);
272223Smckusic 		return;
282223Smckusic 	}
292223Smckusic 	if (retval == 0) {
303869Smckusic 		ERROR("%s: Bad data found on real read\n", curfile->pfname);
311680Smckusick 		return;
321680Smckusick 	}
336498Smckusick 	if (errno == ERANGE) {
346498Smckusick 		if (data == 0.0)
356498Smckusick 			ERROR("%s: Underflow on real read\n", curfile->pfname);
366498Smckusick 		else
376498Smckusick 			ERROR("%s: Overflow on real read\n", curfile->pfname);
386498Smckusick 		return;
396498Smckusick 	}
406498Smckusick 	if (errno != 0) {
4115127Smckusick 		PERROR("Error encountered on real read ", curfile->pfname);
426498Smckusick 		return;
436498Smckusick 	}
4415127Smckusick 	return (data);
451680Smckusick }
4615127Smckusick 
4715127Smckusick /*
4815127Smckusick  *	given a file pointer, read a sequence of characters of the
4915127Smckusick  *	syntax of section 6.1.5 and form them into a double.
5015127Smckusick  *
5115127Smckusick  *	the syntax of a signed-real is:
5215127Smckusick  *	    [-|+] digit {digit} e [+|-] digit {digit}
5315127Smckusick  *	or
5415127Smckusick  *	    [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}]
5515127Smckusick  *
5615127Smckusick  *	returns:
5715127Smckusick  *		1	for success (with value in *doublep)
5815127Smckusick  *		0	on error (with *doublep unchanged)
5915127Smckusick  *	       -1	on end-of-file during read (with *doublep unchanged)
6015127Smckusick  *	side effects:
6115127Smckusick  *	      errno	may be set to ERANGE if atof() sets it.
6215127Smckusick  */
63*15302Smckusick readreal(curfile, doublep)
64*15302Smckusick 	struct iorec	*curfile;
65*15302Smckusick 	double		*doublep;
6615127Smckusick {
67*15302Smckusick 	FILE	*filep = curfile->fbuf;	/* current file variable */
6815127Smckusick 	char	*sequencep;		/* a pointer into sequence */
6915127Smckusick 	int	read;			/* return value from fscanf() */
70*15302Smckusick 	char	sequence[BUFSIZ];	/* the character sequence */
7115127Smckusick 	double	atof();
7215127Smckusick 
73*15302Smckusick #define PUSHBACK(curfile, sequencep) \
74*15302Smckusick 	if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \
75*15302Smckusick 		*(sequencep) = '\0'; \
76*15302Smckusick 	} else if ((curfile)->funit & SYNC) { \
77*15302Smckusick 		(curfile)->funit &= ~SYNC; \
78*15302Smckusick 		*(curfile)->fileptr = *(sequencep); \
79*15302Smckusick 		*(sequencep) = '\0'; \
80*15302Smckusick 	} else { \
81*15302Smckusick 		return (0); \
82*15302Smckusick 	}
83*15302Smckusick 
8415127Smckusick #define	RETURN_ON_EOF(read) \
8515127Smckusick 	if (read == EOF) \
8615127Smckusick 		return (EOF); \
8715127Smckusick 	else \
8815127Smckusick 		/* void */;
8915127Smckusick 
9015127Smckusick #define	PUSH_TO_NULL(sequencep) \
9115127Smckusick 	while (*sequencep) \
9215127Smckusick 		sequencep++;
9315127Smckusick 
9415127Smckusick #define	SOME(read, filep, format, sequencep) \
9515127Smckusick 	read = fscanf(filep, format, sequencep); \
9615127Smckusick 	RETURN_ON_EOF(read); \
9715127Smckusick 	PUSH_TO_NULL(sequencep);
9815127Smckusick 
9915127Smckusick #define	AT_LEAST_ONE(read, filep, format, sequencep) \
10015127Smckusick 	read = fscanf(filep, format, sequencep); \
10115127Smckusick 	RETURN_ON_EOF(read); \
10215127Smckusick 	if (strlen(sequencep) < 1) \
10315127Smckusick 		return (0); \
10415127Smckusick 	PUSH_TO_NULL(sequencep);
10515127Smckusick 
10615127Smckusick #define	EXACTLY_ONE(read, filep, format, sequencep) \
10715127Smckusick 	read = fscanf(filep, format, sequencep); \
10815127Smckusick 	RETURN_ON_EOF(read); \
10915127Smckusick 	if (strlen(sequencep) != 1) \
11015127Smckusick 		return (0); \
11115127Smckusick 	PUSH_TO_NULL(sequencep);
11215127Smckusick 
11315127Smckusick #define	AT_MOST_ONE(read, filep, format, sequencep) \
11415127Smckusick 	read = fscanf(filep, format, sequencep); \
11515127Smckusick 	RETURN_ON_EOF(read); \
11615127Smckusick 	if (strlen(sequencep) > 1) \
11715127Smckusick 		return (0); \
11815127Smckusick 	PUSH_TO_NULL(sequencep);
11915127Smckusick 
12015127Smckusick 	sequencep = &sequence[0];
12115127Smckusick 	*sequencep = '\0';
12215127Smckusick 	/*
12315127Smckusick 	 * skip leading whitespace
12415127Smckusick 	 */
12515127Smckusick 	SOME(read, filep, "%*[ \t\n]", sequencep);
12615127Smckusick 	/*
12715127Smckusick 	 *	[ "+" | "-" ] digit {digits}
12815127Smckusick 	 */
12915127Smckusick 	AT_MOST_ONE(read, filep, "%[+-]", sequencep);
13015127Smckusick 	AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
13115127Smckusick 	/*
13215127Smckusick 	 *	either
13315127Smckusick 	 *		"." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ]
13415127Smckusick 	 *	or
13515127Smckusick 	 *		"e" [ "+" | "-" ] digit {digits}
13615127Smckusick 	 */
137*15302Smckusick 	AT_MOST_ONE(read, filep, "%c", sequencep);
138*15302Smckusick 	switch (sequencep[-1]) {
139*15302Smckusick 	default:
140*15302Smckusick 		PUSHBACK(curfile, sequencep);
141*15302Smckusick 		goto convert;
142*15302Smckusick 	case '.':
143*15302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
144*15302Smckusick 		if (!read) {
145*15302Smckusick 			PUSHBACK(curfile, sequencep);
146*15302Smckusick 			goto convert;
14715127Smckusick 		}
148*15302Smckusick 		AT_MOST_ONE(read, filep, "%c", sequencep);
149*15302Smckusick 		if (sequencep[-1] != 'e') {
150*15302Smckusick 			PUSHBACK(curfile, sequencep);
151*15302Smckusick 			goto convert;
152*15302Smckusick 		}
153*15302Smckusick 		/* fall through */
154*15302Smckusick 	case 'e':
155*15302Smckusick 		AT_MOST_ONE(read, filep, "%c", sequencep);
156*15302Smckusick 		if (sequencep[-1] != '+' && sequencep[-1] != '-') {
157*15302Smckusick 			PUSHBACK(curfile, sequencep);
158*15302Smckusick 			SOME(read, filep, "%[0123456789]", sequencep);
159*15302Smckusick 			if (!read)
160*15302Smckusick 				PUSHBACK(curfile, sequencep);
161*15302Smckusick 			goto convert;
162*15302Smckusick 		}
163*15302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
164*15302Smckusick 		if (!read) {
165*15302Smckusick 			PUSHBACK(curfile, sequencep);
166*15302Smckusick 			PUSHBACK(curfile, sequencep);
167*15302Smckusick 		}
16815127Smckusick 	}
169*15302Smckusick 
170*15302Smckusick convert:
17115127Smckusick 	/*
17215127Smckusick 	 * convert sequence to double
17315127Smckusick 	 */
17415127Smckusick 	*doublep = atof(&sequence[0]);
17515127Smckusick 	return (1);
17615127Smckusick }
177