Annotation of 43BSD/ingres/source/parser/norml.c, revision 1.1.1.1

1.1       root        1: # include      <ingres.h>
                      2: # include      <aux.h>
                      3: # include      <tree.h>
                      4: # include      <symbol.h>
                      5: # include      <sccs.h>
                      6: 
                      7: SCCSID(@(#)norml.c     8.1     12/31/84)
                      8: 
                      9: /*
                     10: **  NORML.C -- functions for normalizing tree
                     11: **
                     12: **     Defines
                     13: **             norml -- main routine
                     14: **             norm
                     15: **             travers
                     16: **             nnorm
                     17: **             notpush
                     18: **             adjust
                     19: **             treedup
                     20: **             mvands
                     21: **
                     22: **     Trace Flags:
                     23: **             NORMAL.C ~~ 56, 57
                     24: */
                     25: 
                     26: /*
                     27: **  NORML -- normalizing routine
                     28: **
                     29: **     this routine passes the qualification clause portion of the query
                     30: **     tree to the routines for depressing nots and for conjunctive 
                     31: **     normalization.  It also calls a routine to place an and with one
                     32: **     null branch at the rightmost end of the tree.
                     33: **
                     34: **     Parameters:
                     35: **             ptr -- tree to normalize
                     36: **
                     37: **     Returns:
                     38: **             nothing
                     39: **
                     40: **     Trace Flags:
                     41: **             norml ~~ 56.0
                     42: */
                     43: 
                     44: QTREE *
                     45: norml(ptr)
                     46: QTREE  *ptr;
                     47: {
                     48:        extern QTREE    *nnorm();
                     49:        extern QTREE    *travers();
                     50:        extern QTREE    *tree();
                     51:        extern char     Qbuf[];
                     52: 
                     53: # ifdef        xPTR1
                     54:        tTfp(56, 0, "norml(%d)\n", ptr);
                     55: # endif
                     56: 
                     57:        if (ptr == NULL)
                     58:                return (tree(NULL, NULL, QLEND, 0, 0));
                     59: 
                     60:        /* push through the 'nots' as far a possible */
                     61:        ptr = nnorm(ptr);
                     62: 
                     63:        /* make tree into conjunctive normal form */
                     64:        ptr = travers(ptr);
                     65: 
                     66:        /* terminate the list on the rightmost branch */
                     67:        adjust(&ptr);
                     68: 
                     69:        /* make 'ands' into a linear list */
                     70:        mvands(ptr);
                     71: 
                     72: # ifdef        xPTR1
                     73:        tTfp(56, 1, ">>norml(%d)\n", ptr);
                     74: # endif
                     75: 
                     76:        return (ptr);
                     77: }
                     78: 
                     79: 
                     80: /*
                     81: ** NORM
                     82: **     this routine takes a tree which has nots only at the lower ends, and
                     83: **     places it into conjunctive normal form by repeatedly applying the
                     84: **     replacement rule: A or (B and C) ==> (A or B) and (A or C)
                     85: **
                     86: **     Trace Flags:
                     87: **             norm ~~ 56.4
                     88: */
                     89: 
                     90: QTREE *
                     91: norm(p)
                     92: register QTREE         *p;
                     93: {
                     94:        register QTREE          *lptr;
                     95:        register QTREE          *rptr;
                     96:        extern QTREE            *treedup();
                     97:        extern QTREE            *tree();
                     98: 
                     99: # ifdef        xPTR1
                    100:        tTfp(56, 4, "norm(%d)\n", p);
                    101: # endif
                    102: 
                    103:        switch (p->sym.type)
                    104:        {
                    105:          case AND:
                    106:                p->left = norm(p->left);
                    107:                p->right = norm(p->right);
                    108:                break;
                    109: 
                    110:          case OR:
                    111:                if (p->right->sym.type == AND)
                    112:                {
                    113:                andright:
                    114:                        /*
                    115:                        ** combine left subtree with each subtree of the
                    116:                        ** right subtree
                    117:                        */
                    118:                        /*
                    119:                        ** use copy first so that the copy is guaranteed to be
                    120:                        ** the same as the original
                    121:                        */
                    122:                        lptr = tree(treedup(p->left), p->right->left, OR, sizeof(struct rootnode) - 2, 0);
                    123:                        rptr = tree(p->left, p->right->right, OR, sizeof(struct rootnode) - 2, 0);
                    124:                        lptr = norm(lptr);
                    125:                        rptr = norm(rptr);
                    126:                        /* change node type to AND from OR */
                    127:                        p->left = lptr;
                    128:                        p->right = rptr;
                    129:                        p->sym.type = AND;      /* length is same */
                    130:                        break;
                    131:                }
                    132:                if (p->left->sym.type == AND)
                    133:                {
                    134:                andleft:
                    135:                        /*
                    136:                        ** combine right subtree with each subtree of the
                    137:                        ** left subtree
                    138:                        */
                    139:                        /*
                    140:                        ** again, the copy should be used first
                    141:                        */
                    142:                        lptr = tree(p->left->left, treedup(p->right), OR, sizeof(struct rootnode) - 2, 0);
                    143:                        rptr = tree(p->left->right, p->right, OR, sizeof(struct rootnode) - 2, 0);
                    144:                        lptr = norm(lptr);
                    145:                        rptr = norm(rptr);
                    146:                        /* change node type to AND from OR */
                    147:                        p->left = lptr;
                    148:                        p->right = rptr;
                    149:                        p->sym.type = AND;
                    150:                        break;
                    151:                }
                    152:                /*
                    153:                ** when TRAVERS is being used to optomize the normalization
                    154:                ** order there should never be (I think) an OR as a child
                    155:                ** of the OR in the parent.  Since TRAVERS works bottom up
                    156:                ** in the tree the second OR level should be gone.
                    157:                */
                    158:                if (p->right->sym.type == OR)
                    159:                {
                    160:                        /* skip this (p->sym.type) "or" and normalize the right subtree */
                    161:                        p->right = norm(p->right);
                    162: 
                    163:                        /* now re-try the current node */
                    164:                        if (p->right->sym.type == AND)
                    165:                                goto andright;
                    166:                        break;
                    167:                }
                    168:                if (p->left->sym.type == OR)
                    169:                {
                    170:                        /* skip this "or" and normalize the left subtree */
                    171:                        p->left = norm(p->left);
                    172: 
                    173:                        /* now re-try the current node */
                    174:                        if (p->left->sym.type == AND)
                    175:                                goto andleft;
                    176:                        break;
                    177:                }
                    178:                break;
                    179:        }
                    180:        return (p);
                    181: }
                    182: 
                    183: /*
                    184: ** TRAVERS
                    185: **     traverse the tree so that conversion of ORs of ANDs can
                    186: **     take place at the innermost clauses first.  IE, normalize
                    187: **     before replication rather than after replication.
                    188: **
                    189: **     This routine need not be used.  The NORM routine will completely
                    190: **     traverse the tree and normalize it but...    TRAVERS finds
                    191: **     the lowest subtree to normalize first so that sub-trees can
                    192: **     be normalized before replication, hence reducing the time required
                    193: **     to normalize large trees.  It will also make OR-less trees faster
                    194: **     to normalize (since nothing need be done to it).
                    195: **
                    196: **     Trace Flags:
                    197: **             travers ~~ 56.8
                    198: */
                    199: 
                    200: QTREE *
                    201: travers(p1)
                    202: QTREE  *p1;
                    203: {
                    204:        register QTREE  *p;
                    205:        extern QTREE            *norm();
                    206: 
                    207: # ifdef        xPTR1
                    208:        tTfp(56, 8, "travers(%d)\n", p1);
                    209: # endif
                    210: 
                    211:        p = p1;
                    212:        if (p->right != NULL)
                    213:                p->right = travers(p->right);
                    214:        if (p->left != NULL)
                    215:                p->left = travers(p->left);
                    216:        if (p->sym.type == OR)
                    217:                p = norm(p);
                    218:        return (p);
                    219: }
                    220: /*
                    221: ** NNORM
                    222: **     this routine depresses nots in the query tree to the lowest possible
                    223: **     nodes.  It may also affect arithmetic operators in this procedure
                    224: **
                    225: **     Trace Flags:
                    226: **             nnorm ~~ 56.12
                    227: */
                    228: QTREE *
                    229: nnorm(p1)
                    230: QTREE  *p1;
                    231: {
                    232:        extern QTREE            *notpush();
                    233:        register QTREE  *p;
                    234: 
                    235: # ifdef        xPTR1
                    236:        tTfp(56, 12, "nnorm(%d)\n", p1);
                    237: # endif
                    238: 
                    239:        p = p1;
                    240:        if (p->sym.type == AGHEAD)
                    241:        {
                    242:                /*
                    243:                ** don't need to continue past an AGHEAD
                    244:                ** actually, it causes problems if you do
                    245:                ** because the qualification on the agg
                    246:                ** has already been normalized and the
                    247:                ** QLEND needs to stay put
                    248:                */
                    249:                return (p);
                    250:        }
                    251:        if ((p->sym.type == UOP) && (p->sym.value.sym_op.opno == opNOT))
                    252:        {
                    253:                /* skip not node */
                    254:                p = p->right;
                    255:                p = notpush(p);
                    256:        }
                    257:        else
                    258:        {
                    259:                if (p->left != NULL)
                    260:                        p->left = nnorm(p->left);
                    261:                if (p->right != NULL)
                    262:                        p->right = nnorm(p->right);
                    263:        }
                    264:        return (p);
                    265: }
                    266: 
                    267: /*
                    268: ** NOTPUSH
                    269: **     this routine decides what to do once a not has been found in the
                    270: **     query tree
                    271: **
                    272: **     Trace Flags:
                    273: **             notpush ~~ 57.0
                    274: */
                    275: QTREE *
                    276: notpush(p1)
                    277: QTREE  *p1;
                    278: {
                    279:        extern QTREE            *nnorm();
                    280:        register QTREE  *p;
                    281: 
                    282: # ifdef        xPTR1
                    283:        tTfp(57, 0, "notpush(%d)\n", p1);
                    284: # endif
                    285: 
                    286:        p = p1;
                    287:        switch (p->sym.type)
                    288:        {
                    289:          case AND:
                    290:                p->sym.type = OR;
                    291:                p->left = notpush(p->left);
                    292:                p->right = notpush(p->right);
                    293:                break;
                    294: 
                    295:          case OR:
                    296:                p->sym.type = AND;
                    297:                p->left = notpush(p->left);
                    298:                p->right = notpush(p->right);
                    299:                break;
                    300: 
                    301:          case BOP:
                    302:                switch (p->sym.value.sym_op.opno)
                    303:                {
                    304:                  case opEQ:
                    305:                        p->sym.value.sym_op.opno = opNE;
                    306:                        break;
                    307: 
                    308:                  case opNE:
                    309:                        p->sym.value.sym_op.opno = opEQ;
                    310:                        break;
                    311: 
                    312:                  case opLT:
                    313:                        p->sym.value.sym_op.opno = opGE;
                    314:                        break;
                    315: 
                    316:                  case opGE:
                    317:                        p->sym.value.sym_op.opno = opLT;
                    318:                        break;
                    319: 
                    320:                  case opLE:
                    321:                        p->sym.value.sym_op.opno = opGT;
                    322:                        break;
                    323: 
                    324:                  case opGT:
                    325:                        p->sym.value.sym_op.opno = opLE;
                    326:                        break;
                    327: 
                    328:                  default:
                    329:                        syserr("strange BOP in notpush '%d'", p->sym.value.sym_op.opno);
                    330:                }
                    331:                break;
                    332: 
                    333:          case UOP:
                    334:                if (p->sym.value.sym_op.opno == opNOT)
                    335:                {
                    336:                        /* skip not node */
                    337:                        p = p->right;
                    338:                        p = nnorm(p);
                    339:                }
                    340:                else
                    341:                        syserr("strange UOP in notpush '%d'", p->sym.value.sym_op.opno);
                    342:                break;
                    343: 
                    344:          default:
                    345:                syserr("unrecognizable node type in notpush '%d'", p->sym.type);
                    346:        }
                    347:        return (p);
                    348: }
                    349: 
                    350: /*
                    351: ** ADJUST
                    352: **     terminate qual with an AND and a QLEND at the rightmost branch
                    353: **
                    354: **     Trace Flags:
                    355: **             adjust ~~ 57.4
                    356: */
                    357: adjust(pp)
                    358: QTREE  **pp;
                    359: {
                    360:        extern QTREE            *tree();
                    361:        register QTREE  *p;
                    362: 
                    363: # ifdef        xPTR1
                    364:        tTfp(57, 4, "adjust(%d)\n", pp);
                    365: # endif
                    366: 
                    367:        p = *pp;
                    368:        switch (p->sym.type)
                    369:        {
                    370:          case AND: 
                    371:                adjust(&(p->right));
                    372:                break;
                    373: 
                    374:          case OR:
                    375:          default:
                    376:                *pp = tree(p, tree(NULL, NULL, QLEND, 0, NULL), AND, sizeof(struct rootnode) - 2, 0);
                    377:                break;
                    378:        }
                    379: }
                    380: /*
                    381: **  TREEDUP -- 
                    382: **
                    383: **     Trace Flags:
                    384: **             norm ~~ 57.8
                    385: */
                    386: 
                    387: 
                    388: QTREE
                    389: *treedup(p1)
                    390: QTREE  *p1;
                    391: {
                    392:        register QTREE  *np;
                    393:        register QTREE  *p;
                    394:        extern char     Qbuf[];
                    395:        extern char     *need();
                    396: 
                    397: # ifdef        xPTR1
                    398:        tTfp(57, 8, "treedup(%d)\n", p1);
                    399: # endif
                    400: 
                    401:        if ((p = p1) == NULL)
                    402:                return (p);
                    403: 
                    404:        np = (QTREE *) need(Qbuf, (p->sym.len & I1MASK) + QT_HDR_SIZ);
                    405: 
                    406:        bmove(p, np, (p->sym.len & I1MASK) + QT_HDR_SIZ);
                    407: 
                    408:        np->left = treedup(p->left);
                    409:        np->right = treedup(p->right);
                    410:        return (np);
                    411: }
                    412: 
                    413: /*
                    414: **     MVANDS -- pushes all AND's in Qual into linear list
                    415: **
                    416: **     Trace Flags:
                    417: **             mvands ~~ 57.12
                    418: */
                    419: mvands(andp)
                    420: QTREE  *andp;
                    421: {
                    422:        register QTREE  *ap, *lp, *rp;
                    423: 
                    424: # ifdef        xPTR1
                    425:        tTfp(57, 12, "mvands(%d)\n", andp);
                    426: # endif
                    427: 
                    428:        ap = andp;
                    429:        if (ap->sym.type == QLEND)
                    430:                return;
                    431:        rp = ap->right;
                    432:        lp = ap->left;
                    433:        if (lp->sym.type == AND)
                    434:        {
                    435:                ap->left = lp->right;
                    436:                ap->right = lp;
                    437:                lp->right = rp;
                    438:                mvands(ap);
                    439:        }
                    440:        else
                    441:                mvands(rp);
                    442: }

unix.superglobalmegacorp.com

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