xref: /csrg-svn/usr.bin/pascal/libpc/READ8.c (revision 62096)
140865Sbostic /*-
2*62096Sbostic  * Copyright (c) 1979, 1993
3*62096Sbostic  *	The Regents of the University of California.  All rights reserved.
440865Sbostic  *
540865Sbostic  * %sccs.include.redist.c%
640865Sbostic  */
71680Smckusick 
840865Sbostic #ifndef lint
9*62096Sbostic static char sccsid[] = "@(#)READ8.c	8.1 (Berkeley) 06/06/93";
1040865Sbostic #endif /* not lint */
111680Smckusick 
121680Smckusick #include "h00vars.h"
136498Smckusick #include <errno.h>
146498Smckusick extern int errno;
151680Smckusick 
161680Smckusick double
READ8(curfile)171680Smckusick READ8(curfile)
181680Smckusick 	register struct iorec	*curfile;
191680Smckusick {
201680Smckusick 	double			data;
212223Smckusic 	int			retval;
221680Smckusick 
231680Smckusick 	if (curfile->funit & FWRITE) {
243869Smckusic 		ERROR("%s: Attempt to read, but open for writing\n",
253869Smckusic 			curfile->pfname);
261680Smckusick 	}
271680Smckusick 	UNSYNC(curfile);
286498Smckusick 	errno = 0;
2915302Smckusick 	retval = readreal(curfile, &data);
302223Smckusic 	if (retval == EOF) {
313869Smckusic 		ERROR("%s: Tried to read past end of file\n", curfile->pfname);
322223Smckusic 	}
332223Smckusic 	if (retval == 0) {
343869Smckusic 		ERROR("%s: Bad data found on real read\n", curfile->pfname);
351680Smckusick 	}
366498Smckusick 	if (errno == ERANGE) {
376498Smckusick 		if (data == 0.0)
386498Smckusick 			ERROR("%s: Underflow on real read\n", curfile->pfname);
396498Smckusick 		else
406498Smckusick 			ERROR("%s: Overflow on real read\n", curfile->pfname);
416498Smckusick 	}
426498Smckusick 	if (errno != 0) {
4315127Smckusick 		PERROR("Error encountered on real read ", curfile->pfname);
446498Smckusick 	}
4515127Smckusick 	return (data);
461680Smckusick }
4715127Smckusick 
4815127Smckusick /*
4915127Smckusick  *	given a file pointer, read a sequence of characters of the
5015127Smckusick  *	syntax of section 6.1.5 and form them into a double.
5115127Smckusick  *
5215127Smckusick  *	the syntax of a signed-real is:
5315388Speter  *	    [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ]
5415127Smckusick  *
5515127Smckusick  *	returns:
5615127Smckusick  *		1	for success (with value in *doublep)
5715127Smckusick  *		0	on error (with *doublep unchanged)
5815127Smckusick  *	       -1	on end-of-file during read (with *doublep unchanged)
5915127Smckusick  *	side effects:
6015127Smckusick  *	      errno	may be set to ERANGE if atof() sets it.
6115127Smckusick  */
6215302Smckusick readreal(curfile, doublep)
6315302Smckusick 	struct iorec	*curfile;
6415302Smckusick 	double		*doublep;
6515127Smckusick {
6615302Smckusick 	FILE	*filep = curfile->fbuf;	/* current file variable */
6715127Smckusick 	char	*sequencep;		/* a pointer into sequence */
6815127Smckusick 	int	read;			/* return value from fscanf() */
6915302Smckusick 	char	sequence[BUFSIZ];	/* the character sequence */
7015127Smckusick 	double	atof();
7115127Smckusick 
7215302Smckusick #define PUSHBACK(curfile, sequencep) \
7315302Smckusick 	if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \
7415302Smckusick 		*(sequencep) = '\0'; \
7515302Smckusick 	} else if ((curfile)->funit & SYNC) { \
7615302Smckusick 		(curfile)->funit &= ~SYNC; \
7715302Smckusick 		*(curfile)->fileptr = *(sequencep); \
7815302Smckusick 		*(sequencep) = '\0'; \
7915302Smckusick 	} else { \
8015302Smckusick 		return (0); \
8115302Smckusick 	}
8215302Smckusick 
8315127Smckusick #define	RETURN_ON_EOF(read) \
8415127Smckusick 	if (read == EOF) \
8515127Smckusick 		return (EOF); \
8615127Smckusick 	else \
8715127Smckusick 		/* void */;
8815127Smckusick 
8915127Smckusick #define	PUSH_TO_NULL(sequencep) \
9015127Smckusick 	while (*sequencep) \
9115127Smckusick 		sequencep++;
9215127Smckusick 
9315388Speter 	/* general reader of the next character */
9415388Speter #define	NEXT_CHAR(read, filep, format, sequencep) \
9515388Speter 	read = fscanf(filep, "%c", sequencep); \
9615388Speter 	RETURN_ON_EOF(read); \
9715388Speter 	*++sequencep = '\0';
9815388Speter 
9915388Speter 	/* e.g. use %[0123456789] for {digit}, and check read */
10015127Smckusick #define	SOME(read, filep, format, sequencep) \
10115127Smckusick 	read = fscanf(filep, format, sequencep); \
10215127Smckusick 	RETURN_ON_EOF(read); \
10315127Smckusick 	PUSH_TO_NULL(sequencep);
10415127Smckusick 
10515388Speter 	/* e.g. use %[0123456789] for digit {digit} */
10615127Smckusick #define	AT_LEAST_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 
11315388Speter #define	ANY_ONE_OF(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 #define	AT_MOST_ONE(read, filep, format, sequencep) \
12115127Smckusick 	read = fscanf(filep, format, sequencep); \
12215127Smckusick 	RETURN_ON_EOF(read); \
12315127Smckusick 	if (strlen(sequencep) > 1) \
12415127Smckusick 		return (0); \
12515127Smckusick 	PUSH_TO_NULL(sequencep);
12615127Smckusick 
12715127Smckusick 	sequencep = &sequence[0];
12815127Smckusick 	*sequencep = '\0';
12915127Smckusick 	/*
13015388Speter 	 *	skip leading whitespace
13115127Smckusick 	 */
13215127Smckusick 	SOME(read, filep, "%*[ \t\n]", sequencep);
13315127Smckusick 	/*
13415388Speter 	 *	this much is required:
13515127Smckusick 	 *	[ "+" | "-" ] digit {digits}
13615127Smckusick 	 */
13715127Smckusick 	AT_MOST_ONE(read, filep, "%[+-]", sequencep);
13815127Smckusick 	AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
13915127Smckusick 	/*
14015388Speter 	 *	any of this is optional:
14115388Speter 	 *	[ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ]
14215127Smckusick 	 */
14315388Speter 	NEXT_CHAR(read, filep, "%c", sequencep);
14415302Smckusick 	switch (sequencep[-1]) {
14515302Smckusick 	default:
14615302Smckusick 		PUSHBACK(curfile, sequencep);
14715302Smckusick 		goto convert;
14815302Smckusick 	case '.':
14915302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
15015302Smckusick 		if (!read) {
15115302Smckusick 			PUSHBACK(curfile, sequencep);
15215302Smckusick 			goto convert;
15315127Smckusick 		}
15415388Speter 		NEXT_CHAR(read, filep, "%c", sequencep);
15515302Smckusick 		if (sequencep[-1] != 'e') {
15615302Smckusick 			PUSHBACK(curfile, sequencep);
15715302Smckusick 			goto convert;
15815302Smckusick 		}
15915302Smckusick 		/* fall through */
16015302Smckusick 	case 'e':
16115388Speter 		NEXT_CHAR(read, filep, "%c", sequencep);
16215302Smckusick 		if (sequencep[-1] != '+' && sequencep[-1] != '-') {
16315302Smckusick 			PUSHBACK(curfile, sequencep);
16415302Smckusick 			SOME(read, filep, "%[0123456789]", sequencep);
16515302Smckusick 			if (!read)
16615302Smckusick 				PUSHBACK(curfile, sequencep);
16715302Smckusick 			goto convert;
16815302Smckusick 		}
16915302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
17015302Smckusick 		if (!read) {
17115302Smckusick 			PUSHBACK(curfile, sequencep);
17215302Smckusick 			PUSHBACK(curfile, sequencep);
17315302Smckusick 		}
17415127Smckusick 	}
17515302Smckusick 
17615302Smckusick convert:
17715127Smckusick 	/*
17815127Smckusick 	 * convert sequence to double
17915127Smckusick 	 */
18015127Smckusick 	*doublep = atof(&sequence[0]);
18115127Smckusick 	return (1);
18215127Smckusick }
183