summaryrefslogtreecommitdiff
path: root/src/cplxdeps.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cplxdeps.c')
-rw-r--r--src/cplxdeps.c170
1 files changed, 144 insertions, 26 deletions
diff --git a/src/cplxdeps.c b/src/cplxdeps.c
index 1be6868..aadbc48 100644
--- a/src/cplxdeps.c
+++ b/src/cplxdeps.c
@@ -96,10 +96,12 @@ print_depblocks(Pool *pool, Queue *bq, int start)
#endif
/* invert all literals in the blocks. note that this also turns DNF into CNF and vice versa */
-static void
-invert_depblocks(Pool *pool, Queue *bq, int start)
+static int
+invert_depblocks(Pool *pool, Queue *bq, int start, int r)
{
int i, j, end;
+ if (r == 0 || r == 1)
+ return r ? 0 : 1;
expand_simpledeps(pool, bq, start, 0);
end = bq->count;
for (i = j = start; i < end; i++)
@@ -122,6 +124,7 @@ invert_depblocks(Pool *pool, Queue *bq, int start)
}
j = i + 1;
}
+ return -1;
}
/*
@@ -147,40 +150,129 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
{
int rdflags = rd->flags;
+ Id name = rd->name;
+ Id evr = rd->evr;
int r, mode;
- /* in inverted mode, COND means AND. otherwise it means OR NOT */
- if (rdflags == REL_COND && todnf)
- rdflags = REL_AND;
- mode = rdflags == REL_AND ? 0 : 1;
+ if (rdflags == REL_COND)
+ {
+ /* check for relly complex ELSE case */
+ if (ISRELDEP(evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ int r2;
+ /* really complex case */
+ if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_1)
+ {
+ /* A OR ~B */
+ rdflags = REL_COND;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_2)
+ {
+ /* C OR B */
+ rdflags = REL_OR;
+ name = rd2->evr;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_1)
+ {
+ /* A AND B */
+ rdflags = REL_AND;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_2)
+ {
+ /* A AND C */
+ rdflags = REL_AND;
+ evr = rd2->evr;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_3)
+ {
+ /* C AND ~B */
+ rdflags = REL_ELSE;
+ name = rd2->evr;
+ evr = rd2->name;
+ }
+ else if (!todnf)
+ {
+ /* we want AND: A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
+ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_1);
+ if (r == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
+ return 0;
+ r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_2);
+ if (r2 == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
+ {
+ queue_truncate(bq, bqcnt);
+ return 0;
+ }
+ if (r == -1 || r2 == -1)
+ return -1;
+ return r == 1 || r2 == 1 ? 1 : 0;
+ }
+ else
+ {
+ int r2, r3;
+ /* we want OR: A IF (B ELSE C) -> (A AND B) OR (A AND C) OR (~B AND C) */
+ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_1);
+ if (r == 1)
+ return 1;
+ r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_2);
+ if (r2 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ r3 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_3);
+ if (r3 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ if (r == -1 || r2 == -1 || r3 == -1)
+ return -1;
+ return 0;
+ }
+ }
+ }
+ }
+ mode = rdflags == REL_AND || rdflags == REL_ELSE ? 0 : 1;
/* get blocks of first argument */
- r = normalize_dep(pool, rd->name, bq, flags);
+ r = normalize_dep(pool, name, bq, flags);
if (r == 0)
{
+ if (rdflags == REL_ELSE)
+ return 0;
if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0)
return 0;
if (rdflags == REL_COND)
{
- r = normalize_dep(pool, rd->evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
- if (r == 0 || r == 1)
- return r == 0 ? 1 : 0;
- invert_depblocks(pool, bq, bqcnt); /* invert block for COND */
- return r;
+ r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
+ return invert_depblocks(pool, bq, bqcnt, r); /* invert block for COND */
}
- return normalize_dep(pool, rd->evr, bq, flags);
+ return normalize_dep(pool, evr, bq, flags);
}
if (r == 1)
{
- if (rdflags != REL_AND)
+ if (rdflags == REL_ELSE)
+ {
+ r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
+ return invert_depblocks(pool, bq, bqcnt, r); /* invert block for ELSE */
+ }
+ if (rdflags == REL_OR || rdflags == REL_COND)
return 1;
- return normalize_dep(pool, rd->evr, bq, flags);
+ return normalize_dep(pool, evr, bq, flags);
}
/* get blocks of second argument */
bqcnt2 = bq->count;
/* COND is OR with NEG on evr block, so we invert the todnf flag in that case */
- r = normalize_dep(pool, rd->evr, bq, rdflags == REL_COND ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
+ r = normalize_dep(pool, evr, bq, rdflags == REL_COND || rdflags == REL_ELSE ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
+ if (rdflags == REL_COND || rdflags == REL_ELSE)
+ r = invert_depblocks(pool, bq, bqcnt2, r); /* invert 2nd block */
if (r == 0)
{
if (rdflags == REL_OR)
@@ -188,19 +280,17 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0)
return -1;
queue_truncate(bq, bqcnt);
- return rdflags == REL_COND ? 1 : 0;
+ return 0;
}
if (r == 1)
{
- if (rdflags == REL_OR)
+ if (rdflags == REL_COND || rdflags == REL_OR)
{
queue_truncate(bq, bqcnt);
return 1;
}
return -1;
}
- if (rdflags == REL_COND)
- invert_depblocks(pool, bq, bqcnt2); /* invert 2nd block */
if (mode == todnf)
{
/* simple case: just join em. nothing more to do here. */
@@ -315,12 +405,7 @@ pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags)
expand_simpledeps(pool, bq, bqcnt, 0);
}
if ((flags & CPLXDEPS_INVERT) != 0)
- {
- if (i == 0 || i == 1)
- i ^= 1;
- else
- invert_depblocks(pool, bq, bqcnt);
- }
+ i = invert_depblocks(pool, bq, bqcnt, i);
#ifdef CPLXDEBUG
if (i == 0)
printf("NONE\n");
@@ -332,5 +417,38 @@ pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags)
return i;
}
+void
+pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg)
+{
+ while (ISRELDEP(dep))
+ {
+ Reldep *rd = GETRELDEP(pool, dep);
+ if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND)
+ break;
+ pool_add_pos_literals_complex_dep(pool, rd->name, q, m, neg);
+ dep = rd->evr;
+ if (rd->flags == REL_COND)
+ {
+ neg = !neg;
+ if (ISRELDEP(dep))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ pool_add_pos_literals_complex_dep(pool, rd2->evr, q, m, !neg);
+ dep = rd2->name;
+ }
+ }
+ }
+ }
+ if (!neg)
+ {
+ Id p, pp;
+ FOR_PROVIDES(p, pp, dep)
+ if (!MAPTST(m, p))
+ queue_push(q, p);
+ }
+}
+
#endif /* ENABLE_COMPLEX_DEPS */