]> git.sur5r.net Git - u-boot/blob - scripts/kconfig/expr.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[u-boot] / scripts / kconfig / expr.c
1 /*
2  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3  * Released under the terms of the GNU GPL v2.0.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "lkc.h"
11
12 #define DEBUG_EXPR      0
13
14 static int expr_eq(struct expr *e1, struct expr *e2);
15 static struct expr *expr_eliminate_yn(struct expr *e);
16 static struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
17 static struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
18 static void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
19
20 struct expr *expr_alloc_symbol(struct symbol *sym)
21 {
22         struct expr *e = xcalloc(1, sizeof(*e));
23         e->type = E_SYMBOL;
24         e->left.sym = sym;
25         return e;
26 }
27
28 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
29 {
30         struct expr *e = xcalloc(1, sizeof(*e));
31         e->type = type;
32         e->left.expr = ce;
33         return e;
34 }
35
36 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
37 {
38         struct expr *e = xcalloc(1, sizeof(*e));
39         e->type = type;
40         e->left.expr = e1;
41         e->right.expr = e2;
42         return e;
43 }
44
45 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
46 {
47         struct expr *e = xcalloc(1, sizeof(*e));
48         e->type = type;
49         e->left.sym = s1;
50         e->right.sym = s2;
51         return e;
52 }
53
54 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
55 {
56         if (!e1)
57                 return e2;
58         return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
59 }
60
61 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
62 {
63         if (!e1)
64                 return e2;
65         return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
66 }
67
68 struct expr *expr_copy(const struct expr *org)
69 {
70         struct expr *e;
71
72         if (!org)
73                 return NULL;
74
75         e = xmalloc(sizeof(*org));
76         memcpy(e, org, sizeof(*org));
77         switch (org->type) {
78         case E_SYMBOL:
79                 e->left = org->left;
80                 break;
81         case E_NOT:
82                 e->left.expr = expr_copy(org->left.expr);
83                 break;
84         case E_EQUAL:
85         case E_UNEQUAL:
86                 e->left.sym = org->left.sym;
87                 e->right.sym = org->right.sym;
88                 break;
89         case E_AND:
90         case E_OR:
91         case E_LIST:
92                 e->left.expr = expr_copy(org->left.expr);
93                 e->right.expr = expr_copy(org->right.expr);
94                 break;
95         default:
96                 printf("can't copy type %d\n", e->type);
97                 free(e);
98                 e = NULL;
99                 break;
100         }
101
102         return e;
103 }
104
105 void expr_free(struct expr *e)
106 {
107         if (!e)
108                 return;
109
110         switch (e->type) {
111         case E_SYMBOL:
112                 break;
113         case E_NOT:
114                 expr_free(e->left.expr);
115                 return;
116         case E_EQUAL:
117         case E_UNEQUAL:
118                 break;
119         case E_OR:
120         case E_AND:
121                 expr_free(e->left.expr);
122                 expr_free(e->right.expr);
123                 break;
124         default:
125                 printf("how to free type %d?\n", e->type);
126                 break;
127         }
128         free(e);
129 }
130
131 static int trans_count;
132
133 #define e1 (*ep1)
134 #define e2 (*ep2)
135
136 static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
137 {
138         if (e1->type == type) {
139                 __expr_eliminate_eq(type, &e1->left.expr, &e2);
140                 __expr_eliminate_eq(type, &e1->right.expr, &e2);
141                 return;
142         }
143         if (e2->type == type) {
144                 __expr_eliminate_eq(type, &e1, &e2->left.expr);
145                 __expr_eliminate_eq(type, &e1, &e2->right.expr);
146                 return;
147         }
148         if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
149             e1->left.sym == e2->left.sym &&
150             (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
151                 return;
152         if (!expr_eq(e1, e2))
153                 return;
154         trans_count++;
155         expr_free(e1); expr_free(e2);
156         switch (type) {
157         case E_OR:
158                 e1 = expr_alloc_symbol(&symbol_no);
159                 e2 = expr_alloc_symbol(&symbol_no);
160                 break;
161         case E_AND:
162                 e1 = expr_alloc_symbol(&symbol_yes);
163                 e2 = expr_alloc_symbol(&symbol_yes);
164                 break;
165         default:
166                 ;
167         }
168 }
169
170 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
171 {
172         if (!e1 || !e2)
173                 return;
174         switch (e1->type) {
175         case E_OR:
176         case E_AND:
177                 __expr_eliminate_eq(e1->type, ep1, ep2);
178         default:
179                 ;
180         }
181         if (e1->type != e2->type) switch (e2->type) {
182         case E_OR:
183         case E_AND:
184                 __expr_eliminate_eq(e2->type, ep1, ep2);
185         default:
186                 ;
187         }
188         e1 = expr_eliminate_yn(e1);
189         e2 = expr_eliminate_yn(e2);
190 }
191
192 #undef e1
193 #undef e2
194
195 static int expr_eq(struct expr *e1, struct expr *e2)
196 {
197         int res, old_count;
198
199         if (e1->type != e2->type)
200                 return 0;
201         switch (e1->type) {
202         case E_EQUAL:
203         case E_UNEQUAL:
204                 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
205         case E_SYMBOL:
206                 return e1->left.sym == e2->left.sym;
207         case E_NOT:
208                 return expr_eq(e1->left.expr, e2->left.expr);
209         case E_AND:
210         case E_OR:
211                 e1 = expr_copy(e1);
212                 e2 = expr_copy(e2);
213                 old_count = trans_count;
214                 expr_eliminate_eq(&e1, &e2);
215                 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
216                        e1->left.sym == e2->left.sym);
217                 expr_free(e1);
218                 expr_free(e2);
219                 trans_count = old_count;
220                 return res;
221         case E_LIST:
222         case E_RANGE:
223         case E_NONE:
224                 /* panic */;
225         }
226
227         if (DEBUG_EXPR) {
228                 expr_fprint(e1, stdout);
229                 printf(" = ");
230                 expr_fprint(e2, stdout);
231                 printf(" ?\n");
232         }
233
234         return 0;
235 }
236
237 static struct expr *expr_eliminate_yn(struct expr *e)
238 {
239         struct expr *tmp;
240
241         if (e) switch (e->type) {
242         case E_AND:
243                 e->left.expr = expr_eliminate_yn(e->left.expr);
244                 e->right.expr = expr_eliminate_yn(e->right.expr);
245                 if (e->left.expr->type == E_SYMBOL) {
246                         if (e->left.expr->left.sym == &symbol_no) {
247                                 expr_free(e->left.expr);
248                                 expr_free(e->right.expr);
249                                 e->type = E_SYMBOL;
250                                 e->left.sym = &symbol_no;
251                                 e->right.expr = NULL;
252                                 return e;
253                         } else if (e->left.expr->left.sym == &symbol_yes) {
254                                 free(e->left.expr);
255                                 tmp = e->right.expr;
256                                 *e = *(e->right.expr);
257                                 free(tmp);
258                                 return e;
259                         }
260                 }
261                 if (e->right.expr->type == E_SYMBOL) {
262                         if (e->right.expr->left.sym == &symbol_no) {
263                                 expr_free(e->left.expr);
264                                 expr_free(e->right.expr);
265                                 e->type = E_SYMBOL;
266                                 e->left.sym = &symbol_no;
267                                 e->right.expr = NULL;
268                                 return e;
269                         } else if (e->right.expr->left.sym == &symbol_yes) {
270                                 free(e->right.expr);
271                                 tmp = e->left.expr;
272                                 *e = *(e->left.expr);
273                                 free(tmp);
274                                 return e;
275                         }
276                 }
277                 break;
278         case E_OR:
279                 e->left.expr = expr_eliminate_yn(e->left.expr);
280                 e->right.expr = expr_eliminate_yn(e->right.expr);
281                 if (e->left.expr->type == E_SYMBOL) {
282                         if (e->left.expr->left.sym == &symbol_no) {
283                                 free(e->left.expr);
284                                 tmp = e->right.expr;
285                                 *e = *(e->right.expr);
286                                 free(tmp);
287                                 return e;
288                         } else if (e->left.expr->left.sym == &symbol_yes) {
289                                 expr_free(e->left.expr);
290                                 expr_free(e->right.expr);
291                                 e->type = E_SYMBOL;
292                                 e->left.sym = &symbol_yes;
293                                 e->right.expr = NULL;
294                                 return e;
295                         }
296                 }
297                 if (e->right.expr->type == E_SYMBOL) {
298                         if (e->right.expr->left.sym == &symbol_no) {
299                                 free(e->right.expr);
300                                 tmp = e->left.expr;
301                                 *e = *(e->left.expr);
302                                 free(tmp);
303                                 return e;
304                         } else if (e->right.expr->left.sym == &symbol_yes) {
305                                 expr_free(e->left.expr);
306                                 expr_free(e->right.expr);
307                                 e->type = E_SYMBOL;
308                                 e->left.sym = &symbol_yes;
309                                 e->right.expr = NULL;
310                                 return e;
311                         }
312                 }
313                 break;
314         default:
315                 ;
316         }
317         return e;
318 }
319
320 /*
321  * bool FOO!=n => FOO
322  */
323 struct expr *expr_trans_bool(struct expr *e)
324 {
325         if (!e)
326                 return NULL;
327         switch (e->type) {
328         case E_AND:
329         case E_OR:
330         case E_NOT:
331                 e->left.expr = expr_trans_bool(e->left.expr);
332                 e->right.expr = expr_trans_bool(e->right.expr);
333                 break;
334         case E_UNEQUAL:
335                 // FOO!=n -> FOO
336                 if (e->left.sym->type == S_TRISTATE) {
337                         if (e->right.sym == &symbol_no) {
338                                 e->type = E_SYMBOL;
339                                 e->right.sym = NULL;
340                         }
341                 }
342                 break;
343         default:
344                 ;
345         }
346         return e;
347 }
348
349 /*
350  * e1 || e2 -> ?
351  */
352 static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
353 {
354         struct expr *tmp;
355         struct symbol *sym1, *sym2;
356
357         if (expr_eq(e1, e2))
358                 return expr_copy(e1);
359         if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
360                 return NULL;
361         if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
362                 return NULL;
363         if (e1->type == E_NOT) {
364                 tmp = e1->left.expr;
365                 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
366                         return NULL;
367                 sym1 = tmp->left.sym;
368         } else
369                 sym1 = e1->left.sym;
370         if (e2->type == E_NOT) {
371                 if (e2->left.expr->type != E_SYMBOL)
372                         return NULL;
373                 sym2 = e2->left.expr->left.sym;
374         } else
375                 sym2 = e2->left.sym;
376         if (sym1 != sym2)
377                 return NULL;
378         if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
379                 return NULL;
380         if (sym1->type == S_TRISTATE) {
381                 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
382                     ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
383                      (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
384                         // (a='y') || (a='m') -> (a!='n')
385                         return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
386                 }
387                 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
388                     ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
389                      (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
390                         // (a='y') || (a='n') -> (a!='m')
391                         return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
392                 }
393                 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
394                     ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
395                      (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
396                         // (a='m') || (a='n') -> (a!='y')
397                         return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
398                 }
399         }
400         if (sym1->type == S_BOOLEAN && sym1 == sym2) {
401                 if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
402                     (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
403                         return expr_alloc_symbol(&symbol_yes);
404         }
405
406         if (DEBUG_EXPR) {
407                 printf("optimize (");
408                 expr_fprint(e1, stdout);
409                 printf(") || (");
410                 expr_fprint(e2, stdout);
411                 printf(")?\n");
412         }
413         return NULL;
414 }
415
416 static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
417 {
418         struct expr *tmp;
419         struct symbol *sym1, *sym2;
420
421         if (expr_eq(e1, e2))
422                 return expr_copy(e1);
423         if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
424                 return NULL;
425         if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
426                 return NULL;
427         if (e1->type == E_NOT) {
428                 tmp = e1->left.expr;
429                 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
430                         return NULL;
431                 sym1 = tmp->left.sym;
432         } else
433                 sym1 = e1->left.sym;
434         if (e2->type == E_NOT) {
435                 if (e2->left.expr->type != E_SYMBOL)
436                         return NULL;
437                 sym2 = e2->left.expr->left.sym;
438         } else
439                 sym2 = e2->left.sym;
440         if (sym1 != sym2)
441                 return NULL;
442         if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
443                 return NULL;
444
445         if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
446             (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
447                 // (a) && (a='y') -> (a='y')
448                 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
449
450         if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
451             (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
452                 // (a) && (a!='n') -> (a)
453                 return expr_alloc_symbol(sym1);
454
455         if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
456             (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
457                 // (a) && (a!='m') -> (a='y')
458                 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
459
460         if (sym1->type == S_TRISTATE) {
461                 if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
462                         // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
463                         sym2 = e1->right.sym;
464                         if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
465                                 return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
466                                                              : expr_alloc_symbol(&symbol_no);
467                 }
468                 if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
469                         // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
470                         sym2 = e2->right.sym;
471                         if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
472                                 return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
473                                                              : expr_alloc_symbol(&symbol_no);
474                 }
475                 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
476                            ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
477                             (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
478                         // (a!='y') && (a!='n') -> (a='m')
479                         return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
480
481                 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
482                            ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
483                             (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
484                         // (a!='y') && (a!='m') -> (a='n')
485                         return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
486
487                 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
488                            ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
489                             (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
490                         // (a!='m') && (a!='n') -> (a='m')
491                         return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
492
493                 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
494                     (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
495                     (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
496                     (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
497                         return NULL;
498         }
499
500         if (DEBUG_EXPR) {
501                 printf("optimize (");
502                 expr_fprint(e1, stdout);
503                 printf(") && (");
504                 expr_fprint(e2, stdout);
505                 printf(")?\n");
506         }
507         return NULL;
508 }
509
510 static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
511 {
512 #define e1 (*ep1)
513 #define e2 (*ep2)
514         struct expr *tmp;
515
516         if (e1->type == type) {
517                 expr_eliminate_dups1(type, &e1->left.expr, &e2);
518                 expr_eliminate_dups1(type, &e1->right.expr, &e2);
519                 return;
520         }
521         if (e2->type == type) {
522                 expr_eliminate_dups1(type, &e1, &e2->left.expr);
523                 expr_eliminate_dups1(type, &e1, &e2->right.expr);
524                 return;
525         }
526         if (e1 == e2)
527                 return;
528
529         switch (e1->type) {
530         case E_OR: case E_AND:
531                 expr_eliminate_dups1(e1->type, &e1, &e1);
532         default:
533                 ;
534         }
535
536         switch (type) {
537         case E_OR:
538                 tmp = expr_join_or(e1, e2);
539                 if (tmp) {
540                         expr_free(e1); expr_free(e2);
541                         e1 = expr_alloc_symbol(&symbol_no);
542                         e2 = tmp;
543                         trans_count++;
544                 }
545                 break;
546         case E_AND:
547                 tmp = expr_join_and(e1, e2);
548                 if (tmp) {
549                         expr_free(e1); expr_free(e2);
550                         e1 = expr_alloc_symbol(&symbol_yes);
551                         e2 = tmp;
552                         trans_count++;
553                 }
554                 break;
555         default:
556                 ;
557         }
558 #undef e1
559 #undef e2
560 }
561
562 static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
563 {
564 #define e1 (*ep1)
565 #define e2 (*ep2)
566         struct expr *tmp, *tmp1, *tmp2;
567
568         if (e1->type == type) {
569                 expr_eliminate_dups2(type, &e1->left.expr, &e2);
570                 expr_eliminate_dups2(type, &e1->right.expr, &e2);
571                 return;
572         }
573         if (e2->type == type) {
574                 expr_eliminate_dups2(type, &e1, &e2->left.expr);
575                 expr_eliminate_dups2(type, &e1, &e2->right.expr);
576         }
577         if (e1 == e2)
578                 return;
579
580         switch (e1->type) {
581         case E_OR:
582                 expr_eliminate_dups2(e1->type, &e1, &e1);
583                 // (FOO || BAR) && (!FOO && !BAR) -> n
584                 tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
585                 tmp2 = expr_copy(e2);
586                 tmp = expr_extract_eq_and(&tmp1, &tmp2);
587                 if (expr_is_yes(tmp1)) {
588                         expr_free(e1);
589                         e1 = expr_alloc_symbol(&symbol_no);
590                         trans_count++;
591                 }
592                 expr_free(tmp2);
593                 expr_free(tmp1);
594                 expr_free(tmp);
595                 break;
596         case E_AND:
597                 expr_eliminate_dups2(e1->type, &e1, &e1);
598                 // (FOO && BAR) || (!FOO || !BAR) -> y
599                 tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
600                 tmp2 = expr_copy(e2);
601                 tmp = expr_extract_eq_or(&tmp1, &tmp2);
602                 if (expr_is_no(tmp1)) {
603                         expr_free(e1);
604                         e1 = expr_alloc_symbol(&symbol_yes);
605                         trans_count++;
606                 }
607                 expr_free(tmp2);
608                 expr_free(tmp1);
609                 expr_free(tmp);
610                 break;
611         default:
612                 ;
613         }
614 #undef e1
615 #undef e2
616 }
617
618 struct expr *expr_eliminate_dups(struct expr *e)
619 {
620         int oldcount;
621         if (!e)
622                 return e;
623
624         oldcount = trans_count;
625         while (1) {
626                 trans_count = 0;
627                 switch (e->type) {
628                 case E_OR: case E_AND:
629                         expr_eliminate_dups1(e->type, &e, &e);
630                         expr_eliminate_dups2(e->type, &e, &e);
631                 default:
632                         ;
633                 }
634                 if (!trans_count)
635                         break;
636                 e = expr_eliminate_yn(e);
637         }
638         trans_count = oldcount;
639         return e;
640 }
641
642 struct expr *expr_transform(struct expr *e)
643 {
644         struct expr *tmp;
645
646         if (!e)
647                 return NULL;
648         switch (e->type) {
649         case E_EQUAL:
650         case E_UNEQUAL:
651         case E_SYMBOL:
652         case E_LIST:
653                 break;
654         default:
655                 e->left.expr = expr_transform(e->left.expr);
656                 e->right.expr = expr_transform(e->right.expr);
657         }
658
659         switch (e->type) {
660         case E_EQUAL:
661                 if (e->left.sym->type != S_BOOLEAN)
662                         break;
663                 if (e->right.sym == &symbol_no) {
664                         e->type = E_NOT;
665                         e->left.expr = expr_alloc_symbol(e->left.sym);
666                         e->right.sym = NULL;
667                         break;
668                 }
669                 if (e->right.sym == &symbol_mod) {
670                         printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
671                         e->type = E_SYMBOL;
672                         e->left.sym = &symbol_no;
673                         e->right.sym = NULL;
674                         break;
675                 }
676                 if (e->right.sym == &symbol_yes) {
677                         e->type = E_SYMBOL;
678                         e->right.sym = NULL;
679                         break;
680                 }
681                 break;
682         case E_UNEQUAL:
683                 if (e->left.sym->type != S_BOOLEAN)
684                         break;
685                 if (e->right.sym == &symbol_no) {
686                         e->type = E_SYMBOL;
687                         e->right.sym = NULL;
688                         break;
689                 }
690                 if (e->right.sym == &symbol_mod) {
691                         printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
692                         e->type = E_SYMBOL;
693                         e->left.sym = &symbol_yes;
694                         e->right.sym = NULL;
695                         break;
696                 }
697                 if (e->right.sym == &symbol_yes) {
698                         e->type = E_NOT;
699                         e->left.expr = expr_alloc_symbol(e->left.sym);
700                         e->right.sym = NULL;
701                         break;
702                 }
703                 break;
704         case E_NOT:
705                 switch (e->left.expr->type) {
706                 case E_NOT:
707                         // !!a -> a
708                         tmp = e->left.expr->left.expr;
709                         free(e->left.expr);
710                         free(e);
711                         e = tmp;
712                         e = expr_transform(e);
713                         break;
714                 case E_EQUAL:
715                 case E_UNEQUAL:
716                         // !a='x' -> a!='x'
717                         tmp = e->left.expr;
718                         free(e);
719                         e = tmp;
720                         e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
721                         break;
722                 case E_OR:
723                         // !(a || b) -> !a && !b
724                         tmp = e->left.expr;
725                         e->type = E_AND;
726                         e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
727                         tmp->type = E_NOT;
728                         tmp->right.expr = NULL;
729                         e = expr_transform(e);
730                         break;
731                 case E_AND:
732                         // !(a && b) -> !a || !b
733                         tmp = e->left.expr;
734                         e->type = E_OR;
735                         e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
736                         tmp->type = E_NOT;
737                         tmp->right.expr = NULL;
738                         e = expr_transform(e);
739                         break;
740                 case E_SYMBOL:
741                         if (e->left.expr->left.sym == &symbol_yes) {
742                                 // !'y' -> 'n'
743                                 tmp = e->left.expr;
744                                 free(e);
745                                 e = tmp;
746                                 e->type = E_SYMBOL;
747                                 e->left.sym = &symbol_no;
748                                 break;
749                         }
750                         if (e->left.expr->left.sym == &symbol_mod) {
751                                 // !'m' -> 'm'
752                                 tmp = e->left.expr;
753                                 free(e);
754                                 e = tmp;
755                                 e->type = E_SYMBOL;
756                                 e->left.sym = &symbol_mod;
757                                 break;
758                         }
759                         if (e->left.expr->left.sym == &symbol_no) {
760                                 // !'n' -> 'y'
761                                 tmp = e->left.expr;
762                                 free(e);
763                                 e = tmp;
764                                 e->type = E_SYMBOL;
765                                 e->left.sym = &symbol_yes;
766                                 break;
767                         }
768                         break;
769                 default:
770                         ;
771                 }
772                 break;
773         default:
774                 ;
775         }
776         return e;
777 }
778
779 int expr_contains_symbol(struct expr *dep, struct symbol *sym)
780 {
781         if (!dep)
782                 return 0;
783
784         switch (dep->type) {
785         case E_AND:
786         case E_OR:
787                 return expr_contains_symbol(dep->left.expr, sym) ||
788                        expr_contains_symbol(dep->right.expr, sym);
789         case E_SYMBOL:
790                 return dep->left.sym == sym;
791         case E_EQUAL:
792         case E_UNEQUAL:
793                 return dep->left.sym == sym ||
794                        dep->right.sym == sym;
795         case E_NOT:
796                 return expr_contains_symbol(dep->left.expr, sym);
797         default:
798                 ;
799         }
800         return 0;
801 }
802
803 bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
804 {
805         if (!dep)
806                 return false;
807
808         switch (dep->type) {
809         case E_AND:
810                 return expr_depends_symbol(dep->left.expr, sym) ||
811                        expr_depends_symbol(dep->right.expr, sym);
812         case E_SYMBOL:
813                 return dep->left.sym == sym;
814         case E_EQUAL:
815                 if (dep->left.sym == sym) {
816                         if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
817                                 return true;
818                 }
819                 break;
820         case E_UNEQUAL:
821                 if (dep->left.sym == sym) {
822                         if (dep->right.sym == &symbol_no)
823                                 return true;
824                 }
825                 break;
826         default:
827                 ;
828         }
829         return false;
830 }
831
832 static struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
833 {
834         struct expr *tmp = NULL;
835         expr_extract_eq(E_AND, &tmp, ep1, ep2);
836         if (tmp) {
837                 *ep1 = expr_eliminate_yn(*ep1);
838                 *ep2 = expr_eliminate_yn(*ep2);
839         }
840         return tmp;
841 }
842
843 static struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
844 {
845         struct expr *tmp = NULL;
846         expr_extract_eq(E_OR, &tmp, ep1, ep2);
847         if (tmp) {
848                 *ep1 = expr_eliminate_yn(*ep1);
849                 *ep2 = expr_eliminate_yn(*ep2);
850         }
851         return tmp;
852 }
853
854 static void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
855 {
856 #define e1 (*ep1)
857 #define e2 (*ep2)
858         if (e1->type == type) {
859                 expr_extract_eq(type, ep, &e1->left.expr, &e2);
860                 expr_extract_eq(type, ep, &e1->right.expr, &e2);
861                 return;
862         }
863         if (e2->type == type) {
864                 expr_extract_eq(type, ep, ep1, &e2->left.expr);
865                 expr_extract_eq(type, ep, ep1, &e2->right.expr);
866                 return;
867         }
868         if (expr_eq(e1, e2)) {
869                 *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
870                 expr_free(e2);
871                 if (type == E_AND) {
872                         e1 = expr_alloc_symbol(&symbol_yes);
873                         e2 = expr_alloc_symbol(&symbol_yes);
874                 } else if (type == E_OR) {
875                         e1 = expr_alloc_symbol(&symbol_no);
876                         e2 = expr_alloc_symbol(&symbol_no);
877                 }
878         }
879 #undef e1
880 #undef e2
881 }
882
883 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
884 {
885         struct expr *e1, *e2;
886
887         if (!e) {
888                 e = expr_alloc_symbol(sym);
889                 if (type == E_UNEQUAL)
890                         e = expr_alloc_one(E_NOT, e);
891                 return e;
892         }
893         switch (e->type) {
894         case E_AND:
895                 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
896                 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
897                 if (sym == &symbol_yes)
898                         e = expr_alloc_two(E_AND, e1, e2);
899                 if (sym == &symbol_no)
900                         e = expr_alloc_two(E_OR, e1, e2);
901                 if (type == E_UNEQUAL)
902                         e = expr_alloc_one(E_NOT, e);
903                 return e;
904         case E_OR:
905                 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
906                 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
907                 if (sym == &symbol_yes)
908                         e = expr_alloc_two(E_OR, e1, e2);
909                 if (sym == &symbol_no)
910                         e = expr_alloc_two(E_AND, e1, e2);
911                 if (type == E_UNEQUAL)
912                         e = expr_alloc_one(E_NOT, e);
913                 return e;
914         case E_NOT:
915                 return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
916         case E_UNEQUAL:
917         case E_EQUAL:
918                 if (type == E_EQUAL) {
919                         if (sym == &symbol_yes)
920                                 return expr_copy(e);
921                         if (sym == &symbol_mod)
922                                 return expr_alloc_symbol(&symbol_no);
923                         if (sym == &symbol_no)
924                                 return expr_alloc_one(E_NOT, expr_copy(e));
925                 } else {
926                         if (sym == &symbol_yes)
927                                 return expr_alloc_one(E_NOT, expr_copy(e));
928                         if (sym == &symbol_mod)
929                                 return expr_alloc_symbol(&symbol_yes);
930                         if (sym == &symbol_no)
931                                 return expr_copy(e);
932                 }
933                 break;
934         case E_SYMBOL:
935                 return expr_alloc_comp(type, e->left.sym, sym);
936         case E_LIST:
937         case E_RANGE:
938         case E_NONE:
939                 /* panic */;
940         }
941         return NULL;
942 }
943
944 tristate expr_calc_value(struct expr *e)
945 {
946         tristate val1, val2;
947         const char *str1, *str2;
948
949         if (!e)
950                 return yes;
951
952         switch (e->type) {
953         case E_SYMBOL:
954                 sym_calc_value(e->left.sym);
955                 return e->left.sym->curr.tri;
956         case E_AND:
957                 val1 = expr_calc_value(e->left.expr);
958                 val2 = expr_calc_value(e->right.expr);
959                 return EXPR_AND(val1, val2);
960         case E_OR:
961                 val1 = expr_calc_value(e->left.expr);
962                 val2 = expr_calc_value(e->right.expr);
963                 return EXPR_OR(val1, val2);
964         case E_NOT:
965                 val1 = expr_calc_value(e->left.expr);
966                 return EXPR_NOT(val1);
967         case E_EQUAL:
968                 sym_calc_value(e->left.sym);
969                 sym_calc_value(e->right.sym);
970                 str1 = sym_get_string_value(e->left.sym);
971                 str2 = sym_get_string_value(e->right.sym);
972                 return !strcmp(str1, str2) ? yes : no;
973         case E_UNEQUAL:
974                 sym_calc_value(e->left.sym);
975                 sym_calc_value(e->right.sym);
976                 str1 = sym_get_string_value(e->left.sym);
977                 str2 = sym_get_string_value(e->right.sym);
978                 return !strcmp(str1, str2) ? no : yes;
979         default:
980                 printf("expr_calc_value: %d?\n", e->type);
981                 return no;
982         }
983 }
984
985 static int expr_compare_type(enum expr_type t1, enum expr_type t2)
986 {
987         if (t1 == t2)
988                 return 0;
989         switch (t1) {
990         case E_EQUAL:
991         case E_UNEQUAL:
992                 if (t2 == E_NOT)
993                         return 1;
994         case E_NOT:
995                 if (t2 == E_AND)
996                         return 1;
997         case E_AND:
998                 if (t2 == E_OR)
999                         return 1;
1000         case E_OR:
1001                 if (t2 == E_LIST)
1002                         return 1;
1003         case E_LIST:
1004                 if (t2 == 0)
1005                         return 1;
1006         default:
1007                 return -1;
1008         }
1009         printf("[%dgt%d?]", t1, t2);
1010         return 0;
1011 }
1012
1013 static inline struct expr *
1014 expr_get_leftmost_symbol(const struct expr *e)
1015 {
1016
1017         if (e == NULL)
1018                 return NULL;
1019
1020         while (e->type != E_SYMBOL)
1021                 e = e->left.expr;
1022
1023         return expr_copy(e);
1024 }
1025
1026 /*
1027  * Given expression `e1' and `e2', returns the leaf of the longest
1028  * sub-expression of `e1' not containing 'e2.
1029  */
1030 struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
1031 {
1032         struct expr *ret;
1033
1034         switch (e1->type) {
1035         case E_OR:
1036                 return expr_alloc_and(
1037                     expr_simplify_unmet_dep(e1->left.expr, e2),
1038                     expr_simplify_unmet_dep(e1->right.expr, e2));
1039         case E_AND: {
1040                 struct expr *e;
1041                 e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
1042                 e = expr_eliminate_dups(e);
1043                 ret = (!expr_eq(e, e1)) ? e1 : NULL;
1044                 expr_free(e);
1045                 break;
1046                 }
1047         default:
1048                 ret = e1;
1049                 break;
1050         }
1051
1052         return expr_get_leftmost_symbol(ret);
1053 }
1054
1055 void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
1056 {
1057         if (!e) {
1058                 fn(data, NULL, "y");
1059                 return;
1060         }
1061
1062         if (expr_compare_type(prevtoken, e->type) > 0)
1063                 fn(data, NULL, "(");
1064         switch (e->type) {
1065         case E_SYMBOL:
1066                 if (e->left.sym->name)
1067                         fn(data, e->left.sym, e->left.sym->name);
1068                 else
1069                         fn(data, NULL, "<choice>");
1070                 break;
1071         case E_NOT:
1072                 fn(data, NULL, "!");
1073                 expr_print(e->left.expr, fn, data, E_NOT);
1074                 break;
1075         case E_EQUAL:
1076                 if (e->left.sym->name)
1077                         fn(data, e->left.sym, e->left.sym->name);
1078                 else
1079                         fn(data, NULL, "<choice>");
1080                 fn(data, NULL, "=");
1081                 fn(data, e->right.sym, e->right.sym->name);
1082                 break;
1083         case E_UNEQUAL:
1084                 if (e->left.sym->name)
1085                         fn(data, e->left.sym, e->left.sym->name);
1086                 else
1087                         fn(data, NULL, "<choice>");
1088                 fn(data, NULL, "!=");
1089                 fn(data, e->right.sym, e->right.sym->name);
1090                 break;
1091         case E_OR:
1092                 expr_print(e->left.expr, fn, data, E_OR);
1093                 fn(data, NULL, " || ");
1094                 expr_print(e->right.expr, fn, data, E_OR);
1095                 break;
1096         case E_AND:
1097                 expr_print(e->left.expr, fn, data, E_AND);
1098                 fn(data, NULL, " && ");
1099                 expr_print(e->right.expr, fn, data, E_AND);
1100                 break;
1101         case E_LIST:
1102                 fn(data, e->right.sym, e->right.sym->name);
1103                 if (e->left.expr) {
1104                         fn(data, NULL, " ^ ");
1105                         expr_print(e->left.expr, fn, data, E_LIST);
1106                 }
1107                 break;
1108         case E_RANGE:
1109                 fn(data, NULL, "[");
1110                 fn(data, e->left.sym, e->left.sym->name);
1111                 fn(data, NULL, " ");
1112                 fn(data, e->right.sym, e->right.sym->name);
1113                 fn(data, NULL, "]");
1114                 break;
1115         default:
1116           {
1117                 char buf[32];
1118                 sprintf(buf, "<unknown type %d>", e->type);
1119                 fn(data, NULL, buf);
1120                 break;
1121           }
1122         }
1123         if (expr_compare_type(prevtoken, e->type) > 0)
1124                 fn(data, NULL, ")");
1125 }
1126
1127 static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
1128 {
1129         xfwrite(str, strlen(str), 1, data);
1130 }
1131
1132 void expr_fprint(struct expr *e, FILE *out)
1133 {
1134         expr_print(e, expr_print_file_helper, out, E_NONE);
1135 }
1136
1137 static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
1138 {
1139         struct gstr *gs = (struct gstr*)data;
1140         const char *sym_str = NULL;
1141
1142         if (sym)
1143                 sym_str = sym_get_string_value(sym);
1144
1145         if (gs->max_width) {
1146                 unsigned extra_length = strlen(str);
1147                 const char *last_cr = strrchr(gs->s, '\n');
1148                 unsigned last_line_length;
1149
1150                 if (sym_str)
1151                         extra_length += 4 + strlen(sym_str);
1152
1153                 if (!last_cr)
1154                         last_cr = gs->s;
1155
1156                 last_line_length = strlen(gs->s) - (last_cr - gs->s);
1157
1158                 if ((last_line_length + extra_length) > gs->max_width)
1159                         str_append(gs, "\\\n");
1160         }
1161
1162         str_append(gs, str);
1163         if (sym && sym->type != S_UNKNOWN)
1164                 str_printf(gs, " [=%s]", sym_str);
1165 }
1166
1167 void expr_gstr_print(struct expr *e, struct gstr *gs)
1168 {
1169         expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1170 }