Cleaned up and simplified global state setting stuff (e.g. --verbose)

This commit is contained in:
Bruce Hill 2021-01-15 02:05:17 -08:00
parent 8ff80b09cc
commit b29060f38b
7 changed files with 119 additions and 133 deletions

154
bp.c
View File

@ -39,10 +39,21 @@ static const char *usage = (
" -c --context <context> set number of lines of context to print (all: the whole file, 0: only the match, 1: the line, N: N lines of context)\n"
" -g --grammar <grammar file> use the specified file as a grammar\n");
// Flag-configurable options:
#define USE_DEFAULT_CONTEXT -2
#define ALL_CONTEXT -1
static int print_color = 0;
static int print_line_numbers = 0;
static int context_lines = USE_DEFAULT_CONTEXT;
static unsigned int print_color = 0;
static unsigned int print_line_numbers = 0;
static unsigned int ignorecase = 0;
static unsigned int verbose = 0;
static enum {
MODE_NORMAL,
MODE_LISTFILES,
MODE_INPLACE,
MODE_JSON,
MODE_EXPLAIN,
} mode = MODE_NORMAL;
__attribute__((nonnull))
static char *getflag(const char *flag, char *argv[], int *i);
@ -91,16 +102,16 @@ static int is_text_file(const char *filename)
//
// Print matches in JSON format.
//
static int print_matches_as_json(def_t *defs, file_t *f, vm_op_t *pattern, unsigned int flags)
static int print_matches_as_json(def_t *defs, file_t *f, vm_op_t *pattern)
{
int matches = 0;
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, flags)); ) {
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
if (++matches > 1)
printf(",\n");
printf("{\"filename\":\"%s\",", f->filename ? f->filename : "-");
printf("{\"filename\":\"%s\",", f->filename);
printf("\"tree\":{\"rule\":\"text\",\"start\":%d,\"end\":%ld,\"children\":[",
0, f->end - f->contents);
json_match(f->contents, m, (flags & BP_VERBOSE) ? 1 : 0);
json_match(f->contents, m, verbose);
printf("]}}\n");
}
return matches;
@ -109,10 +120,10 @@ static int print_matches_as_json(def_t *defs, file_t *f, vm_op_t *pattern, unsig
//
// Print matches in a visual explanation style
//
static int explain_matches(def_t *defs, file_t *f, vm_op_t *pattern, unsigned int flags)
static int explain_matches(def_t *defs, file_t *f, vm_op_t *pattern)
{
int matches = 0;
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, flags)); ) {
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
if (++matches == 1) {
if (print_color)
printf("\033[0;1;4;33m%s\033[0m\n", f->filename);
@ -130,21 +141,21 @@ static int explain_matches(def_t *defs, file_t *f, vm_op_t *pattern, unsigned in
// Replace a file's contents with the text version of a match.
// (Useful for replacements)
//
static int inplace_modify_file(def_t *defs, file_t *f, vm_op_t *pattern, int context, unsigned int flags)
static int inplace_modify_file(def_t *defs, file_t *f, vm_op_t *pattern)
{
// Need to do this before matching:
intern_file(f);
printer_t pr = {
.file = f,
.context_lines = context,
.context_lines = context_lines,
.use_color = 0,
.print_line_numbers = 0,
};
FILE *inplace_file = NULL; // Lazy-open this on the first match
int matches = 0;
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, flags)); ) {
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
++matches;
if (print_errors(&pr, m) > 0)
exit(1);
@ -166,18 +177,18 @@ static int inplace_modify_file(def_t *defs, file_t *f, vm_op_t *pattern, int con
//
// Print all the matches in a file.
//
static int print_matches(def_t *defs, file_t *f, vm_op_t *pattern, int context, unsigned int flags)
static int print_matches(def_t *defs, file_t *f, vm_op_t *pattern)
{
static int printed_filenames = 0;
int matches = 0;
printer_t pr = {
.file = f,
.context_lines = context,
.context_lines = context_lines,
.use_color = print_color,
.print_line_numbers = print_line_numbers,
};
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, flags)); ) {
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
if (print_errors(&pr, m) > 0)
exit(1);
@ -205,27 +216,27 @@ static int print_matches(def_t *defs, file_t *f, vm_op_t *pattern, int context,
// For a given filename, open the file and attempt to match the given pattern
// against it, printing any results according to the flags.
//
static int process_file(def_t *defs, const char *filename, vm_op_t *pattern, int context, unsigned int flags)
static int process_file(def_t *defs, const char *filename, vm_op_t *pattern)
{
file_t *f = load_file(NULL, filename);
check(f, "Could not open file: %s", filename);
int matches = 0;
if (flags & BP_EXPLAIN) {
matches += explain_matches(defs, f, pattern, flags);
} else if (flags & BP_LISTFILES) {
match_t *m = next_match(defs, f, NULL, pattern, flags);
if (mode == MODE_EXPLAIN) {
matches += explain_matches(defs, f, pattern);
} else if (mode == MODE_LISTFILES) {
match_t *m = next_match(defs, f, NULL, pattern, ignorecase);
if (m) {
recycle_if_unused(&m);
printf("%s\n", f->filename);
matches += 1;
}
} else if (flags & BP_JSON) {
matches += print_matches_as_json(defs, f, pattern, flags);
} else if (flags & BP_INPLACE) {
matches += inplace_modify_file(defs, f, pattern, context, flags);
} else if (mode == MODE_JSON) {
matches += print_matches_as_json(defs, f, pattern);
} else if (mode == MODE_INPLACE) {
matches += inplace_modify_file(defs, f, pattern);
} else {
matches += print_matches(defs, f, pattern, context, flags);
matches += print_matches(defs, f, pattern);
}
#ifdef DEBUG_HEAP
@ -240,33 +251,24 @@ static int process_file(def_t *defs, const char *filename, vm_op_t *pattern, int
int main(int argc, char *argv[])
{
unsigned int flags = 0;
int context = USE_DEFAULT_CONTEXT;
char *flag = NULL;
char path[PATH_MAX] = {0};
def_t *defs = NULL;
file_t *loaded_files = NULL;
// Define an opcode that is just a reference to the rule `pattern`
file_t *pat_file = spoof_file(&loaded_files, "<pattern>", "pattern");
vm_op_t *pattern = bp_pattern(pat_file, pat_file->contents);
vm_op_t *pattern = bp_pattern(loaded_files, pat_file->contents);
// Define an opcode that is just a reference to the rule `replacement`
file_t *rep_file = spoof_file(&loaded_files, "<replacement>", "replacement");
vm_op_t *replacement = bp_pattern(rep_file, rep_file->contents);
// Load builtins:
if (access("/etc/xdg/bp/builtins.bp", R_OK) != -1) {
file_t *f = load_file(&loaded_files, "/etc/xdg/bp/builtins.bp");
defs = load_grammar(defs, f);
}
sprintf(path, "%s/.config/bp/builtins.bp", getenv("HOME"));
if (access(path, R_OK) != -1) {
file_t *f = load_file(&loaded_files, path);
defs = load_grammar(defs, f);
}
file_t *xdg_file = load_file(&loaded_files, "/etc/xdg/bp/builtins.bp");
if (xdg_file) defs = load_grammar(defs, xdg_file);
file_t *local_file = load_file(&loaded_files, "%s/.config/bp/builtins.bp", getenv("HOME"));
if (local_file) defs = load_grammar(defs, local_file);
int i, npatterns = 0;
check(argc > 1, "%s", usage);
@ -279,18 +281,18 @@ int main(int argc, char *argv[])
printf("%s\n", usage);
return 0;
} else if (streq(argv[i], "--verbose")) {
flags |= BP_VERBOSE;
verbose = 1;
} else if (streq(argv[i], "--explain")) {
flags |= BP_EXPLAIN;
mode = MODE_EXPLAIN;
} else if (streq(argv[i], "--json")) {
flags |= BP_JSON;
mode = MODE_JSON;
} else if (streq(argv[i], "--inplace")) {
flags |= BP_INPLACE;
context = ALL_CONTEXT;
mode = MODE_INPLACE;
context_lines = ALL_CONTEXT;
} else if (streq(argv[i], "--ignore-case")) {
flags |= BP_IGNORECASE;
ignorecase = 1;
} else if (streq(argv[i], "--list-files")) {
flags |= BP_LISTFILES;
mode = MODE_LISTFILES;
} else if (FLAG("--replace") || FLAG("-r")) {
// TODO: spoof file as sprintf("pattern => '%s'", flag)
// except that would require handling edge cases like quotation marks etc.
@ -299,17 +301,14 @@ int main(int argc, char *argv[])
check(rep, "Replacement failed to compile: %s", flag);
defs = with_def(defs, replace_file, strlen("replacement"), "replacement", rep);
pattern = replacement;
if (context == USE_DEFAULT_CONTEXT) context = 1;
if (context_lines == USE_DEFAULT_CONTEXT)
context_lines = ALL_CONTEXT;
} else if (FLAG("--grammar") || FLAG("-g")) {
file_t *f = load_file(&loaded_files, flag);
if (f == NULL) {
sprintf(path, "%s/.config/bp/%s.bp", getenv("HOME"), flag);
f = load_file(&loaded_files, path);
}
if (f == NULL) {
sprintf(path, "/etc/xdg/bp/%s.bp", flag);
f = load_file(&loaded_files, path);
}
if (f == NULL)
f = load_file(&loaded_files, "%s/.config/bp/%s.bp", getenv("HOME"), flag);
if (f == NULL)
f = load_file(&loaded_files, "/etc/xdg/bp/%s.bp", flag);
check(f != NULL, "Couldn't find grammar: %s", flag);
defs = load_grammar(defs, f); // Keep in memory for debug output
} else if (FLAG("--define") || FLAG("-d")) {
@ -347,19 +346,21 @@ int main(int argc, char *argv[])
++npatterns;
} else if (FLAG("--context") || FLAG("-c")) {
if (streq(flag, "all"))
context = ALL_CONTEXT;
context_lines = ALL_CONTEXT;
else if (streq(flag, "none"))
context_lines = 0;
else
context = (int)strtol(flag, NULL, 10);
context_lines = (int)strtol(flag, NULL, 10);
} else if (argv[i][0] == '-' && argv[i][1] && argv[i][1] != '-') { // single-char flags
for (char *c = &argv[i][1]; *c; ++c) {
switch (*c) {
case 'h': goto flag_help; // -h
case 'v': flags |= BP_VERBOSE; break; // -v
case 'e': flags |= BP_EXPLAIN; break; // -e
case 'j': flags |= BP_JSON; break; // -j
case 'I': flags |= BP_INPLACE; context = ALL_CONTEXT; break; // -I
case 'i': flags |= BP_IGNORECASE; break; // -i
case 'l': flags |= BP_LISTFILES; break; // -l
case 'v': verbose = 1; break; // -v
case 'e': mode = MODE_EXPLAIN; break; // -e
case 'j': mode = MODE_JSON; break; // -j
case 'I': mode = MODE_INPLACE; break; // -I
case 'i': ignorecase = 1; break; // -i
case 'l': mode = MODE_LISTFILES; break; // -l
default:
printf("Unrecognized flag: -%c\n\n%s\n", *c, usage);
return 1;
@ -379,22 +380,9 @@ int main(int argc, char *argv[])
}
}
if (((flags & BP_JSON) != 0) + ((flags & BP_EXPLAIN) != 0) + ((flags & BP_LISTFILES) != 0) > 1) {
printf("Please choose no more than one of the flags: -j/--json, -e/--explain, and -l/--list-files.\n"
"They are mutually contradictory.\n");
return 1;
}
if (context < 0) {
if (context == USE_DEFAULT_CONTEXT) context = 1;
else if (context != ALL_CONTEXT) context = 0;
}
if (flags & BP_INPLACE && context != ALL_CONTEXT) {
printf("--inplace and --context are mutually exclusive.\n"
"Please drop one of the two arguments and try again.\n");
return 1;
}
if (mode == MODE_INPLACE) context_lines = ALL_CONTEXT;
if (context_lines == USE_DEFAULT_CONTEXT) context_lines = 1;
if (context_lines < 0 && context_lines != ALL_CONTEXT) context_lines = 0;
if (isatty(STDOUT_FILENO)) {
print_color = 1;
@ -402,11 +390,11 @@ int main(int argc, char *argv[])
}
int found = 0;
if (flags & BP_JSON) printf("[");
if (mode == MODE_JSON) printf("[");
if (i < argc) {
// Files pass in as command line args:
for (int nfiles = 0; i < argc; nfiles++, i++) {
found += process_file(defs, argv[i], pattern, context, flags);
found += process_file(defs, argv[i], pattern);
}
} else if (isatty(STDIN_FILENO)) {
// No files, no piped in input, so use * **/*:
@ -415,14 +403,14 @@ int main(int argc, char *argv[])
glob("**/*", GLOB_APPEND, NULL, &globbuf);
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
if (is_text_file(globbuf.gl_pathv[i]))
found += process_file(defs, globbuf.gl_pathv[i], pattern, context, flags);
found += process_file(defs, globbuf.gl_pathv[i], pattern);
}
globfree(&globbuf);
} else {
// Piped in input:
found += process_file(defs, NULL, pattern, context, flags);
found += process_file(defs, NULL, pattern);
}
if (flags & BP_JSON) printf("]\n");
if (mode == MODE_JSON) printf("]\n");
#ifdef DEBUG_HEAP
// This code frees up all residual heap-allocated memory. Since the program

View File

@ -42,10 +42,16 @@ static void populate_lines(file_t *f)
//
// Read an entire file into memory.
//
file_t *load_file(file_t **files, const char *filename)
file_t *load_file(file_t **files, const char *fmt, ...)
{
if (filename == NULL) filename = "-";
int fd = streq(filename, "-") ? STDIN_FILENO : open(filename, O_RDONLY);
char filename[PATH_MAX+1] = {0};
va_list args;
va_start(args, fmt);
check(vsnprintf(filename, PATH_MAX, fmt, args) <= PATH_MAX,
"File name is too large");
va_end(args);
int fd = filename[0] == '\0' ? STDIN_FILENO : open(filename, O_RDONLY);
if (fd < 0) return NULL;
size_t length;
file_t *f = new(file_t);

View File

@ -17,7 +17,8 @@ typedef struct file_s {
unsigned int mmapped:1;
} file_t;
file_t *load_file(file_t **files, const char *filename);
__attribute__((format(printf,2,3)))
file_t *load_file(file_t **files, const char *fmt, ...);
__attribute__((nonnull(3), returns_nonnull))
file_t *spoof_file(file_t **files, const char *filename, const char *text);
__attribute__((nonnull))
@ -30,7 +31,7 @@ __attribute__((pure, nonnull))
size_t get_char_number(file_t *f, const char *p);
__attribute__((pure, nonnull))
const char *get_line(file_t *f, size_t line_number);
__attribute__((nonnull(1,2,3), format(printf, 5, 6)))
__attribute__((nonnull(1,2,3), format(printf,5,6)))
void fprint_line(FILE *dest, file_t *f, const char *start, const char *end, const char *fmt, ...);
#endif

6
json.c
View File

@ -7,14 +7,14 @@
#include "types.h"
__attribute__((nonnull))
static int _json_match(const char *text, match_t *m, int comma, int verbose);
static int _json_match(const char *text, match_t *m, int comma, unsigned int verbose);
//
// Helper function for json_match().
// `comma` is used to track whether a comma will need to be printed before the
// next object or not.
//
static int _json_match(const char *text, match_t *m, int comma, int verbose)
static int _json_match(const char *text, match_t *m, int comma, unsigned int verbose)
{
if (!verbose) {
if (m->op->type != VM_REF) {
@ -49,7 +49,7 @@ static int _json_match(const char *text, match_t *m, int comma, int verbose)
//
// Print a match object as a JSON object.
//
void json_match(const char *text, match_t *m, int verbose)
void json_match(const char *text, match_t *m, unsigned int verbose)
{
_json_match(text, m, 0, verbose);
}

2
json.h
View File

@ -5,7 +5,7 @@
#define JSON__H
__attribute__((nonnull))
void json_match(const char *text, match_t *m, int verbose);
void json_match(const char *text, match_t *m, unsigned int verbose);
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1

View File

@ -8,15 +8,6 @@
#include "file_loader.h"
enum BPFlag {
BP_VERBOSE = 1 << 0,
BP_IGNORECASE = 1 << 1,
BP_EXPLAIN = 1 << 2,
BP_JSON = 1 << 3,
BP_LISTFILES = 1 << 4,
BP_INPLACE = 1 << 5,
};
//
// BP virtual machine opcodes (these must be kept in sync with the names in vm.c)
//

58
vm.c
View File

@ -36,7 +36,7 @@ static match_t *in_use_matches = NULL;
__attribute__((nonnull, pure))
static inline const char *next_char(file_t *f, const char *str);
__attribute__((nonnull))
static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, unsigned int flags);
static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, unsigned int ignorecase);
__attribute__((nonnull))
static match_t *get_capture_by_num(match_t *m, int *n);
__attribute__((nonnull, pure))
@ -66,7 +66,7 @@ static inline const char *next_char(file_t *f, const char *str)
// Attempt to match text against a previously captured value.
// Return the character position after the backref has matched, or NULL if no match has occurred.
//
static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, unsigned int flags)
static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, unsigned int ignorecase)
{
check(op->type == VM_BACKREF, "Attempt to match backref against something that's not a backref");
if (cap->op->type == VM_REPLACE) {
@ -87,7 +87,7 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
++r;
match_t *value = get_capture(cap, &r);
if (value != NULL) {
str = match_backref(str, op, value, flags);
str = match_backref(str, op, value, ignorecase);
if (str == NULL) return NULL;
}
}
@ -96,7 +96,7 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
for (match_t *child = cap->child; child; child = child->nextsibling) {
if (child->start > prev) {
size_t len = (size_t)(child->start - prev);
if ((flags & BP_IGNORECASE) ? memicmp(str, prev, len) != 0
if (ignorecase ? memicmp(str, prev, len) != 0
: memcmp(str, prev, len) != 0) {
return NULL;
}
@ -104,13 +104,13 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
prev = child->start;
}
if (child->start < prev) continue;
str = match_backref(str, op, child, flags);
str = match_backref(str, op, child, ignorecase);
if (str == NULL) return NULL;
prev = child->end;
}
if (cap->end > prev) {
size_t len = (size_t)(cap->end - prev);
if ((flags & BP_IGNORECASE) ? memicmp(str, prev, len) != 0
if (ignorecase ? memicmp(str, prev, len) != 0
: memcmp(str, prev, len) != 0) {
return NULL;
}
@ -124,7 +124,7 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
//
// Find the next match after prev (or the first match if prev is NULL)
//
match_t *next_match(def_t *defs, file_t *f, match_t *prev, vm_op_t *op, unsigned int flags)
match_t *next_match(def_t *defs, file_t *f, match_t *prev, vm_op_t *op, unsigned int ignorecase)
{
const char *str;
if (prev) {
@ -134,7 +134,7 @@ match_t *next_match(def_t *defs, file_t *f, match_t *prev, vm_op_t *op, unsigned
str = f->contents;
}
for (; str < f->end; ++str) {
match_t *m = match(defs, f, str, op, flags);
match_t *m = match(defs, f, str, op, ignorecase);
if (m) return m;
}
return NULL;
@ -145,7 +145,7 @@ match_t *next_match(def_t *defs, file_t *f, match_t *prev, vm_op_t *op, unsigned
// a match struct, or NULL if no match is found.
// The returned value should be free()'d to avoid memory leaking.
//
match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned int flags)
match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned int ignorecase)
{
switch (op->type) {
case VM_LEFTRECURSION: {
@ -158,7 +158,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
++op->args.leftrec.visits;
return op->args.leftrec.match;
} else {
return match(defs, f, str, op->args.leftrec.fallback, flags);
return match(defs, f, str, op->args.leftrec.fallback, ignorecase);
}
}
case VM_ANYCHAR: {
@ -172,7 +172,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
}
case VM_STRING: {
if (&str[op->len] > f->end) return NULL;
if ((flags & BP_IGNORECASE) ? memicmp(str, op->args.s, (size_t)op->len) != 0
if (ignorecase ? memicmp(str, op->args.s, (size_t)op->len) != 0
: memcmp(str, op->args.s, (size_t)op->len) != 0)
return NULL;
match_t *m = new_match();
@ -192,7 +192,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_NOT: {
match_t *m = match(defs, f, str, op->args.pat, flags);
match_t *m = match(defs, f, str, op->args.pat, ignorecase);
if (m != NULL) {
recycle_if_unused(&m);
return NULL;
@ -219,7 +219,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
for (const char *prev = NULL; prev < str; ) {
prev = str;
if (pat) {
match_t *p = match(defs, f, str, pat, flags);
match_t *p = match(defs, f, str, pat, ignorecase);
if (p != NULL) {
ADD_OWNER(*dest, p);
m->end = p->end;
@ -230,7 +230,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
if (skip) {
match_t *s = match(defs, f, str, skip, flags);
match_t *s = match(defs, f, str, skip, ignorecase);
if (s != NULL) {
ADD_OWNER(*dest, s);
dest = &s->nextsibling;
@ -261,11 +261,11 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
// Separator
match_t *sep = NULL;
if (op->args.repetitions.sep != NULL && reps > 0) {
sep = match(defs, f, str, op->args.repetitions.sep, flags);
sep = match(defs, f, str, op->args.repetitions.sep, ignorecase);
if (sep == NULL) break;
str = sep->end;
}
match_t *p = match(defs, f, str, op->args.repetitions.repeat_pat, flags);
match_t *p = match(defs, f, str, op->args.repetitions.repeat_pat, ignorecase);
if (p == NULL) {
str = start;
recycle_if_unused(&sep);
@ -306,7 +306,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
ssize_t backtrack = op->args.pat->len;
check(backtrack != -1, "'<' is only allowed for fixed-length operations");
if (str - backtrack < f->contents) return NULL;
match_t *before = match(defs, f, str - backtrack, op->args.pat, flags);
match_t *before = match(defs, f, str - backtrack, op->args.pat, ignorecase);
if (before == NULL) return NULL;
match_t *m = new_match();
m->start = str;
@ -316,7 +316,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_BEFORE: {
match_t *after = match(defs, f, str, op->args.pat, flags);
match_t *after = match(defs, f, str, op->args.pat, ignorecase);
if (after == NULL) return NULL;
match_t *m = new_match();
m->start = str;
@ -326,7 +326,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_CAPTURE: {
match_t *p = match(defs, f, str, op->args.pat, flags);
match_t *p = match(defs, f, str, op->args.pat, ignorecase);
if (p == NULL) return NULL;
match_t *m = new_match();
m->start = str;
@ -336,18 +336,18 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_OTHERWISE: {
match_t *m = match(defs, f, str, op->args.multiple.first, flags);
if (m == NULL) m = match(defs, f, str, op->args.multiple.second, flags);
match_t *m = match(defs, f, str, op->args.multiple.first, ignorecase);
if (m == NULL) m = match(defs, f, str, op->args.multiple.second, ignorecase);
return m;
}
case VM_CHAIN: {
match_t *m1 = match(defs, f, str, op->args.multiple.first, flags);
match_t *m1 = match(defs, f, str, op->args.multiple.first, ignorecase);
if (m1 == NULL) return NULL;
match_t *m2;
{ // Push backrefs and run matching, then cleanup
def_t *defs2 = with_backrefs(defs, f, m1);
m2 = match(defs2, f, m1->end, op->args.multiple.second, flags);
m2 = match(defs2, f, m1->end, op->args.multiple.second, ignorecase);
free_defs(&defs2, defs);
}
@ -364,7 +364,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_EQUAL: case VM_NOT_EQUAL: {
match_t *m1 = match(defs, f, str, op->args.multiple.first, flags);
match_t *m1 = match(defs, f, str, op->args.multiple.first, ignorecase);
if (m1 == NULL) return NULL;
// <p1>==<p2> matches iff the text of <p1> matches <p2>
@ -376,7 +376,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
.nlines=1 + get_line_number(f, m1->end)-get_line_number(f, m1->start),
.mmapped=f->mmapped,
};
match_t *m2 = match(defs, &inner, str, op->args.multiple.second, flags);
match_t *m2 = match(defs, &inner, str, op->args.multiple.second, ignorecase);
if ((m2 == NULL) == (op->type == VM_EQUAL)) {
recycle_if_unused(&m1);
if (m2 != NULL) recycle_if_unused(&m2);
@ -397,7 +397,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
case VM_REPLACE: {
match_t *p = NULL;
if (op->args.replace.pat) {
p = match(defs, f, str, op->args.replace.pat, flags);
p = match(defs, f, str, op->args.replace.pat, ignorecase);
if (p == NULL) return NULL;
}
match_t *m = new_match();
@ -437,7 +437,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
};
const char *prev = str;
match_t *m = match(&defs2, f, str, ref, flags);
match_t *m = match(&defs2, f, str, ref, ignorecase);
if (m == NULL) return NULL;
while (rec_op.args.leftrec.visits > 0) {
@ -445,7 +445,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
REMOVE_OWNERSHIP(rec_op.args.leftrec.match);
ADD_OWNER(rec_op.args.leftrec.match, m);
prev = m->end;
match_t *m2 = match(&defs2, f, str, ref, flags);
match_t *m2 = match(&defs2, f, str, ref, ignorecase);
if (m2 == NULL) break;
if (m2->end <= prev) {
recycle_if_unused(&m2);
@ -465,7 +465,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned in
return m;
}
case VM_BACKREF: {
const char *end = match_backref(str, op, op->args.backref, flags);
const char *end = match_backref(str, op, op->args.backref, ignorecase);
if (end == NULL) return NULL;
match_t *m = new_match();
m->op = op;