1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)READ8.c 1.8 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 fprintf(stderr, "leading sign <%s>\n", sequence); 137 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 138 fprintf(stderr, "leading digits <%s>\n", sequence); 139 /* 140 * any of this is optional: 141 * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ] 142 */ 143 *sequencep = getc(filep); 144 fprintf(stderr, "before [.e] 0x%x\n", *sequencep); 145 ungetc(*sequencep, filep); 146 *sequencep = '\0'; 147 /* ANY_ONE_OF(read, filep, "%c", sequencep);*/ 148 /* read = fscanf(filep, "%c", sequencep); 149 * *++sequencep = '\0'; 150 */ 151 NEXT_CHAR(read, filep, "%c", sequencep); 152 fprintf(stderr, "[.e] (read %d) <%s>\n", read, sequence); 153 switch (sequencep[-1]) { 154 default: 155 PUSHBACK(curfile, sequencep); 156 goto convert; 157 case '.': 158 SOME(read, filep, "%[0123456789]", sequencep); 159 fprintf(stderr, "trailing digits <%s>\n", sequence); 160 if (!read) { 161 PUSHBACK(curfile, sequencep); 162 goto convert; 163 } 164 /* AT_MOST_ONE(read, filep, "%c", sequencep); */ 165 NEXT_CHAR(read, filep, "%c", sequencep); 166 fprintf(stderr, "optional e <%s>\n", sequence); 167 if (sequencep[-1] != 'e') { 168 PUSHBACK(curfile, sequencep); 169 goto convert; 170 } 171 /* fall through */ 172 case 'e': 173 /* ANY_ONE_OF(read, filep, "%c", sequencep); */ 174 NEXT_CHAR(read, filep, "%c", sequencep); 175 fprintf(stderr, "exponent sign <%s>\n", sequence); 176 if (sequencep[-1] != '+' && sequencep[-1] != '-') { 177 PUSHBACK(curfile, sequencep); 178 SOME(read, filep, "%[0123456789]", sequencep); 179 fprintf(stderr, "signed exponent <%s>\n", sequence); 180 if (!read) 181 PUSHBACK(curfile, sequencep); 182 goto convert; 183 } 184 SOME(read, filep, "%[0123456789]", sequencep); 185 fprintf(stderr, "unsigned exponent <%s>\n", sequence); 186 if (!read) { 187 PUSHBACK(curfile, sequencep); 188 PUSHBACK(curfile, sequencep); 189 } 190 } 191 192 convert: 193 /* 194 * convert sequence to double 195 */ 196 fprintf(stderr, "convert <%s>\n", sequence); 197 *doublep = atof(&sequence[0]); 198 return (1); 199 } 200