2 * Copyright (c) 2014, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * normalize complex dependencies into CNF/DNF form
23 #ifdef ENABLE_COMPLEX_DEPS
28 pool_is_complex_dep_rd(Pool *pool, Reldep *rd)
32 if (rd->flags == REL_AND || rd->flags == REL_COND) /* those two are the complex ones */
34 if (rd->flags != REL_OR)
36 if (ISRELDEP(rd->name) && pool_is_complex_dep_rd(pool, GETRELDEP(pool, rd->name)))
38 if (!ISRELDEP(rd->evr))
40 rd = GETRELDEP(pool, rd->evr);
44 /* expand simple dependencies into package lists */
46 expand_simpledeps(Pool *pool, Queue *bq, int start, int split)
51 for (i = start; i < end; i++)
54 newsplit = bq->count - (end - start);
56 if (x == pool->nsolvables)
58 Id *dp = pool->whatprovidesdata + bq->elements[++i];
66 newsplit = bq->count - (end - start);
67 queue_deleten(bq, start, end - start);
71 /* invert all literals in the blocks. note that this also turns DNF into CNF and vice versa */
73 invert_depblocks(Pool *pool, Queue *bq, int start)
76 expand_simpledeps(pool, bq, start, 0);
78 for (i = j = start; i < end; i++)
82 bq->elements[i] = -bq->elements[i];
85 /* end of block reached, reorder */
89 for (k = i - 1; j < k; j++, k--)
91 Id t = bq->elements[j];
92 bq->elements[j] = bq->elements[k];
104 * -1: at least one block
107 normalize_dep(Pool *pool, Id dep, Queue *bq, int todnf)
109 int bqcnt = bq->count;
114 printf("normalize_dep %s todnf:%d\n", pool_dep2str(pool, dep), todnf);
116 if (pool_is_complex_dep(pool, dep))
118 Reldep *rd = GETRELDEP(pool, dep);
119 if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
121 int flags = rd->flags;
124 /* in inverted mode, COND means AND. otherwise it means OR NOT */
125 if (flags == REL_COND && todnf)
127 mode = flags == REL_AND ? 0 : 1;
129 /* get blocks of first argument */
130 r = normalize_dep(pool, rd->name, bq, todnf);
133 if (flags == REL_AND)
135 if (flags == REL_COND)
137 r = normalize_dep(pool, rd->evr, bq, todnf ^ 1);
138 if (r == 0 || r == 1)
139 return r == 0 ? 1 : 0;
140 invert_depblocks(pool, bq, bqcnt); /* invert block for COND */
143 return normalize_dep(pool, rd->evr, bq, todnf);
147 if (flags != REL_AND)
149 return normalize_dep(pool, rd->evr, bq, todnf);
152 /* get blocks of second argument */
154 /* COND is OR with NEG on evr block, so we invert the todnf flag in that case*/
155 r = normalize_dep(pool, rd->evr, bq, flags == REL_COND ? todnf ^ 1 : todnf);
160 queue_truncate(bq, bqcnt);
161 return flags == REL_COND ? 1 : 0;
167 queue_truncate(bq, bqcnt);
172 if (flags == REL_COND)
173 invert_depblocks(pool, bq, bqcnt2); /* invert 2nd block */
176 /* simple case: just join em. nothing more to do here. */
178 printf("SIMPLE JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
184 /* complex case: mix em */
187 printf("COMPLEX JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
189 bqcnt2 = expand_simpledeps(pool, bq, bqcnt, bqcnt2);
191 for (i = bqcnt; i < bqcnt2; i++)
193 for (j = bqcnt2; j < bqcnt3; j++)
196 int bqcnt4 = bq->count;
199 /* mix i block with j block, both blocks are sorted */
200 while (bq->elements[k] && bq->elements[j])
202 if (bq->elements[k] < bq->elements[j])
203 queue_push(bq, bq->elements[k++]);
206 if (bq->elements[k] == bq->elements[j])
208 queue_push(bq, bq->elements[j++]);
211 while (bq->elements[j])
212 queue_push(bq, bq->elements[j++]);
213 while (bq->elements[k])
214 queue_push(bq, bq->elements[k++]);
216 /* block is finished, check for A + -A */
217 for (a = bqcnt4, b = bq->count - 1; a < b; )
219 if (-bq->elements[a] == bq->elements[b])
221 if (-bq->elements[a] > bq->elements[b])
227 queue_truncate(bq, bqcnt4); /* ignore this block */
229 queue_push(bq, 0); /* finish block */
231 /* advance to next block */
232 while (bq->elements[i])
236 if (bqcnt3 == bq->count) /* ignored all blocks? */
238 queue_deleten(bq, bqcnt, bqcnt3 - bqcnt);
244 /* fallback case: just use package list */
245 dp = pool_whatprovides(pool, dep);
246 if (dp <= 2 || !pool->whatprovidesdata[dp])
247 return dp == 2 ? 1 : 0;
250 for (; pool->whatprovidesdata[dp]; dp++)
251 queue_push2(bq, pool->whatprovidesdata[dp], 0);
255 queue_push2(bq, pool->nsolvables, dp); /* not yet expanded marker */
262 pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags)
264 int i, bqcnt = bq->count;
266 i = normalize_dep(pool, dep, bq, (flags & CPLXDEPS_TODNF) ? 1 : 0);
267 if ((flags & CPLXDEPS_EXPAND) != 0)
269 if (i != 0 && i != 1)
270 expand_simpledeps(pool, bq, bqcnt, 0);
272 if ((flags & CPLXDEPS_INVERT) != 0)
274 if (i == 0 || i == 1)
277 invert_depblocks(pool, bq, bqcnt);
286 for (i = bqcnt; i < bq->count; i++)
288 if (bq->elements[i] == pool->nsolvables)
290 Id *dp = pool->whatprovidesdata + bq->elements[++i];
293 printf(" %s", pool_solvid2str(pool, *dp++));
296 else if (bq->elements[i] > 0)
297 printf(" %s", pool_solvid2str(pool, bq->elements[i]));
298 else if (bq->elements[i] < 0)
299 printf(" -%s", pool_solvid2str(pool, -bq->elements[i]));
310 #endif /* ENABLE_COMPLEX_DEPS */