xref: /csrg-svn/usr.bin/pascal/libpc/READ8.c (revision 15127)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)READ8.c 1.6 10/01/83";
4 
5 #include "h00vars.h"
6 #include <errno.h>
7 extern int errno;
8 
9 double
10 READ8(curfile)
11 
12 	register struct iorec	*curfile;
13 {
14 	double			data;
15 	int			retval;
16 
17 	if (curfile->funit & FWRITE) {
18 		ERROR("%s: Attempt to read, but open for writing\n",
19 			curfile->pfname);
20 		return;
21 	}
22 	UNSYNC(curfile);
23 	errno = 0;
24 	retval = readreal(curfile->fbuf, &data);
25 	if (retval == EOF) {
26 		ERROR("%s: Tried to read past end of file\n", curfile->pfname);
27 		return;
28 	}
29 	if (retval == 0) {
30 		ERROR("%s: Bad data found on real read\n", curfile->pfname);
31 		return;
32 	}
33 	if (errno == ERANGE) {
34 		if (data == 0.0)
35 			ERROR("%s: Underflow on real read\n", curfile->pfname);
36 		else
37 			ERROR("%s: Overflow on real read\n", curfile->pfname);
38 		return;
39 	}
40 	if (errno != 0) {
41 		PERROR("Error encountered on real read ", curfile->pfname);
42 		return;
43 	}
44 	curfile->funit &= ~EOLN;
45 	curfile->funit |= SYNC;
46 	return (data);
47 }
48 
49 /*
50  *	given a file pointer, read a sequence of characters of the
51  *	syntax of section 6.1.5 and form them into a double.
52  *
53  *	the syntax of a signed-real is:
54  *	    [-|+] digit {digit} e [+|-] digit {digit}
55  *	or
56  *	    [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}]
57  *
58  *	returns:
59  *		1	for success (with value in *doublep)
60  *		0	on error (with *doublep unchanged)
61  *	       -1	on end-of-file during read (with *doublep unchanged)
62  *	side effects:
63  *	      errno	may be set to ERANGE if atof() sets it.
64  */
65 readreal(filep, doublep)
66 	FILE	*filep;
67 	double	*doublep;
68 {
69 	char	sequence[BUFSIZ];	/* the character sequence */
70 	char	*sequencep;		/* a pointer into sequence */
71 	int	read;			/* return value from fscanf() */
72 	double	atof();
73 
74 #define	RETURN_ON_EOF(read) \
75 	if (read == EOF) \
76 		return (EOF); \
77 	else \
78 		/* void */;
79 
80 #define	PUSH_TO_NULL(sequencep) \
81 	while (*sequencep) \
82 		sequencep++;
83 
84 #define	SOME(read, filep, format, sequencep) \
85 	read = fscanf(filep, format, sequencep); \
86 	RETURN_ON_EOF(read); \
87 	PUSH_TO_NULL(sequencep);
88 
89 #define	AT_LEAST_ONE(read, filep, format, sequencep) \
90 	read = fscanf(filep, format, sequencep); \
91 	RETURN_ON_EOF(read); \
92 	if (strlen(sequencep) < 1) \
93 		return (0); \
94 	PUSH_TO_NULL(sequencep);
95 
96 #define	EXACTLY_ONE(read, filep, format, sequencep) \
97 	read = fscanf(filep, format, sequencep); \
98 	RETURN_ON_EOF(read); \
99 	if (strlen(sequencep) != 1) \
100 		return (0); \
101 	PUSH_TO_NULL(sequencep);
102 
103 #define	AT_MOST_ONE(read, filep, format, sequencep) \
104 	read = fscanf(filep, format, sequencep); \
105 	RETURN_ON_EOF(read); \
106 	if (strlen(sequencep) > 1) \
107 		return (0); \
108 	PUSH_TO_NULL(sequencep);
109 
110 	sequencep = &sequence[0];
111 	*sequencep = '\0';
112 	/*
113 	 * skip leading whitespace
114 	 */
115 	SOME(read, filep, "%*[ \t\n]", sequencep);
116 	/*
117 	 *	[ "+" | "-" ] digit {digits}
118 	 */
119 	AT_MOST_ONE(read, filep, "%[+-]", sequencep);
120 	AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
121 	/*
122 	 *	either
123 	 *		"." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ]
124 	 *	or
125 	 *		"e" [ "+" | "-" ] digit {digits}
126 	 */
127 	AT_MOST_ONE(read, filep, "%[.]", sequencep);
128 	if (read) {
129 		AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
130 		AT_MOST_ONE(read, filep, "%[e]", sequencep);
131 		if (read) {
132 			AT_MOST_ONE(read, filep, "%[+-]", sequencep);
133 			AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
134 		}
135 	} else {
136 		EXACTLY_ONE(read, filep, "%[e]", sequencep);
137 		AT_MOST_ONE(read, filep, "%[+-]", sequencep);
138 		AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
139 	}
140 	/*
141 	 * convert sequence to double
142 	 */
143 	*doublep = atof(&sequence[0]);
144 	return (1);
145 }
146