Annotation of qemu/roms/seabios/tools/kconfig/expr.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.