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