1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)READ8.c 1.9 11/06/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 } 181