diff --git a/Makefile b/Makefile index fb36a07..2026e30 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=cc PREFIX=/usr/local SYSCONFDIR=/etc CFLAGS=-std=c99 -Werror -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -flto=auto -CWARN=-Wall -Wextra +CWARN=-Wall -Wextra -Wno-format # -Wpedantic -Wsign-conversion -Wtype-limits -Wunused-result -Wnull-dereference \ # -Waggregate-return -Walloc-zero -Walloca -Warith-conversion -Wcast-align -Wcast-align=strict \ # -Wdangling-else -Wdate-time -Wdisabled-optimization -Wdouble-promotion -Wduplicated-branches \ diff --git a/bp.c b/bp.c index 68c07d0..3f17736 100644 --- a/bp.c +++ b/bp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -558,6 +559,9 @@ int main(int argc, char *argv[]) { char *flag = NULL; + if (set_pattern_printf_specifier('P')) + errx(1, "Couldn't set printf specifier"); + pat_t *defs = NULL; file_t *loaded_files = NULL; pat_t *pattern = NULL; @@ -678,6 +682,9 @@ int main(int argc, char *argv[]) // Handle exit() calls gracefully: require(atexit(&cleanup), "Failed to set cleanup handler at exit"); + if (options.verbose) + printf("Matching pattern: %P\n", pattern); + int found = 0; if (options.mode == MODE_JSON) printf("["); if (options.git_mode) { // Get the list of files from `git --ls-files ...` diff --git a/pattern.c b/pattern.c index 3be5a94..61e6a5d 100644 --- a/pattern.c +++ b/pattern.c @@ -3,9 +3,11 @@ // #include #include +#include #include #include #include +#include #include #include @@ -272,7 +274,7 @@ static pat_t *_bp_simplepattern(const char *str, const char *end, bool inside_st all = either_pat(all, pat); } else { size_t len = (size_t)(str - c1_loc); - pat_t *pat = Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=c1_loc); + pat_t *pat = Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=strndup(c1_loc, len)); all = either_pat(all, pat); } } while (*str++ == ','); @@ -338,7 +340,7 @@ static pat_t *_bp_simplepattern(const char *str, const char *end, bool inside_st str = next_char(str, end); size_t len = (size_t)(str - litstart); str = next_char(str, end); - return Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=litstart); + return Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=strndup(litstart, len)); } // Not case '!': { @@ -504,7 +506,7 @@ maybe_pat_t bp_stringpattern(const char *str, const char *end) while (str < end && *str != '{') str = next_char(str, end); size_t len = (size_t)(str - start); - pat_t *pat = len > 0 ? Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=start) : NULL; + pat_t *pat = len > 0 ? Pattern(BP_STRING, start, str, len, (ssize_t)len, .string=strndup(start, len)) : NULL; str += 1; if (str < end) { pat_t *interp = bp_pattern_nl(str, end, true); @@ -588,7 +590,7 @@ static pat_t *bp_pattern_nl(const char *str, const char *end, bool allow_nl) // pat_t *bp_raw_literal(const char *str, size_t len) { - return Pattern(BP_STRING, str, &str[len], len, (ssize_t)len, .string=str); + return Pattern(BP_STRING, str, &str[len], len, (ssize_t)len, .string=strndup(str, len)); } // @@ -642,6 +644,7 @@ void delete_pat(pat_t **at_pat, bool recursive) T(BP_AFTER, F(pat)) T(BP_BEFORE, F(pat)) T(BP_LEFTRECURSION, F(fallback)) + T(BP_STRING, if (_data->string) { free((char*)_data->string); _data->string = NULL; }) default: break; } } @@ -653,4 +656,59 @@ void delete_pat(pat_t **at_pat, bool recursive) delete(at_pat); } +static int printf_pattern_size(const struct printf_info *info, size_t n, int argtypes[n], int sizes[n]) +{ + if (n < 1) return -1; + (void)info; + argtypes[0] = PA_POINTER; + sizes[0] = sizeof(void*); + return 1; +} + +static int printf_pattern(FILE *stream, const struct printf_info *info, const void *const args[]) +{ + (void)info; + pat_t *pat = *(pat_t**)args[0]; + if (!pat) return fputs("(null)", stream); + + switch (pat->type) { +#define P(name, ...) case BP_ ## name: { __auto_type data = pat->__tagged.BP_##name; (void)data; return fprintf(stream, #name __VA_ARGS__); } + P(ERROR) + P(ANYCHAR) + P(ID_START) + P(ID_CONTINUE) + P(STRING, "(\"%s\")", data.string) + P(RANGE, "('%c'-'%c')", data.low, data.high) + P(NOT, "(%P)", data.pat) + P(UPTO, "(%P, skip=%P)", data.target, data.skip) + P(UPTO_STRICT, "(%P, skip=%P)", data.target, data.skip) + P(REPEAT, "(%u-%d, %P, sep=%P)", data.min, data.max, data.repeat_pat, data.sep) + P(BEFORE, "(%P)", data.pat) + P(AFTER, "(%P)", data.pat) + P(CAPTURE, "(%P, name=%.*s, backref=%s)", data.pat, data.namelen, data.name, data.backreffable ? "yes" : "no") + P(OTHERWISE, "(%P, %P)", data.first, data.second); + P(CHAIN, "(%P, %P)", data.first, data.second); + P(MATCH, "(%P, matches=%P)", data.pat, data.must_match); + P(NOT_MATCH, "(%P, not_matches=%P)", data.pat, data.must_not_match); + P(REPLACE, "(%P, \"%.*s\")", data.pat, data.len, data.text); + P(REF, "(%.*s)", data.len, data.name); + P(NODENT) + P(CURDENT) + P(START_OF_FILE) + P(START_OF_LINE) + P(END_OF_FILE) + P(END_OF_LINE) + P(WORD_BOUNDARY) + P(DEFINITIONS, "(%.*s=%P); %P", data.namelen, data.name, data.meaning, data.next_def) + P(TAGGED, "(%.*s=%P, backref=%s)", data.namelen, data.name, data.pat, data.backreffable ? "yes" : "no") +#undef P + default: return fputs("???", stream); + } +} + +int set_pattern_printf_specifier(char specifier) +{ + return register_printf_specifier(specifier, printf_pattern, printf_pattern_size); +} + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/pattern.h b/pattern.h index 32a2311..046a792 100644 --- a/pattern.h +++ b/pattern.h @@ -3,8 +3,10 @@ // #pragma once +#include #include #include +#include #include #include @@ -67,7 +69,7 @@ typedef struct pat_s { struct {} BP_ANYCHAR; struct {} BP_ID_START; struct {} BP_ID_CONTINUE; - struct {const char *string;} BP_STRING; + struct {const char *string; size_t len; } BP_STRING; struct {unsigned char low, high; } BP_RANGE; struct {struct pat_s *pat;} BP_NOT; struct {struct pat_s *target, *skip;} BP_UPTO; @@ -163,5 +165,6 @@ maybe_pat_t bp_pattern(const char *str, const char *end); void free_all_pats(void); __attribute__((nonnull)) void delete_pat(pat_t **at_pat, bool recursive); +int set_pattern_printf_specifier(char specifier); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/printmatch.c b/printmatch.c index 346b7ab..aa2f1d5 100644 --- a/printmatch.c +++ b/printmatch.c @@ -277,5 +277,4 @@ int fprint_match(FILE *out, const char *file_start, match_t *m, print_options_t return printed; } - // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0