11680Smckusick /* Copyright (c) 1979 Regents of the University of California */ 21680Smckusick 3*15127Smckusick static char sccsid[] = "@(#)READ8.c 1.6 10/01/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*15127Smckusick retval = readreal(curfile->fbuf, &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) { 41*15127Smckusick PERROR("Error encountered on real read ", curfile->pfname); 426498Smckusick return; 436498Smckusick } 442309Smckusic curfile->funit &= ~EOLN; 451680Smckusick curfile->funit |= SYNC; 46*15127Smckusick return (data); 471680Smckusick } 48*15127Smckusick 49*15127Smckusick /* 50*15127Smckusick * given a file pointer, read a sequence of characters of the 51*15127Smckusick * syntax of section 6.1.5 and form them into a double. 52*15127Smckusick * 53*15127Smckusick * the syntax of a signed-real is: 54*15127Smckusick * [-|+] digit {digit} e [+|-] digit {digit} 55*15127Smckusick * or 56*15127Smckusick * [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}] 57*15127Smckusick * 58*15127Smckusick * returns: 59*15127Smckusick * 1 for success (with value in *doublep) 60*15127Smckusick * 0 on error (with *doublep unchanged) 61*15127Smckusick * -1 on end-of-file during read (with *doublep unchanged) 62*15127Smckusick * side effects: 63*15127Smckusick * errno may be set to ERANGE if atof() sets it. 64*15127Smckusick */ 65*15127Smckusick readreal(filep, doublep) 66*15127Smckusick FILE *filep; 67*15127Smckusick double *doublep; 68*15127Smckusick { 69*15127Smckusick char sequence[BUFSIZ]; /* the character sequence */ 70*15127Smckusick char *sequencep; /* a pointer into sequence */ 71*15127Smckusick int read; /* return value from fscanf() */ 72*15127Smckusick double atof(); 73*15127Smckusick 74*15127Smckusick #define RETURN_ON_EOF(read) \ 75*15127Smckusick if (read == EOF) \ 76*15127Smckusick return (EOF); \ 77*15127Smckusick else \ 78*15127Smckusick /* void */; 79*15127Smckusick 80*15127Smckusick #define PUSH_TO_NULL(sequencep) \ 81*15127Smckusick while (*sequencep) \ 82*15127Smckusick sequencep++; 83*15127Smckusick 84*15127Smckusick #define SOME(read, filep, format, sequencep) \ 85*15127Smckusick read = fscanf(filep, format, sequencep); \ 86*15127Smckusick RETURN_ON_EOF(read); \ 87*15127Smckusick PUSH_TO_NULL(sequencep); 88*15127Smckusick 89*15127Smckusick #define AT_LEAST_ONE(read, filep, format, sequencep) \ 90*15127Smckusick read = fscanf(filep, format, sequencep); \ 91*15127Smckusick RETURN_ON_EOF(read); \ 92*15127Smckusick if (strlen(sequencep) < 1) \ 93*15127Smckusick return (0); \ 94*15127Smckusick PUSH_TO_NULL(sequencep); 95*15127Smckusick 96*15127Smckusick #define EXACTLY_ONE(read, filep, format, sequencep) \ 97*15127Smckusick read = fscanf(filep, format, sequencep); \ 98*15127Smckusick RETURN_ON_EOF(read); \ 99*15127Smckusick if (strlen(sequencep) != 1) \ 100*15127Smckusick return (0); \ 101*15127Smckusick PUSH_TO_NULL(sequencep); 102*15127Smckusick 103*15127Smckusick #define AT_MOST_ONE(read, filep, format, sequencep) \ 104*15127Smckusick read = fscanf(filep, format, sequencep); \ 105*15127Smckusick RETURN_ON_EOF(read); \ 106*15127Smckusick if (strlen(sequencep) > 1) \ 107*15127Smckusick return (0); \ 108*15127Smckusick PUSH_TO_NULL(sequencep); 109*15127Smckusick 110*15127Smckusick sequencep = &sequence[0]; 111*15127Smckusick *sequencep = '\0'; 112*15127Smckusick /* 113*15127Smckusick * skip leading whitespace 114*15127Smckusick */ 115*15127Smckusick SOME(read, filep, "%*[ \t\n]", sequencep); 116*15127Smckusick /* 117*15127Smckusick * [ "+" | "-" ] digit {digits} 118*15127Smckusick */ 119*15127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 120*15127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 121*15127Smckusick /* 122*15127Smckusick * either 123*15127Smckusick * "." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ] 124*15127Smckusick * or 125*15127Smckusick * "e" [ "+" | "-" ] digit {digits} 126*15127Smckusick */ 127*15127Smckusick AT_MOST_ONE(read, filep, "%[.]", sequencep); 128*15127Smckusick if (read) { 129*15127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 130*15127Smckusick AT_MOST_ONE(read, filep, "%[e]", sequencep); 131*15127Smckusick if (read) { 132*15127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 133*15127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 134*15127Smckusick } 135*15127Smckusick } else { 136*15127Smckusick EXACTLY_ONE(read, filep, "%[e]", sequencep); 137*15127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 138*15127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 139*15127Smckusick } 140*15127Smckusick /* 141*15127Smckusick * convert sequence to double 142*15127Smckusick */ 143*15127Smckusick *doublep = atof(&sequence[0]); 144*15127Smckusick return (1); 145*15127Smckusick } 146