xref: /csrg-svn/usr.bin/pascal/libpc/READ8.c (revision 15388)
11680Smckusick /* Copyright (c) 1979 Regents of the University of California */
21680Smckusick 
3*15388Speter static char sccsid[] = "@(#)READ8.c 1.8 11/06/83";
41680Smckusick 
51680Smckusick #include "h00vars.h"
66498Smckusick #include <errno.h>
76498Smckusick extern int errno;
81680Smckusick 
91680Smckusick double
101680Smckusick READ8(curfile)
111680Smckusick 	register struct iorec	*curfile;
121680Smckusick {
131680Smckusick 	double			data;
142223Smckusic 	int			retval;
151680Smckusick 
161680Smckusick 	if (curfile->funit & FWRITE) {
173869Smckusic 		ERROR("%s: Attempt to read, but open for writing\n",
183869Smckusic 			curfile->pfname);
191680Smckusick 		return;
201680Smckusick 	}
211680Smckusick 	UNSYNC(curfile);
226498Smckusick 	errno = 0;
2315302Smckusick 	retval = readreal(curfile, &data);
242223Smckusic 	if (retval == EOF) {
253869Smckusic 		ERROR("%s: Tried to read past end of file\n", curfile->pfname);
262223Smckusic 		return;
272223Smckusic 	}
282223Smckusic 	if (retval == 0) {
293869Smckusic 		ERROR("%s: Bad data found on real read\n", curfile->pfname);
301680Smckusick 		return;
311680Smckusick 	}
326498Smckusick 	if (errno == ERANGE) {
336498Smckusick 		if (data == 0.0)
346498Smckusick 			ERROR("%s: Underflow on real read\n", curfile->pfname);
356498Smckusick 		else
366498Smckusick 			ERROR("%s: Overflow on real read\n", curfile->pfname);
376498Smckusick 		return;
386498Smckusick 	}
396498Smckusick 	if (errno != 0) {
4015127Smckusick 		PERROR("Error encountered on real read ", curfile->pfname);
416498Smckusick 		return;
426498Smckusick 	}
4315127Smckusick 	return (data);
441680Smckusick }
4515127Smckusick 
4615127Smckusick /*
4715127Smckusick  *	given a file pointer, read a sequence of characters of the
4815127Smckusick  *	syntax of section 6.1.5 and form them into a double.
4915127Smckusick  *
5015127Smckusick  *	the syntax of a signed-real is:
51*15388Speter  *	    [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ]
5215127Smckusick  *
5315127Smckusick  *	returns:
5415127Smckusick  *		1	for success (with value in *doublep)
5515127Smckusick  *		0	on error (with *doublep unchanged)
5615127Smckusick  *	       -1	on end-of-file during read (with *doublep unchanged)
5715127Smckusick  *	side effects:
5815127Smckusick  *	      errno	may be set to ERANGE if atof() sets it.
5915127Smckusick  */
6015302Smckusick readreal(curfile, doublep)
6115302Smckusick 	struct iorec	*curfile;
6215302Smckusick 	double		*doublep;
6315127Smckusick {
6415302Smckusick 	FILE	*filep = curfile->fbuf;	/* current file variable */
6515127Smckusick 	char	*sequencep;		/* a pointer into sequence */
6615127Smckusick 	int	read;			/* return value from fscanf() */
6715302Smckusick 	char	sequence[BUFSIZ];	/* the character sequence */
6815127Smckusick 	double	atof();
6915127Smckusick 
7015302Smckusick #define PUSHBACK(curfile, sequencep) \
7115302Smckusick 	if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \
7215302Smckusick 		*(sequencep) = '\0'; \
7315302Smckusick 	} else if ((curfile)->funit & SYNC) { \
7415302Smckusick 		(curfile)->funit &= ~SYNC; \
7515302Smckusick 		*(curfile)->fileptr = *(sequencep); \
7615302Smckusick 		*(sequencep) = '\0'; \
7715302Smckusick 	} else { \
7815302Smckusick 		return (0); \
7915302Smckusick 	}
8015302Smckusick 
8115127Smckusick #define	RETURN_ON_EOF(read) \
8215127Smckusick 	if (read == EOF) \
8315127Smckusick 		return (EOF); \
8415127Smckusick 	else \
8515127Smckusick 		/* void */;
8615127Smckusick 
8715127Smckusick #define	PUSH_TO_NULL(sequencep) \
8815127Smckusick 	while (*sequencep) \
8915127Smckusick 		sequencep++;
9015127Smckusick 
91*15388Speter 	/* general reader of the next character */
92*15388Speter #define	NEXT_CHAR(read, filep, format, sequencep) \
93*15388Speter 	read = fscanf(filep, "%c", sequencep); \
94*15388Speter 	RETURN_ON_EOF(read); \
95*15388Speter 	*++sequencep = '\0';
96*15388Speter 
97*15388Speter 	/* e.g. use %[0123456789] for {digit}, and check read */
9815127Smckusick #define	SOME(read, filep, format, sequencep) \
9915127Smckusick 	read = fscanf(filep, format, sequencep); \
10015127Smckusick 	RETURN_ON_EOF(read); \
10115127Smckusick 	PUSH_TO_NULL(sequencep);
10215127Smckusick 
103*15388Speter 	/* e.g. use %[0123456789] for digit {digit} */
10415127Smckusick #define	AT_LEAST_ONE(read, filep, format, sequencep) \
10515127Smckusick 	read = fscanf(filep, format, sequencep); \
10615127Smckusick 	RETURN_ON_EOF(read); \
10715127Smckusick 	if (strlen(sequencep) < 1) \
10815127Smckusick 		return (0); \
10915127Smckusick 	PUSH_TO_NULL(sequencep);
11015127Smckusick 
111*15388Speter #define	ANY_ONE_OF(read, filep, format, sequencep) \
11215127Smckusick 	read = fscanf(filep, format, sequencep); \
11315127Smckusick 	RETURN_ON_EOF(read); \
11415127Smckusick 	if (strlen(sequencep) != 1) \
11515127Smckusick 		return (0); \
11615127Smckusick 	PUSH_TO_NULL(sequencep);
11715127Smckusick 
11815127Smckusick #define	AT_MOST_ONE(read, filep, format, sequencep) \
11915127Smckusick 	read = fscanf(filep, format, sequencep); \
12015127Smckusick 	RETURN_ON_EOF(read); \
12115127Smckusick 	if (strlen(sequencep) > 1) \
12215127Smckusick 		return (0); \
12315127Smckusick 	PUSH_TO_NULL(sequencep);
12415127Smckusick 
12515127Smckusick 	sequencep = &sequence[0];
12615127Smckusick 	*sequencep = '\0';
12715127Smckusick 	/*
128*15388Speter 	 *	skip leading whitespace
12915127Smckusick 	 */
13015127Smckusick 	SOME(read, filep, "%*[ \t\n]", sequencep);
13115127Smckusick 	/*
132*15388Speter 	 *	this much is required:
13315127Smckusick 	 *	[ "+" | "-" ] digit {digits}
13415127Smckusick 	 */
13515127Smckusick 	AT_MOST_ONE(read, filep, "%[+-]", sequencep);
136*15388Speter fprintf(stderr,	"leading sign		<%s>\n", sequence);
13715127Smckusick 	AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
138*15388Speter fprintf(stderr,	"leading digits		<%s>\n", sequence);
13915127Smckusick 	/*
140*15388Speter 	 *	any of this is optional:
141*15388Speter 	 *	[ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ]
14215127Smckusick 	 */
143*15388Speter *sequencep = getc(filep);
144*15388Speter fprintf(stderr,	"before [.e]		0x%x\n", *sequencep);
145*15388Speter ungetc(*sequencep, filep);
146*15388Speter *sequencep = '\0';
147*15388Speter 	/* ANY_ONE_OF(read, filep, "%c", sequencep);*/
148*15388Speter 	/* read = fscanf(filep, "%c", sequencep);
149*15388Speter 	 * *++sequencep = '\0';
150*15388Speter 	 */
151*15388Speter 	NEXT_CHAR(read, filep, "%c", sequencep);
152*15388Speter fprintf(stderr,	"[.e] (read %d)		<%s>\n", read, sequence);
15315302Smckusick 	switch (sequencep[-1]) {
15415302Smckusick 	default:
15515302Smckusick 		PUSHBACK(curfile, sequencep);
15615302Smckusick 		goto convert;
15715302Smckusick 	case '.':
15815302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
159*15388Speter fprintf(stderr,	"trailing digits	<%s>\n", sequence);
16015302Smckusick 		if (!read) {
16115302Smckusick 			PUSHBACK(curfile, sequencep);
16215302Smckusick 			goto convert;
16315127Smckusick 		}
164*15388Speter 		/* AT_MOST_ONE(read, filep, "%c", sequencep); */
165*15388Speter 		NEXT_CHAR(read, filep, "%c", sequencep);
166*15388Speter fprintf(stderr,	"optional e		<%s>\n", sequence);
16715302Smckusick 		if (sequencep[-1] != 'e') {
16815302Smckusick 			PUSHBACK(curfile, sequencep);
16915302Smckusick 			goto convert;
17015302Smckusick 		}
17115302Smckusick 		/* fall through */
17215302Smckusick 	case 'e':
173*15388Speter 		/* ANY_ONE_OF(read, filep, "%c", sequencep); */
174*15388Speter 		NEXT_CHAR(read, filep, "%c", sequencep);
175*15388Speter fprintf(stderr,	"exponent sign		<%s>\n", sequence);
17615302Smckusick 		if (sequencep[-1] != '+' && sequencep[-1] != '-') {
17715302Smckusick 			PUSHBACK(curfile, sequencep);
17815302Smckusick 			SOME(read, filep, "%[0123456789]", sequencep);
179*15388Speter fprintf(stderr,	"signed exponent	<%s>\n", sequence);
18015302Smckusick 			if (!read)
18115302Smckusick 				PUSHBACK(curfile, sequencep);
18215302Smckusick 			goto convert;
18315302Smckusick 		}
18415302Smckusick 		SOME(read, filep, "%[0123456789]", sequencep);
185*15388Speter fprintf(stderr,	"unsigned exponent	<%s>\n", sequence);
18615302Smckusick 		if (!read) {
18715302Smckusick 			PUSHBACK(curfile, sequencep);
18815302Smckusick 			PUSHBACK(curfile, sequencep);
18915302Smckusick 		}
19015127Smckusick 	}
19115302Smckusick 
19215302Smckusick convert:
19315127Smckusick 	/*
19415127Smckusick 	 * convert sequence to double
19515127Smckusick 	 */
196*15388Speter fprintf(stderr,	"convert		<%s>\n", sequence);
19715127Smckusick 	*doublep = atof(&sequence[0]);
19815127Smckusick 	return (1);
19915127Smckusick }
200