From owner-svn-src-head@freebsd.org Fri Apr 20 03:08:47 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 04711F9825A; Fri, 20 Apr 2018 03:08:47 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id ABF23856D8; Fri, 20 Apr 2018 03:08:46 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8CA5B12B54; Fri, 20 Apr 2018 03:08:46 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3K38khe014774; Fri, 20 Apr 2018 03:08:46 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3K38kih014773; Fri, 20 Apr 2018 03:08:46 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201804200308.w3K38kih014773@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Fri, 20 Apr 2018 03:08:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332805 - head/usr.bin/grep X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: head/usr.bin/grep X-SVN-Commit-Revision: 332805 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Apr 2018 03:08:47 -0000 Author: kevans Date: Fri Apr 20 03:08:46 2018 New Revision: 332805 URL: https://svnweb.freebsd.org/changeset/base/332805 Log: bsdgrep: Split match processing out of procfile procfile is getting kind of hairy, and it's not going to get better as we correct some more bits that assume we process one line at a time. Modified: head/usr.bin/grep/util.c Modified: head/usr.bin/grep/util.c ============================================================================== --- head/usr.bin/grep/util.c Fri Apr 20 01:25:48 2018 (r332804) +++ head/usr.bin/grep/util.c Fri Apr 20 03:08:46 2018 (r332805) @@ -72,6 +72,18 @@ struct parsec { bool binary; /* Binary file? */ }; +/* + * Match printing context + */ +struct mprintc { + long long tail; /* Number of trailing lines to record */ + int last_outed; /* Number of lines since last output */ + bool doctx; /* Printing context? */ + bool printmatch; /* Printing matches? */ + bool same_file; /* Same file as previously printed? */ +}; + +static bool procmatches(struct mprintc *mc, struct parsec *pc, bool matched); #ifdef WITH_INTERNAL_NOSPEC static int litexec(const struct pat *pat, const char *string, size_t nmatch, regmatch_t pmatch[]); @@ -197,6 +209,71 @@ grep_tree(char **argv) } /* + * Process any matches in the current parsing context, return a boolean + * indicating whether we should halt any further processing or not. 'true' to + * continue processing, 'false' to halt. + */ +static bool +procmatches(struct mprintc *mc, struct parsec *pc, bool matched) +{ + + /* Deal with any -B context or context separators */ + if (matched && mc->doctx) { + if (!first_match && (!mc->same_file || mc->last_outed > 0)) + printf("--\n"); + if (Bflag > 0) + printqueue(); + mc->tail = Aflag; + } + + /* Print the matching line, but only if not quiet/binary */ + if (matched && mc->printmatch) { + printline(pc, ':'); + while (pc->matchidx >= MAX_MATCHES) { + /* Reset matchidx and try again */ + pc->matchidx = 0; + if (procline(pc) == 0) + printline(pc, ':'); + else + break; + } + first_match = false; + mc->same_file = true; + mc->last_outed = 0; + } + + if (!matched && mc->doctx) { + /* Deal with any -A context */ + if (mc->tail > 0) { + grep_printline(&pc->ln, '-'); + mc->tail--; + if (Bflag > 0) + clearqueue(); + } else { + /* + * Enqueue non-matching lines for -B context. + * If we're not actually doing -B context or if + * the enqueue resulted in a line being rotated + * out, then go ahead and increment last_outed + * to signify a gap between context/match. + */ + if (Bflag == 0 || (Bflag > 0 && enqueue(&pc->ln))) + ++mc->last_outed; + } + } + + /* Count the matches if we have a match limit */ + if (matched && mflag) { + /* XXX TODO: Decrement by number of matched lines */ + mcount -= 1; + if (mflag && mcount <= 0) + return (false); + } + + return (true); +} + +/* * Opens a file and processes it. Each file is processed line-by-line * passing the lines to procline(). */ @@ -204,13 +281,11 @@ int procfile(const char *fn) { struct parsec pc; - long long tail; + struct mprintc mc; struct file *f; struct stat sb; - struct str *ln; mode_t s; - int c, last_outed, t; - bool doctx, printmatch, same_file; + int c, t; if (strcmp(fn, "-") == 0) { fn = label != NULL ? label : getstr(1); @@ -234,8 +309,6 @@ procfile(const char *fn) return (0); } - /* Convenience */ - ln = &pc.ln; pc.ln.file = grep_malloc(strlen(fn) + 1); strcpy(pc.ln.file, fn); pc.ln.line_no = 0; @@ -243,17 +316,13 @@ procfile(const char *fn) pc.ln.boff = 0; pc.ln.off = -1; pc.binary = f->binary; - pc.printed = 0; - tail = 0; - last_outed = 0; - same_file = false; - doctx = false; - printmatch = true; + memset(&mc, 0, sizeof(mc)); + mc.printmatch = true; if ((pc.binary && binbehave == BINFILE_BIN) || cflag || qflag || lflag || Lflag) - printmatch = false; - if (printmatch && (Aflag != 0 || Bflag != 0)) - doctx = true; + mc.printmatch = false; + if (mc.printmatch && (Aflag != 0 || Bflag != 0)) + mc.doctx = true; mcount = mlimit; for (c = 0; c == 0 || !(lflag || qflag); ) { @@ -282,56 +351,9 @@ procfile(const char *fn) if ((t = procline(&pc)) == 0) ++c; - /* Deal with any -B context or context separators */ - if (t == 0 && doctx) { - if (!first_match && (!same_file || last_outed > 0)) - printf("--\n"); - if (Bflag > 0) - printqueue(); - tail = Aflag; - } - /* Print the matching line, but only if not quiet/binary */ - if (t == 0 && printmatch) { - printline(&pc, ':'); - while (pc.matchidx >= MAX_MATCHES) { - /* Reset matchidx and try again */ - pc.matchidx = 0; - if (procline(&pc) == 0) - printline(&pc, ':'); - else - break; - } - first_match = false; - same_file = true; - last_outed = 0; - } - if (t != 0 && doctx) { - /* Deal with any -A context */ - if (tail > 0) { - grep_printline(&pc.ln, '-'); - tail--; - if (Bflag > 0) - clearqueue(); - } else { - /* - * Enqueue non-matching lines for -B context. - * If we're not actually doing -B context or if - * the enqueue resulted in a line being rotated - * out, then go ahead and increment last_outed - * to signify a gap between context/match. - */ - if (Bflag == 0 || (Bflag > 0 && enqueue(ln))) - ++last_outed; - } - } - - /* Count the matches if we have a match limit */ - if (t == 0 && mflag) { - --mcount; - if (mflag && mcount <= 0) - break; - } - + /* Halt processing if we hit our match limit */ + if (!procmatches(&mc, &pc, t == 0)) + break; } if (Bflag > 0) clearqueue();