root/scripts/kconfig/expr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. expr_alloc_symbol
  2. expr_alloc_one
  3. expr_alloc_two
  4. expr_alloc_comp
  5. expr_alloc_and
  6. expr_alloc_or
  7. expr_copy
  8. expr_free
  9. __expr_eliminate_eq
  10. expr_eliminate_eq
  11. expr_eq
  12. expr_eliminate_yn
  13. expr_trans_bool
  14. expr_join_or
  15. expr_join_and
  16. expr_eliminate_dups1
  17. expr_eliminate_dups
  18. expr_transform
  19. expr_contains_symbol
  20. expr_depends_symbol
  21. expr_trans_compare
  22. expr_parse_string
  23. expr_calc_value
  24. expr_compare_type
  25. expr_print
  26. expr_print_file_helper
  27. expr_fprint
  28. expr_print_gstr_helper
  29. expr_gstr_print
  30. expr_print_revdep
  31. expr_gstr_print_revdep

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

/* [<][>][^][v][top][bottom][index][help] */