aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2019-04-28 09:57:05 +0200
committerFabian Groffen <grobian@gentoo.org>2019-04-28 09:57:05 +0200
commitc5aba3a0bd055688120dbabb9c3826ed46ffc795 (patch)
treed3cb8a6749eb8a9d63d2ea8ad901eee90ac91596 /qgrep.c
parentmain.h: include limits.h for Linux PATH_MAX (diff)
downloadportage-utils-c5aba3a0bd055688120dbabb9c3826ed46ffc795.tar.gz
portage-utils-c5aba3a0bd055688120dbabb9c3826ed46ffc795.tar.bz2
portage-utils-c5aba3a0bd055688120dbabb9c3826ed46ffc795.zip
qgrep: rewrite using libq/vdb and libq/cache
(re)use the traversion logic from libq instead of re-implementing this. Additional benefits are less code and usage of metadata when available. Signed-off-by: Fabian Groffen <grobian@gentoo.org>
Diffstat (limited to 'qgrep.c')
-rw-r--r--qgrep.c756
1 files changed, 410 insertions, 346 deletions
diff --git a/qgrep.c b/qgrep.c
index 16bb4c1..3950c22 100644
--- a/qgrep.c
+++ b/qgrep.c
@@ -64,35 +64,6 @@ static const char * const qgrep_opts_help[] = {
};
#define qgrep_usage(ret) usage(ret, QGREP_FLAGS, qgrep_long_opts, qgrep_opts_help, NULL, lookup_applet_idx("qgrep"))
-static char
-qgrep_name_match(const char* name, const int argc, depend_atom** argv)
-{
- depend_atom* atom;
- int i;
-
- if ((atom = atom_explode(name)) == NULL)
- return 0;
-
- for (i = 0; i < argc; i++) {
- if (argv[i] == NULL)
- continue;
- if (atom->CATEGORY && argv[i]->CATEGORY && *(argv[i]->CATEGORY)
- && strcmp(atom->CATEGORY, argv[i]->CATEGORY))
- continue;
- if (atom->PN && argv[i]->PN && *(argv[i]->PN)
- && strcmp(atom->PN, argv[i]->PN))
- continue;
- if (atom->PVR && argv[i]->PVR && *(argv[i]->PVR)
- && strcmp(atom->PVR, argv[i]->PVR))
- continue;
- atom_implode(atom);
- return 1;
- }
-
- atom_implode(atom);
- return 0;
-}
-
/* Circular list of line buffers for --before */
typedef struct qgrep_buf {
char valid;
@@ -221,91 +192,356 @@ qgrep_print_before_context(qgrep_buf_t *current, const char num_lines_before,
}
}
-/* Yield the path of one of the installed ebuilds (from VDB). */
-static char *
-get_next_installed_ebuild(
- char *ebuild_path,
- size_t ebuild_path_len,
- DIR *vdb_dir,
- struct dirent **cat_dirent_pt,
- DIR **cat_dir_pt)
+struct qgrep_grepargs {
+ bool do_count:1;
+ bool do_regex:1;
+ bool do_list:1;
+ bool show_filename:1;
+ bool show_name:1;
+ bool skip_comments:1;
+ bool invert_list:1;
+ bool invert_match:1;
+ char *skip_pattern;
+ char num_lines_before;
+ char num_lines_after;
+ qgrep_buf_t *buf_list;
+ regex_t skip_preg;
+ regex_t preg;
+ const char *query;
+ QGREP_STR_FUNC strfunc;
+ depend_atom **include_atoms;
+ const char *portdir;
+};
+
+static int
+qgrep_grepat(int fd, const char *file, const char *label,
+ struct qgrep_grepargs *a)
+{
+ FILE *newfp;
+ int need_separator = 0;
+ int count = 0;
+ int lineno = 0;
+ char remaining_after_context = 0;
+ char status = 1;
+ char *p;
+ bool per_file_output;
+
+ /* do we report results once per file or per line ? */
+ per_file_output =
+ a->do_count || (a->do_list && (!verbose || a->invert_list));
+
+ if (fd >= 0) {
+ int sfd = openat(fd, file, O_RDONLY|O_CLOEXEC);
+ newfp = sfd >= 0 ? fdopen(sfd, "r") : NULL;
+ } else {
+ newfp = fopen(file, "r");
+ }
+ if (newfp == NULL)
+ return status;
+
+ count = 0;
+ /* if there have been some matches already, then a
+ * separator will be needed */
+ need_separator =
+ !status && (a->num_lines_before || a->num_lines_after);
+ /* whatever is in the circular buffers list is no more a
+ * valid context */
+ qgrep_buf_list_invalidate(a->buf_list);
+
+ /* reading a new line always happen in the next buffer
+ * of the list */
+ while ((a->buf_list = a->buf_list->next) &&
+ fgets(a->buf_list->buf, sizeof(a->buf_list->buf), newfp))
+ {
+ lineno++;
+ a->buf_list->valid = 1;
+
+ /* cleanup EOL */
+ if ((p = strrchr(a->buf_list->buf, '\n')) != NULL)
+ *p = 0;
+ if ((p = strrchr(a->buf_list->buf, '\r')) != NULL)
+ *p = 0;
+
+ if (a->skip_comments) {
+ /* reject comments line ("^[ \t]*#") */
+ p = a->buf_list->buf;
+ while (*p == ' ' || *p == '\t') p++;
+ if (*p == '#')
+ goto print_after_context;
+ }
+
+ if (a->skip_pattern) {
+ /* reject some other lines which match an
+ * optional pattern */
+ if (!a->do_regex) {
+ if (a->strfunc(a->buf_list->buf, a->skip_pattern) != NULL)
+ goto print_after_context;
+ } else {
+ if (regexec(&a->skip_preg, a->buf_list->buf,
+ 0, NULL, 0) == 0)
+ goto print_after_context;
+ }
+ }
+
+ /* four ways to match a line (with/without inversion
+ * and regexp) */
+ if (!a->invert_match) {
+ if (a->do_regex == 0) {
+ if (a->strfunc(a->buf_list->buf, a->query) == NULL)
+ goto print_after_context;
+ } else {
+ if (regexec(&a->preg, a->buf_list->buf, 0, NULL, 0) != 0)
+ goto print_after_context;
+ }
+ } else {
+ if (a->do_regex == 0) {
+ if (a->strfunc(a->buf_list->buf, a->query) != NULL)
+ goto print_after_context;
+ } else {
+ if (regexec(&a->preg, a->buf_list->buf, 0, NULL, 0) == 0)
+ goto print_after_context;
+ }
+ }
+
+ count++;
+ status = 0; /* got a match, exit status should be 0 */
+ if (per_file_output)
+ continue;
+ /* matching files are listed out of this loop */
+
+ if ((need_separator > 0)
+ && (a->num_lines_before || a->num_lines_after))
+ printf("--\n");
+ /* "need_separator" is not a flag, but a counter, so that
+ * adjacent contextes are not separated */
+ need_separator = 0 - a->num_lines_before;
+ if (!a->do_list) {
+ /* print the leading context */
+ qgrep_print_before_context(a->buf_list,
+ a->num_lines_before, label,
+ ((verbose > 1) ? lineno : -1));
+ /* print matching line */
+ if (a->invert_match || *RED == '\0')
+ qgrep_print_matching_line_nocolor(a->buf_list, label,
+ ((verbose > 1) ? lineno : -1));
+ else if (a->do_regex)
+ qgrep_print_matching_line_regcolor(a->buf_list, label,
+ ((verbose > 1) ? lineno : -1), &a->preg);
+ else
+ qgrep_print_matching_line_strcolor(a->buf_list, label,
+ ((verbose > 1) ? lineno : -1), a->strfunc,
+ a->query);
+ } else {
+ /* in verbose do_list mode, list the file once
+ * per match */
+ printf("%s", label);
+ if (verbose > 1)
+ printf(":%d", lineno);
+ putchar('\n');
+ }
+ /* init count down of trailing context lines */
+ remaining_after_context = a->num_lines_after;
+ continue;
+
+print_after_context:
+ /* print some trailing context lines when needed */
+ if (!remaining_after_context) {
+ if (!status)
+ /* we're getting closer to the need of a
+ * separator between current match block and
+ * the next one */
+ ++need_separator;
+ } else {
+ qgrep_print_context_line(a->buf_list, label,
+ ((verbose > 1) ? lineno : -1));
+ --remaining_after_context;
+ }
+ }
+ fclose(newfp);
+ if (per_file_output) {
+ /* matches were already displayed, line per line */
+ if (a->do_count && count) {
+ if (label != NULL)
+ /* -c without -v/-N/-H only outputs
+ * the matches count of the file */
+ printf("%s:", label);
+ printf("%d\n", count);
+ } else if ((count && !a->invert_list) ||
+ (!count && a->invert_list))
+ {
+ printf("%s\n", label);
+ }
+ /* do_list == 1, or we wouldn't be here */
+ }
+
+ return status;
+}
+
+static int
+qgrep_cache_cb(cache_pkg_ctx *pkg_ctx, void *priv)
+{
+ struct qgrep_grepargs *data = (struct qgrep_grepargs *)priv;
+ char buf[_Q_PATH_MAX];
+ char name[_Q_PATH_MAX];
+ char *label;
+ depend_atom *patom = NULL;
+ cache_ctx *cctx;
+ int ret;
+ int pfd;
+
+ snprintf(buf, sizeof(buf), "%s/%s",
+ pkg_ctx->cat_ctx->name, pkg_ctx->name);
+ patom = atom_explode(buf);
+ if (patom == NULL)
+ return EXIT_FAILURE;
+
+ if (data->include_atoms != NULL) {
+ depend_atom **d;
+ for (d = data->include_atoms; *d != NULL; d++) {
+ if (atom_compare(patom, *d) == EQUAL)
+ break;
+ }
+ if (*d == NULL) {
+ atom_implode(patom);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* need to construct path in portdir to ebuild, pass it to grep */
+ cctx = (cache_ctx *)(pkg_ctx->cat_ctx->ctx);
+ if (cctx->cachetype == CACHE_EBUILD) {
+ pfd = cctx->dir_ctx->vdb_fd;
+ } else {
+ pfd = openat(cctx->dir_ctx->vdb_fd, "../..", O_RDONLY|O_CLOEXEC);
+ }
+
+ /* cat/pkg/pkg-ver.ebuild */
+ snprintf(buf, sizeof(buf), "%s/%s/%s.ebuild",
+ patom->CATEGORY, patom->PN, patom->P);
+
+ label = NULL;
+ if (data->show_name) {
+ snprintf(name, sizeof(name), "%s/%s", patom->CATEGORY, patom->P);
+ label = name;
+ } else if (data->show_filename) {
+ label = buf;
+ }
+
+ ret = qgrep_grepat(pfd, buf, label, data);
+
+ atom_implode(patom);
+
+ return ret;
+}
+
+static int
+qgrep_vdb_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
{
- struct dirent *pkg_dirent = NULL;
- if (*cat_dirent_pt == NULL || *cat_dir_pt == NULL)
- goto get_next_category;
-get_next_ebuild_from_category:
- if ((pkg_dirent = readdir(*cat_dir_pt)) == NULL)
- goto get_next_category;
- if (pkg_dirent->d_name[0] == '.')
- goto get_next_ebuild_from_category;
- snprintf(ebuild_path, ebuild_path_len, "%s/%s/%s.ebuild",
- (*cat_dirent_pt)->d_name, pkg_dirent->d_name, pkg_dirent->d_name);
- return ebuild_path;
-get_next_category:
- if (*cat_dir_pt != NULL)
- closedir(*cat_dir_pt);
- *cat_dirent_pt = q_vdb_get_next_dir(vdb_dir);
- if (*cat_dirent_pt == NULL)
- return NULL;
- if ((*cat_dir_pt = opendir((*cat_dirent_pt)->d_name)) == NULL)
- goto get_next_category;
- goto get_next_ebuild_from_category;
+ struct qgrep_grepargs *data = (struct qgrep_grepargs *)priv;
+ char buf[_Q_PATH_MAX];
+ char name[_Q_PATH_MAX];
+ char *label;
+ depend_atom *patom = NULL;
+ int ret;
+ int pfd;
+
+ snprintf(buf, sizeof(buf), "%s/%s",
+ pkg_ctx->cat_ctx->name, pkg_ctx->name);
+ patom = atom_explode(buf);
+ if (patom == NULL)
+ return EXIT_FAILURE;
+
+ if (data->include_atoms != NULL) {
+ depend_atom **d;
+ for (d = data->include_atoms; *d != NULL; d++) {
+ if (atom_compare(patom, *d) == EQUAL)
+ break;
+ }
+ if (*d == NULL) {
+ atom_implode(patom);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* get path to portdir */
+ pfd = openat(pkg_ctx->cat_ctx->ctx->portroot_fd,
+ data->portdir, O_RDONLY|O_CLOEXEC);
+
+ /* cat/pkg/pkg-ver.ebuild */
+ snprintf(buf, sizeof(buf), "%s/%s/%s.ebuild",
+ patom->CATEGORY, patom->PN, patom->P);
+
+ label = NULL;
+ if (data->show_name) {
+ snprintf(name, sizeof(name), "%s/%s", patom->CATEGORY, patom->P);
+ label = name;
+ } else if (data->show_filename) {
+ label = buf;
+ }
+
+ ret = qgrep_grepat(pfd, buf, label, data);
+
+ atom_implode(patom);
+
+ return ret;
}
int qgrep_main(int argc, char **argv)
{
int i;
- int count = 0;
char *p;
- char do_count, do_regex, do_eclass, do_installed, do_list;
- char show_filename, skip_comments, invert_list, show_name;
- char per_file_output;
- FILE *fp = NULL;
+ bool do_eclass;
+ bool do_installed;
DIR *eclass_dir = NULL;
- DIR *vdb_dir = NULL;
- DIR *cat_dir = NULL;
struct dirent *dentry = NULL;
- char ebuild[_Q_PATH_MAX * 4];
- char name[_Q_PATH_MAX * 2];
- char *label;
int reflags = 0;
- char invert_match = 0;
- regex_t preg, skip_preg;
- char *skip_pattern = NULL;
- depend_atom** include_atoms = NULL;
unsigned long int context_optarg;
- char num_lines_before = 0;
- char num_lines_after = 0;
- qgrep_buf_t *buf_list;
- int need_separator = 0;
char status = 1;
+ size_t n;
+ char *overlay;
- QGREP_STR_FUNC strfunc = strstr;
-
- do_count = do_regex = do_eclass = do_installed = do_list = 0;
- show_filename = skip_comments = invert_list = show_name = 0;
+ struct qgrep_grepargs args = {
+ .do_count = 0,
+ .do_regex = 0,
+ .do_list = 0,
+ .show_filename = 0,
+ .show_name = 0,
+ .skip_comments = 0,
+ .invert_list = 0,
+ .invert_match = 0,
+ .skip_pattern = NULL,
+ .num_lines_before = 0,
+ .num_lines_after = 0,
+ .buf_list = NULL,
+ .query = NULL,
+ .strfunc = strstr,
+ .include_atoms = NULL,
+ .portdir = NULL,
+ };
+
+ do_eclass = do_installed = 0;
while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) {
switch (i) {
- case 'I': invert_match = 1; break;
+ case 'I': args.invert_match = 1; break;
case 'i':
- strfunc = strcasestr;
+ args.strfunc = strcasestr;
reflags |= REG_ICASE;
break;
- case 'c': do_count = 1; break;
- case 'l': do_list = 1; break;
- case 'L': do_list = invert_list = 1; break;
- case 'e': do_regex = 1; break;
+ case 'c': args.do_count = 1; break;
+ case 'l': args.do_list = 1; break;
+ case 'L': args.do_list = args.invert_list = 1; break;
+ case 'e': args.do_regex = 1; break;
case 'x':
- do_regex = 1;
+ args.do_regex = 1;
reflags |= REG_EXTENDED;
break;
case 'J': do_installed = 1; break;
case 'E': do_eclass = 1; break;
- case 'H': show_filename = 1; break;
- case 'N': show_name = 1; break;
- case 's': skip_comments = 1; break;
- case 'S': skip_pattern = optarg; break;
+ case 'H': args.show_filename = 1; break;
+ case 'N': args.show_name = 1; break;
+ case 's': args.skip_comments = 1; break;
+ case 'S': args.skip_pattern = optarg; break;
case 'B':
case 'A':
errno = 0;
@@ -317,9 +553,9 @@ int qgrep_main(int argc, char **argv)
if (context_optarg > 254)
err("%s: silly value!", optarg);
if (i == 'B')
- num_lines_before = context_optarg;
+ args.num_lines_before = context_optarg;
else
- num_lines_after = context_optarg;
+ args.num_lines_after = context_optarg;
break;
COMMON_GETOPTS_CASES(qgrep)
}
@@ -327,312 +563,140 @@ int qgrep_main(int argc, char **argv)
if (argc == optind)
qgrep_usage(EXIT_FAILURE);
- if (do_list && do_count) {
+ if (args.do_list && args.do_count) {
warn("%s and --count are incompatible options. The former wins.",
- (invert_list ? "--invert-list" : "--list"));
- do_count = 0;
+ (args.invert_list ? "--invert-list" : "--list"));
+ args.do_count = false;
}
- if (show_name && show_filename) {
+ if (args.show_name && args.show_filename) {
warn("--with-name and --with-filename are incompatible options. "
"The former wins.");
- show_filename = 0;
+ args.show_filename = false;
}
- if (do_list && num_lines_before) {
+ if (args.do_list && args.num_lines_before) {
warn("%s and --before are incompatible options. The former wins.",
- (invert_list ? "--invert-list" : "--list"));
- num_lines_before = 0;
+ (args.invert_list ? "--invert-list" : "--list"));
+ args.num_lines_before = 0;
}
- if (do_list && num_lines_after) {
+ if (args.do_list && args.num_lines_after) {
warn("%s and --after are incompatible options. The former wins.",
- (invert_list ? "--invert-list" : "--list"));
- num_lines_after = 0;
+ (args.invert_list ? "--invert-list" : "--list"));
+ args.num_lines_after = 0;
}
- if (do_count && num_lines_before) {
+ if (args.do_count && args.num_lines_before) {
warn("--count and --before are incompatible options. The former wins.");
- num_lines_before = 0;
+ args.num_lines_before = 0;
}
- if (do_count && num_lines_after) {
+ if (args.do_count && args.num_lines_after) {
warn("--count and --after are incompatible options. The former wins.");
- num_lines_after = 0;
+ args.num_lines_after = 0;
}
if (do_installed && do_eclass) {
warn("--installed and --eclass are incompatible options. "
"The former wins.");
- do_eclass = 0;
+ do_eclass = false;
}
- /* do we report results once per file or per line ? */
- per_file_output = do_count || (do_list && (!verbose || invert_list));
- /* label for prefixing matching lines or listing matching files */
- label = (show_name ? name :
- ((verbose || show_filename || do_list) ? ebuild : NULL));
-
if (argc > (optind + 1)) {
- include_atoms = xcalloc(sizeof(depend_atom*), (argc - optind - 1));
- for (i = (optind + 1); i < argc; i++)
- if ((include_atoms[i - optind - 1] = atom_explode(argv[i])) == NULL)
+ depend_atom **d = args.include_atoms =
+ xcalloc(sizeof(depend_atom *), (argc - optind - 1) + 1);
+ for (i = (optind + 1); i < argc; i++) {
+ *d = atom_explode(argv[i]);
+ if (*d == NULL) {
warn("%s: invalid atom, will be ignored", argv[i]);
+ } else {
+ d++;
+ }
+ }
+ *d = NULL;
}
+ /* make it easier to see what needs to be printed */
+ if (!args.show_name && (verbose || args.do_list))
+ args.show_filename = true;
+
/* pre-compile regexps once for all */
- if (do_regex) {
- if (invert_match || *RED == '\0')
+ if (args.do_regex) {
+ if (args.invert_match || *RED == '\0')
reflags |= REG_NOSUB;
- xregcomp(&preg, argv[optind], reflags);
+ xregcomp(&args.preg, argv[optind], reflags);
reflags |= REG_NOSUB;
- if (skip_pattern)
- xregcomp(&skip_preg, skip_pattern, reflags);
+ if (args.skip_pattern)
+ xregcomp(&args.skip_preg, args.skip_pattern, reflags);
}
+ args.query = argv[optind];
/* allocate a circular buffers list for --before */
- buf_list = qgrep_buf_list_alloc(num_lines_before + 1);
+ args.buf_list = qgrep_buf_list_alloc(args.num_lines_before + 1);
- size_t n;
- char *overlay;
array_for_each(overlays, n, overlay) {
+ args.portdir = overlay;
+ if (do_eclass) {
+ char buf[_Q_PATH_MAX];
+ char name[_Q_PATH_MAX];
+ char *label;
+ int efd;
- /* go look either in ebuilds or eclasses or VDB */
- /* FIXME: use libq/vdb and libq/cache here */
- if (!do_eclass && !do_installed) {
- /* TODO: use libq/cache here */ continue;
- } else if (do_eclass) {
- xchdir(overlay);
- if ((eclass_dir = opendir("eclass")) == NULL) {
+ snprintf(buf, sizeof(buf), "%s/%s/eclass", portroot, overlay);
+ efd = open(buf, O_RDONLY|O_CLOEXEC);
+ if (efd == -1 || (eclass_dir = fdopendir(efd)) == NULL) {
if (errno != ENOENT)
warnp("opendir(\"%s/eclass\") failed", overlay);
continue;
}
- } else { /* if (do_install) */
- /* TODO: use libq/vdb here */
- char buf[_Q_PATH_MAX];
- snprintf(buf, sizeof(buf), "%s/%s", portroot, portvdb);
- xchdir(buf);
- if ((vdb_dir = opendir(".")) == NULL)
- errp("could not opendir(%s/%s) for ROOT/VDB",
- portroot, portvdb);
- }
-
- /* iteration is either over ebuilds or eclasses */
- while (do_eclass
- ? ((dentry = readdir(eclass_dir))
- && snprintf(ebuild, sizeof(ebuild),
- "eclass/%s", dentry->d_name))
- : (do_installed
- ? (get_next_installed_ebuild(ebuild, sizeof(ebuild),
- vdb_dir, &dentry, &cat_dir) != NULL)
- : (fgets(ebuild, sizeof(ebuild), fp) != NULL)))
- {
- FILE *newfp;
-
- /* filter badly named files, prepare eclass or package name, etc. */
- if (do_eclass) {
- if ((p = strrchr(ebuild, '.')) == NULL)
- continue;
- if (strcmp(p, ".eclass"))
+ while ((dentry = readdir(eclass_dir)) != NULL) {
+ if (strstr(dentry->d_name, ".eclass") == NULL)
continue;
- if (show_name || (include_atoms != NULL)) {
- /* cut ".eclass" */
- *p = '\0';
- /* and skip "eclass/" */
- snprintf(name, sizeof(name), "%s", ebuild + 7);
- /* restore the filepath */
- *p = '.';
- }
- } else {
- if ((p = strchr(ebuild, '\n')) != NULL)
- *p = '\0';
- if (show_name || (include_atoms != NULL)) {
- size_t l;
- /* cut ".ebuild" */
- if (p == NULL)
- p = ebuild + strlen(ebuild);
- *(p-7) = '\0';
- /* cut "/foo/" from "cat/foo/foo-x.y" */
- if ((p = strchr(ebuild, '/')) == NULL)
- continue;
- *(p++) = '\0';
- /* find head of the ebuild basename */
- if ((p = strchr(p, '/')) == NULL)
- continue;
- /* find start of the pkg name, break up in two to
- * avoid warning about possible truncation (very
- * unlikely) */
- l = snprintf(name, sizeof(name), "%s", ebuild);
- snprintf(name + l, sizeof(name) - l, "%s", p);
- /* restore the filepath */
- *p = '/';
- *(p + strlen(p)) = '.';
- ebuild[strlen(ebuild)] = '/';
- }
- }
-
- /* filter the files we grep when there are extra args */
- if (include_atoms != NULL)
- if (!qgrep_name_match(name, (argc - optind - 1), include_atoms))
- continue;
-
- if ((newfp = fopen(ebuild, "r")) != NULL) {
- int lineno = 0;
- char remaining_after_context = 0;
- count = 0;
- /* if there have been some matches already, then a
- * separator will be needed */
- need_separator =
- !status && (num_lines_before || num_lines_after);
- /* whatever is in the circular buffers list is no more a
- * valid context */
- qgrep_buf_list_invalidate(buf_list);
-
- /* reading a new line always happen in the next buffer
- * of the list */
- while ((buf_list = buf_list->next) &&
- fgets(buf_list->buf, sizeof(buf_list->buf), newfp))
- {
- lineno++;
- buf_list->valid = 1;
-
- /* cleanup EOL */
- if ((p = strrchr(buf_list->buf, '\n')) != NULL)
- *p = 0;
- if ((p = strrchr(buf_list->buf, '\r')) != NULL)
- *p = 0;
-
- if (skip_comments) {
- /* reject comments line ("^[ \t]*#") */
- p = buf_list->buf;
- while (*p == ' ' || *p == '\t') p++;
- if (*p == '#')
- goto print_after_context;
+ /* filter the files we grep when there are extra args */
+ if (args.include_atoms != NULL) {
+ depend_atom **d;
+ for (d = args.include_atoms; *d != NULL; d++) {
+ if ((*d)->PN != NULL && strncmp(dentry->d_name,
+ (*d)->PN, strlen((*d)->PN)) == 0)
+ break;
}
-
- if (skip_pattern) {
- /* reject some other lines which match an
- * optional pattern */
- if (!do_regex) {
- if (strfunc(buf_list->buf, skip_pattern) != NULL)
- goto print_after_context;
- } else {
- if (regexec(&skip_preg, buf_list->buf,
- 0, NULL, 0) == 0)
- goto print_after_context;
- }
- }
-
- /* four ways to match a line (with/without inversion
- * and regexp) */
- if (!invert_match) {
- if (do_regex == 0) {
- if (strfunc(buf_list->buf, argv[optind]) == NULL)
- goto print_after_context;
- } else {
- if (regexec(&preg, buf_list->buf, 0, NULL, 0) != 0)
- goto print_after_context;
- }
- } else {
- if (do_regex == 0) {
- if (strfunc(buf_list->buf, argv[optind]) != NULL)
- goto print_after_context;
- } else {
- if (regexec(&preg, buf_list->buf, 0, NULL, 0) == 0)
- goto print_after_context;
- }
- }
-
- count++;
- status = 0; /* got a match, exit status should be 0 */
- if (per_file_output)
+ if (*d == NULL)
continue;
- /* matching files are listed out of this loop */
-
- if ((need_separator > 0)
- && (num_lines_before || num_lines_after))
- printf("--\n");
- /* "need_separator" is not a flag, but a counter, so that
- * adjacent contextes are not separated */
- need_separator = 0 - num_lines_before;
- if (!do_list) {
- /* print the leading context */
- qgrep_print_before_context(buf_list,
- num_lines_before, label,
- ((verbose > 1) ? lineno : -1));
- /* print matching line */
- if (invert_match || *RED == '\0')
- qgrep_print_matching_line_nocolor(buf_list, label,
- ((verbose > 1) ? lineno : -1));
- else if (do_regex)
- qgrep_print_matching_line_regcolor(buf_list, label,
- ((verbose > 1) ? lineno : -1), &preg);
- else
- qgrep_print_matching_line_strcolor(buf_list, label,
- ((verbose > 1) ? lineno : -1), strfunc,
- argv[optind]);
- } else {
- /* in verbose do_list mode, list the file once
- * per match */
- printf("%s", label);
- if (verbose > 1)
- printf(":%d", lineno);
- putchar('\n');
- }
- /* init count down of trailing context lines */
- remaining_after_context = num_lines_after;
- continue;
+ }
- print_after_context:
- /* print some trailing context lines when needed */
- if (!remaining_after_context) {
- if (!status)
- /* we're getting closer to the need of a
- * separator between current match block and
- * the next one */
- ++need_separator;
- } else {
- qgrep_print_context_line(buf_list, label,
- ((verbose > 1) ? lineno : -1));
- --remaining_after_context;
- }
+ label = NULL;
+ if (args.show_name) {
+ snprintf(name, sizeof(name), "%.*s",
+ (int)(strlen(dentry->d_name) - 7), dentry->d_name);
+ label = name;
+ } else if (args.show_filename) {
+ snprintf(name, sizeof(name), "eclass/%s", dentry->d_name);
+ label = name;
}
- fclose(newfp);
- if (!per_file_output)
- continue;
- /* matches were already displayed, line per line */
- if (do_count && count) {
- if (label != NULL)
- /* -c without -v/-N/-H only outputs
- * the matches count of the file */
- printf("%s:", label);
- printf("%d\n", count);
- } else if ((count && !invert_list) || (!count && invert_list))
- printf("%s\n", label);
- /* do_list == 1, or we wouldn't be here */
+ status = qgrep_grepat(efd, dentry->d_name, label, &args);
}
- }
- if (do_eclass)
closedir(eclass_dir);
- else if (!do_installed)
- fclose(fp);
-
- if (do_installed)
- break;
+ } else if (do_installed) {
+ status = q_vdb_foreach_pkg(portroot, portvdb,
+ qgrep_vdb_cb, &args, NULL);
+ } else { /* do_ebuild */
+ status = cache_foreach_pkg(portroot, overlay,
+ qgrep_cache_cb, &args, NULL);
+ }
}
- if (do_regex)
- regfree(&preg);
- if (do_regex && skip_pattern)
- regfree(&skip_preg);
- if (include_atoms != NULL) {
+ if (args.do_regex)
+ regfree(&args.preg);
+ if (args.do_regex && args.skip_pattern)
+ regfree(&args.skip_preg);
+ if (args.include_atoms != NULL) {
for (i = 0; i < (argc - optind - 1); i++)
- if (include_atoms[i] != NULL)
- atom_implode(include_atoms[i]);
- free(include_atoms);
+ if (args.include_atoms[i] != NULL)
+ atom_implode(args.include_atoms[i]);
+ free(args.include_atoms);
}
- qgrep_buf_list_free(buf_list);
+ qgrep_buf_list_free(args.buf_list);
return status;
}