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