1*40865Sbostic /*- 2*40865Sbostic * Copyright (c) 1979 The Regents of the University of California. 3*40865Sbostic * All rights reserved. 4*40865Sbostic * 5*40865Sbostic * %sccs.include.redist.c% 6*40865Sbostic */ 71680Smckusick 8*40865Sbostic #ifndef lint 9*40865Sbostic static char sccsid[] = "@(#)READ8.c 1.11 (Berkeley) 04/09/90"; 10*40865Sbostic #endif /* not lint */ 111680Smckusick 121680Smckusick #include "h00vars.h" 136498Smckusick #include <errno.h> 146498Smckusick extern int errno; 151680Smckusick 161680Smckusick double 171680Smckusick READ8(curfile) 181680Smckusick register struct iorec *curfile; 191680Smckusick { 201680Smckusick double data; 212223Smckusic int retval; 221680Smckusick 231680Smckusick if (curfile->funit & FWRITE) { 243869Smckusic ERROR("%s: Attempt to read, but open for writing\n", 253869Smckusic curfile->pfname); 261680Smckusick } 271680Smckusick UNSYNC(curfile); 286498Smckusick errno = 0; 2915302Smckusick retval = readreal(curfile, &data); 302223Smckusic if (retval == EOF) { 313869Smckusic ERROR("%s: Tried to read past end of file\n", curfile->pfname); 322223Smckusic } 332223Smckusic if (retval == 0) { 343869Smckusic ERROR("%s: Bad data found on real read\n", curfile->pfname); 351680Smckusick } 366498Smckusick if (errno == ERANGE) { 376498Smckusick if (data == 0.0) 386498Smckusick ERROR("%s: Underflow on real read\n", curfile->pfname); 396498Smckusick else 406498Smckusick ERROR("%s: Overflow on real read\n", curfile->pfname); 416498Smckusick } 426498Smckusick if (errno != 0) { 4315127Smckusick PERROR("Error encountered on real read ", curfile->pfname); 446498Smckusick } 4515127Smckusick return (data); 461680Smckusick } 4715127Smckusick 4815127Smckusick /* 4915127Smckusick * given a file pointer, read a sequence of characters of the 5015127Smckusick * syntax of section 6.1.5 and form them into a double. 5115127Smckusick * 5215127Smckusick * the syntax of a signed-real is: 5315388Speter * [-|+] digit {digit} [ . digit {digit} ] [ e [+|-] digit {digit} ] 5415127Smckusick * 5515127Smckusick * returns: 5615127Smckusick * 1 for success (with value in *doublep) 5715127Smckusick * 0 on error (with *doublep unchanged) 5815127Smckusick * -1 on end-of-file during read (with *doublep unchanged) 5915127Smckusick * side effects: 6015127Smckusick * errno may be set to ERANGE if atof() sets it. 6115127Smckusick */ 6215302Smckusick readreal(curfile, doublep) 6315302Smckusick struct iorec *curfile; 6415302Smckusick double *doublep; 6515127Smckusick { 6615302Smckusick FILE *filep = curfile->fbuf; /* current file variable */ 6715127Smckusick char *sequencep; /* a pointer into sequence */ 6815127Smckusick int read; /* return value from fscanf() */ 6915302Smckusick char sequence[BUFSIZ]; /* the character sequence */ 7015127Smckusick double atof(); 7115127Smckusick 7215302Smckusick #define PUSHBACK(curfile, sequencep) \ 7315302Smckusick if (ungetc(*--(sequencep), (curfile)->fbuf) != EOF) { \ 7415302Smckusick *(sequencep) = '\0'; \ 7515302Smckusick } else if ((curfile)->funit & SYNC) { \ 7615302Smckusick (curfile)->funit &= ~SYNC; \ 7715302Smckusick *(curfile)->fileptr = *(sequencep); \ 7815302Smckusick *(sequencep) = '\0'; \ 7915302Smckusick } else { \ 8015302Smckusick return (0); \ 8115302Smckusick } 8215302Smckusick 8315127Smckusick #define RETURN_ON_EOF(read) \ 8415127Smckusick if (read == EOF) \ 8515127Smckusick return (EOF); \ 8615127Smckusick else \ 8715127Smckusick /* void */; 8815127Smckusick 8915127Smckusick #define PUSH_TO_NULL(sequencep) \ 9015127Smckusick while (*sequencep) \ 9115127Smckusick sequencep++; 9215127Smckusick 9315388Speter /* general reader of the next character */ 9415388Speter #define NEXT_CHAR(read, filep, format, sequencep) \ 9515388Speter read = fscanf(filep, "%c", sequencep); \ 9615388Speter RETURN_ON_EOF(read); \ 9715388Speter *++sequencep = '\0'; 9815388Speter 9915388Speter /* e.g. use %[0123456789] for {digit}, and check read */ 10015127Smckusick #define SOME(read, filep, format, sequencep) \ 10115127Smckusick read = fscanf(filep, format, sequencep); \ 10215127Smckusick RETURN_ON_EOF(read); \ 10315127Smckusick PUSH_TO_NULL(sequencep); 10415127Smckusick 10515388Speter /* e.g. use %[0123456789] for digit {digit} */ 10615127Smckusick #define AT_LEAST_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 11315388Speter #define ANY_ONE_OF(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 #define AT_MOST_ONE(read, filep, format, sequencep) \ 12115127Smckusick read = fscanf(filep, format, sequencep); \ 12215127Smckusick RETURN_ON_EOF(read); \ 12315127Smckusick if (strlen(sequencep) > 1) \ 12415127Smckusick return (0); \ 12515127Smckusick PUSH_TO_NULL(sequencep); 12615127Smckusick 12715127Smckusick sequencep = &sequence[0]; 12815127Smckusick *sequencep = '\0'; 12915127Smckusick /* 13015388Speter * skip leading whitespace 13115127Smckusick */ 13215127Smckusick SOME(read, filep, "%*[ \t\n]", sequencep); 13315127Smckusick /* 13415388Speter * this much is required: 13515127Smckusick * [ "+" | "-" ] digit {digits} 13615127Smckusick */ 13715127Smckusick AT_MOST_ONE(read, filep, "%[+-]", sequencep); 13815127Smckusick AT_LEAST_ONE(read, filep, "%[0123456789]", sequencep); 13915127Smckusick /* 14015388Speter * any of this is optional: 14115388Speter * [ `.' digit {digit} ] [ `e' [ `+' | `-' ] digit {digits} ] 14215127Smckusick */ 14315388Speter NEXT_CHAR(read, filep, "%c", sequencep); 14415302Smckusick switch (sequencep[-1]) { 14515302Smckusick default: 14615302Smckusick PUSHBACK(curfile, sequencep); 14715302Smckusick goto convert; 14815302Smckusick case '.': 14915302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 15015302Smckusick if (!read) { 15115302Smckusick PUSHBACK(curfile, sequencep); 15215302Smckusick goto convert; 15315127Smckusick } 15415388Speter NEXT_CHAR(read, filep, "%c", sequencep); 15515302Smckusick if (sequencep[-1] != 'e') { 15615302Smckusick PUSHBACK(curfile, sequencep); 15715302Smckusick goto convert; 15815302Smckusick } 15915302Smckusick /* fall through */ 16015302Smckusick case 'e': 16115388Speter NEXT_CHAR(read, filep, "%c", sequencep); 16215302Smckusick if (sequencep[-1] != '+' && sequencep[-1] != '-') { 16315302Smckusick PUSHBACK(curfile, sequencep); 16415302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 16515302Smckusick if (!read) 16615302Smckusick PUSHBACK(curfile, sequencep); 16715302Smckusick goto convert; 16815302Smckusick } 16915302Smckusick SOME(read, filep, "%[0123456789]", sequencep); 17015302Smckusick if (!read) { 17115302Smckusick PUSHBACK(curfile, sequencep); 17215302Smckusick PUSHBACK(curfile, sequencep); 17315302Smckusick } 17415127Smckusick } 17515302Smckusick 17615302Smckusick convert: 17715127Smckusick /* 17815127Smckusick * convert sequence to double 17915127Smckusick */ 18015127Smckusick *doublep = atof(&sequence[0]); 18115127Smckusick return (1); 18215127Smckusick } 183