aboutsummaryrefslogtreecommitdiff
path: root/bp.c
diff options
context:
space:
mode:
Diffstat (limited to 'bp.c')
-rw-r--r--bp.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/bp.c b/bp.c
index b700c1c..3acafe4 100644
--- a/bp.c
+++ b/bp.c
@@ -180,7 +180,7 @@ static int is_text_file(const char *filename)
static int print_matches_as_json(def_t *defs, file_t *f, pat_t *pattern)
{
int nmatches = 0;
- for (match_t *m = NULL; next_match(&m, defs, f, pattern, options.skip, options.ignorecase); ) {
+ for (match_t *m = NULL; next_match(&m, defs, f->start, f->end, pattern, options.skip, options.ignorecase); ) {
if (++nmatches > 1)
printf(",\n");
printf("{\"filename\":\"%s\",\"match\":", f->filename);
@@ -196,7 +196,7 @@ static int print_matches_as_json(def_t *defs, file_t *f, pat_t *pattern)
static int explain_matches(def_t *defs, file_t *f, pat_t *pattern)
{
int nmatches = 0;
- for (match_t *m = NULL; next_match(&m, defs, f, pattern, options.skip, options.ignorecase); ) {
+ for (match_t *m = NULL; next_match(&m, defs, f->start, f->end, pattern, options.skip, options.ignorecase); ) {
if (++nmatches == 1) {
if (options.print_filenames)
fprint_filename(stdout, f->filename);
@@ -234,6 +234,36 @@ static void sig_handler(int sig)
if (kill(0, sig)) _exit(EXIT_FAILURE);
}
+void fprint_between(FILE *out, file_t *f, const char *prev, const char *next)
+{
+ // if (options.context_before == NO_CONTEXT && options.context_after == NO_CONTEXT)
+ // return;
+ if (options.context_before == ALL_CONTEXT || options.context_after == ALL_CONTEXT) {
+ fwrite(prev ? prev : f->start, sizeof(char), (size_t)((next ? next : f->end) - (prev ? prev : f->start)), out);
+ return;
+ }
+ const char *after_prev = prev, *before_next = next;
+ if (prev && options.context_after >= 0) {
+ size_t after_prev_line = get_line_number(f, prev) + (size_t)options.context_after + 1;
+ after_prev = get_line(f, after_prev_line > f->nlines ? f->nlines : after_prev_line);
+ }
+ if (next && options.context_before >= 0) {
+ size_t before_next_line = get_line_number(f, next);
+ before_next_line = options.context_before >= (int)before_next_line ? 1 : before_next_line - (size_t)options.context_before;
+ before_next = get_line(f, before_next_line);
+ }
+ if (!prev) {
+ fwrite(before_next, sizeof(char), (size_t)(next - before_next), out);
+ } else if (!next) {
+ fwrite(prev, sizeof(char), (size_t)(after_prev - prev), out);
+ } else if (after_prev >= before_next) {
+ fwrite(prev, sizeof(char), (size_t)(next - prev), out);
+ } else {
+ fwrite(prev, sizeof(char), (size_t)(after_prev - prev), out);
+ fwrite(before_next, sizeof(char), (size_t)(next - before_next), out);
+ }
+}
+
//
// Print all the matches in a file.
//
@@ -241,29 +271,18 @@ static int print_matches(FILE *out, def_t *defs, file_t *f, pat_t *pattern)
{
static int printed_filenames = 0;
int matches = 0;
- printer_t pr = {
- .file = f,
- .context_before = options.context_before,
- .context_after = options.context_after,
- .use_color = options.format == FORMAT_FANCY,
- .lineformat = LINE_FORMATS[options.format],
- };
-
- for (match_t *m = NULL; next_match(&m, defs, f, pattern, options.skip, options.ignorecase); ) {
+ const char *prev = NULL;
+ for (match_t *m = NULL; next_match(&m, defs, f->start, f->end, pattern, options.skip, options.ignorecase); ) {
if (++matches == 1 && options.print_filenames) {
if (printed_filenames++ > 0) printf("\n");
fprint_filename(out, f->filename);
}
- print_match(out, &pr, m);
- }
-
- if (matches > 0 || (f->filename[0] == '\0' && options.context_before == ALL_CONTEXT)) {
- // Print trailing context lines:
- print_match(out, &pr, NULL);
- // Guarantee trailing newline:
- if (!pr.needs_line_number) fprintf(out, "\n");
+ fprint_between(out, f, prev, m->start);
+ fprint_match(out, f->start, m);
+ prev = m->end;
}
-
+ if (matches > 0)
+ fprint_between(out, f, prev, NULL);
return matches;
}
@@ -285,7 +304,7 @@ static int process_file(def_t *defs, const char *filename, pat_t *pattern)
matches += explain_matches(defs, f, pattern);
} else if (options.mode == MODE_LISTFILES) {
match_t *m = NULL;
- if (next_match(&m, defs, f, pattern, options.skip, options.ignorecase)) {
+ if (next_match(&m, defs, f->start, f->end, pattern, options.skip, options.ignorecase)) {
printf("%s\n", f->filename);
matches += 1;
}
@@ -294,7 +313,7 @@ static int process_file(def_t *defs, const char *filename, pat_t *pattern)
matches += print_matches_as_json(defs, f, pattern);
} else if (options.mode == MODE_INPLACE) {
match_t *m = NULL;
- bool found = next_match(&m, defs, f, pattern, options.skip, options.ignorecase);
+ bool found = next_match(&m, defs, f->start, f->end, pattern, options.skip, options.ignorecase);
stop_matching(&m);
if (!found) return 0;
@@ -394,6 +413,20 @@ static int process_git_files(def_t *defs, pat_t *pattern, int argc, char *argv[]
}
//
+// Load the given grammar (semicolon-separated definitions)
+// and return the first rule defined.
+//
+static def_t *load_grammar(def_t *defs, file_t *f)
+{
+ maybe_pat_t maybe_pat = bp_pattern(f->start, f->end);
+ if (!maybe_pat.success)
+ file_err(f, maybe_pat.value.error.start, maybe_pat.value.error.end, maybe_pat.value.error.msg);
+ for (pat_t *p = maybe_pat.value.pat; p && p->type == BP_DEFINITION; p = p->args.def.pat)
+ defs = with_def(defs, p->args.def.namelen, p->args.def.name, p->args.def.def);
+ return defs;
+}
+
+//
// Convert a context string to an integer
//
static int context_from_flag(const char *flag)