xref: /csrg-svn/usr.bin/pascal/libpc/READ8.c (revision 15127)
11680Smckusick /* Copyright (c) 1979 Regents of the University of California */
21680Smckusick 
3*15127Smckusick static char sccsid[] = "@(#)READ8.c 1.6 10/01/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*15127Smckusick 	retval = readreal(curfile->fbuf, &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) {
41*15127Smckusick 		PERROR("Error encountered on real read ", curfile->pfname);
426498Smckusick 		return;
436498Smckusick 	}
442309Smckusic 	curfile->funit &= ~EOLN;
451680Smckusick 	curfile->funit |= SYNC;
46*15127Smckusick 	return (data);
471680Smckusick }
48*15127Smckusick 
49*15127Smckusick /*
50*15127Smckusick  *	given a file pointer, read a sequence of characters of the
51*15127Smckusick  *	syntax of section 6.1.5 and form them into a double.
52*15127Smckusick  *
53*15127Smckusick  *	the syntax of a signed-real is:
54*15127Smckusick  *	    [-|+] digit {digit} e [+|-] digit {digit}
55*15127Smckusick  *	or
56*15127Smckusick  *	    [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}]
57*15127Smckusick  *
58*15127Smckusick  *	returns:
59*15127Smckusick  *		1	for success (with value in *doublep)
60*15127Smckusick  *		0	on error (with *doublep unchanged)
61*15127Smckusick  *	       -1	on end-of-file during read (with *doublep unchanged)
62*15127Smckusick  *	side effects:
63*15127Smckusick  *	      errno	may be set to ERANGE if atof() sets it.
64*15127Smckusick  */
65*15127Smckusick readreal(filep, doublep)
66*15127Smckusick 	FILE	*filep;
67*15127Smckusick 	double	*doublep;
68*15127Smckusick {
69*15127Smckusick 	char	sequence[BUFSIZ];	/* the character sequence */
70*15127Smckusick 	char	*sequencep;		/* a pointer into sequence */
71*15127Smckusick 	int	read;			/* return value from fscanf() */
72*15127Smckusick 	double	atof();
73*15127Smckusick 
74*15127Smckusick #define	RETURN_ON_EOF(read) \
75*15127Smckusick 	if (read == EOF) \
76*15127Smckusick 		return (EOF); \
77*15127Smckusick 	else \
78*15127Smckusick 		/* void */;
79*15127Smckusick 
80*15127Smckusick #define	PUSH_TO_NULL(sequencep) \
81*15127Smckusick 	while (*sequencep) \
82*15127Smckusick 		sequencep++;
83*15127Smckusick 
84*15127Smckusick #define	SOME(read, filep, format, sequencep) \
85*15127Smckusick 	read = fscanf(filep, format, sequencep); \
86*15127Smckusick 	RETURN_ON_EOF(read); \
87*15127Smckusick 	PUSH_TO_NULL(sequencep);
88*15127Smckusick 
89*15127Smckusick #define	AT_LEAST_ONE(read, filep, format, sequencep) \
90*15127Smckusick 	read = fscanf(filep, format, sequencep); \
91*15127Smckusick 	RETURN_ON_EOF(read); \
92*15127Smckusick 	if (strlen(sequencep) < 1) \
93*15127Smckusick 		return (0); \
94*15127Smckusick 	PUSH_TO_NULL(sequencep);
95*15127Smckusick 
96*15127Smckusick #define	EXACTLY_ONE(read, filep, format, sequencep) \
97*15127Smckusick 	read = fscanf(filep, format, sequencep); \
98*15127Smckusick 	RETURN_ON_EOF(read); \
99*15127Smckusick 	if (strlen(sequencep) != 1) \
100*15127Smckusick 		return (0); \
101*15127Smckusick 	PUSH_TO_NULL(sequencep);
102*15127Smckusick 
103*15127Smckusick #define	AT_MOST_ONE(read, filep, format, sequencep) \
104*15127Smckusick 	read = fscanf(filep, format, sequencep); \
105*15127Smckusick 	RETURN_ON_EOF(read); \
106*15127Smckusick 	if (strlen(sequencep) > 1) \
107*15127Smckusick 		return (0); \
108*15127Smckusick 	PUSH_TO_NULL(sequencep);
109*15127Smckusick 
110*15127Smckusick 	sequencep = &sequence[0];
111*15127Smckusick 	*sequencep = '\0';
112*15127Smckusick 	/*
113*15127Smckusick 	 * skip leading whitespace
114*15127Smckusick 	 */
115*15127Smckusick 	SOME(read, filep, "%*[ \t\n]", sequencep);
116*15127Smckusick 	/*
117*15127Smckusick 	 *	[ "+" | "-" ] digit {digits}
118*15127Smckusick 	 */
119*15127Smckusick 	AT_MOST_ONE(read, filep, "%[+-]", sequencep);
120*15127Smckusick 	AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
121*15127Smckusick 	/*
122*15127Smckusick 	 *	either
123*15127Smckusick 	 *		"." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ]
124*15127Smckusick 	 *	or
125*15127Smckusick 	 *		"e" [ "+" | "-" ] digit {digits}
126*15127Smckusick 	 */
127*15127Smckusick 	AT_MOST_ONE(read, filep, "%[.]", sequencep);
128*15127Smckusick 	if (read) {
129*15127Smckusick 		AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
130*15127Smckusick 		AT_MOST_ONE(read, filep, "%[e]", sequencep);
131*15127Smckusick 		if (read) {
132*15127Smckusick 			AT_MOST_ONE(read, filep, "%[+-]", sequencep);
133*15127Smckusick 			AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
134*15127Smckusick 		}
135*15127Smckusick 	} else {
136*15127Smckusick 		EXACTLY_ONE(read, filep, "%[e]", sequencep);
137*15127Smckusick 		AT_MOST_ONE(read, filep, "%[+-]", sequencep);
138*15127Smckusick 		AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
139*15127Smckusick 	}
140*15127Smckusick 	/*
141*15127Smckusick 	 * convert sequence to double
142*15127Smckusick 	 */
143*15127Smckusick 	*doublep = atof(&sequence[0]);
144*15127Smckusick 	return (1);
145*15127Smckusick }
146