1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)READ8.c 1.6 10/01/83"; 4 5 #include "h00vars.h" 6 #include <errno.h> 7 extern int errno; 8 9 double 10 READ8(curfile) 11 12 register struct iorec *curfile; 13 { 14 double data; 15 int retval; 16 17 if (curfile->funit & FWRITE) { 18 ERROR("%s: Attempt to read, but open for writing\n", 19 curfile->pfname); 20 return; 21 } 22 UNSYNC(curfile); 23 errno = 0; 24 retval = readreal(curfile->fbuf, &data); 25 if (retval == EOF) { 26 ERROR("%s: Tried to read past end of file\n", curfile->pfname); 27 return; 28 } 29 if (retval == 0) { 30 ERROR("%s: Bad data found on real read\n", curfile->pfname); 31 return; 32 } 33 if (errno == ERANGE) { 34 if (data == 0.0) 35 ERROR("%s: Underflow on real read\n", curfile->pfname); 36 else 37 ERROR("%s: Overflow on real read\n", curfile->pfname); 38 return; 39 } 40 if (errno != 0) { 41 PERROR("Error encountered on real read ", curfile->pfname); 42 return; 43 } 44 curfile->funit &= ~EOLN; 45 curfile->funit |= SYNC; 46 return (data); 47 } 48 49 /* 50 * given a file pointer, read a sequence of characters of the 51 * syntax of section 6.1.5 and form them into a double. 52 * 53 * the syntax of a signed-real is: 54 * [-|+] digit {digit} e [+|-] digit {digit} 55 * or 56 * [-|+] digit {digit} . digit {digit} [e [+|-] digit {digit}] 57 * 58 * returns: 59 * 1 for success (with value in *doublep) 60 * 0 on error (with *doublep unchanged) 61 * -1 on end-of-file during read (with *doublep unchanged) 62 * side effects: 63 * errno may be set to ERANGE if atof() sets it. 64 */ 65 readreal(filep, doublep) 66 FILE *filep; 67 double *doublep; 68 { 69 char sequence[BUFSIZ]; /* the character sequence */ 70 char *sequencep; /* a pointer into sequence */ 71 int read; /* return value from fscanf() */ 72 double atof(); 73 74 #define RETURN_ON_EOF(read) \ 75 if (read == EOF) \ 76 return (EOF); \ 77 else \ 78 /* void */; 79 80 #define PUSH_TO_NULL(sequencep) \ 81 while (*sequencep) \ 82 sequencep++; 83 84 #define SOME(read, filep, format, sequencep) \ 85 read = fscanf(filep, format, sequencep); \ 86 RETURN_ON_EOF(read); \ 87 PUSH_TO_NULL(sequencep); 88 89 #define AT_LEAST_ONE(read, filep, format, sequencep) \ 90 read = fscanf(filep, format, sequencep); \ 91 RETURN_ON_EOF(read); \ 92 if (strlen(sequencep) < 1) \ 93 return (0); \ 94 PUSH_TO_NULL(sequencep); 95 96 #define EXACTLY_ONE(read, filep, format, sequencep) \ 97 read = fscanf(filep, format, sequencep); \ 98 RETURN_ON_EOF(read); \ 99 if (strlen(sequencep) != 1) \ 100 return (0); \ 101 PUSH_TO_NULL(sequencep); 102 103 #define AT_MOST_ONE(read, filep, format, sequencep) \ 104 read = fscanf(filep, format, sequencep); \ 105 RETURN_ON_EOF(read); \ 106 if (strlen(sequencep) > 1) \ 107 return (0); \ 108 PUSH_TO_NULL(sequencep); 109 110 sequencep = &sequence[0]; 111 *sequencep = '\0'; 112 /* 113 * skip leading whitespace 114 */ 115 SOME(read, filep, "%*[ \t\n]", sequencep); 116 /* 117 * [ "+" | "-" ] digit {digits} 118 */ 119 AT_MOST_ONE(read, filep, "%[+-]", sequencep); 120 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 121 /* 122 * either 123 * "." digit {digit} [ "e" [ "+" | "-" ] digit {digits} ] 124 * or 125 * "e" [ "+" | "-" ] digit {digits} 126 */ 127 AT_MOST_ONE(read, filep, "%[.]", sequencep); 128 if (read) { 129 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 130 AT_MOST_ONE(read, filep, "%[e]", sequencep); 131 if (read) { 132 AT_MOST_ONE(read, filep, "%[+-]", sequencep); 133 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 134 } 135 } else { 136 EXACTLY_ONE(read, filep, "%[e]", sequencep); 137 AT_MOST_ONE(read, filep, "%[+-]", sequencep); 138 AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 139 } 140 /* 141 * convert sequence to double 142 */ 143 *doublep = atof(&sequence[0]); 144 return (1); 145 } 146