Annotation of 43BSD/ingres/source/decomp/aggregate.c, revision 1.1.1.1

1.1       root        1: # include      <ingres.h>
                      2: # include      <tree.h>
                      3: # include      <symbol.h>
                      4: # include      "globs.h"
                      5: # include      <sccs.h>
                      6: # include      <errors.h>
                      7: 
                      8: SCCSID(@(#)aggregate.c 8.3     2/8/85)
                      9: 
                     10: 
                     11: 
                     12: 
                     13: /*
                     14: **     AGGREGATE - replace aggregates with their values
                     15: **
                     16: **     Aggregate attempts to optimize aggregate processing
                     17: **     wherever possible. It replaces aggregates with their
                     18: **     values, and links aggregate functions which have
                     19: **     identical by-lists together.
                     20: **
                     21: **     Note that for the sake of this code, A "prime"
                     22: **     aggregate is one in which duplicates are removed.
                     23: **     These are COUNTU, SUMU, and AVGU.
                     24: **
                     25: **     Aggregate first forms a list of all aggregates in
                     26: **     the order they should be processed.
                     27: **
                     28: **     For each aggregate, it looks at all other aggregates
                     29: **     to see if there are two simple aggregates
                     30: **     or if there is another aggregate funtion with the
                     31: **     same by-list.
                     32: **
                     33: **     An attempt is made to run
                     34: **     as many aggregates as possible at once. This can be
                     35: **     done only if two or more aggregates have the same
                     36: **     qualifications and in the case of aggregate functions,
                     37: **     they must have identical by-lists.
                     38: **     Even then, certain combinations
                     39: **     of aggregates cannot occure together. The list is
                     40: **     itemized later in the code.
                     41: **
                     42: **     Aggregate calls BYEVAL or AGEVAL to actually process
                     43: **     aggregate functions or aggregates respectively.
                     44: **
                     45: **     Trace Flags:
                     46: **             40
                     47: */
                     48: 
                     49: aggregate(root)
                     50: QTREE  *root;
                     51: {
                     52:        struct agglist  alist[MAXAGG + 1];
                     53:        QTREE           *rlist[MAXAGG + 1];
                     54:        struct agglist  *al, *al1;
                     55:        register QTREE  *agg, *aop1, *r;
                     56:        QTREE           *aop, *agg1;
                     57:        int             i, simple_agg, varmap;
                     58:        int             attcnt, anyagg, attoff, twidth;
                     59:        QTREE           *makavar(), *agspace();
                     60:        extern char     *rangename();
                     61:        extern QTREE    *ageval();
                     62:        extern QTREE    *byeval();
                     63: 
                     64:        al = alist;
                     65:        De.de_aggnext = al;
                     66:        De.de_agglim = &al[MAXAGG];
                     67: 
                     68:        findagg(&root, root);   /* generate list of all aggregates */
                     69:        De.de_aggnext->agpoint = 0;     /* mark end of the list */
                     70:        anyagg = 0;
                     71: 
                     72:        varmap = root->sym.value.sym_root.lvarm | root->sym.value.sym_root.rvarm;
                     73: 
                     74:        /* process each aggregate */
                     75:        for (;agg = al->agpoint; al++)
                     76:        {
                     77:                /* is this still an aggregate? */
                     78:                if (agg->sym.type != AGHEAD)
                     79:                        continue;
                     80:                mapvar(agg, 0); /* map the aggregate tree */
                     81:                anyagg++;
                     82: 
                     83:                De.de_sourcevar = bitpos(agg->sym.value.sym_root.lvarm | agg->sym.value.sym_root.rvarm);
                     84: #              ifdef xDTR1
                     85:                if (tTf(40, 4))
                     86:                        printf("De.de_sourcevar=%d,rel=%s\n", De.de_sourcevar, rangename(De.de_sourcevar));
                     87: #              endif
                     88: 
                     89:                simple_agg = (agg->left->sym.type == AOP);      /* TRUE if no bylist */
                     90:                aop = agg->left;        /* assume it was TRUE */
                     91: #              ifdef xDTR1
                     92:                if (tTf(40, 0))
                     93:                        printf("%s\n", simple_agg ? "agg" : "agg-func");
                     94: #              endif
                     95:                if (simple_agg)
                     96:                {
                     97:                        /* simple aggregate */
                     98:                        rlist[0] = agspace(aop);
                     99:                        twidth = aop->sym.value.sym_op.opfrml & I1MASK; /* init width to the width of the aggregate */
                    100:                }
                    101:                else
                    102:                {
                    103:                        attoff = agg->left->left->sym.value.sym_resdom.resno + 2;
                    104:                        aop = aop->right;       /* find the AOP node */
                    105:                        /* assign  new source variable for aggregate */
                    106:                        al->agvarno = getrange(&varmap);
                    107:                        /* compute width of bylist + count field */
                    108:                        twidth = findwid(agg->left) + 4;
                    109: 
                    110:                        /* make sure the aggregate does not exceed max dimensions */
                    111:                        if (chkwidth(aop, &twidth, attoff))
                    112:                                derror(AGFTOBIG);
                    113:                }
                    114:                attcnt = 1;     /* one aggregate so far */
                    115: 
                    116:                /* look for another identical aggregate */
                    117:                for (al1 = al + 1; agg1 = al1->agpoint; al1++)
                    118:                {
                    119: 
                    120:                        /* if agg is nested inside agg1 then ignore it */
                    121:                        if (al->agfather == agg1 || agg1->sym.type != AGHEAD)
                    122:                        {
                    123:                                continue;
                    124:                        }
                    125: 
                    126:                        /* split aggs and agg-func apart */
                    127:                        /* check for identical aggregate */
                    128:                        if (simple_agg)
                    129:                        {
                    130:                                aop1 = agg1->left;      /* find AOP node */
                    131: 
                    132:                                if (aop1->sym.type != AOP)
                    133:                                        continue;       /* not a simple agg */
                    134: 
                    135:                                /* make sure they can be run together */
                    136:                                if (checkagg(agg, aop, agg1, aop1) == 0) 
                    137:                                        continue;
                    138: 
                    139:                                if ((i = sameagg(agg, aop1, attcnt)) >= 0)
                    140:                                {
                    141:                                        /* found identical aggregate to rlist[i] */
                    142:                                        r = rlist[i];
                    143:                                }
                    144:                                else
                    145:                                {
                    146:                                        /* put this agg in with the others */
                    147: 
                    148:                                        /* first make sure it won't exceed tuple length */
                    149:                                        if (chkwidth(aop1, &twidth, 0))
                    150:                                                continue;       /* can't be included */
                    151:                                        r = rlist[attcnt++] = agspace(aop1);
                    152: 
                    153:                                        /* connect into tree */
                    154:                                        aop1->left = agg->left;
                    155:                                        agg->left = aop1;
                    156:                                }
                    157:                        }
                    158:                        else
                    159:                        {
                    160:                                /* aggregate function */
                    161:                                if (!sameafcn(agg->left->left, agg1->left->left))
                    162:                                        continue;
                    163: 
                    164:                                aop1 = agg1->left->right;       /* find AOP */
                    165: 
                    166: 
                    167:                                if (checkagg(agg, aop, agg1, aop1) == 0)
                    168:                                {
                    169:                                        /* same by-lists but they can't be run together */
                    170:                                        continue;
                    171:                                }
                    172: 
                    173:                                if ((i = sameagg(agg, aop1, attcnt)) < 0)
                    174:                                {
                    175:                                        /* make sure there is room */
                    176:                                        if (chkwidth(aop1, &twidth, attcnt + attoff))
                    177:                                                continue;
                    178: 
                    179:                                        /* add aggregate into tree */
                    180:                                        i = attcnt++;
                    181: 
                    182:                                        aop1->left = agg->left->right;
                    183:                                        agg->left->right = aop1;
                    184:                                }
                    185: 
                    186:                                r = makavar(aop1, al->agvarno, i + attoff);
                    187:                        }
                    188:                        /* replace aggregate in original tree with its value */
                    189:                        *(al1->father) = r;
                    190: 
                    191:                        /* remove aggregate from local list */
                    192:                        agg1->sym.type = -1;
                    193: #                      ifdef xDTR1
                    194:                        if (tTf(40, 3))
                    195:                                printf("including aghead %x\n", agg1);
                    196: #                      endif
                    197:                }
                    198: 
                    199:                /* process aggregate */
                    200:                if (simple_agg)
                    201:                {
                    202:                        rlist[attcnt] = 0;
                    203:                        ageval(agg, rlist);     /* pass tree and result list */
                    204:                        r = rlist[0];
                    205:                }
                    206:                else
                    207:                {
                    208:                        opt_bylist(alist, agg);
                    209:                        byeval(al->agfather, agg, al->agvarno);
                    210:                        r = makavar(aop, al->agvarno, attoff);
                    211:                }
                    212:                /*
                    213:                ** Link result into tree. al->father hold the address
                    214:                ** &(tree->left) or &(tree->right).
                    215:                */
                    216:                *(al->father) = r;
                    217: #              ifdef xDTR1
                    218:                if (tTf(40, 4))
                    219:                {
                    220:                        printf("agg value\n");
                    221:                        treepr(*(al->father));
                    222:                }
                    223: #              endif
                    224:        }
                    225:        if (anyagg)
                    226:        {
                    227:                opt_bylist(alist, root);
                    228:                mapvar(root, 0);        /* remap main tree */
                    229:        }
                    230: }
                    231: /*
                    232: **     findagg builds a list of all aggregates
                    233: **     in the tree. It finds them by leftmost
                    234: **     innermost first.
                    235: **
                    236: **     The parameters represent:
                    237: **             nodep:  the address of the node pointing to you
                    238: **                             eg. &(tree->left) or &(tree->right)
                    239: **             agf:    the root node. or if we are inside
                    240: **                     a nested aggregate, the AGHEAD node
                    241: */
                    242: 
                    243: findagg(nodep,  agf)
                    244: QTREE  **nodep;
                    245: QTREE  *agf;
                    246: {
                    247:        register QTREE          *q, *f;
                    248:        register struct agglist *list;
                    249:        int                     agg;
                    250: 
                    251:        if ((q = *nodep) == NULL)
                    252:                return;
                    253: 
                    254:        f = agf;
                    255:        if (agg = (q->sym.type == AGHEAD))
                    256:                f = q;  /* this aggregate is now the father root */
                    257: 
                    258:        /* find all aggregates below */
                    259:        findagg(&(q->left), f);
                    260:        findagg(&(q->right), f);
                    261: 
                    262:        /* if this is an aggregate, put it on the list */
                    263:        if (agg)
                    264:        {
                    265:                if (De.de_aggnext >= De.de_agglim)
                    266:                        derror(TOOMANYAGGS);
                    267:                list = De.de_aggnext;
                    268:                list->father = nodep;
                    269:                list->agpoint = q;
                    270:                list->agfather = agf;
                    271:                De.de_aggnext++;
                    272:        }
                    273: }
                    274: /*
                    275: **     Agspace allocates space for the result of
                    276: **     a simple aggregate.
                    277: */
                    278: 
                    279: QTREE *
                    280: agspace(aop)
                    281: QTREE  *aop;
                    282: {
                    283:        register QTREE  *a, *r;
                    284:        register int    length;
                    285:        extern char     *need();
                    286: 
                    287:        a = aop;
                    288:        length = a->sym.value.sym_op.opfrml & I1MASK;
                    289:        r = (QTREE *) need(De.de_qbuf, length + QT_HDR_SIZ);
                    290:        r->left = r->right = 0;
                    291:        r->sym.type = a->sym.value.sym_op.opfrmt;
                    292:        r->sym.len = length;
                    293: 
                    294:        return (r);
                    295: }
                    296: /*
                    297: ** Chkwidth -- make sure that the inclusion of another aggregate will
                    298: **     not exceed the system limit. This means that the total width
                    299: **     cannot exceed MAXTUP and the number of domains cannot exceed MAXDOM-1
                    300: */
                    301: 
                    302: chkwidth(aop, widthp, domno)
                    303: QTREE  *aop;
                    304: int    *widthp;
                    305: int    domno;
                    306: {
                    307:        register int    width;
                    308: 
                    309:        width = *widthp;
                    310: 
                    311: #      ifdef xDTR1
                    312:        if (tTf(40, 10))
                    313:                printf("agg width %d,dom %d\n", width, domno);
                    314: #      endif
                    315: 
                    316:        width += (aop->sym.value.sym_op.opfrml & I1MASK);
                    317: 
                    318:        if (width > MAXTUP || domno > MAXDOM - 1)
                    319:                return (1);
                    320: 
                    321:        *widthp = width;
                    322:        return (0);
                    323: }
                    324: /*
                    325: **     Determine whether an aggregate is prime
                    326: **     or a don't care aggregate. Returns TRUE
                    327: **     if COUNTU,SUMU,AVGU,MIN,MAX,ANY.
                    328: **     Returns false if COUNT,SUM,AVG.
                    329: */
                    330: 
                    331: cprime(aop)
                    332: QTREE  *aop;
                    333: {
                    334:        register int    i;
                    335: 
                    336:        i = TRUE;
                    337:        switch (aop->sym.value.sym_op.opno)
                    338:        {
                    339:          case opCOUNT:
                    340:          case opSUM:
                    341:          case opAVG:
                    342:                i = FALSE;
                    343:        }
                    344:        return (i);
                    345: }
                    346: /*
                    347: **     Getrange find a free slot in the range table
                    348: **     for an aggregate function.
                    349: **
                    350: **     If there are no free slots,derror is called
                    351: */
                    352: 
                    353: getrange(varmap)
                    354: int    *varmap;
                    355: {
                    356:        register int    i, map, bit;
                    357: 
                    358:        map = *varmap;
                    359: 
                    360:        for (i = 0; i < MAXRANGE; i++)
                    361:        {
                    362:                /* if slot is used, continue */
                    363:                if ((bit = 1 << i) & map)
                    364:                        continue;
                    365: 
                    366:                map |= bit;     /* "or" bit into the map */
                    367:                *varmap = map;
                    368: 
                    369: #              ifdef xDTR1
                    370:                if (tTf(40, 10))
                    371:                        printf("Assn var %d, map %o\n", i, map);
                    372: #              endif
                    373: 
                    374:                return (i);
                    375:        }
                    376:        derror(NODESCAG);
                    377:        return  (-1);
                    378: }
                    379: 
                    380: 
                    381: checkagg(aghead1, aop1, aghead2, aop2)
                    382: QTREE  *aghead1;
                    383: QTREE  *aop1;
                    384: QTREE  *aghead2;
                    385: QTREE  *aop2;
                    386: {
                    387:        register QTREE  *aop_1, *aop_2, *agg1;
                    388:        int             ok;
                    389: 
                    390:        /* two aggregate functions can be run together
                    391:        ** according to the following table:
                    392:        **
                    393:        **              prime   !prime  don't care
                    394:        **
                    395:        ** prime        afcn?   never   afcn?
                    396:        ** !prime       never   always  always
                    397:        ** don't care   afcn?   always  always
                    398:        **
                    399:        ** don't care includes: ANY, MIN, MAX
                    400:        ** afcn? means only if a-fcn's are identical
                    401:        */
                    402: 
                    403:        aop_1 = aop1;
                    404:        aop_2 = aop2;
                    405:        agg1 = aghead1;
                    406: 
                    407:        if (!prime(aop_1) && !prime(aop_2))
                    408:                ok = TRUE;
                    409:        else
                    410:                if (sameafcn(aop_1->right, aop_2->right))
                    411:                        ok = cprime(aop_1) && cprime(aop_2);
                    412:                else
                    413:                        ok = FALSE;
                    414:        /* The two aggregates must range over the same variables */
                    415:        if ((agg1->sym.value.sym_root.lvarm | agg1->sym.value.sym_root.rvarm) != (aghead2->sym.value.sym_root.lvarm | aghead2->sym.value.sym_root.rvarm))
                    416:                ok = FALSE;
                    417: 
                    418: 
                    419:        /* check the qualifications */
                    420:        if (ok)
                    421:                ok = sameafcn(agg1->right, aghead2->right);
                    422:        return (ok);
                    423: }
                    424: 
                    425: 
                    426: sameagg(aghead, newaop, agg_depth)
                    427: QTREE  *aghead;
                    428: QTREE  *newaop;
                    429: int    agg_depth;
                    430: {
                    431:        register QTREE  *agg, *newa;
                    432:        register int    i;
                    433: 
                    434:        agg = aghead;
                    435:        newa = newaop;
                    436:        agg = agg->left;
                    437:        if (agg->sym.type == BYHEAD)
                    438:                agg = agg->right;
                    439: 
                    440:        /* agg now points to first aggregate */
                    441:        for (i = 1; agg; agg = agg->left, i++)
                    442:                if (sameafcn(agg->right, newa->right) && agg->sym.value.sym_resdom.resno == newa->sym.value.sym_op.opno)
                    443:                {
                    444: #                      ifdef xDTR1
                    445:                        if (tTf(40, 6))
                    446:                                printf("found identical aop %x\n", newa);
                    447: #                      endif
                    448:                        return (agg_depth - i);
                    449:                }
                    450: 
                    451:        /* no match */
                    452:        return (-1);
                    453: }
                    454: 
                    455: 
                    456: 
                    457: 
                    458: opt_bylist(alist, root)
                    459: struct agglist *alist;
                    460: QTREE          *root;
                    461: {
                    462:        register struct agglist *al;
                    463:        register QTREE          *agg;
                    464:        register struct hitlist *hl;
                    465:        QTREE                   **tpr, *tree, *lnodv[MAXDOM+2];
                    466:        struct hitlist          hlist[30];
                    467:        int                     anyop, i, usedmap, vars, treemap;
                    468: 
                    469:        /* compute bitmap of all possible vars in tree (can include xtra vars) */
                    470:        treemap = root->sym.value.sym_root.lvarm | root->sym.value.sym_root.rvarm;
                    471:        anyop = FALSE;
                    472: 
                    473:        /* scan the list of aggregates looking for one nested in root */
                    474:        for (al = alist; (agg = al->agpoint) && agg != root; al++)
                    475:        {
                    476:                if (agg->sym.type == AGHEAD && agg->left->sym.type == BYHEAD &&
                    477:                                al->agfather == root)
                    478:                {
                    479: 
                    480:                        /* this aggregate function is nested in root */
                    481: 
                    482:                        /* make sure it has some vars of interest */
                    483:                        if ((treemap & varfind(agg->left->left, (QTREE *)NULL)) == 0)
                    484:                                continue;
                    485: 
                    486: #                      ifdef xDTR1
                    487:                        if (tTf(40, 11))
                    488:                        {
                    489:                                printf("nested agg\n");
                    490:                                treepr(agg);
                    491:                        }
                    492: #                      endif
                    493: 
                    494:                        /* form list of bydomains */
                    495:                        lnodv[lnode(agg->left->left, lnodv, 0)] = 0;
                    496:                        usedmap = 0;
                    497: 
                    498:                        De.de_hnext = &hlist[0];
                    499:                        De.de_hlimit = &hlist[30];
                    500: 
                    501:                        /* find all possible replacements */
                    502:                        vars = modtree(&root, lnodv, &usedmap);
                    503: 
                    504:                        /*
                    505:                        ** All references to a variable must be replaced
                    506:                        ** in order to use this aggregates by-domains.
                    507:                        */
                    508:                        if (usedmap && ((vars & usedmap) == 0))
                    509:                        {
                    510: #                              ifdef xDTR1
                    511:                                if (tTf(40, 7))
                    512:                                        printf("Committed\n");
                    513: #                              endif
                    514:                                /* success. Committ the tree changes */
                    515:                                De.de_hnext->trepr = NULL;
                    516: 
                    517:                                for (hl = &hlist[0]; tpr = hl->trepr; hl++)
                    518:                                {
                    519:                                        /* get bydomain number */
                    520:                                        i = hl->byno;
                    521: 
                    522:                                        /* get node being replaced */
                    523:                                        tree = *tpr;
                    524: 
                    525:                                        /* if it is already a var, just change it */
                    526:                                        if (tree->sym.type == VAR)
                    527:                                        {
                    528:                                                tree->sym.value.sym_var.varno = al->agvarno;
                    529:                                                tree->sym.value.sym_var.attno = i + 2;
                    530:                                        }
                    531:                                        else
                    532:                                                *tpr = makavar(lnodv[i], al->agvarno, i + 2);
                    533: 
                    534:                                        anyop = TRUE;
                    535: #                                      ifdef xDTR1
                    536:                                        if (tTf(40, 7))
                    537:                                        {
                    538:                                                printf("modified tree\n");
                    539:                                                treepr(*tpr);
                    540:                                        }
                    541: #                                      endif
                    542:                                }
                    543:                        }
                    544:                        /* vars is now a map of the variables in the root */
                    545:                        treemap = vars;
                    546:                }
                    547:        }
                    548: 
                    549:        /* if any changes were made, get rid of the unnecessary links */
                    550:        if (anyop)
                    551:                chklink(root);
                    552: }
                    553: 
                    554: 
                    555: 
                    556: 
                    557: modtree(pnode, lnodv, replmap)
                    558: QTREE  **pnode;
                    559: QTREE  *lnodv[];
                    560: int    *replmap;
                    561: {
                    562:        register QTREE  *tree;
                    563:        register int    vars, i;
                    564:        QTREE           *afcn;
                    565: 
                    566:        /* point up current node */
                    567:        if ((tree = *pnode) == NULL)
                    568:                return (0);
                    569: 
                    570:        /* examine each by-list for match on this subtree */
                    571:        for (i = 0; afcn = lnodv[i]; i++)
                    572:        {
                    573:                if (sameafcn(tree, afcn->right))
                    574:                {
                    575: #                      ifdef xDTR1
                    576:                        if (tTf(40, 9))
                    577:                        {
                    578:                                printf("potential Jackpot");
                    579:                                treepr(tree);
                    580:                        }
                    581: #                      endif
                    582:                        vars = varfind(tree, (QTREE *)NULL);
                    583:                        if (De.de_hnext == De.de_hlimit)
                    584:                                return (vars);  /* no more room */
                    585: 
                    586:                        /* record what needs to be done */
                    587:                        De.de_hnext->trepr = pnode;
                    588:                        De.de_hnext->byno = i;
                    589:                        De.de_hnext++;
                    590:                        *replmap |= vars;
                    591:                        return (0);
                    592:                }
                    593:        }
                    594:        if (tree->sym.type == VAR)
                    595:                return (01 << tree->sym.value.sym_var.varno);
                    596: 
                    597:        /* try the subtrees */
                    598:        vars = modtree(&(tree->left), lnodv, replmap);
                    599:        if ((vars & *replmap) == 0)
                    600:                vars |= modtree(&(tree->right), lnodv, replmap);
                    601: 
                    602:        return (vars);
                    603: }
                    604: 
                    605: 
                    606: chklink(root)
                    607: QTREE  *root;
                    608: {
                    609:        register QTREE  *r, *b, *last;
                    610: 
                    611:        last = root;
                    612: 
                    613:        for (r = last->right; r->sym.type != QLEND; r = r->right)
                    614:        {
                    615:                /* if this is an EQ node then check for an unnecessary compare */
                    616:                if ((b = r->left)->sym.type == BOP && b->sym.value.sym_op.opno == opEQ)
                    617:                {
                    618:                        if (sameafcn(b->left, b->right))
                    619:                        {
                    620: #                              ifdef xDTR1
                    621:                                if (tTf(40, 5))
                    622:                                {
                    623:                                        printf("unnec clause\n");
                    624:                                        treepr(b);
                    625:                                }
                    626: #                              endif
                    627:                                last->right = r->right;
                    628:                                continue;
                    629:                        }
                    630:                }
                    631:                last = r;
                    632:        }
                    633: }
                    634: 
                    635: 
                    636: 
                    637: sameafcn(q1, q2)
                    638: QTREE *q1, *q2;
                    639: {
                    640: 
                    641:        register QTREE  *t1, *t2;
                    642:        register int    len;
                    643:        int             type;
                    644: 
                    645:        t1 = q1;
                    646:        t2 = q2;
                    647: 
                    648:        if (!(t1 && t2)) 
                    649:                return(!(t1 || t2));
                    650:        len = (t1->sym.len & I1MASK) + SYM_HDR_SIZ;
                    651:        type = t1->sym.type;
                    652:        if (type == VAR)
                    653:                len = sizeof(struct varnode);
                    654:        if (type == AND)
                    655:                len = 2;
                    656:        if (!bequal(&t1->sym.type, &t2->sym.type, len)) 
                    657:                return(0);
                    658:        return(sameafcn(t1->left,t2->left) && sameafcn(t1->right,t2->right));
                    659: }
                    660: /*
                    661: **     varfind -- find all variables in the tree pointed to by "root".
                    662: **             Examine all parts of the tree except aggregates. For
                    663: **             aggregates, ignore simple aggregate and look only
                    664: **             at the by-lists of aggregate functions. If the aggregate
                    665: **             is "aghead" then ignore it. There is no reason to look
                    666: **             at yourself!!!!
                    667: **             This routine is called by byeval() to determine
                    668: **             whether to link the aggregate to the root tree.
                    669: **
                    670: **     Curiosity note: since the tree being examined has not been
                    671: **     processed by decomp yet, ckvar does not need to be called
                    672: **     since the var could not have been altered.
                    673: */
                    674: 
                    675: varfind(root, aghead)
                    676: QTREE  *root;
                    677: QTREE  *aghead;
                    678: {
                    679:        register QTREE  *tree;
                    680:        register int    type;
                    681: 
                    682:        if ((tree = root) == NULL)
                    683:                return (0);
                    684: 
                    685:        if ((type = tree->sym.type) == AGHEAD)
                    686:        {
                    687:                /* ignore if it matches aghead */
                    688:                if (tree == aghead)
                    689:                        return (0);
                    690:                /* if this is an aggregate function, look at bylist */
                    691:                tree = tree->left;
                    692:                if ((type = tree->sym.type) != BYHEAD)
                    693:                        return (0);
                    694:        }
                    695: 
                    696:        if (type == VAR)
                    697:                return (1 << tree->sym.value.sym_var.varno);
                    698: 
                    699:        return (varfind(tree->left, aghead) | varfind(tree->right, aghead));
                    700: }

unix.superglobalmegacorp.com

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