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 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