[comp.os.minix] Request for help testing some routines

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