diff options
author | June McEnroe <june@causal.agency> | 2019-02-07 12:55:31 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2019-02-07 12:55:31 -0500 |
commit | 22b87208f68956ab91c262f9b6433ed92d44f2f7 (patch) | |
tree | 48e493a01529af577905f11ae5f710005a860608 | |
parent | Add Escape class to hi (diff) | |
download | src-22b87208f68956ab91c262f9b6433ed92d44f2f7.tar.gz src-22b87208f68956ab91c262f9b6433ed92d44f2f7.zip |
Factor out hi check
Fix subexpression bounds check and compile pattends.
-rw-r--r-- | bin/hi.c | 54 |
1 files changed, 27 insertions, 27 deletions
diff --git a/bin/hi.c b/bin/hi.c index 2a5a235d..59a68605 100644 --- a/bin/hi.c +++ b/bin/hi.c @@ -95,6 +95,7 @@ static void highlight(struct Language lang, enum Class *hi, const char *str) { if (syn.pattend) regend = compile(syn.pattend, 0); assert(syn.subexp < SubsLen); + assert(syn.subexp <= regex.re_nsub); regmatch_t subs[SubsLen] = {{0}}; for (size_t offset = 0; str[offset]; offset += subs[syn.subexp].rm_eo) { int error = regexec( @@ -125,6 +126,28 @@ static void highlight(struct Language lang, enum Class *hi, const char *str) { } } +static void check(void) { + for (size_t i = 0; i < ARRAY_LEN(Languages); ++i) { + regex_t regex = compile(Languages[i].pattern, REG_NOSUB); + regfree(®ex); + for (size_t j = 0; j < Languages[i].len; ++j) { + struct Syntax syn = Languages[i].syntax[j]; + regex = compile(syn.pattern, 0); + if (syn.subexp >= SubsLen || syn.subexp > regex.re_nsub) { + errx( + EX_SOFTWARE, "subexpression %zu out of bounds: %s", + syn.subexp, syn.pattern + ); + } + regfree(®ex); + if (syn.pattend) { + regex = compile(syn.pattend, REG_NOSUB); + regfree(®ex); + } + } + } +} + typedef void HeaderFn(const char *path); typedef void OutputFn(enum Class class, const char *str, size_t len); @@ -227,14 +250,16 @@ static const struct Format { }; int main(int argc, char *argv[]) { - bool check = false; const struct Language *lang = NULL; const struct Format *format = NULL; int opt; while (0 < (opt = getopt(argc, argv, "cf:l:"))) { switch (opt) { - break; case 'c': check = true; + break; case 'c': { + check(); + return EX_OK; + } break; case 'f': { for (size_t i = 0; i < ARRAY_LEN(Formats); ++i) { if (strcmp(optarg, Formats[i].name)) continue; @@ -255,31 +280,6 @@ int main(int argc, char *argv[]) { } } - if (check) { - for (size_t i = 0; i < ARRAY_LEN(Languages); ++i) { - regex_t regex = compile(Languages[i].pattern, REG_NOSUB); - regfree(®ex); - for (size_t j = 0; j < Languages[i].len; ++j) { - struct Syntax syn = Languages[i].syntax[j]; - regex = compile(syn.pattern, 0); - if (regex.re_nsub >= SubsLen) { - errx( - EX_SOFTWARE, - "too many subexpressions: %s", syn.pattern - ); - } - if (syn.subexp > regex.re_nsub) { - errx( - EX_SOFTWARE, - "no subexpression %zu: %s", syn.subexp, syn.pattern - ); - } - regfree(®ex); - } - } - return EX_OK; - } - const char *path = "(stdin)"; FILE *file = stdin; if (optind < argc) { |