|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.