1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)READ8.c 1.7 10/28/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, &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 return (data); 45 } 46 47 /* 48 * given a file pointer, read a sequence of characters of the 49 * syntax of section 6.1.5 and form them into a double. 50 * 51 * the syntax of a signed-real is: 52 * [-|+] digit {digit} e [+|-] digit {digit} 53 * or 54 * [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}] 55 * 56 * returns: 57 * 1 for success (with value in *doublep) 58 * 0 on error (with *doublep unchanged) 59 * -1 on end-of-file during read (with *doublep unchanged) 60 * side effects: 61 * errno may be set to ERANGE if atof() sets it. 62 */ 63 readreal(curfile, doublep) 64 struct iorec *curfile; 65 double *doublep; 66 { 67 FILE *filep = curfile->fbuf; /* current file variable */ 68 char *sequencep; /* a pointer into sequence */ 69 int read; /* return value from fscanf() */ 70 char sequence[BUFSIZ]; /* the character sequence */ 71 double atof(); 72 73 #define PUSHBACK(curfile, sequencep) \ 74 if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ 75 *(sequencep) = '\0'; \ 76 } else if ((curfile)->funit & SYNC) { \ 77 (curfile)->funit &= ~SYNC; \ 78 *(curfile)->fileptr = *(sequencep); \ 79 *(sequencep) = '\0'; \ 80 } else { \ 81 return (0); \ 82 } 83 84 #define RETURN_ON_EOF(read) \ 85 if (read == EOF) \ 86 return (EOF); \ 87 else \ 88 /* void */; 89 90 #define PUSH_TO_NULL(sequencep) \ 91 while (*sequencep) \ 92 sequencep++; 93 94 #define SOME(read, filep, format, sequencep) \ 95 read = fscanf(filep, format, sequencep); \ 96 RETURN_ON_EOF(read); \ 97 PUSH_TO_NULL(sequencep); 98 99 #define AT_LEAST_ONE(read, filep, format, sequencep) \ 100 read = fscanf(filep, format, sequencep); \ 101 RETURN_ON_EOF(read); \ 102 if (strlen(sequencep) < 1) \ 103 return (0); \ 104 PUSH_TO_NULL(sequencep); 105 106 #define EXACTLY_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 AT_MOST_ONE(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 sequencep = &sequence[0]; 121 *sequencep = '\0'; 122 /* 123 * skip leading whitespace 124 */ 125 SOME(read, filep, "%*[ \t\n]", sequencep); 126 /* 127 * [ "+" | "-" ] digit {digits} 128 */ 129 AT_MOST_ONE(read, filep, "%[+-]", sequencep); 130 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 131 /* 132 * either 133 * "." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ] 134 * or 135 * "e" [ "+" | "-" ] digit {digits} 136 */ 137 AT_MOST_ONE(read, filep, "%c", sequencep); 138 switch (sequencep[-1]) { 139 default: 140 PUSHBACK(curfile, sequencep); 141 goto convert; 142 case '.': 143 SOME(read, filep, "%[0123456789]", sequencep); 144 if (!read) { 145 PUSHBACK(curfile, sequencep); 146 goto convert; 147 } 148 AT_MOST_ONE(read, filep, "%c", sequencep); 149 if (sequencep[-1] != 'e') { 150 PUSHBACK(curfile, sequencep); 151 goto convert; 152 } 153 /* fall through */ 154 case 'e': 155 AT_MOST_ONE(read, filep, "%c", sequencep); 156 if (sequencep[-1] != '+' && sequencep[-1] != '-') { 157 PUSHBACK(curfile, sequencep); 158 SOME(read, filep, "%[0123456789]", sequencep); 159 if (!read) 160 PUSHBACK(curfile, sequencep); 161 goto convert; 162 } 163 SOME(read, filep, "%[0123456789]", sequencep); 164 if (!read) { 165 PUSHBACK(curfile, sequencep); 166 PUSHBACK(curfile, sequencep); 167 } 168 } 169 170 convert: 171 /* 172 * convert sequence to double 173 */ 174 *doublep = atof(&sequence[0]); 175 return (1); 176 } 177