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