Skip to content

Commit

Permalink
Refactor cmd_errorfmt() and add_error_fmt()
Browse files Browse the repository at this point in the history
  • Loading branch information
craigbarnes committed Jan 13, 2025
1 parent 5727160 commit 340e75c
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 60 deletions.
39 changes: 37 additions & 2 deletions src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -756,15 +756,50 @@ static bool cmd_erase_word(EditorState *e, const CommandArgs *a)

static bool cmd_errorfmt(EditorState *e, const CommandArgs *a)
{
BUG_ON(a->nr_args == 0);
BUG_ON(a->nr_args == 0 || a->nr_args > 2 + ERRORFMT_CAPTURE_MAX);
const char *name = a->args[0];
if (a->nr_args == 1) {
remove_compiler(&e->compilers, name);
return true;
}

static_assert(NR_ERRFMT_INDICES == 4);
size_t max_idx = 0;
int8_t indices[NR_ERRFMT_INDICES] = {
[ERRFMT_FILE] = -1,
[ERRFMT_LINE] = -1,
[ERRFMT_COLUMN] = -1,
[ERRFMT_MESSAGE] = 0,
};

for (size_t i = 0, n = a->nr_args - 2; i < n; i++) {
char *cap_name = a->args[i + 2];
if (streq(cap_name, "_")) {
continue;
}
ssize_t cap_idx = errorfmt_capture_name_to_index(cap_name);
if (unlikely(cap_idx < 0)) {
return error_msg(e->err, "unknown substring name %s", cap_name);
}
max_idx = i + 1;
indices[cap_idx] = max_idx;
}


const char *pattern = a->args[1];
regex_t re;
if (unlikely(!regexp_compile(&re, pattern, 0))) {
return false;
}

if (unlikely(max_idx > re.re_nsub)) {
regfree(&re);
return error_msg(e->err, "invalid substring count");
}

bool ignore = has_flag(a, 'i');
return add_error_fmt(&e->compilers, name, ignore, a->args[1], a->args + 2);
add_error_fmt(&e->compilers, name, pattern, &re, indices, ignore);
return true;
}

static bool cmd_exec(EditorState *e, const CommandArgs *a)
Expand Down
70 changes: 19 additions & 51 deletions src/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
#include <string.h>
#include "compiler.h"
#include "command/serialize.h"
#include "error.h"
#include "regexp.h"
#include "util/array.h"
#include "util/debug.h"
#include "util/intern.h"
#include "util/str-util.h"
#include "util/xmalloc.h"

static const char capture_names[][8] = {
static const char capture_names[NR_ERRFMT_INDICES][8] = {
[ERRFMT_FILE] = "file",
[ERRFMT_LINE] = "line",
[ERRFMT_COLUMN] = "column",
Expand All @@ -21,69 +20,38 @@ UNITTEST {
CHECK_STRING_ARRAY(capture_names);
}

static Compiler *find_or_add_compiler(HashMap *compilers, const char *name)
ssize_t errorfmt_capture_name_to_index(const char *name)
{
Compiler *c = find_compiler(compilers, name);
return c ? c : hashmap_insert(compilers, xstrdup(name), xnew0(Compiler, 1));
for (size_t i = 0; i < ARRAYLEN(capture_names); i++) {
if (streq(name, capture_names[i])) {
return i;
}
}
return -1;
}

Compiler *find_compiler(const HashMap *compilers, const char *name)
static Compiler *find_or_add_compiler(HashMap *compilers, const char *name)
{
return hashmap_get(compilers, name);
Compiler *c = find_compiler(compilers, name);
return c ? c : hashmap_insert(compilers, xstrdup(name), xnew0(Compiler, 1));
}

bool add_error_fmt (
void add_error_fmt (
HashMap *compilers,
const char *name,
bool ignore,
const char *format,
char **desc
const char *pattern,
regex_t *re,
int8_t idx[NR_ERRFMT_INDICES],
bool ignore
) {
int8_t idx[] = {
[ERRFMT_FILE] = -1,
[ERRFMT_LINE] = -1,
[ERRFMT_COLUMN] = -1,
[ERRFMT_MESSAGE] = 0,
};

size_t max_idx = 0;
for (size_t i = 0, j = 0, n = ARRAYLEN(capture_names); desc[i]; i++) {
BUG_ON(i >= ERRORFMT_CAPTURE_MAX);
if (streq(desc[i], "_")) {
continue;
}
for (j = 0; j < n; j++) {
if (streq(desc[i], capture_names[j])) {
max_idx = i + 1;
idx[j] = max_idx;
break;
}
}
if (unlikely(j == n)) {
return error_msg_("unknown substring name %s", desc[i]);
}
}

ErrorFormat *f = xnew(ErrorFormat, 1);
f->ignore = ignore;
static_assert_compatible_types(f->capture_index, idx);
memcpy(f->capture_index, idx, sizeof(idx));

if (unlikely(!regexp_compile(&f->re, format, 0))) {
free(f);
return false;
}

if (unlikely(max_idx > f->re.re_nsub)) {
regfree(&f->re);
free(f);
return error_msg_("invalid substring count");
}
f->re = *re; // Takes ownership (responsible for calling regfree(3))
memcpy(f->capture_index, idx, NR_ERRFMT_INDICES);

Compiler *compiler = find_or_add_compiler(compilers, name);
f->pattern = str_intern(format);
f->pattern = str_intern(pattern);
ptr_array_append(&compiler->error_formats, f);
return true;
}

static void free_error_format(ErrorFormat *f)
Expand Down
22 changes: 15 additions & 7 deletions src/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <regex.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "util/hashmap.h"
#include "util/macros.h"
#include "util/ptr-array.h"
Expand All @@ -18,10 +19,11 @@ enum {
ERRFMT_LINE,
ERRFMT_COLUMN,
ERRFMT_MESSAGE,
NR_ERRFMT_INDICES
};

typedef struct {
int8_t capture_index[4];
int8_t capture_index[NR_ERRFMT_INDICES];
bool ignore;
const char *pattern; // Original pattern string (interned)
regex_t re; // Compiled pattern
Expand All @@ -31,19 +33,25 @@ typedef struct {
PointerArray error_formats;
} Compiler;

Compiler *find_compiler(const HashMap *compilers, const char *name) NONNULL_ARGS;
static inline Compiler *find_compiler(const HashMap *compilers, const char *name)
{
return hashmap_get(compilers, name);
}

void remove_compiler(HashMap *compilers, const char *name) NONNULL_ARGS;
void free_compiler(Compiler *c) NONNULL_ARGS;
ssize_t errorfmt_capture_name_to_index(const char *name) NONNULL_ARGS WARN_UNUSED_RESULT;
void collect_errorfmt_capture_names(PointerArray *a, const char *prefix) NONNULL_ARGS;
void dump_compiler(const Compiler *c, const char *name, String *s) NONNULL_ARGS;

NONNULL_ARGS WARN_UNUSED_RESULT
bool add_error_fmt (
NONNULL_ARGS
void add_error_fmt (
HashMap *compilers,
const char *name,
bool ignore,
const char *format,
char **desc
const char *pattern,
regex_t *re, // Takes ownership
int8_t idx[NR_ERRFMT_INDICES],
bool ignore
);

#endif

0 comments on commit 340e75c

Please sign in to comment.