[augeas-devel] [PATCH 3/3] * src/fa.c (fa_as_regexp): convert strings more efficiently
lutter at redhat.com
lutter at redhat.com
Thu Jan 14 01:23:10 UTC 2010
From: David Lutterkort <lutter at redhat.com>
Since we are building the transitive closure of the FA, cut down the size
of the FA by first extracting strings and removing their internal states.
---
src/fa.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/src/fa.c b/src/fa.c
index 2949f9b..c48d497 100644
--- a/src/fa.c
+++ b/src/fa.c
@@ -3778,6 +3778,68 @@ static int re_collapse_trans(struct state *s1, struct state *s2,
return -1;
}
+static int convert_strings(struct fa *fa) {
+ struct state_set *worklist = state_set_init(-1, S_NONE);
+ int result = -1;
+
+ _E(worklist == NULL);
+
+ /* Abuse hash to count indegree, reachable to mark visited states */
+ list_for_each(s, fa->initial) {
+ s->hash = 0;
+ s->reachable = 0;
+ }
+
+ list_for_each(s, fa->initial) {
+ for_each_trans(t, s) {
+ t->to->hash += 1;
+ }
+ }
+
+ for (struct state *s = fa->initial;
+ s != NULL;
+ s = state_set_pop(worklist)) {
+ for_each_trans(t, s) {
+ struct state *to = t->to;
+ while (to->hash == 1 && to->tused == 1 && ! to->accept) {
+ if (t->re == NULL) {
+ t->re = to->trans->re;
+ to->trans->re = NULL;
+ } else {
+ t->re = make_re_binop(CONCAT, t->re, to->trans->re);
+ if (t->re == NULL)
+ goto error;
+ }
+ t->to = to->trans->to;
+ to->tused = 0;
+ to->hash = 0;
+ to = t->to;
+ }
+
+ if (! to->reachable) {
+ to->reachable = 1;
+ _F(state_set_push(worklist, to));
+ }
+ }
+ }
+
+ for (struct state *s = fa->initial; s->next != NULL; ) {
+ if (s->next->hash == 0 && s->next->tused == 0) {
+ struct state *del = s->next;
+ s->next = del->next;
+ free(del->trans);
+ free(del);
+ } else {
+ s = s->next;
+ }
+ }
+ result = 0;
+
+ error:
+ state_set_free(worklist);
+ return result;
+}
+
/* Convert an FA to a regular expression.
* The strategy is the following:
* (1) For all states S1 and S2, convert the transitions between them
@@ -3841,6 +3903,8 @@ int fa_as_regexp(struct fa *fa, char **regexp, size_t *regexp_len) {
goto error;
set_initial(fa, ini);
+ convert_strings(fa);
+
list_for_each(s, fa->initial->next) {
if (s == fin)
continue;
--
1.6.5.2
More information about the augeas-devel
mailing list