[augeas-devel] augeas: master - * src/lens.c: throw exception on regexp syntax errors
David Lutterkort
lutter at fedoraproject.org
Wed Feb 11 21:43:23 UTC 2009
Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=e41c183e688015b423ee804b9c9c113f1b1767ff
Commit: e41c183e688015b423ee804b9c9c113f1b1767ff
Parent: 007908c4f17eb319055dd428f807d2e05412557e
Author: David Lutterkort <lutter at redhat.com>
AuthorDate: Wed Feb 11 11:45:37 2009 -0800
Committer: David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Feb 11 11:45:37 2009 -0800
* src/lens.c: throw exception on regexp syntax errors
---
src/lens.c | 96 ++++++++++++++++++++++++++++++++++++++++++----------------
src/regexp.c | 12 -------
src/syntax.h | 7 ----
3 files changed, 70 insertions(+), 45 deletions(-)
diff --git a/src/lens.c b/src/lens.c
index faf29ee..fb2ecf7 100644
--- a/src/lens.c
+++ b/src/lens.c
@@ -41,6 +41,44 @@ static const char *const tags[] = {
"subtree", "star", "maybe"
};
+/* 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,
+ fa_t *fa) {
+ int error;
+ struct value *exn = NULL;
+ size_t re_err_len;
+ char *re_str, *re_err;
+
+ error = fa_compile(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;
+}
+
+static struct value *regexp_to_fa(struct regexp *regexp, fa_t *fa) {
+ return str_to_fa(regexp->info, regexp->pattern->str, fa);
+}
+
static struct lens *make_lens(enum lens_tag tag, struct info *info) {
struct lens *lens;
make_ref(lens);
@@ -249,17 +287,14 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info,
/* Typecheck */
if (tag == L_KEY) {
- int error = fa_compile("(.|\n)*/(.|\n)*", &fa_slash);
- if (error != REG_NOERROR) {
- exn = make_exn_value(info,
- "unexpected error from fa_compile %d", error);
+ exn = str_to_fa(info, "(.|\n)*/(.|\n)*", &fa_slash);
+ if (exn != NULL)
goto error;
- }
- fa_key = regexp_to_fa(regexp);
- if (fa_key == NULL) {
- exn = make_exn_value(info, "fa_compile of key failed");
+
+ exn = regexp_to_fa(regexp, &fa_key);
+ if (exn != NULL)
goto error;
- }
+
fa_isect = fa_intersect(fa_slash, fa_key);
if (! fa_is_basic(fa_isect, FA_EMPTY)) {
exn = make_exn_value(info,
@@ -322,17 +357,18 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info,
*/
static struct value *disjoint_check(struct info *info, const char *msg,
struct regexp *r1, struct regexp *r2) {
- fa_t fa1 = regexp_to_fa(r1);
- fa_t fa2 = regexp_to_fa(r2);
+ fa_t fa1 = NULL;
+ fa_t fa2 = NULL;
fa_t fa = NULL;
struct value *exn = NULL;
- if (fa1 == NULL || fa2 == NULL) {
- fa_free(fa1);
- fa_free(fa2);
- return make_exn_value(ref(info),
- "internal error: compile in disjoint_check failed");
- }
+ exn = regexp_to_fa(r1, &fa1);
+ if (exn != NULL)
+ goto done;
+
+ exn = regexp_to_fa(r2, &fa2);
+ if (exn != NULL)
+ goto done;
fa = fa_intersect(fa1, fa2);
if (! fa_is_basic(fa, FA_EMPTY)) {
@@ -344,6 +380,7 @@ static struct value *disjoint_check(struct info *info, const char *msg,
free(xmpl);
}
+ done:
fa_free(fa);
fa_free(fa1);
fa_free(fa2);
@@ -400,17 +437,20 @@ static struct value *ambig_check(struct info *info, fa_t fa1, fa_t fa2,
static struct value *ambig_concat_check(struct info *info, const char *msg,
struct regexp *r1, struct regexp *r2) {
- fa_t fa1 = regexp_to_fa(r1);
- fa_t fa2 = regexp_to_fa(r2);
+ fa_t fa1 = NULL;
+ fa_t fa2 = NULL;
struct value *result = NULL;
- if (fa1 == NULL || fa2 == NULL) {
- fa_free(fa1);
- fa_free(fa2);
- return make_exn_value(ref(info), "Internal error: regexp_to_fa failed");
- }
+ result = regexp_to_fa(r1, &fa1);
+ if (result != NULL)
+ goto done;
+
+ result = regexp_to_fa(r2, &fa2);
+ if (result != NULL)
+ goto done;
result = ambig_check(info, fa1, fa2, msg);
+ done:
fa_free(fa1);
fa_free(fa2);
return result;
@@ -439,14 +479,18 @@ static struct value *typecheck_concat(struct info *info,
static struct value *ambig_iter_check(struct info *info, const char *msg,
struct regexp *r) {
- fa_t fas, fa;
+ fa_t fas = NULL, fa = NULL;
struct value *result = NULL;
- fa = regexp_to_fa(r);
+ result = regexp_to_fa(r, &fa);
+ if (result != NULL)
+ goto done;
+
fas = fa_iter(fa, 0, -1);
result = ambig_check(info, fa, fas, msg);
+ done:
fa_free(fa);
fa_free(fas);
return result;
diff --git a/src/regexp.c b/src/regexp.c
index 76024a6..9a96b55 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -285,18 +285,6 @@ int regexp_nsub(struct regexp *r) {
return r->re->re_nsub;
}
-fa_t regexp_to_fa(struct regexp *regexp) {
- fa_t fa;
- int error = fa_compile(regexp->pattern->str, &fa);
- if (error != REG_NOERROR) {
- syntax_error(regexp->info,
- "unexpected error from fa_compile %d compiling %s",
- error, regexp->pattern->str);
- return NULL;
- }
- return fa;
-}
-
void regexp_release(struct regexp *regexp) {
if (regexp->re != NULL) {
regfree(regexp->re);
diff --git a/src/syntax.h b/src/syntax.h
index d0d6f84..d7a53fc 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -210,13 +210,6 @@ struct regexp *regexp_make_empty(struct info *);
regular expressions */
void regexp_release(struct regexp *regexp);
-/* Construct a finite automaton from REGEXP. The pattern for REGEXP
- * must be known to be syntactically correct.
- *
- * Return a new automaton, or NULL if the REGEXP has a syntax error
- */
-fa_t regexp_to_fa(struct regexp *regexp);
-
struct native {
unsigned int argc;
struct type *type;
More information about the augeas-devel
mailing list