aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bp.c34
-rw-r--r--compiler.c13
-rw-r--r--file_loader.c1
-rw-r--r--file_loader.h3
-rw-r--r--grammar.c1
-rw-r--r--grammar.h2
-rw-r--r--json.c1
-rw-r--r--printing.c31
-rw-r--r--printing.h2
-rw-r--r--vm.c26
-rw-r--r--vm.h4
11 files changed, 76 insertions, 42 deletions
diff --git a/bp.c b/bp.c
index f97970a..8d48ed3 100644
--- a/bp.c
+++ b/bp.c
@@ -41,6 +41,11 @@ static const char *usage = (
static print_options_t print_options = 0;
+//
+// Return a pointer to the value part of a flag, if present, otherwise NULL.
+// This works for --foo=value or --foo value
+//
+__attribute__((nonnull))
static char *getflag(const char *flag, char *argv[], int *i)
{
size_t n = strlen(flag);
@@ -57,22 +62,11 @@ static char *getflag(const char *flag, char *argv[], int *i)
return NULL;
}
-static int print_errors(file_t *f, match_t *m)
-{
- int ret = 0;
- if (m->op->type == VM_CAPTURE && m->op->args.capture.name && streq(m->op->args.capture.name, "!")) {
- printf("\033[31;1m");
- print_match(stdout, f, m, print_options);
- printf("\033[0m\n");
- fprint_line(stdout, f, m->start, m->end, " ");
- return 1;
- }
- if (m->child) ret += print_errors(f, m->child);
- if (m->nextsibling) ret += print_errors(f, m->nextsibling);
- return ret;
-}
-
-static int run_match(def_t *defs, const char *filename, vm_op_t *pattern, unsigned int flags)
+//
+// 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, unsigned int flags)
{
static int printed_matches = 0;
int success = 0;
@@ -81,7 +75,7 @@ static int run_match(def_t *defs, const char *filename, vm_op_t *pattern, unsign
if (flags & BP_INPLACE) // Need to do this before matching
intern_file(f);
match_t *m = match(defs, f, f->contents, pattern, flags);
- if (m && print_errors(f, m) > 0)
+ if (m && print_errors(f, m, print_options) > 0)
_exit(1);
if (m != NULL && m->end > m->start + 1) {
success = 1;
@@ -271,7 +265,7 @@ int main(int argc, char *argv[])
if (i < argc) {
// Files pass in as command line args:
for (int nfiles = 0; i < argc; nfiles++, i++) {
- found += run_match(defs, argv[i], pattern, flags);
+ found += process_file(defs, argv[i], pattern, flags);
}
} else if (isatty(STDIN_FILENO)) {
// No files, no piped in input, so use * **/*:
@@ -279,12 +273,12 @@ int main(int argc, char *argv[])
glob("*", 0, NULL, &globbuf);
glob("**/*", GLOB_APPEND, NULL, &globbuf);
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
- found += run_match(defs, globbuf.gl_pathv[i], pattern, flags);
+ found += process_file(defs, globbuf.gl_pathv[i], pattern, flags);
}
globfree(&globbuf);
} else {
// Piped in input:
- found += run_match(defs, NULL, pattern, flags);
+ found += process_file(defs, NULL, pattern, flags);
}
if (flags & BP_JSON) printf("]\n");
diff --git a/compiler.c b/compiler.c
index 1c8974c..aa82942 100644
--- a/compiler.c
+++ b/compiler.c
@@ -12,10 +12,13 @@
#define file_err(f, ...) do { fprint_line(stderr, f, __VA_ARGS__); _exit(1); } while(0)
-__attribute__((nonnull)) static vm_op_t *expand_chain(file_t *f, vm_op_t *first);
-__attribute__((nonnull)) static vm_op_t *expand_choices(file_t *f, vm_op_t *first);
+__attribute__((nonnull))
+static vm_op_t *expand_chain(file_t *f, vm_op_t *first);
+__attribute__((nonnull))
+static vm_op_t *expand_choices(file_t *f, vm_op_t *first);
static vm_op_t *chain_together(vm_op_t *first, vm_op_t *second);
-__attribute__((nonnull(1,4))) static void set_range(vm_op_t *op, ssize_t min, ssize_t max, vm_op_t *pat, vm_op_t *sep);
+__attribute__((nonnull(1,4)))
+static void set_range(vm_op_t *op, ssize_t min, ssize_t max, vm_op_t *pat, vm_op_t *sep);
//
// Helper function to initialize a range object.
@@ -113,6 +116,10 @@ static vm_op_t *expand_choices(file_t *f, vm_op_t *first)
return choice;
}
+//
+// Given two patterns, return a new opcode for the first pattern followed by
+// the second. If either pattern is NULL, return the other.
+//
static vm_op_t *chain_together(vm_op_t *first, vm_op_t *second)
{
if (first == NULL) return second;
diff --git a/file_loader.c b/file_loader.c
index 1452907..a7ce56d 100644
--- a/file_loader.c
+++ b/file_loader.c
@@ -19,6 +19,7 @@
// In the file object, populate the `lines` array with pointers to the
// beginning of each line.
//
+__attribute__((nonnull))
static void populate_lines(file_t *f)
{
// Calculate line numbers:
diff --git a/file_loader.h b/file_loader.h
index b4e7938..3b0f15b 100644
--- a/file_loader.h
+++ b/file_loader.h
@@ -14,6 +14,7 @@ typedef struct {
} file_t;
file_t *load_file(const char *filename);
+__attribute__((nonnull(2), returns_nonnull))
file_t *spoof_file(const char *filename, char *text);
__attribute__((nonnull))
void intern_file(file_t *f);
@@ -25,7 +26,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__((format (printf, 5, 6)))
+__attribute__((nonnull(1,2,3,4), format(printf, 5, 6)))
void fprint_line(FILE *dest, file_t *f, const char *start, const char *end, const char *fmt, ...);
#endif
diff --git a/grammar.c b/grammar.c
index 01168af..e9ea4b4 100644
--- a/grammar.c
+++ b/grammar.c
@@ -67,6 +67,7 @@ vm_op_t *lookup(def_t *defs, const char *name)
//
// Push a backreference onto the backreference stack
//
+__attribute__((nonnull))
static def_t *with_backref(def_t *defs, file_t *f, const char *name, match_t *m)
{
vm_op_t *op = new(vm_op_t);
diff --git a/grammar.h b/grammar.h
index fe7280e..a7eedc4 100644
--- a/grammar.h
+++ b/grammar.h
@@ -7,7 +7,7 @@
#include "file_loader.h"
#include "types.h"
-__attribute__((nonnull(2,3,4)))
+__attribute__((nonnull(2,3,4), returns_nonnull))
def_t *with_def(def_t *defs, file_t *f, const char *name, vm_op_t *op);
__attribute__((nonnull(2,3)))
def_t *with_backrefs(def_t *defs, file_t *f, match_t *m);
diff --git a/json.c b/json.c
index 22a3ae2..f099554 100644
--- a/json.c
+++ b/json.c
@@ -11,6 +11,7 @@
// `comma` is used to track whether a comma will need to be printed before the
// next object or not.
//
+__attribute__((nonnull))
static int _json_match(const char *text, match_t *m, int comma, int verbose)
{
if (!verbose) {
diff --git a/printing.c b/printing.c
index 71fff17..9491646 100644
--- a/printing.c
+++ b/printing.c
@@ -25,11 +25,12 @@ typedef struct {
// Return the height of a match object (i.e. the number of descendents of the
// structure).
//
-static int match_height(match_t *m)
+__attribute__((nonnull, pure))
+static int height_of_match(match_t *m)
{
int height = 0;
for (match_t *c = m->child; c; c = c->nextsibling) {
- int childheight = match_height(c);
+ int childheight = height_of_match(c);
if (childheight > height) height = childheight;
}
return 1 + height;
@@ -38,10 +39,9 @@ static int match_height(match_t *m)
//
// Print a visual explanation for the as-yet-unprinted matches provided.
//
+__attribute__((nonnull))
static void _visualize_matches(match_node_t *firstmatch, int depth, const char *text, size_t textlen)
{
- if (!firstmatch) return;
-
const char *V = "│"; // Vertical bar
const char *H = "─"; // Horizontal bar
const char *color = (depth % 2 == 0) ? "34" : "33";
@@ -54,7 +54,7 @@ static void _visualize_matches(match_node_t *firstmatch, int depth, const char *
// while also printing earlier matches first when it doesn't affect overall
// output height.
for (match_node_t *p = firstmatch; p; p = p->next)
- if (match_height(p->m) > match_height(viz))
+ if (height_of_match(p->m) > height_of_match(viz))
viz = p->m;
const char *viz_type = viz->op->start;
size_t viz_typelen = (size_t)(viz->op->end - viz->op->start);
@@ -164,6 +164,7 @@ static void _visualize_matches(match_node_t *firstmatch, int depth, const char *
// Recursively look for references to a rule called "pattern" and print an
// explanation for each one.
//
+__attribute__((nonnull))
static void _visualize_patterns(match_t *m)
{
if (m->op->type == VM_REF && streq(m->op->args.s, "pattern")) {
@@ -190,6 +191,7 @@ void visualize_match(match_t *m)
//
// Print a line number.
//
+__attribute__((nonnull))
static void print_line_number(FILE *out, print_state_t *state, print_options_t options)
{
state->printed_line = state->line;
@@ -203,6 +205,7 @@ static void print_line_number(FILE *out, print_state_t *state, print_options_t o
//
// Helper function for print_match(), using a struct to keep track of some state.
//
+__attribute__((nonnull))
static void _print_match(FILE *out, file_t *f, match_t *m, print_state_t *state, print_options_t options)
{
static const char *hl = "\033[0;31;1m";
@@ -300,4 +303,22 @@ void print_match(FILE *out, file_t *f, match_t *m, print_options_t options)
_print_match(out, f, m, &state, options);
}
+//
+// Print any errors that are present in the given match object.
+//
+int print_errors(file_t *f, match_t *m, print_options_t options)
+{
+ int ret = 0;
+ if (m->op->type == VM_CAPTURE && m->op->args.capture.name && streq(m->op->args.capture.name, "!")) {
+ printf("\033[31;1m");
+ print_match(stdout, f, m, options);
+ printf("\033[0m\n");
+ fprint_line(stdout, f, m->start, m->end, " ");
+ return 1;
+ }
+ if (m->child) ret += print_errors(f, m->child, options);
+ if (m->nextsibling) ret += print_errors(f, m->nextsibling, options);
+ return ret;
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/printing.h b/printing.h
index 37e3d41..f81dcef 100644
--- a/printing.h
+++ b/printing.h
@@ -15,6 +15,8 @@ __attribute__((nonnull))
void visualize_match(match_t *m);
__attribute__((nonnull))
void print_match(FILE *out, file_t *f, match_t *m, print_options_t options);
+__attribute__((nonnull))
+int print_errors(file_t *f, match_t *m, print_options_t options);
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/vm.c b/vm.c
index 7cfeda9..330f24f 100644
--- a/vm.c
+++ b/vm.c
@@ -16,6 +16,7 @@
//
// UTF8-compliant char iteration
//
+__attribute__((nonnull, pure))
static inline const char *next_char(file_t *f, const char *str)
{
char c = *str;
@@ -55,6 +56,7 @@ typedef struct recursive_ref_s {
// 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.
//
+__attribute__((nonnull))
static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, unsigned int flags)
{
check(op->type == VM_BACKREF, "Attempt to match backref against something that's not a backref");
@@ -100,7 +102,7 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
if (cap->end > prev) {
size_t len = (size_t)(cap->end - prev);
if ((flags & BP_IGNORECASE) ? memicmp(str, prev, len) != 0
- : memcmp(str, prev, len) != 0) {
+ : memcmp(str, prev, len) != 0) {
return NULL;
}
str += len;
@@ -115,6 +117,7 @@ static const char *match_backref(const char *str, vm_op_t *op, match_t *cap, uns
// a match struct, or NULL if no match is found.
// The returned value should be free()'d to avoid memory leaking.
//
+__attribute__((hot, nonnull(2,3,4)))
static match_t *_match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned int flags, recursive_ref_t *rec)
{
switch (op->type) {
@@ -474,6 +477,7 @@ static match_t *_match(def_t *defs, file_t *f, const char *str, vm_op_t *op, uns
//
// Get a specific numbered pattern capture.
//
+__attribute__((nonnull))
static match_t *get_capture_by_num(match_t *m, int *n)
{
if (*n == 0) return m;
@@ -489,6 +493,7 @@ static match_t *get_capture_by_num(match_t *m, int *n)
//
// Get a capture with a specific name.
//
+__attribute__((nonnull, pure))
static match_t *get_capture_by_name(match_t *m, const char *name)
{
if (m->op->type == VM_CAPTURE && m->op->args.capture.name
@@ -502,21 +507,22 @@ static match_t *get_capture_by_name(match_t *m, const char *name)
}
//
-// Get a capture by name.
+// Get a capture by identifier (name or number).
+// Update *id to point to after the identifier (if found).
//
-match_t *get_capture(match_t *m, const char **r)
+match_t *get_capture(match_t *m, const char **id)
{
- if (isdigit(**r)) {
- int n = (int)strtol(*r, (char**)r, 10);
+ if (isdigit(**id)) {
+ int n = (int)strtol(*id, (char**)id, 10);
return get_capture_by_num(m->child, &n);
} else {
- const char *end = after_name(*r);
- if (end == *r) return NULL;
- char *name = strndup(*r, (size_t)(end-*r));
+ const char *end = after_name(*id);
+ if (end == *id) return NULL;
+ char *name = strndup(*id, (size_t)(end-*id));
match_t *cap = get_capture_by_name(m, name);
xfree(&name);
- *r = end;
- if (**r == ';') ++(*r);
+ *id = end;
+ if (**id == ';') ++(*id);
return cap;
}
return NULL;
diff --git a/vm.h b/vm.h
index b498b6c..6417f32 100644
--- a/vm.h
+++ b/vm.h
@@ -8,12 +8,12 @@
#include "types.h"
-__attribute__((hot, nonnull(2,3,4)))
+__attribute__((nonnull(2,3,4)))
match_t *match(def_t *defs, file_t *f, const char *str, vm_op_t *op, unsigned int flags);
__attribute__((nonnull))
void destroy_match(match_t **m);
__attribute__((nonnull))
-match_t *get_capture(match_t *m, const char **r);
+match_t *get_capture(match_t *m, const char **id);
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1