11680Smckusick /* Copyright (c) 1979 Regents of the University of California */ 21680Smckusick 3*15388Speter static char sccsid[] = "@(#)READ8.c 1.8 11/06/83"; 41680Smckusick 51680Smckusick #include "h00vars.h" 66498Smckusick #include <errno.h> 76498Smckusick extern int errno; 81680Smckusick 91680Smckusick double 101680Smckusick READ8(curfile) 111680Smckusick register struct iorec *curfile; 121680Smckusick { 131680Smckusick double data; 142223Smckusic int retval; 151680Smckusick 161680Smckusick if (curfile->funit & FWRITE) { 173869Smckusic ERROR("%s: Attempt to read, but open for writing\n", 183869Smckusic curfile->pfname); 191680Smckusick return; 201680Smckusick } 211680Smckusick UNSYNC(curfile); 226498Smckusick errno = 0; 2315302Smckusick retval = readreal(curfile, &data); 242223Smckusic if (retval == EOF) { 253869Smckusic ERROR("%s: Tried to read past end of file\n", curfile->pfname); 262223Smckusic return; 272223Smckusic } 282223Smckusic if (retval == 0) { 293869Smckusic ERROR("%s: Bad data found on real read\n", curfile->pfname); 301680Smckusick return; 311680Smckusick } 326498Smckusick if (errno == ERANGE) { 336498Smckusick if (data == 0.0) 346498Smckusick ERROR("%s: Underflow on real read\n", curfile->pfname); 356498Smckusick else 366498Smckusick ERROR("%s: Overflow on real read\n", curfile->pfname); 376498Smckusick return; 386498Smckusick } 396498Smckusick if (errno != 0) { 4015127Smckusick PERROR("Error encountered on real read ", curfile->pfname); 416498Smckusick return; 426498Smckusick } 4315127Smckusick return (data); 441680Smckusick } 4515127Smckusick 4615127Smckusick /* 4715127Smckusick * given a file pointer, read a sequence of characters of the 4815127Smckusick * syntax of section 6.1.5 and form them into a double. 4915127Smckusick * 5015127Smckusick * the syntax of a signed-real is: 51*15388Speter * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ] 5215127Smckusick * 5315127Smckusick * returns: 5415127Smckusick * 1 for success (with value in *doublep) 5515127Smckusick * 0 on error (with *doublep unchanged) 5615127Smckusick * -1 on end-of-file during read (with *doublep unchanged) 5715127Smckusick * side effects: 5815127Smckusick * errno may be set to ERANGE if atof() sets it. 5915127Smckusick */ 6015302Smckusick readreal(curfile, doublep) 6115302Smckusick struct iorec *curfile; 6215302Smckusick double *doublep; 6315127Smckusick { 6415302Smckusick FILE *filep = curfile->fbuf; /* current file variable */ 6515127Smckusick char *sequencep; /* a pointer into sequence */ 6615127Smckusick int read; /* return value from fscanf() */ 6715302Smckusick char sequence[BUFSIZ]; /* the character sequence */ 6815127Smckusick double atof(); 6915127Smckusick 7015302Smckusick #define PUSHBACK(curfile, sequencep) \ 7115302Smckusick if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ 7215302Smckusick *(sequencep) = '\0'; \ 7315302Smckusick } else if ((curfile)->funit & SYNC) { \ 7415302Smckusick (curfile)->funit &= ~SYNC; \ 7515302Smckusick *(curfile)->fileptr = *(sequencep); \ 7615302Smckusick *(sequencep) = '\0'; \ 7715302Smckusick } else { \ 7815302Smckusick return (0); \ 7915302Smckusick } 8015302Smckusick 8115127Smckusick #define RETURN_ON_EOF(read) \ 8215127Smckusick if (read == EOF) \ 8315127Smckusick return (EOF); \ 8415127Smckusick else \ 8515127Smckusick /* void */; 8615127Smckusick 8715127Smckusick #define PUSH_TO_NULL(sequencep) \ 8815127Smckusick while (*sequencep) \ 8915127Smckusick sequencep++; 9015127Smckusick 91*15388Speter /* general reader of the next character */ 92*15388Speter #define NEXT_CHAR(read, filep, format, sequencep) \ 93*15388Speter read = fscanf(filep, "%c", sequencep); \ 94*15388Speter RETURN_ON_EOF(read); \ 95*15388Speter *++sequencep = '\0'; 96*15388Speter 97*15388Speter /* e.g. use %[0123456789] for {digit}, and check read */ 9815127Smckusick #define SOME(read, filep, format, sequencep) \ 9915127Smckusick read = fscanf(filep, format, sequencep); \ 10015127Smckusick RETURN_ON_EOF(read); \ 10115127Smckusick PUSH_TO_NULL(sequencep); 10215127Smckusick 103*15388Speter /* e.g. use %[0123456789] for digit {digit} */ 10415127Smckusick #define AT_LEAST_ONE(read, filep, format, sequencep) \ 10515127Smckusick read = fscanf(filep, format, sequencep); \ 10615127Smckusick RETURN_ON_EOF(read); \ 10715127Smckusick if (strlen(sequencep) < 1) \ 10815127Smckusick return (0); \ 10915127Smckusick PUSH_TO_NULL(sequencep); 11015127Smckusick 111*15388Speter #define ANY_ONE_OF(read, filep, format, sequencep) \ 11215127Smckusick read = fscanf(filep, format, sequencep); \ 11315127Smckusick RETURN_ON_EOF(read); \ 11415127Smckusick if (strlen(sequencep) != 1) \ 11515127Smckusick return (0); \ 11615127Smckusick PUSH_TO_NULL(sequencep); 11715127Smckusick 11815127Smckusick #define AT_MOST_ONE(read, filep, format, sequencep) \ 11915127Smckusick read = fscanf(filep, format, sequencep); \ 12015127Smckusick RETURN_ON_EOF(read); \ 12115127Smckusick if (strlen(sequencep) > 1) \ 12215127Smckusick return (0); \ 12315127Smckusick PUSH_TO_NULL(sequencep); 12415127Smckusick 12515127Smckusick sequencep = &sequence[0]; 12615127Smckusick *sequencep = '\0'; 12715127Smckusick /* 128*15388Speter * skip leading whitespace 12915127Smckusick */ 13015127Smckusick SOME(read, filep, "%*[ \t\n]", sequencep); 13115127Smckusick /* 132*15388Speter * this much is required: 13315127Smckusick * [ "+" | "-" ] digit {digits} 13415127Smckusick */ 13515127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 136*15388Speter fprintf(stderr, "leading sign <%s>\n", sequence); 13715127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 138*15388Speter fprintf(stderr, "leading digits <%s>\n", sequence); 13915127Smckusick /* 140*15388Speter * any of this is optional: 141*15388Speter * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ] 14215127Smckusick */ 143*15388Speter *sequencep = getc(filep); 144*15388Speter fprintf(stderr, "before [.e] 0x%x\n", *sequencep); 145*15388Speter ungetc(*sequencep, filep); 146*15388Speter *sequencep = '\0'; 147*15388Speter /* ANY_ONE_OF(read, filep, "%c", sequencep);*/ 148*15388Speter /* read = fscanf(filep, "%c", sequencep); 149*15388Speter * *++sequencep = '\0'; 150*15388Speter */ 151*15388Speter NEXT_CHAR(read, filep, "%c", sequencep); 152*15388Speter fprintf(stderr, "[.e] (read %d) <%s>\n", read, sequence); 15315302Smckusick switch (sequencep[-1]) { 15415302Smckusick default: 15515302Smckusick PUSHBACK(curfile, sequencep); 15615302Smckusick goto convert; 15715302Smckusick case '.': 15815302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 159*15388Speter fprintf(stderr, "trailing digits <%s>\n", sequence); 16015302Smckusick if (!read) { 16115302Smckusick PUSHBACK(curfile, sequencep); 16215302Smckusick goto convert; 16315127Smckusick } 164*15388Speter /* AT_MOST_ONE(read, filep, "%c", sequencep); */ 165*15388Speter NEXT_CHAR(read, filep, "%c", sequencep); 166*15388Speter fprintf(stderr, "optional e <%s>\n", sequence); 16715302Smckusick if (sequencep[-1] != 'e') { 16815302Smckusick PUSHBACK(curfile, sequencep); 16915302Smckusick goto convert; 17015302Smckusick } 17115302Smckusick /* fall through */ 17215302Smckusick case 'e': 173*15388Speter /* ANY_ONE_OF(read, filep, "%c", sequencep); */ 174*15388Speter NEXT_CHAR(read, filep, "%c", sequencep); 175*15388Speter fprintf(stderr, "exponent sign <%s>\n", sequence); 17615302Smckusick if (sequencep[-1] != '+' && sequencep[-1] != '-') { 17715302Smckusick PUSHBACK(curfile, sequencep); 17815302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 179*15388Speter fprintf(stderr, "signed exponent <%s>\n", sequence); 18015302Smckusick if (!read) 18115302Smckusick PUSHBACK(curfile, sequencep); 18215302Smckusick goto convert; 18315302Smckusick } 18415302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 185*15388Speter fprintf(stderr, "unsigned exponent <%s>\n", sequence); 18615302Smckusick if (!read) { 18715302Smckusick PUSHBACK(curfile, sequencep); 18815302Smckusick PUSHBACK(curfile, sequencep); 18915302Smckusick } 19015127Smckusick } 19115302Smckusick 19215302Smckusick convert: 19315127Smckusick /* 19415127Smckusick * convert sequence to double 19515127Smckusick */ 196*15388Speter fprintf(stderr, "convert <%s>\n", sequence); 19715127Smckusick *doublep = atof(&sequence[0]); 19815127Smckusick return (1); 19915127Smckusick } 200