|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1979 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)READ8.c 1.11 (Berkeley) 4/9/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include "h00vars.h" ! 25: #include <errno.h> ! 26: extern int errno; ! 27: ! 28: double ! 29: READ8(curfile) ! 30: register struct iorec *curfile; ! 31: { ! 32: double data; ! 33: int retval; ! 34: ! 35: if (curfile->funit & FWRITE) { ! 36: ERROR("%s: Attempt to read, but open for writing\n", ! 37: curfile->pfname); ! 38: } ! 39: UNSYNC(curfile); ! 40: errno = 0; ! 41: retval = readreal(curfile, &data); ! 42: if (retval == EOF) { ! 43: ERROR("%s: Tried to read past end of file\n", curfile->pfname); ! 44: } ! 45: if (retval == 0) { ! 46: ERROR("%s: Bad data found on real read\n", curfile->pfname); ! 47: } ! 48: if (errno == ERANGE) { ! 49: if (data == 0.0) ! 50: ERROR("%s: Underflow on real read\n", curfile->pfname); ! 51: else ! 52: ERROR("%s: Overflow on real read\n", curfile->pfname); ! 53: } ! 54: if (errno != 0) { ! 55: PERROR("Error encountered on real read ", curfile->pfname); ! 56: } ! 57: return (data); ! 58: } ! 59: ! 60: /* ! 61: * given a file pointer, read a sequence of characters of the ! 62: * syntax of section 6.1.5 and form them into a double. ! 63: * ! 64: * the syntax of a signed-real is: ! 65: * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ] ! 66: * ! 67: * returns: ! 68: * 1 for success (with value in *doublep) ! 69: * 0 on error (with *doublep unchanged) ! 70: * -1 on end-of-file during read (with *doublep unchanged) ! 71: * side effects: ! 72: * errno may be set to ERANGE if atof() sets it. ! 73: */ ! 74: readreal(curfile, doublep) ! 75: struct iorec *curfile; ! 76: double *doublep; ! 77: { ! 78: FILE *filep = curfile->fbuf; /* current file variable */ ! 79: char *sequencep; /* a pointer into sequence */ ! 80: int read; /* return value from fscanf() */ ! 81: char sequence[BUFSIZ]; /* the character sequence */ ! 82: double atof(); ! 83: ! 84: #define PUSHBACK(curfile, sequencep) \ ! 85: if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ ! 86: *(sequencep) = '\0'; \ ! 87: } else if ((curfile)->funit & SYNC) { \ ! 88: (curfile)->funit &= ~SYNC; \ ! 89: *(curfile)->fileptr = *(sequencep); \ ! 90: *(sequencep) = '\0'; \ ! 91: } else { \ ! 92: return (0); \ ! 93: } ! 94: ! 95: #define RETURN_ON_EOF(read) \ ! 96: if (read == EOF) \ ! 97: return (EOF); \ ! 98: else \ ! 99: /* void */; ! 100: ! 101: #define PUSH_TO_NULL(sequencep) \ ! 102: while (*sequencep) \ ! 103: sequencep++; ! 104: ! 105: /* general reader of the next character */ ! 106: #define NEXT_CHAR(read, filep, format, sequencep) \ ! 107: read = fscanf(filep, "%c", sequencep); \ ! 108: RETURN_ON_EOF(read); \ ! 109: *++sequencep = '\0'; ! 110: ! 111: /* e.g. use %[0123456789] for {digit}, and check read */ ! 112: #define SOME(read, filep, format, sequencep) \ ! 113: read = fscanf(filep, format, sequencep); \ ! 114: RETURN_ON_EOF(read); \ ! 115: PUSH_TO_NULL(sequencep); ! 116: ! 117: /* e.g. use %[0123456789] for digit {digit} */ ! 118: #define AT_LEAST_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: #define ANY_ONE_OF(read, filep, format, sequencep) \ ! 126: read = fscanf(filep, format, sequencep); \ ! 127: RETURN_ON_EOF(read); \ ! 128: if (strlen(sequencep) != 1) \ ! 129: return (0); \ ! 130: PUSH_TO_NULL(sequencep); ! 131: ! 132: #define AT_MOST_ONE(read, filep, format, sequencep) \ ! 133: read = fscanf(filep, format, sequencep); \ ! 134: RETURN_ON_EOF(read); \ ! 135: if (strlen(sequencep) > 1) \ ! 136: return (0); \ ! 137: PUSH_TO_NULL(sequencep); ! 138: ! 139: sequencep = &sequence[0]; ! 140: *sequencep = '\0'; ! 141: /* ! 142: * skip leading whitespace ! 143: */ ! 144: SOME(read, filep, "%*[ \t\n]", sequencep); ! 145: /* ! 146: * this much is required: ! 147: * [ "+" | "-" ] digit {digits} ! 148: */ ! 149: AT_MOST_ONE(read, filep, "%[+-]", sequencep); ! 150: AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); ! 151: /* ! 152: * any of this is optional: ! 153: * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ] ! 154: */ ! 155: NEXT_CHAR(read, filep, "%c", sequencep); ! 156: switch (sequencep[-1]) { ! 157: default: ! 158: PUSHBACK(curfile, sequencep); ! 159: goto convert; ! 160: case '.': ! 161: SOME(read, filep, "%[0123456789]", sequencep); ! 162: if (!read) { ! 163: PUSHBACK(curfile, sequencep); ! 164: goto convert; ! 165: } ! 166: NEXT_CHAR(read, filep, "%c", sequencep); ! 167: if (sequencep[-1] != 'e') { ! 168: PUSHBACK(curfile, sequencep); ! 169: goto convert; ! 170: } ! 171: /* fall through */ ! 172: case 'e': ! 173: NEXT_CHAR(read, filep, "%c", sequencep); ! 174: if (sequencep[-1] != '+' && sequencep[-1] != '-') { ! 175: PUSHBACK(curfile, sequencep); ! 176: SOME(read, filep, "%[0123456789]", sequencep); ! 177: if (!read) ! 178: PUSHBACK(curfile, sequencep); ! 179: goto convert; ! 180: } ! 181: SOME(read, filep, "%[0123456789]", sequencep); ! 182: if (!read) { ! 183: PUSHBACK(curfile, sequencep); ! 184: PUSHBACK(curfile, sequencep); ! 185: } ! 186: } ! 187: ! 188: convert: ! 189: /* ! 190: * convert sequence to double ! 191: */ ! 192: *doublep = atof(&sequence[0]); ! 193: return (1); ! 194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.