325 lines · 5.8 KB · C
RawDownload
#define	EXTERN#include	"grep.h" char *validflags = "bchIiLlnsv";voidusage(void){	fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [file ...]\n", validflags);	exits("usage");} voidmain(int argc, char *argv[]){	int i, status; 	ARGBEGIN {	default:		if(utfrune(validflags, ARGC()) == nil)			usage();		flags[ARGC()]++;		break; 	case 'e':		flags['e']++;		lineno = 0;		str2top(EARGF(usage()));		break; 	case 'f':		flags['f']++;		filename = EARGF(usage());		rein = Bopen(filename, OREAD);		if(rein == 0) {			fprint(2, "grep: can't open %s: %r\n", filename);			exits("open");		}		lineno = 1;		str2top(filename);		break;	} ARGEND 	if(flags['f'] == 0 && flags['e'] == 0) {		if(argc <= 0)			usage();		str2top(argv[0]);		argc--;		argv++;	} 	follow = mal(maxfollow*sizeof(*follow));	state0 = initstate(topre.beg); 	Binit(&bout, 1, OWRITE);	switch(argc) {	case 0:		status = search(0, 0);		break;	case 1:		status = search(argv[0], 0);		break;	default:		status = 0;		for(i=0; i<argc; i++)			status |= search(argv[i], Hflag);		break;	}	if(status)		exits(0);	exits("no matches");} intsearch(char *file, int flag){	Rune r;	State *s, *ns;	int c, fid, eof, nl, empty;	long count, lineno, n;	uchar rem[10], *remp, *reme;	uchar *elp, *lp, *bol; 	if(file == 0) {		file = "stdin";		fid = 0;		flag |= Bflag;	} else		fid = open(file, OREAD); 	if(fid < 0) {		fprint(2, "grep: can't open %s: %r\n", file);		return 0;	} 	if(flags['b'])		flag ^= Bflag;		/* dont buffer output */	if(flags['c'])		flag |= Cflag;		/* count */	if(flags['h'])		flag &= ~Hflag;		/* do not print file name in output */	if(flags['i'])		flag |= Iflag;		/* fold upper-lower */	if(flags['I'])		flag |= IIflag;		/* fold runes to base rune */	if(flags['l'])		flag |= Llflag;		/* print only name of file if any match */	if(flags['L'])		flag |= LLflag;		/* print only name of file if any non match */	if(flags['n'])		flag |= Nflag;		/* count only */	if(flags['s'])		flag |= Sflag;		/* status only */	if(flags['v'])		flag |= Vflag;		/* inverse match */ 	s = state0;	lineno = 0;	count = 0;	eof = 0;	empty = 1;	nl = 0;	lp = u.buf;	bol = lp;	reme = remp = rem; loop0:	n = lp-bol;	if(n > sizeof(u.pre))		n = sizeof(u.pre);	memmove(u.buf-n, bol, n);	bol = u.buf-n;	n = read(fid, u.buf, sizeof(u.buf));	/* if file has no final newline, simulate one to emit matches to last line */	if(n > 0) {		empty = 0;		nl = u.buf[n-1]=='\n';	} else {		if(n < 0){			fprint(2, "grep: read error on %s: %r\n", file);			return count != 0;		}		if(!eof && !nl && !empty) {			u.buf[0] = '\n';			n = 1;			eof = 1;		}	}	if(n <= 0) {		close(fid);		if(flag & Cflag) {			if(flag & Hflag)				Bprint(&bout, "%s:", file);			Bprint(&bout, "%ld\n", count);		}		if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))			Bprint(&bout, "%s\n", file);		Bflush(&bout);		return count != 0;	}	lp = u.buf;	elp = lp+n;	if(flag & IIflag)		goto loopI;	if(flag & Iflag)		goto loopi; /* * normal character loop */loop:	c = *lp;	ns = s->next[c];	if(ns == 0) {		increment(s, c);		goto loop;	}//	if(flags['2'])//		if(s->match)//			print("%d: %.2x**\n", s, c);//		else//			print("%d: %.2x\n", s, c);	lp++;	s = ns;	if(c == '\n') {		lineno++;		if(!!s->match == !(flag&Vflag)) {			count++;			if(flag & (Cflag|Sflag|Llflag|LLflag))				goto cont;			if(flag & Hflag)				Bprint(&bout, "%s:", file);			if(flag & Nflag)				Bprint(&bout, "%ld: ", lineno);			/* suppress extra newline at EOF unless we are labeling matches with file name */			Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));			if(flag & Bflag)				Bflush(&bout);		}		if((lineno & Flshcnt) == 0)			Bflush(&bout);	cont:		bol = lp;	}	if(lp != elp)		goto loop;	goto loop0; /* * character loop for -i flag * for speed */loopi:	c = *lp;	if(c >= 'A' && c <= 'Z')		c += 'a'-'A';	ns = s->next[c];	if(ns == 0) {		increment(s, c);		goto loopi;	}	lp++;	s = ns;	if(c == '\n') {		lineno++;		if(!!s->match == !(flag&Vflag)) {			count++;			if(flag & (Cflag|Sflag|Llflag|LLflag))				goto conti;			if(flag & Hflag)				Bprint(&bout, "%s:", file);			if(flag & Nflag)				Bprint(&bout, "%ld: ", lineno);			/* suppress extra newline at EOF unless we are labeling matches with file name */			Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));			if(flag & Bflag)				Bflush(&bout);		}		if((lineno & Flshcnt) == 0)			Bflush(&bout);	conti:		bol = lp;	}	if(lp != elp)		goto loopi;	goto loop0; /* * character loop for -I flag * for speed */loopI:	if(remp != reme)		c = *remp++;	else{		c = *lp;		if(c > Runesync){			if(!fullrune((char*)lp, elp-lp) && !empty)				goto loop0;			lp += chartorune(&r, (char*)lp);			r = tobaserune(r);			if(flag & Iflag)				r = tolowerrune(r);			reme = rem + runetochar((char*)rem, &r);			*reme = 0;			remp = rem;			c = *remp++;		}else{			lp++;			if((flag & Iflag) && c >= 'A' && c <= 'Z')				c += 'a'-'A';		}	}loopI0:	ns = s->next[c];	if(ns == 0) {		increment(s, c);		goto loopI0;	}	s = ns;	if(c == '\n') {		lineno++;		if(!!s->match == !(flag&Vflag)) {			count++;			if(flag & (Cflag|Sflag|Llflag|LLflag))				goto contI;			if(flag & Hflag)				Bprint(&bout, "%s:", file);			if(flag & Nflag)				Bprint(&bout, "%ld: ", lineno);			/* suppress extra newline at EOF unless we are labeling matches with file name */			Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));			if(flag & Bflag)				Bflush(&bout);		}		if((lineno & Flshcnt) == 0)			Bflush(&bout);	contI:		bol = lp;	}	if(lp != elp)		goto loopI;	goto loop0; } State*initstate(Re *r){	State *s;	int i; 	addcase(r);	if(flags['1'])		reprint("r", r);	nfollow = 0;	gen++;	fol1(r, Cbegin);	follow[nfollow++] = r;	qsort(follow, nfollow, sizeof(*follow), fcmp); 	s = sal(nfollow);	for(i=0; i<nfollow; i++)		s->re[i] = follow[i];	return s;}