summary refs log tree commit diff
path: root/bin/hi.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-02-07 12:55:31 -0500
committerJune McEnroe <june@causal.agency>2019-02-07 12:55:31 -0500
commit6787c7b43129ca945108efccb3456e58086f4726 (patch)
tree2560f687b107fc5d73db01970af6ca44a5efde4d /bin/hi.c
parentAdd Escape class to hi (diff)
downloadsrc-6787c7b43129ca945108efccb3456e58086f4726.tar.gz
src-6787c7b43129ca945108efccb3456e58086f4726.zip
Factor out hi check
Fix subexpression bounds check and compile pattends.
Diffstat (limited to '')
-rw-r--r--bin/hi.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/bin/hi.c b/bin/hi.c
index 328578f5..51ea63e4 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(&regex);
+		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(&regex);
+			if (syn.pattend) {
+				regex = compile(syn.pattend, REG_NOSUB);
+				regfree(&regex);
+			}
+		}
+	}
+}
+
 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(&regex);
-			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(&regex);
-			}
-		}
-		return EX_OK;
-	}
-
 	const char *path = "(stdin)";
 	FILE *file = stdin;
 	if (optind < argc) {