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