|
|
1.1 root 1: /*-
2: * Copyright (c) 1979 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)READ8.c 1.11 (Berkeley) 4/9/90";
22: #endif /* not lint */
23:
24: #include "h00vars.h"
25: #include <errno.h>
26: extern int errno;
27:
28: double
29: READ8(curfile)
30: register struct iorec *curfile;
31: {
32: double data;
33: int retval;
34:
35: if (curfile->funit & FWRITE) {
36: ERROR("%s: Attempt to read, but open for writing\n",
37: curfile->pfname);
38: }
39: UNSYNC(curfile);
40: errno = 0;
41: retval = readreal(curfile, &data);
42: if (retval == EOF) {
43: ERROR("%s: Tried to read past end of file\n", curfile->pfname);
44: }
45: if (retval == 0) {
46: ERROR("%s: Bad data found on real read\n", curfile->pfname);
47: }
48: if (errno == ERANGE) {
49: if (data == 0.0)
50: ERROR("%s: Underflow on real read\n", curfile->pfname);
51: else
52: ERROR("%s: Overflow on real read\n", curfile->pfname);
53: }
54: if (errno != 0) {
55: PERROR("Error encountered on real read ", curfile->pfname);
56: }
57: return (data);
58: }
59:
60: /*
61: * given a file pointer, read a sequence of characters of the
62: * syntax of section 6.1.5 and form them into a double.
63: *
64: * the syntax of a signed-real is:
65: * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ]
66: *
67: * returns:
68: * 1 for success (with value in *doublep)
69: * 0 on error (with *doublep unchanged)
70: * -1 on end-of-file during read (with *doublep unchanged)
71: * side effects:
72: * errno may be set to ERANGE if atof() sets it.
73: */
74: readreal(curfile, doublep)
75: struct iorec *curfile;
76: double *doublep;
77: {
78: FILE *filep = curfile->fbuf; /* current file variable */
79: char *sequencep; /* a pointer into sequence */
80: int read; /* return value from fscanf() */
81: char sequence[BUFSIZ]; /* the character sequence */
82: double atof();
83:
84: #define PUSHBACK(curfile, sequencep) \
85: if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \
86: *(sequencep) = '\0'; \
87: } else if ((curfile)->funit & SYNC) { \
88: (curfile)->funit &= ~SYNC; \
89: *(curfile)->fileptr = *(sequencep); \
90: *(sequencep) = '\0'; \
91: } else { \
92: return (0); \
93: }
94:
95: #define RETURN_ON_EOF(read) \
96: if (read == EOF) \
97: return (EOF); \
98: else \
99: /* void */;
100:
101: #define PUSH_TO_NULL(sequencep) \
102: while (*sequencep) \
103: sequencep++;
104:
105: /* general reader of the next character */
106: #define NEXT_CHAR(read, filep, format, sequencep) \
107: read = fscanf(filep, "%c", sequencep); \
108: RETURN_ON_EOF(read); \
109: *++sequencep = '\0';
110:
111: /* e.g. use %[0123456789] for {digit}, and check read */
112: #define SOME(read, filep, format, sequencep) \
113: read = fscanf(filep, format, sequencep); \
114: RETURN_ON_EOF(read); \
115: PUSH_TO_NULL(sequencep);
116:
117: /* e.g. use %[0123456789] for digit {digit} */
118: #define AT_LEAST_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: #define ANY_ONE_OF(read, filep, format, sequencep) \
126: read = fscanf(filep, format, sequencep); \
127: RETURN_ON_EOF(read); \
128: if (strlen(sequencep) != 1) \
129: return (0); \
130: PUSH_TO_NULL(sequencep);
131:
132: #define AT_MOST_ONE(read, filep, format, sequencep) \
133: read = fscanf(filep, format, sequencep); \
134: RETURN_ON_EOF(read); \
135: if (strlen(sequencep) > 1) \
136: return (0); \
137: PUSH_TO_NULL(sequencep);
138:
139: sequencep = &sequence[0];
140: *sequencep = '\0';
141: /*
142: * skip leading whitespace
143: */
144: SOME(read, filep, "%*[ \t\n]", sequencep);
145: /*
146: * this much is required:
147: * [ "+" | "-" ] digit {digits}
148: */
149: AT_MOST_ONE(read, filep, "%[+-]", sequencep);
150: AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep);
151: /*
152: * any of this is optional:
153: * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ]
154: */
155: NEXT_CHAR(read, filep, "%c", sequencep);
156: switch (sequencep[-1]) {
157: default:
158: PUSHBACK(curfile, sequencep);
159: goto convert;
160: case '.':
161: SOME(read, filep, "%[0123456789]", sequencep);
162: if (!read) {
163: PUSHBACK(curfile, sequencep);
164: goto convert;
165: }
166: NEXT_CHAR(read, filep, "%c", sequencep);
167: if (sequencep[-1] != 'e') {
168: PUSHBACK(curfile, sequencep);
169: goto convert;
170: }
171: /* fall through */
172: case 'e':
173: NEXT_CHAR(read, filep, "%c", sequencep);
174: if (sequencep[-1] != '+' && sequencep[-1] != '-') {
175: PUSHBACK(curfile, sequencep);
176: SOME(read, filep, "%[0123456789]", sequencep);
177: if (!read)
178: PUSHBACK(curfile, sequencep);
179: goto convert;
180: }
181: SOME(read, filep, "%[0123456789]", sequencep);
182: if (!read) {
183: PUSHBACK(curfile, sequencep);
184: PUSHBACK(curfile, sequencep);
185: }
186: }
187:
188: convert:
189: /*
190: * convert sequence to double
191: */
192: *doublep = atof(&sequence[0]);
193: return (1);
194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.