11680Smckusick /* Copyright (c) 1979 Regents of the University of California */ 21680Smckusick 3*15302Smckusick static char sccsid[] = "@(#)READ8.c 1.7 10/28/83"; 41680Smckusick 51680Smckusick #include "h00vars.h" 66498Smckusick #include <errno.h> 76498Smckusick extern int errno; 81680Smckusick 91680Smckusick double 101680Smckusick READ8(curfile) 111680Smckusick 121680Smckusick register struct iorec *curfile; 131680Smckusick { 141680Smckusick double data; 152223Smckusic int retval; 161680Smckusick 171680Smckusick if (curfile->funit & FWRITE) { 183869Smckusic ERROR("%s: Attempt to read, but open for writing\n", 193869Smckusic curfile->pfname); 201680Smckusick return; 211680Smckusick } 221680Smckusick UNSYNC(curfile); 236498Smckusick errno = 0; 24*15302Smckusick retval = readreal(curfile, &data); 252223Smckusic if (retval == EOF) { 263869Smckusic ERROR("%s: Tried to read past end of file\n", curfile->pfname); 272223Smckusic return; 282223Smckusic } 292223Smckusic if (retval == 0) { 303869Smckusic ERROR("%s: Bad data found on real read\n", curfile->pfname); 311680Smckusick return; 321680Smckusick } 336498Smckusick if (errno == ERANGE) { 346498Smckusick if (data == 0.0) 356498Smckusick ERROR("%s: Underflow on real read\n", curfile->pfname); 366498Smckusick else 376498Smckusick ERROR("%s: Overflow on real read\n", curfile->pfname); 386498Smckusick return; 396498Smckusick } 406498Smckusick if (errno != 0) { 4115127Smckusick PERROR("Error encountered on real read ", curfile->pfname); 426498Smckusick return; 436498Smckusick } 4415127Smckusick return (data); 451680Smckusick } 4615127Smckusick 4715127Smckusick /* 4815127Smckusick * given a file pointer, read a sequence of characters of the 4915127Smckusick * syntax of section 6.1.5 and form them into a double. 5015127Smckusick * 5115127Smckusick * the syntax of a signed-real is: 5215127Smckusick * [-|+] digit {digit} e [+|-] digit {digit} 5315127Smckusick * or 5415127Smckusick * [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}] 5515127Smckusick * 5615127Smckusick * returns: 5715127Smckusick * 1 for success (with value in *doublep) 5815127Smckusick * 0 on error (with *doublep unchanged) 5915127Smckusick * -1 on end-of-file during read (with *doublep unchanged) 6015127Smckusick * side effects: 6115127Smckusick * errno may be set to ERANGE if atof() sets it. 6215127Smckusick */ 63*15302Smckusick readreal(curfile, doublep) 64*15302Smckusick struct iorec *curfile; 65*15302Smckusick double *doublep; 6615127Smckusick { 67*15302Smckusick FILE *filep = curfile->fbuf; /* current file variable */ 6815127Smckusick char *sequencep; /* a pointer into sequence */ 6915127Smckusick int read; /* return value from fscanf() */ 70*15302Smckusick char sequence[BUFSIZ]; /* the character sequence */ 7115127Smckusick double atof(); 7215127Smckusick 73*15302Smckusick #define PUSHBACK(curfile, sequencep) \ 74*15302Smckusick if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ 75*15302Smckusick *(sequencep) = '\0'; \ 76*15302Smckusick } else if ((curfile)->funit & SYNC) { \ 77*15302Smckusick (curfile)->funit &= ~SYNC; \ 78*15302Smckusick *(curfile)->fileptr = *(sequencep); \ 79*15302Smckusick *(sequencep) = '\0'; \ 80*15302Smckusick } else { \ 81*15302Smckusick return (0); \ 82*15302Smckusick } 83*15302Smckusick 8415127Smckusick #define RETURN_ON_EOF(read) \ 8515127Smckusick if (read == EOF) \ 8615127Smckusick return (EOF); \ 8715127Smckusick else \ 8815127Smckusick /* void */; 8915127Smckusick 9015127Smckusick #define PUSH_TO_NULL(sequencep) \ 9115127Smckusick while (*sequencep) \ 9215127Smckusick sequencep++; 9315127Smckusick 9415127Smckusick #define SOME(read, filep, format, sequencep) \ 9515127Smckusick read = fscanf(filep, format, sequencep); \ 9615127Smckusick RETURN_ON_EOF(read); \ 9715127Smckusick PUSH_TO_NULL(sequencep); 9815127Smckusick 9915127Smckusick #define AT_LEAST_ONE(read, filep, format, sequencep) \ 10015127Smckusick read = fscanf(filep, format, sequencep); \ 10115127Smckusick RETURN_ON_EOF(read); \ 10215127Smckusick if (strlen(sequencep) < 1) \ 10315127Smckusick return (0); \ 10415127Smckusick PUSH_TO_NULL(sequencep); 10515127Smckusick 10615127Smckusick #define EXACTLY_ONE(read, filep, format, sequencep) \ 10715127Smckusick read = fscanf(filep, format, sequencep); \ 10815127Smckusick RETURN_ON_EOF(read); \ 10915127Smckusick if (strlen(sequencep) != 1) \ 11015127Smckusick return (0); \ 11115127Smckusick PUSH_TO_NULL(sequencep); 11215127Smckusick 11315127Smckusick #define AT_MOST_ONE(read, filep, format, sequencep) \ 11415127Smckusick read = fscanf(filep, format, sequencep); \ 11515127Smckusick RETURN_ON_EOF(read); \ 11615127Smckusick if (strlen(sequencep) > 1) \ 11715127Smckusick return (0); \ 11815127Smckusick PUSH_TO_NULL(sequencep); 11915127Smckusick 12015127Smckusick sequencep = &sequence[0]; 12115127Smckusick *sequencep = '\0'; 12215127Smckusick /* 12315127Smckusick * skip leading whitespace 12415127Smckusick */ 12515127Smckusick SOME(read, filep, "%*[ \t\n]", sequencep); 12615127Smckusick /* 12715127Smckusick * [ "+" | "-" ] digit {digits} 12815127Smckusick */ 12915127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 13015127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 13115127Smckusick /* 13215127Smckusick * either 13315127Smckusick * "." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ] 13415127Smckusick * or 13515127Smckusick * "e" [ "+" | "-" ] digit {digits} 13615127Smckusick */ 137*15302Smckusick AT_MOST_ONE(read, filep, "%c", sequencep); 138*15302Smckusick switch (sequencep[-1]) { 139*15302Smckusick default: 140*15302Smckusick PUSHBACK(curfile, sequencep); 141*15302Smckusick goto convert; 142*15302Smckusick case '.': 143*15302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 144*15302Smckusick if (!read) { 145*15302Smckusick PUSHBACK(curfile, sequencep); 146*15302Smckusick goto convert; 14715127Smckusick } 148*15302Smckusick AT_MOST_ONE(read, filep, "%c", sequencep); 149*15302Smckusick if (sequencep[-1] != 'e') { 150*15302Smckusick PUSHBACK(curfile, sequencep); 151*15302Smckusick goto convert; 152*15302Smckusick } 153*15302Smckusick /* fall through */ 154*15302Smckusick case 'e': 155*15302Smckusick AT_MOST_ONE(read, filep, "%c", sequencep); 156*15302Smckusick if (sequencep[-1] != '+' && sequencep[-1] != '-') { 157*15302Smckusick PUSHBACK(curfile, sequencep); 158*15302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 159*15302Smckusick if (!read) 160*15302Smckusick PUSHBACK(curfile, sequencep); 161*15302Smckusick goto convert; 162*15302Smckusick } 163*15302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 164*15302Smckusick if (!read) { 165*15302Smckusick PUSHBACK(curfile, sequencep); 166*15302Smckusick PUSHBACK(curfile, sequencep); 167*15302Smckusick } 16815127Smckusick } 169*15302Smckusick 170*15302Smckusick convert: 17115127Smckusick /* 17215127Smckusick * convert sequence to double 17315127Smckusick */ 17415127Smckusick *doublep = atof(&sequence[0]); 17515127Smckusick return (1); 17615127Smckusick } 177