ast@cs.vu.nl (Andy Tanenbaum) (05/16/88)
I am going through bits and pieces of news that I have saved looking for bug reports. I'd appreciate some help with some of these. For example, some time ago Peter Housel posted some fixes to library routines, including fseek.c, scanf.c, getc.c. The corrected versions are included below. Could people try testing these and letting me know if they are ok? Also,, he posted replacements for rmu4.s and rmi4.s. Has anyone tested those? Thanks. Andy Tanenbaum (ast@cs.vu.nl) : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin echo Extracting \f\s\e\e\k\.\c sed 's/^X//' > \f\s\e\e\k\.\c << '+ END-OF-FILE '\f\s\e\e\k\.\c X#include <stdio.h> X X Xfseek(iop, offset, where) XFILE *iop; Xlong offset; X{ X int count; X long lseek(); X long pos; X X iop->_flags &= ~(_EOF | _ERR); X /* Clear both the end of file and error flags */ X X if ( testflag(iop,READMODE) ) { X if ( where < 2 && iop->_buf && !testflag(iop,UNBUFF) ) { X count = iop->_count; X pos = offset; X X if ( where == 0 ) X pos += count - lseek(fileno(iop), 0L, 1); X else X offset -= count; X X if ( count > 0 && pos <= count X && pos >= iop->_buf - iop->_ptr ) { X iop->_ptr += (int) pos; X iop->_count -= (int) pos; X return(0); X } X } X pos = lseek(fileno(iop), offset, where); X iop->_count = 0; X } else if ( testflag(iop,WRITEMODE) ) { X fflush(iop); X pos = lseek(fileno(iop), offset, where); X } X return((pos == -1) ? -1 : 0 ); X} + END-OF-FILE fseek.c chmod 'u=rw,g=r,o=r' \f\s\e\e\k\.\c set `sum \f\s\e\e\k\.\c` sum=$1 case $sum in 58941) :;; *) echo 'Bad sum in '\f\s\e\e\k\.\c >&2 esac echo Extracting \g\e\t\c\.\c sed 's/^X//' > \g\e\t\c\.\c << '+ END-OF-FILE '\g\e\t\c\.\c X#include <stdio.h> X X X Xgetc(iop) XFILE *iop; X{ X int ch; X X if ( testflag(iop, (_EOF | _ERR ))) X return (EOF); X X if ( !testflag(iop, READMODE) ) X return (EOF); X X if (iop->_count <= 0){ X X if ( testflag(iop, UNBUFF) ) X iop->_count = read(iop->_fd,&ch,1); X else X iop->_count = read(iop->_fd,iop->_buf,BUFSIZ); X X if (iop->_count <= 0){ X if (iop->_count == 0) X iop->_flags |= _EOF; X else X iop->_flags |= _ERR; X X return (EOF); X } X else X iop->_ptr = iop->_buf; X } X X if (testflag(iop,UNBUFF)) X return (ch & CMASK); X else X return (--iop->_count, *iop->_ptr++ & CMASK); X} X + END-OF-FILE getc.c chmod 'u=rw,g=r,o=r' \g\e\t\c\.\c set `sum \g\e\t\c\.\c` sum=$1 case $sum in 00255) :;; *) echo 'Bad sum in '\g\e\t\c\.\c >&2 esac echo Extracting \s\c\a\n\f\.\c sed 's/^X//' > \s\c\a\n\f\.\c << '+ END-OF-FILE '\s\c\a\n\f\.\c X/* scanf - formatted input conversion Author: Patrick van Kleef */ X X#include "stdio.h" X X Xint scanf (format, args) Xchar *format; Xunsigned args; X{ X return _doscanf (0, stdin, format, &args); X} X X X Xint fscanf (fp, format, args) XFILE *fp; Xchar *format; Xunsigned args; X{ X return _doscanf (0, fp, format, &args); X} X X Xint sscanf (string, format, args) Xchar *string; /* source of data */ Xchar *format; /* control string */ Xunsigned args; /* our args */ X{ X return _doscanf (1, string, format, &args); X} X X Xunion ptr_union { X char *chr_p; X unsigned int *uint_p; X unsigned long *ulong_p; X}; X Xstatic int ic; /* the current character */ Xstatic char *rnc_arg; /* the string or the filepointer */ Xstatic rnc_code; /* 1 = read from string, else from FILE */ X X X X X/* get the next character */ X Xstatic rnc () X{ X if (rnc_code) { X if (!(ic = *rnc_arg++)) X ic = EOF; X } else X ic = getc ((FILE *) rnc_arg); X} X X X X/* X * unget the current character X */ X Xstatic ugc () X{ X X if (rnc_code) X --rnc_arg; X else X ungetc (ic, rnc_arg); X} X X X Xstatic scnindex(ch, string) Xchar ch; Xchar *string; X{ X while (*string++ != ch) X if (!*string) X return 0; X return 1; X} X X X/* X * this is cheaper than iswhite from <ctype.h> X */ X Xstatic iswhite (ch) Xint ch; X{ X X return (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); X} X X X X X Xstatic isdigit (ch) Xint ch; X{ X return (ch >= '0' && ch <= '9'); X} X X X X Xstatic tolower (ch) Xint ch; X{ X if (ch >= 'A' && ch <= 'Z') X ch = ch + 'a' - 'A'; X X return ch; X} X X X/* X * the routine that does the job X */ X X_doscanf (code, funcarg, format, argp) Xint code; /* function to get a character */ Xchar *funcarg; /* an argument for the function */ Xchar *format; /* the format control string */ Xunion ptr_union *argp; /* our argument list */ X{ X int done = 0; /* number of items done */ X int base; /* conversion base */ X long val; /* an integer value */ X int sign; /* sign flag */ X int do_assign; /* assignment suppression flag */ X unsigned width; /* width of field */ X int widflag; /* width was specified */ X int longflag; /* true if long */ X int done_some; /* true if we have seen some data */ X int reverse; /* reverse the checking in [...] */ X char *endbracket; /* position of the ] in format string */ X X rnc_arg = funcarg; X rnc_code = code; X X rnc (); /* read the next character */ X X if (ic == EOF) { X done = EOF; X goto quit; X } X X while (1) { X while (iswhite (*format)) X ++format; /* skip whitespace */ X if (!*format) X goto all_done; /* end of format */ X if (ic < 0) X goto quit; /* seen an error */ X if (*format != '%') { X while (iswhite (ic)) X rnc (); X if (ic != *format) X goto all_done; X ++format; X rnc (); X continue; X } X ++format; X do_assign = 1; X if (*format == '*') { X ++format; X do_assign = 0; X } X if (isdigit (*format)) { X widflag = 1; X for (width = 0; isdigit (*format);) X width = width * 10 + *format++ - '0'; X } else X widflag = 0; /* no width spec */ X if (longflag = (tolower (*format) == 'l')) X ++format; X if (*format != 'c') X while (iswhite (ic)) X rnc (); X done_some = 0; /* nothing yet */ X switch (*format) { X case 'o': X base = 8; X goto decimal; X case 'u': X case 'd': X base = 10; X goto decimal; X case 'x': X base = 16; X if (((!widflag) || width >= 2) && ic == '0') { X rnc (); X if (tolower (ic) == 'x') { X width -= 2; X done_some = 1; X rnc (); X } else { X ugc (); X ic = '0'; X } X } X decimal: X val = 0L; /* our result value */ X sign = 0; /* assume positive */ X if (!widflag) X width = 0xffff; /* very wide */ X if (width && ic == '+') X rnc (); X else if (width && ic == '-') { X sign = 1; X rnc (); X } X while (width--) { X if (isdigit (ic) && ic - '0' < base) X ic -= '0'; X else if (base == 16 && tolower (ic) >= 'a' && tolower (ic) <= 'f') X ic = 10 + tolower (ic) - 'a'; X else X break; X val = val * base + ic; X rnc (); X done_some = 1; X } X if (do_assign) { X if (sign) X val = -val; X if (longflag) X *(argp++)->ulong_p = (unsigned long) val; X else X *(argp++)->uint_p = (unsigned) val; X } X if (done_some) { X if(do_assign) ++done; X } X else X goto all_done; X break; X case 'c': X if (!widflag) X width = 1; X while (width-- && ic >= 0) { X if (do_assign) X *(argp)->chr_p++ = (char) ic; X rnc (); X done_some = 1; X } X if (do_assign) X argp++; /* done with this one */ X if (done_some && do_assign) X ++done; X break; X case 's': X if (!widflag) X width = 0xffff; X while (width-- && !iswhite (ic) && ic > 0) { X if (do_assign) X *(argp)->chr_p++ = (char) ic; X rnc (); X done_some = 1; X } X if (do_assign) /* terminate the string */ X *(argp++)->chr_p = '\0'; X if (done_some && do_assign) X ++done; X else X goto all_done; X break; X case '[': X if (!widflag) X width = 0xffff; X X if ( *(++format) == '^' ) { X reverse = 1; X format++; X } else X reverse = 0; X X endbracket = format; X while ( *endbracket != ']' && *endbracket != '\0') X endbracket++; X X if (!*endbracket) X goto quit; X X *endbracket = '\0'; /* change format string */ X X while (width-- && !iswhite (ic) && ic > 0 && X (scnindex (ic, format) ^ reverse)) { X if (do_assign) X *(argp)->chr_p++ = (char) ic; X rnc (); X done_some = 1; X } X format = endbracket; X *format = ']'; /* put it back */ X if (do_assign) /* terminate the string */ X *(argp++)->chr_p = '\0'; X if (done_some && do_assign) X ++done; X else X goto all_done; X break; X } /* end switch */ X ++format; X } Xall_done: X if (ic >= 0) X ugc (); /* restore the character */ Xquit: X return done; X} + END-OF-FILE scanf.c chmod 'u=rw,g=r,o=r' \s\c\a\n\f\.\c set `sum \s\c\a\n\f\.\c` sum=$1 case $sum in 42855) :;; *) echo 'Bad sum in '\s\c\a\n\f\.\c >&2 esac exit 0
tholm@uvicctr.UUCP (Terrence W. Holm) (06/02/88)
> I am going through bits and pieces of news that I have saved looking for bug > reports. I'd appreciate some help with some of these. For example, some time > ago Peter Housel posted some fixes to library routines, including fseek.c, > scanf.c, getc.c. The corrected versions are included below. Could people > try testing these and letting me know if they are ok? Also,, he posted > replacements for rmu4.s and rmi4.s. Has anyone tested those? Thanks. > > Andy Tanenbaum (ast@cs.vu.nl) The posted getc(3) does not work for unbuffered files. I posted simple patches for rmu4.s and rmi4.s (see EFTH report #3). BTW, Bruce Evans' strncxx(3) routines look fine. Terrence W. Holm