/* Construct a finite automaton from REGEXP and return it in *FA. * * Return NULL if REGEXP is valid, if the regexp REGEXP has syntax errors, * return an exception. */ static struct value *str_to_fa(struct info *info, const char *pattern, struct fa **fa) { int error; struct value *exn = NULL; size_t re_err_len; char *re_str, *re_err; error = fa_compile(pattern, strlen(pattern), fa); if (error == REG_NOERROR) return NULL; re_str = escape(pattern, -1); if (re_str == NULL) { FIXME("Out of memory"); } exn = make_exn_value(info, "Invalid regular expression /%s/", re_str); re_err_len = regerror(error, NULL, NULL, 0); if (ALLOC_N(re_err, re_err_len) < 0) { FIXME("Out of memory"); } regerror(error, NULL, re_err, re_err_len); exn_printf_line(exn, "%s", re_err); free(re_str); free(re_err); return exn; }
struct regexp * regexp_minus(struct info *info, struct regexp *r1, struct regexp *r2) { const char *p1 = r1->pattern->str; const char *p2 = r2->pattern->str; struct regexp *result = NULL; struct fa *fa = NULL, *fa1 = NULL, *fa2 = NULL; int r; char *s = NULL; size_t s_len; r = fa_compile(p1, strlen(p1), &fa1); if (r != REG_NOERROR) goto error; r = fa_compile(p2, strlen(p2), &fa2); if (r != REG_NOERROR) goto error; fa = fa_minus(fa1, fa2); if (fa == NULL) goto error; r = fa_as_regexp(fa, &s, &s_len); if (r < 0) goto error; if (s == NULL) { /* FA is the empty set, which we can't represent as a regexp */ goto error; } result = make_regexp(info, s); s = NULL; done: fa_free(fa); fa_free(fa1); fa_free(fa2); free(s); return result; error: unref(result, regexp); goto done; }
static struct fa *regexp_to_fa(struct regexp *r) { const char *p = r->pattern->str; int ret; struct fa *fa = NULL; ret = fa_compile(p, strlen(p), &fa); ERR_NOMEM(ret == REG_ESPACE, r->info); BUG_ON(ret != REG_NOERROR, r->info, NULL); if (r->nocase) { ret = fa_nocase(fa); ERR_NOMEM(ret < 0, r->info); } return fa; error: fa_free(fa); return NULL; }