[comp.bugs.sys5] fgrep bug

rogerc@ncrcae.Columbia.NCR.COM (Roger Collins) (11/04/87)

Execute this command:

echo abcd | fgrep 'abcx
by
cd'

This should output "abcd" because of the match on "cd", however, no patern 
is found.

Anyone have a fix?

	-Roger Collins
	...!ncrcae!rogerc

guy@gorodish.Sun.COM (Guy Harris) (11/06/87)

> Anyone have a fix?

Yes.  Also:

	A significant speedup - don't do case-mapping in a subroutine, do it
	in-line (yes, I know, there are lots of faster scanner programs, don't
	waste people's time asking "why bother fixing 'fgrep'");

	Don't allow more than one "-f" option;

	Print slightly better error messages;

	Check for errors when reading files;

	Fix a bug where "%d" was used to print a "long";

	Drop in a bug fix that came from an addendum to V7, put out by AT&T,
	but that never appeared in a USG release.

*** /arch/s5r2/usr/src/cmd/fgrep.c	Mon Jul 25 14:23:18 1983
--- ./fgrep.c	Fri Nov  6 00:34:04 1987
***************
*** 9,14 ****
--- 9,15 ----
   */
  
  #include <stdio.h>
+ #include <ctype.h>
  
  #define	MAXSIZ 6000
  #define QSIZE 400
***************
*** 30,38 ****
--- 31,41 ----
  int	nsucc;
  long	tln;
  FILE	*wordf;
+ char	*wordfname;
  char	*argptr;
  extern	char *optarg;
  extern	int optind;
+ void exit();
  
  main(argc, argv)
  char **argv;
***************
*** 63,74 ****
  			continue;
  
  		case 'f':
! 			fflag++;
! 			wordf = fopen(optarg, "r");
! 			if (wordf==NULL) {
! 				fprintf(stderr, "fgrep: can't open %s\n", optarg);
  				exit(2);
  			}
  			continue;
  
  		case 'l':
--- 66,77 ----
  			continue;
  
  		case 'f':
! 			if (fflag) {
! 				fprintf(stderr, "fgrep: Only one \"-f\" option allowed\n");
  				exit(2);
  			}
+ 			fflag++;
+ 			wordfname = optarg;
  			continue;
  
  		case 'l':
***************
*** 92,106 ****
  	}
  
  	argc -= optind;
! 	if (errflg || ((argc <= 0) && !fflag)) {
  		printf("usage: fgrep %s\n",usage);
  		exit(2);
  	}
! 	if ( !eflag  && !fflag ) {
! 		argptr = argv[optind];
! 		optind++;
! 		argc--;
  	}
  	cgotofn();
  	cfail();
  	nfile = argc;
--- 95,119 ----
  	}
  
  	argc -= optind;
! 	if (errflg || ((argc <= 0) && !fflag && !eflag)) {
  		printf("usage: fgrep %s\n",usage);
  		exit(2);
  	}
! 	if (fflag) {
! 		wordf = fopen(wordfname, "r");
! 		if (wordf==NULL) {
! 			fprintf(stderr, "fgrep: ");
! 			perror(wordfname);
! 			exit(2);
! 		}
! 	} else {
! 		if (!eflag) {
! 			argptr = argv[optind];
! 			optind++;
! 			argc--;
! 		}
  	}
+ 
  	cgotofn();
  	cfail();
  	nfile = argc;
***************
*** 117,122 ****
--- 130,137 ----
  	exit(retcode != 0 ? retcode : nsucc == 0);
  }
  
+ # define ccomp(a,b) (iflag ? lca(a)==lca(b) : a==b)
+ # define lca(x) (isupper(x) ? _tolower(x) : x)
  execute(file)
  char *file;
  {
***************
*** 128,134 ****
  	char *nlp;
  	if (file) {
  		if ((fptr = fopen(file, "r")) == NULL) {
! 			fprintf(stderr, "fgrep: can't open %s\n", file);
  			retcode = 2;
  			return;
  		}
--- 143,150 ----
  	char *nlp;
  	if (file) {
  		if ((fptr = fopen(file, "r")) == NULL) {
! 			fprintf(stderr, "fgrep: ");
! 			perror(file);
  			retcode = 2;
  			return;
  		}
***************
*** 153,159 ****
  			blkno += ccount;
  		}
  		nstate:
! 			if (same(c->inp,*p)) {
  				c = c->nst;
  			}
  			else if (c->link != 0) {
--- 169,175 ----
  			blkno += ccount;
  		}
  		nstate:
! 			if (ccomp(c->inp,*p)) {
  				c = c->nst;
  			}
  			else if (c->link != 0) {
***************
*** 166,172 ****
  				if (c==0) {
  					c = w;
  					istate:
! 					if (same(c->inp,*p)) {
  						c = c->nst;
  					}
  					else if (c->link != 0) {
--- 182,188 ----
  				if (c==0) {
  					c = w;
  					istate:
! 					if (ccomp(c->inp,*p)) {
  						c = c->nst;
  					}
  					else if (c->link != 0) {
***************
*** 187,192 ****
--- 203,210 ----
  					blkno += ccount;
  				   }
  			}
+ 			if (ccount < 0)
+ 				goto done;
  			if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
  				goto nomatch;
  	succeed:	nsucc = 1;
***************
*** 198,204 ****
  			}
  			else {
  				if (nfile > 1) printf("%s:", file);
! 				if (bflag) printf("%d:", (blkno-ccount-1)/BUFSIZ);
  				if (nflag) printf("%ld:", lnum);
  				if (p <= nlp) {
  					while (nlp < &buf[2*BUFSIZ]) putchar(*nlp++);
--- 216,222 ----
  			}
  			else {
  				if (nfile > 1) printf("%s:", file);
! 				if (bflag) printf("%ld:", (blkno-ccount-1)/BUFSIZ);
  				if (nflag) printf("%ld:", lnum);
  				if (p <= nlp) {
  					while (nlp < &buf[2*BUFSIZ]) putchar(*nlp++);
***************
*** 221,226 ****
--- 239,252 ----
  				failed = 0;
  			}
  	}
+ done:
+ 	if (ccount < 0) {
+ 		fprintf(stderr, "fgrep: Read error on ");
+ 		perror(file ? file : "standard input");
+ 		retcode = 2;
+ 		fclose(fptr);
+ 		return;
+ 	}
  	fclose(fptr);
  	if (cflag) {
  		if (nfile > 1)
***************
*** 232,241 ****
  getargc()
  {
  	register c;
! 	if (wordf)
! 		return(getc(wordf));
! 	if ((c = *argptr++) == '\0')
! 		return(EOF);
  	return(c);
  }
  
--- 258,277 ----
  getargc()
  {
  	register c;
! 	if (wordf) {
! 		c = getc(wordf);
! 		if (c == EOF) {
! 			if (ferror(wordf)) {
! 				fprintf(stderr, "fgrep: Read error on ");
! 				perror(wordfname);
! 				exit(1);
! 			}
! 			fclose(wordf);
! 		}
! 	} else {
! 		if ((c = *argptr++) == '\0')
! 			return(EOF);
! 	}
  	return(c);
  }
  
***************
*** 303,309 ****
  }
  
  overflo() {
! 	fprintf(stderr, "wordlist too large\n");
  	exit(2);
  }
  cfail() {
--- 339,345 ----
  }
  
  overflo() {
! 	fprintf(stderr, "fgrep: wordlist too large\n");
  	exit(2);
  }
  cfail() {
***************
*** 310,315 ****
--- 346,352 ----
  	struct words *queue[QSIZE];
  	struct words **front, **rear;
  	struct words *state;
+ 	int bstart;
  	register char c;
  	register struct words *s;
  	s = w;
***************
*** 328,333 ****
--- 365,371 ----
  			front = queue;
  		else front++;
  	cloop:	if ((c = s->inp) != 0) {
+ 			bstart = 0;
  			*rear = (q = s->nst);
  			if (front < rear)
  				if (rear >= &queue[QSIZE-1])
***************
*** 337,343 ****
  			else
  				if (++rear == front) overflo();
  			state = s->fail;
! 		floop:	if (state == 0) state = w;
  			if (state->inp == c) {
  			qloop:	q->fail = state->nst;
  				if ((state->nst)->out == 1) q->out = 1;
--- 375,384 ----
  			else
  				if (++rear == front) overflo();
  			state = s->fail;
! 		floop:	if (state == 0) {
! 				state = w;
! 				bstart = 1;
! 			}
  			if (state->inp == c) {
  			qloop:	q->fail = state->nst;
  				if ((state->nst)->out == 1) q->out = 1;
***************
*** 345,370 ****
  			}
  			else if ((state = state->link) != 0)
  				goto floop;
  		}
  		if ((s = s->link) != 0)
  			goto cloop;
  	}
- }
- 
- /* The following functions were inserted to allow for the "-i" option */
- 
- same(a, b)
- register int a, b;
- {
- 	return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
- }
- 
- letter(c)
- register int c;
- {
- 	if (c >= 'a' && c <= 'z')
- 		return (c);
- 	if (c >= 'A' && c <= 'z')
- 		return (c + 'a' - 'A');
- 	return(0);
  }
--- 386,397 ----
  			}
  			else if ((state = state->link) != 0)
  				goto floop;
+ 			else if(bstart == 0){
+ 				state = 0;
+ 				goto floop;
+ 			}
  		}
  		if ((s = s->link) != 0)
  			goto cloop;
  	}
  }
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/08/87)

In article <2715@ncrcae.Columbia.NCR.COM> rogerc@ncrcae.UUCP (Roger Collins) writes:
>echo abcd | fgrep 'abcx
>by
>cd'

PLEASE be more specific about the version of software you're having
trouble with.  This test is passed by my version of SVR2 fgrep, which
includes Geoff Whale's bug fixes.