1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)READ8.c 1.10 01/09/89"; 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 } 20 UNSYNC(curfile); 21 errno = 0; 22 retval = readreal(curfile, &data); 23 if (retval == EOF) { 24 ERROR("%s: Tried to read past end of file\n", curfile->pfname); 25 } 26 if (retval == 0) { 27 ERROR("%s: Bad data found on real read\n", curfile->pfname); 28 } 29 if (errno == ERANGE) { 30 if (data == 0.0) 31 ERROR("%s: Underflow on real read\n", curfile->pfname); 32 else 33 ERROR("%s: Overflow on real read\n", curfile->pfname); 34 } 35 if (errno != 0) { 36 PERROR("Error encountered on real read ", curfile->pfname); 37 } 38 return (data); 39 } 40 41 /* 42 * given a file pointer, read a sequence of characters of the 43 * syntax of section 6.1.5 and form them into a double. 44 * 45 * the syntax of a signed-real is: 46 * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ] 47 * 48 * returns: 49 * 1 for success (with value in *doublep) 50 * 0 on error (with *doublep unchanged) 51 * -1 on end-of-file during read (with *doublep unchanged) 52 * side effects: 53 * errno may be set to ERANGE if atof() sets it. 54 */ 55 readreal(curfile, doublep) 56 struct iorec *curfile; 57 double *doublep; 58 { 59 FILE *filep = curfile->fbuf; /* current file variable */ 60 char *sequencep; /* a pointer into sequence */ 61 int read; /* return value from fscanf() */ 62 char sequence[BUFSIZ]; /* the character sequence */ 63 double atof(); 64 65 #define PUSHBACK(curfile, sequencep) \ 66 if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ 67 *(sequencep) = '\0'; \ 68 } else if ((curfile)->funit & SYNC) { \ 69 (curfile)->funit &= ~SYNC; \ 70 *(curfile)->fileptr = *(sequencep); \ 71 *(sequencep) = '\0'; \ 72 } else { \ 73 return (0); \ 74 } 75 76 #define RETURN_ON_EOF(read) \ 77 if (read == EOF) \ 78 return (EOF); \ 79 else \ 80 /* void */; 81 82 #define PUSH_TO_NULL(sequencep) \ 83 while (*sequencep) \ 84 sequencep++; 85 86 /* general reader of the next character */ 87 #define NEXT_CHAR(read, filep, format, sequencep) \ 88 read = fscanf(filep, "%c", sequencep); \ 89 RETURN_ON_EOF(read); \ 90 *++sequencep = '\0'; 91 92 /* e.g. use %[0123456789] for {digit}, and check read */ 93 #define SOME(read, filep, format, sequencep) \ 94 read = fscanf(filep, format, sequencep); \ 95 RETURN_ON_EOF(read); \ 96 PUSH_TO_NULL(sequencep); 97 98 /* e.g. use %[0123456789] for digit {digit} */ 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 ANY_ONE_OF(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 * this much is required: 128 * [ "+" | "-" ] digit {digits} 129 */ 130 AT_MOST_ONE(read, filep, "%[+-]", sequencep); 131 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 132 /* 133 * any of this is optional: 134 * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ] 135 */ 136 NEXT_CHAR(read, filep, "%c", sequencep); 137 switch (sequencep[-1]) { 138 default: 139 PUSHBACK(curfile, sequencep); 140 goto convert; 141 case '.': 142 SOME(read, filep, "%[0123456789]", sequencep); 143 if (!read) { 144 PUSHBACK(curfile, sequencep); 145 goto convert; 146 } 147 NEXT_CHAR(read, filep, "%c", sequencep); 148 if (sequencep[-1] != 'e') { 149 PUSHBACK(curfile, sequencep); 150 goto convert; 151 } 152 /* fall through */ 153 case 'e': 154 NEXT_CHAR(read, filep, "%c", sequencep); 155 if (sequencep[-1] != '+' && sequencep[-1] != '-') { 156 PUSHBACK(curfile, sequencep); 157 SOME(read, filep, "%[0123456789]", sequencep); 158 if (!read) 159 PUSHBACK(curfile, sequencep); 160 goto convert; 161 } 162 SOME(read, filep, "%[0123456789]", sequencep); 163 if (!read) { 164 PUSHBACK(curfile, sequencep); 165 PUSHBACK(curfile, sequencep); 166 } 167 } 168 169 convert: 170 /* 171 * convert sequence to double 172 */ 173 *doublep = atof(&sequence[0]); 174 return (1); 175 } 176