From: Michael Schroeder Date: Mon, 24 Aug 2015 20:06:41 +0000 (+0200) Subject: Add support for REL_ELSE X-Git-Tag: 0.6.12~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c537cf0379b3e96277012766dde7eaf24142d64e;p=thirdparty%2Flibsolv.git Add support for REL_ELSE Also make REL_COND strictly OR_NOT, even in an OR context like Conflicts or Supplements. --- diff --git a/bindings/solv.i b/bindings/solv.i index 9cca7002..cc721e20 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -755,6 +755,11 @@ typedef int Id; %constant int REL_GT; %constant int REL_LT; %constant int REL_ARCH; +%constant int REL_AND; +%constant int REL_OR; +%constant int REL_WITH; +%constant int REL_COND; +%constant int REL_ELSE; typedef struct { Pool* const pool; diff --git a/ext/pool_parserpmrichdep.c b/ext/pool_parserpmrichdep.c index 742823a9..b048aeb4 100644 --- a/ext/pool_parserpmrichdep.c +++ b/ext/pool_parserpmrichdep.c @@ -13,7 +13,6 @@ #include "pool_parserpmrichdep.h" #define REL_THEN 0 -#define REL_ELSE 0 static struct RichOpComp { const char *n; diff --git a/ext/testcase.c b/ext/testcase.c index f8935a6b..e4346fe7 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -378,6 +378,7 @@ struct oplist { { REL_COND, "" }, { REL_COMPAT, "compat >=" }, { REL_KIND, "" }, + { REL_ELSE, "" }, { REL_LT, "<" }, { 0, 0 } }; diff --git a/src/cplxdeps.c b/src/cplxdeps.c index 1be68688..2248b8b8 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"); diff --git a/src/cplxdeps.h b/src/cplxdeps.h index b5533054..1cda760e 100644 --- a/src/cplxdeps.h +++ b/src/cplxdeps.h @@ -34,5 +34,12 @@ extern int pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags); #define CPLXDEPS_NAME (1 << 3) #define CPLXDEPS_DONTFIX (1 << 4) +#define CPLXDEPS_ELSE_AND_1 (1 << 8) +#define CPLXDEPS_ELSE_AND_2 (1 << 9) +#define CPLXDEPS_ELSE_OR_1 (1 << 10) +#define CPLXDEPS_ELSE_OR_2 (1 << 11) +#define CPLXDEPS_ELSE_OR_3 (1 << 12) +#define CPLXDEPS_ELSE_MASK (0x1f00) + #endif diff --git a/src/pool.c b/src/pool.c index 0f95b332..33293b5b 100644 --- a/src/pool.c +++ b/src/pool.c @@ -1014,10 +1014,21 @@ pool_addrelproviders(Pool *pool, Id d) case REL_AND: case REL_OR: + case REL_COND: + if (flags == REL_COND) + { + if (ISRELDEP(evr)) + { + Reldep *rd2 = GETRELDEP(pool, evr); + evr = rd2->flags == REL_ELSE ? rd2->evr : 0; + } + else + evr = 0; /* assume cond is true */ + } wp = pool_whatprovides(pool, name); if (!pool->whatprovidesdata[wp]) - wp = pool_whatprovides(pool, evr); - else + wp = evr ? pool_whatprovides(pool, evr) : 1; + else if (evr) { /* sorted merge */ pp2 = pool_whatprovides_ptr(pool, evr); @@ -1043,11 +1054,6 @@ pool_addrelproviders(Pool *pool, Id d) } break; - case REL_COND: - /* assume the condition is true */ - wp = pool_whatprovides(pool, name); - break; - case REL_NAMESPACE: if (name == NAMESPACE_OTHERPROVIDERS) { diff --git a/src/pool.h b/src/pool.h index 6b98efc9..4a2089d8 100644 --- a/src/pool.h +++ b/src/pool.h @@ -222,6 +222,7 @@ struct _Pool { #define REL_COMPAT 23 #define REL_KIND 24 /* for filters only */ #define REL_MULTIARCH 25 /* debian multiarch annotation */ +#define REL_ELSE 26 /* only as evr part of REL_COND */ #if !defined(__GNUC__) && !defined(__attribute__) # define __attribute__(x) diff --git a/src/poolid.c b/src/poolid.c index 7bcc1f60..2138c421 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -192,6 +192,8 @@ pool_id2rel(const Pool *pool, Id id) return " compat >= "; case REL_KIND: return " KIND "; + case REL_ELSE: + return " ELSE "; default: break; } diff --git a/src/rules.c b/src/rules.c index 67de769a..7a6d7fde 100644 --- a/src/rules.c +++ b/src/rules.c @@ -52,7 +52,9 @@ dep_possible(Solver *solv, Id dep, Map *m) Reldep *rd = GETRELDEP(pool, dep); if (rd->flags >= 8) { - if (rd->flags == REL_AND || rd->flags == REL_COND) + if (rd->flags == REL_COND) + return 1; + if (rd->flags == REL_AND) { if (!dep_possible(solv, rd->name, m)) return 0; diff --git a/src/solver_private.h b/src/solver_private.h index f8df8c71..fe808813 100644 --- a/src/solver_private.h +++ b/src/solver_private.h @@ -27,7 +27,23 @@ solver_dep_fulfilled(Solver *solv, Id dep) if (ISRELDEP(dep)) { Reldep *rd = GETRELDEP(pool, dep); - if (rd->flags == REL_AND || rd->flags == REL_COND) + if (rd->flags == REL_COND) + { + if (ISRELDEP(rd->evr)) + { + Reldep *rd2 = GETRELDEP(pool, rd->evr); + if (rd2->flags == REL_ELSE) + { + if (solver_dep_fulfilled(solv, rd2->name)) + return solver_dep_fulfilled(solv, rd->name); + return solver_dep_fulfilled(solv, rd2->evr); + } + } + if (solver_dep_fulfilled(solv, rd->name)) + return 1; + return !solver_dep_fulfilled(solv, rd->evr); + } + if (rd->flags == REL_AND) { if (!solver_dep_fulfilled(solv, rd->name)) return 0;