1 /*-
2 * Copyright (c) 1979, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)READ8.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 #include "h00vars.h"
13 #include <errno.h>
14 extern int errno;
15
16 double
READ8(curfile)17 READ8(curfile)
18 register struct iorec *curfile;
19 {
20 double data;
21 int retval;
22
23 if (curfile->funit & FWRITE) {
24 ERROR("%s: Attempt to read, but open for writing\n",
25 curfile->pfname);
26 }
27 UNSYNC(curfile);
28 errno = 0;
29 retval = readreal(curfile, &data);
30 if (retval == EOF) {
31 ERROR("%s: Tried to read past end of file\n", curfile->pfname);
32 }
33 if (retval == 0) {
34 ERROR("%s: Bad data found on real read\n", curfile->pfname);
35 }
36 if (errno == ERANGE) {
37 if (data == 0.0)
38 ERROR("%s: Underflow on real read\n", curfile->pfname);
39 else
40 ERROR("%s: Overflow on real read\n", curfile->pfname);
41 }
42 if (errno != 0) {
43 PERROR("Error encountered on real read ", curfile->pfname);
44 }
45 return (data);
46 }
47
48 /*
49 * given a file pointer, read a sequence of characters of the
50 * syntax of section 6.1.5 and form them into a double.
51 *
52 * the syntax of a signed-real is:
53 * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ]
54 *
55 * returns:
56 * 1 for success (with value in *doublep)
57 * 0 on error (with *doublep unchanged)
58 * -1 on end-of-file during read (with *doublep unchanged)
59 * side effects:
60 * errno may be set to ERANGE if atof() sets it.
61 */
62 readreal(curfile, doublep)
63 struct iorec *curfile;
64 double *doublep;
65 {
66 FILE *filep = curfile->fbuf; /* current file variable */
67 char *sequencep; /* a pointer into sequence */
68 int read; /* return value from fscanf() */
69 char sequence[BUFSIZ]; /* the character sequence */
70 double atof();
71
72 #define PUSHBACK(curfile, sequencep) \
73 if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \
74 *(sequencep) = '\0'; \
75 } else if ((curfile)->funit & SYNC) { \
76 (curfile)->funit &= ~SYNC; \
77 *(curfile)->fileptr = *(sequencep); \
78 *(sequencep) = '\0'; \
79 } else { \
80 return (0); \
81 }
82
83 #define RETURN_ON_EOF(read) \
84 if (read == EOF) \
85 return (EOF); \
86 else \
87 /* void */;
88
89 #define PUSH_TO_NULL(sequencep) \
90 while (*sequencep) \
91 sequencep++;
92
93 /* general reader of the next character */
94 #define NEXT_CHAR(read, filep, format, sequencep) \
95 read = fscanf(filep, "%c", sequencep); \
96 RETURN_ON_EOF(read); \
97 *++sequencep = '\0';
98
99 /* e.g. use %[0123456789] for {digit}, and check read */
100 #define SOME(read, filep, format, sequencep) \
101 read = fscanf(filep, format, sequencep); \
102 RETURN_ON_EOF(read); \
103 PUSH_TO_NULL(sequencep);
104
105 /* e.g. use %[0123456789] for digit {digit} */
106 #define AT_LEAST_ONE(read, filep, format, sequencep) \
107 read = fscanf(filep, format, sequencep); \
108 RETURN_ON_EOF(read); \
109 if (strlen(sequencep) < 1) \
110 return (0); \
111 PUSH_TO_NULL(sequencep);
112
113 #define ANY_ONE_OF(read, filep, format, sequencep) \
114 read = fscanf(filep, format, sequencep); \
115 RETURN_ON_EOF(read); \
116 if (strlen(sequencep) != 1) \
117 return (0); \
118 PUSH_TO_NULL(sequencep);
119
120 #define AT_MOST_ONE(read, filep, format, sequencep) \
121 read = fscanf(filep, format, sequencep); \
122 RETURN_ON_EOF(read); \
123 if (strlen(sequencep) > 1) \
124 return (0); \
125 PUSH_TO_NULL(sequencep);
126
127 sequencep = &sequence[0];
128 *sequencep = '\0';
129 /*
130 * skip leading whitespace
131 */
132 SOME(read, filep, "%*[ \t\n]", sequencep);
133 /*
134 * this much is required:
135 * [ "+" | "-" ] digit {digits}
136 */
137 AT_MOST_ONE(read, filep, "%[+-]", sequencep);
138 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
139 /*
140 * any of this is optional:
141 * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ]
142 */
143 NEXT_CHAR(read, filep, "%c", sequencep);
144 switch (sequencep[-1]) {
145 default:
146 PUSHBACK(curfile, sequencep);
147 goto convert;
148 case '.':
149 SOME(read, filep, "%[0123456789]", sequencep);
150 if (!read) {
151 PUSHBACK(curfile, sequencep);
152 goto convert;
153 }
154 NEXT_CHAR(read, filep, "%c", sequencep);
155 if (sequencep[-1] != 'e') {
156 PUSHBACK(curfile, sequencep);
157 goto convert;
158 }
159 /* fall through */
160 case 'e':
161 NEXT_CHAR(read, filep, "%c", sequencep);
162 if (sequencep[-1] != '+' && sequencep[-1] != '-') {
163 PUSHBACK(curfile, sequencep);
164 SOME(read, filep, "%[0123456789]", sequencep);
165 if (!read)
166 PUSHBACK(curfile, sequencep);
167 goto convert;
168 }
169 SOME(read, filep, "%[0123456789]", sequencep);
170 if (!read) {
171 PUSHBACK(curfile, sequencep);
172 PUSHBACK(curfile, sequencep);
173 }
174 }
175
176 convert:
177 /*
178 * convert sequence to double
179 */
180 *doublep = atof(&sequence[0]);
181 return (1);
182 }
183