]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add support for REL_ELSE
authorMichael Schroeder <mls@suse.de>
Mon, 24 Aug 2015 20:06:41 +0000 (22:06 +0200)
committerMichael Schroeder <mls@suse.de>
Mon, 24 Aug 2015 20:06:41 +0000 (22:06 +0200)
Also make REL_COND strictly OR_NOT, even in an OR
context like Conflicts or Supplements.

bindings/solv.i
ext/pool_parserpmrichdep.c
ext/testcase.c
src/cplxdeps.c
src/cplxdeps.h
src/pool.c
src/pool.h
src/poolid.c
src/rules.c
src/solver_private.h

index 9cca7002e8faca6895f40c87dfab37d1466f63e7..cc721e2054fe26c99d0529b6a73ce198df65e911 100644 (file)
@@ -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;
index 742823a9d6915f7d4202551674f54387878505f7..b048aeb4464ba2a63d7992f075560f5f6f2effcb 100644 (file)
@@ -13,7 +13,6 @@
 #include "pool_parserpmrichdep.h"
 
 #define REL_THEN 0
-#define REL_ELSE 0
 
 static struct RichOpComp {
   const char *n;
index f8935a6b3a3ce68ed53a9b49716bbf8ec8457bc9..e4346fe76d7f5ab88424db663a2bece5279a3742 100644 (file)
@@ -378,6 +378,7 @@ struct oplist {
   { REL_COND,  "<IF>" },
   { REL_COMPAT,  "compat >=" },
   { REL_KIND,  "<KIND>" },
+  { REL_ELSE, "<ELSE>" },
   { REL_LT, "<" },
   { 0, 0 }
 };
index 1be68688a6c6d8ef962910ccc43b45207d0877f2..2248b8b8205d4f43902857c7ae7d85c937c13746 100644 (file)
@@ -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");
index b5533054a0138f5eb3bfd2c901a502f82d34ff34..1cda760e66a3f151187c57e0125b20656d3a4b3c 100644 (file)
@@ -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
 
index 0f95b3322e8a5c47cb52fe26f4edc117594fe676..33293b5b00ec06ff813d8fc310b607b40f9da1ed 100644 (file)
@@ -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)
            {
index 6b98efc9ce4ac6291cb8ca199d08b7f863c78e22..4a2089d8b89f30085c25249fbaffdb53d3bddf00 100644 (file)
@@ -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)
index 7bcc1f6094e46562c8f5a16002170ef782fb626e..2138c421906629c7cd8be1c8cea1e92823539082 100644 (file)
@@ -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;
     }
index 67de769ad4703bcdace7e1b06c1641c06f10f33c..7a6d7fdee84c4077033d7d47012612bfdd7861cb 100644 (file)
@@ -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;
index f8df8c7132d0ba03f48910b649d3fbdba53e0329..fe80881337cc9735720d56bec4cd8923a7b52561 100644 (file)
@@ -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;