Annotation of cci/usr/src/bin/cdb/expr.c, revision 1.1.1.1

1.1       root        1: static char sccsid[] = "@(#)expr.c     2.12";
                      2: 
                      3: #include "cdb.h"
                      4: #include "macdefs.h"
                      5: 
                      6: extern long atol();
                      7: extern double atof();
                      8: extern int vrgOffset[];        /* defined in access.c */
                      9: 
                     10: /* the following define the stack mechanism used by the expression parser */
                     11: 
                     12: export int    viopMac;        /* operator stack pointer */
                     13: export int    vivarMac;       /* variable stack pointer */
                     14: 
                     15: #define istkMax 15
                     16: TYR     vrgTy[cTyMax*istkMax];  /* variable stack */
                     17: ADRT   vrgAdr[cTyMax*istkMax]; /* addresses of the variables in vrgTy */
                     18: TKE     vrgTk[istkMax];         /* operator stack */
                     19: 
                     20: #define TOPOP (vrgTk[viopMac-1])
                     21: #define TOPVAR (vrgTy[vivarMac-1])
                     22: #define EmptyStack (vivarMac==0)
                     23: #define precParen 99
                     24: 
                     25: /* parser state */
                     26: #define psFail  0               /* parser tripped */
                     27: #define psOp    1               /* expression parser last saw an OPERATOR */
                     28: #define psVar   2               /* expression parser last saw an VARIABLE */
                     29: typedef int  PSE, *pPSE;     /* parser state */
                     30: 
                     31: ADRT   vadrSb, vadrSbMax;      /* where we can stick strings in child */
                     32: 
                     33: /* P U S H    O P */
                     34: 
                     35: local void PushOp(tk)
                     36: TKE     tk;
                     37: {
                     38:        if (viopMac >= istkMax)
                     39:                UError("Expression stack overflow");
                     40:        vrgTk[viopMac++] = tk;
                     41: } /* PushOp */
                     42: 
                     43: 
                     44: /* P O P    O P */
                     45: 
                     46: local TKE PopOp()
                     47: {
                     48:        if (viopMac <= 0)
                     49:                UError("Operator stack underflow");
                     50:        return(vrgTk[--viopMac]);
                     51: } /* PopOp */
                     52: 
                     53: 
                     54: /* P U S H    V A R */
                     55: 
                     56: local void PushVar(adrLong, ty)
                     57: long    adrLong;
                     58: pTYR    ty;
                     59: {
                     60:        if (vivarMac >= istkMax)
                     61:                UError("Expression stack overflow");
                     62:        CopyTy(vrgTy+vivarMac, ty);
                     63:        vrgAdr[vivarMac] = adrLong;
                     64:        vivarMac += 2;
                     65: } /* PushVar */
                     66: 
                     67: 
                     68: /* F   P O P   V A R */
                     69: 
                     70: local FLAGT FPopVar(pret, ty)
                     71: long    *pret;
                     72: pTYR    ty;
                     73: {
                     74:        if (vivarMac <= 0)
                     75:                return(false);
                     76:        vivarMac -= 2;  /* point to first one */
                     77:        CopyTy(ty, vrgTy+vivarMac);
                     78:        *pret = vrgAdr[vivarMac];
                     79:        return(true);
                     80: } /* FPopVar */
                     81: 
                     82: 
                     83: /* A D R   F   S T O R E */
                     84: 
                     85: export ADRT AdrFStore(sb, cb)
                     86: char   *sb;
                     87: int    cb;
                     88: {
                     89:        ADRT    adr;
                     90:        TYR             ty[cTyMax];
                     91: 
                     92:        /* this routine stores data in the CHILD's address space.
                     93:                     * this is mostly useful for passing strings as arguements to
                     94:                     * procedure calls from the command line.
                     95:                     */
                     96:        if (FOdd(cb))
                     97:                cb++;   /* force to word boundary */
                     98:        /* will it fit? */
                     99:        if ((vadrSb == 0) OR (vadrSb+cb >= vadrSbMax)) {
                    100:                /* no, we will go back and use the buffer over again */
                    101:                vadrSb = AdrFGlobal("__buffer", ty);
                    102:                vadrSbMax = AdrFGlobal("_bufMax", ty);
                    103:                if (vadrSb+cb >= vadrSbMax)
                    104:                        UError("I can't put something that big in the child. See 'end.c'");
                    105:        }
                    106:        adr = vadrSb;
                    107:        vadrSb += cb;   /* advance to next free byte */
                    108:        PutBlock(adr, spaceData, sb, cb);
                    109:        return(adr);
                    110: } /* AdrFStore */
                    111: 
                    112: 
                    113: /* P R E C   F   T K */
                    114: 
                    115: export int PrecFTk(tk)
                    116: TKE     tk;
                    117: {
                    118:        /* determine precedence */
                    119:        /* these values are meaningful only in their relationship to one another */
                    120:        switch (tk) {
                    121:        default:        
                    122:                return(0);
                    123:        case tkBOE:
                    124:        case tkLP:      
                    125:                return(precParen);
                    126:        case tkInside:
                    127:        case tkSizeof:
                    128:        case tkLSB:
                    129:        case tkPtr:
                    130:        case tkDot:     
                    131:                return(96);
                    132:        case tkRef:
                    133:        case tkUMinus:
                    134:        case tkBang:
                    135:        case tkTilda:
                    136:        case tkDeref:   
                    137:                return(95);     /* unary operator */
                    138:        case tkDiv:
                    139:        case tkMul:     
                    140:                return(80);
                    141:        case tkPlus:
                    142:        case tkMinus:   
                    143:                return(70);
                    144:        case tkLShift:
                    145:        case tkRShift:  
                    146:                return(60);
                    147:        case tkLT:
                    148:        case tkLE:
                    149:        case tkGT:
                    150:        case tkGE:      
                    151:                return(50);
                    152:        case tkEqual:
                    153:        case tkNotEqual: 
                    154:                return(40);
                    155:        case tkBitAnd:  
                    156:                return(32);
                    157:        case tkXOR:     
                    158:                return(31);
                    159:        case tkBitOr:   
                    160:                return(30);
                    161:        case tkLAND:    
                    162:                return(21);
                    163:        case tkLOR:     
                    164:                return(20);
                    165:        case tkAssPlus:
                    166:        case tkAssMinus:
                    167:        case tkAssMult:
                    168:        case tkAssDiv:
                    169:        case tkAssXOR:
                    170:        case tkAssBAND:
                    171:        case tkAssBOR:
                    172:        case tkAssLeft:
                    173:        case tkAssRight:
                    174:        case tkAssMod:
                    175:        case tkAssign:  
                    176:                return(3);
                    177:        case tkComma:
                    178:        case tkEOE:
                    179:        case tkRP:
                    180:        case tkIndex:
                    181:        case tkRSB:     
                    182:                return(1);
                    183:        } /* switch */
                    184: } /* PrecFTk */
                    185: 
                    186: 
                    187: /* V A L   F   A D R */
                    188: 
                    189: export long ValFAdr(adrLong, ty)
                    190: long    adrLong;
                    191: pTYR    ty;
                    192: {
                    193:        int             cb, bt;
                    194:        ADRT        adrSrc, adrDest;
                    195:        STUFFU      stuff;
                    196: 
                    197:        if (ty->td.fConstant)
                    198:                return(adrLong); /* it was a constant - ergo, it has no address */
                    199: 
                    200:        stuff.lng = 0;
                    201:        adrSrc = adrLong;
                    202:        cb = CbFTy(ty);
                    203:        if (cb > 4)
                    204:                cb = 4; /* this routine is not designed for more than a long */
                    205: 
                    206:        if (ty->td.st == stReg) {
                    207: #ifndef REGULUS
                    208:                if (cb == CBCHAR) {
                    209:                        stuff.chars.chLoLo = GetReg(adrSrc);
                    210:                } 
                    211:                else if (cb == CBSHORT) {
                    212:                        stuff.shorts.shortLo = GetReg(adrSrc);
                    213:                } 
                    214:                else {
                    215: #if (CBINT == CBSHORT)
                    216:                        stuff.shorts.shortHi = GetReg(adrSrc);
                    217:                        stuff.shorts.shortLo = GetReg(adrSrc+1);
                    218: #else
                    219:                        stuff.lng = GetReg(adrSrc);
                    220: #endif
                    221:                } /* if */
                    222: #else
                    223:                if (trace(ptReadUser, vpid, cb,
                    224:                &stuff, v_ar0+vrgOffset[adrSrc]) < 0)
                    225:                        UError("Bad Access");
                    226: #endif
                    227:                goto extendSign;
                    228:        } /* if */
                    229: 
                    230:        /* figure address we want this read into */
                    231:        adrDest = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) :
                    232:        (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) :
                    233:        (ADRT) &(stuff.lng);
                    234: 
                    235:        if (ty->td.st == stSpc) {
                    236:                /* a `special' variable (lives in debuggers universe) */
                    237:                MoveBytes(adrDest, adrSrc, cb);
                    238:                goto extendSign;
                    239:        } /* if */
                    240: 
                    241:        /* unfortunately, there are some special addresses which look like adrNil! */
                    242:        if (adrSrc == adrNil)
                    243:                return(0);
                    244: 
                    245:        if (cb > 0) {
                    246:                GetBlock(adrSrc, spaceData, adrDest, cb);
                    247:                return(stuff.lng);
                    248:        } 
                    249:        else {
                    250:                /* it must be a bit field spec */
                    251:                /* This is dependent on the order the compiler allocates bits */
                    252: #ifdef BSD41
                    253:                cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR;
                    254:                GetBlock(adrSrc, spaceData, &stuff.lng, cb);
                    255:                stuff.lng = Extract(stuff.lng, ty->valTy, ty->td.width);
                    256:                return(stuff.lng);
                    257: #else
                    258:                Panic("Don't know how to handle bit fields for this machine");
                    259: #endif
                    260:        } /* if */
                    261: 
                    262: extendSign:
                    263:        /* following forces sign extension */
                    264:        bt = ty->td.bt;
                    265:        if (TqFTy(ty, 1) == tqNil) { /* then it is a base type, not a pointer */
                    266:                if (bt == btChar)
                    267:                        stuff.lng = stuff.chars.chLoLo;
                    268:                else if (bt == btShort)
                    269:                        stuff.lng = stuff.shorts.shortLo;
                    270: #if (CBINT == CBSHORT)
                    271:                else if (bt == btInt)
                    272:                        stuff.lng = stuff.shorts.shortLo;
                    273: #endif
                    274:        }
                    275:        return(stuff.lng);
                    276: } /* ValFAdr */
                    277: 
                    278: 
                    279: /* P U T   V A L */
                    280: 
                    281: export void PutVal(adrLong, ty, val)
                    282: long    adrLong;
                    283: pTYR    ty;
                    284: long    val;
                    285: {
                    286:        int             cb;
                    287:        ADRT        adrDest, adrSrc;
                    288:        STUFFU      stuff;
                    289: 
                    290:        if (ty->td.fConstant)
                    291:                return; /* it was a constant - ergo, it lives no where */
                    292: 
                    293:        stuff.lng = val;
                    294:        adrDest = adrLong;
                    295:        cb = CbFTy(ty);
                    296:        if (cb > 4)
                    297:                cb = 4; /* this routine is not designed for more than a long */
                    298: 
                    299:        /* figure address we want this read from */
                    300:        adrSrc = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) :
                    301:        (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) :
                    302:        (ADRT) &(stuff.lng);
                    303: 
                    304:        if (ty->td.st == stReg) {
                    305: #ifndef REGULUS
                    306:                if (cb == CBCHAR) {
                    307:                        PutReg(adrDest, stuff.chars.chLoLo);
                    308:                } 
                    309:                else if (cb == CBSHORT) {
                    310:                        PutReg(adrDest, stuff.shorts.shortLo);
                    311:                } 
                    312:                else {
                    313: #if (CBIBT == CBSHORT)
                    314:                        PutReg(adrDest, stuff.shorts.shortHi);
                    315:                        PutReg(adrDest+1, stuff.shorts.shortLo);
                    316: #else
                    317:                        PutReg(adrDest, stuff.lng);
                    318: #endif
                    319:                } /* if */
                    320: #else
                    321:                if (trace(ptWriteUser, vpid, cb,
                    322:                &stuff, v_ar0+vrgOffset[adrDest]) < 0)
                    323:                        UError("Bad Access");
                    324: #endif
                    325:                return;
                    326:        } /* if */
                    327: 
                    328:        if (ty->td.st == stSpc) {
                    329:                /* a `local' variable */
                    330:                MoveBytes(adrDest, adrSrc, cb);
                    331:                return;
                    332:        } /* if */
                    333: 
                    334:        if (cb > 0) {
                    335:                PutBlock(adrDest, spaceData, adrSrc, cb);
                    336:        } 
                    337:        else {
                    338:                /* it must be a bit field */
                    339: #ifdef BSD41
                    340:                cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR;
                    341:                GetBlock(adrDest, spaceData, &stuff.lng, cb);
                    342:                SetBits(stuff.lng, ty->td.width, ty->valTy, val);
                    343:                PutBlock(adrDest, spaceData, &stuff.lng, cb);
                    344: #else
                    345:                Panic("Don't know how to handle bit fields for this machine");
                    346: #endif
                    347:        } /* if */
                    348: } /* PutVal */
                    349: 
                    350: 
                    351: /* P S   F   D O   O P */
                    352: 
                    353: local PSE PsFDoOp()
                    354: {
                    355:        /* this is the rotuine that actually does the TOP operator */
                    356:        int             cb1, cb2, tq, ipd;
                    357:        ushort      *rgDim;
                    358:        ADRT    adr, adrShort;
                    359:        FLAGT       fDidIt, fDoIntOp;
                    360:        TKE         tk;
                    361:        TYR         aty1[cTyMax], aty2[cTyMax], atyMax[cTyMax];
                    362:        pTYR        ty, ty1, ty2, tyMax;
                    363:        long        adr1, adr2, val1, val2;
                    364:        STUFFU  stuff;
                    365: #define cbAssMax        200
                    366:        char        buf[cbAssMax];
                    367: 
                    368:        ty1 = aty1;
                    369:        ty2 = aty2;
                    370:        tyMax = atyMax;
                    371: 
                    372:        if (viopMac < 0)
                    373:                return(psFail);
                    374: 
                    375:        if (TOPOP == tkLP
                    376:            OR TOPOP == tkBOE)
                    377:                return(psFail); /* they should be waiting for one of these */
                    378:        tk = PopOp();
                    379: 
                    380:        if (!FPopVar(&adr2, ty2)) /* every op needs at least one */
                    381:                return(psFail);
                    382:        val2 = ValFAdr(adr2, ty2);
                    383: 
                    384:        fDidIt = true;
                    385:        switch (tk) {
                    386:                /* unary operators */
                    387:        default:        
                    388:                fDidIt = false; 
                    389:                break;
                    390:        case tkUMinus:  
                    391:                ty2->td.fConstant = true;
                    392:                ty2->td.st = stValue;
                    393:                PushVar(-val2, ty2);
                    394:                break;
                    395:        case tkBang:    
                    396:                PushVar(lengthen(val2==0), vtyCnInt);
                    397:                break;
                    398:        case tkTilda:   
                    399:                ty2->td.fConstant = true;
                    400:                ty2->td.st = stValue;
                    401:                PushVar(~val2, ty2);
                    402:                break;
                    403:        case tkRef:     
                    404:                if (ty2->td.fConstant)
                    405:                        UError("You can't take the address of a constant");
                    406:                if (ty2->td.st == stReg)
                    407:                        UError("You can't take the address of a register");
                    408:                if (!FAdjTd(ty2, tqPtr)) /* add a pointer level */
                    409:                        UError("Type information overflow");
                    410:                ty2->td.fConstant = true;
                    411:                ty2->td.st = stValue;
                    412:                PushVar(adr2, ty2);
                    413:                break;
                    414:        case tkDeref:   
                    415:                tq = TqFTy(ty2, 1);
                    416:                if ((tq == tqPtr) OR (tq == tqArray))
                    417:                        FAdjTd(ty2, tqNil);  /* remove tq */
                    418:                ty2->td.st = stValue;
                    419:                if (ty2->td.fConstant) {
                    420:                        ty2->td.fConstant = false;
                    421:                        PushVar(adr2, ty2);
                    422:                } 
                    423:                else if (tq == tqArray) {
                    424:                        PushVar(adr2, ty2);     /* array is pointer to itself */
                    425:                } 
                    426:                else {
                    427:                        PushVar(val2, ty2);
                    428:                } /* if */
                    429:                break;
                    430:        case tkInside:  
                    431:                adrShort = adr2;
                    432:                ipd = IpdFAdr(adrShort);
                    433:                val2 = (vpc >= vrgPd[ipd].adrStart)
                    434:                        AND (vpc < vrgPd[ipd+1].adrStart);
                    435:                PushVar(val2, vtyCnInt);
                    436:                break;
                    437:        case tkSizeof:  
                    438:                val2 = CbFTy(ty2);
                    439:                PushVar(val2, vtyCnInt);
                    440:                break;
                    441:        } /* switch */
                    442:        if (fDidIt)    /* we must have done one of them - go back */
                    443:                return(psVar);
                    444: 
                    445:        /* not unary, so we pop another and try the binaries */
                    446:        if (!FPopVar(&adr1, ty1))
                    447:                return(psFail);
                    448:        val1 = ValFAdr(adr1, ty1);
                    449: 
                    450:        fDidIt = true;
                    451:        switch (tk) {
                    452:        default:        
                    453:                fDidIt = false; 
                    454:                break;
                    455:        case tkDot:     
                    456:                val1 = adr1;    /* direct address, then do ptr */
                    457:        case tkPtr:     
                    458:                val1 = AdrFField(val1, ty1, ty2);
                    459:                /* ty1 is struct, ty2 is field */
                    460:                PushVar(val1, ty2);
                    461:                break;
                    462:        case tkIndex:   /* foo[x] */
                    463:                tq = TqFTy(ty1, 1);
                    464:                if (tq == tqArray)
                    465:                        val1 = adr1;   /* array value IS the address */
                    466:                FAdjTd(ty1, tqNil);/* remove ptr or array level */
                    467:                adr1 = val1 + (val2 * CbFTy(ty1));
                    468:                PushVar(adr1, ty1);
                    469:                break;
                    470: 
                    471:        } /* switch */
                    472:        if (fDidIt)
                    473:                return(psVar);
                    474: 
                    475:        /* MaxFTyTy may try to do too much.  It first determines if the types
                    476:                     * are such that integer operators may be applied to them (and returns
                    477:                     * a true/false on this)  If so, it copies into tyMax the ty of the
                    478:                     * larger of the two operands.
                    479:                     */
                    480:        fDoIntOp = MaxFTyTy(tyMax, ty1, ty2);
                    481:        if ( (!fDoIntOp) 
                    482:            AND (tk != tkPtr)
                    483:            AND (tk != tkDot)
                    484:            AND (tk != tkAssign) ) {
                    485:                /* they are trying something stupid, like adding structures together */
                    486:                UError("Cannot allow that combination of operand(s) and operator");
                    487:        } /* if */
                    488: 
                    489:        tyMax->td.fConstant = true; /* any op that DOESN'T want this turns it off */
                    490:        tyMax->td.st = stValue;
                    491:        /* binary operators */
                    492:        fDidIt = true;
                    493:        switch (tk) {
                    494:        default:        
                    495:                fDidIt = false;         
                    496:                break;
                    497:        case tkDiv:     
                    498:                val1 = val1 / val2;     
                    499:                break;
                    500:        case tkMul:     
                    501:                val1 = val1 * val2;     
                    502:                break;
                    503:        case tkPlus:    
                    504:                val1 = val1 + val2;     
                    505:                break;
                    506:        case tkMinus:   
                    507:                val1 = val1 - val2;     
                    508:                break;
                    509:        case tkBitAnd:  
                    510:                val1 = val1 & val2;     
                    511:                break;
                    512:        case tkXOR:     
                    513:                val1 = val1 ^ val2;     
                    514:                break;
                    515:        case tkBitOr:   
                    516:                val1 = val1 | val2;     
                    517:                break;
                    518:        } /* switch */
                    519:        if (fDidIt) {
                    520:                PushVar(val1, tyMax);
                    521:                return(psVar);
                    522:        } /* if */
                    523: 
                    524:        fDidIt = true;
                    525:        ty = vtyCnInt;
                    526:        switch (tk) {
                    527:        default:        
                    528:                fDidIt = false;         
                    529:                break;
                    530:        case tkLT:      
                    531:                val1 = val1 < val2;     
                    532:                break;
                    533:        case tkLE:      
                    534:                val1 = val1 <= val2;    
                    535:                break;
                    536:        case tkGT:      
                    537:                val1 = val1 > val2;     
                    538:                break;
                    539:        case tkGE:      
                    540:                val1 = val1 >= val2;    
                    541:                break;
                    542:        case tkEqual:   
                    543:                val1 = val1 == val2;    
                    544:                break;
                    545:        case tkNotEqual: 
                    546:                val1 = val1 != val2;   
                    547:                break;
                    548:        case tkLAND:    
                    549:                val1 = val1 && val2;    
                    550:                break;
                    551:        case tkLOR:     
                    552:                val1 = val1 || val2;    
                    553:                break;
                    554:        case tkLShift:  
                    555:                if (ty1->td.bt == btShort) {
                    556:                        /* we do this to crop it to 16 bits */
                    557:                        stuff.lng = val1;
                    558:                        val1 = stuff.shorts.shortLo << val2;
                    559:                } 
                    560:                else {
                    561:                        val1 = val1 << val2;
                    562:                        ty = vtyCnLong;
                    563:                } /* if */
                    564:                break;
                    565:        case tkRShift:  
                    566:                if (ty1->td.bt == btShort) {
                    567:                        /* we do this to crop it to 16 bits */
                    568:                        stuff.lng = val1;
                    569:                        val1 = stuff.shorts.shortLo >> val2;
                    570:                } 
                    571:                else {
                    572:                        val1 = val1 >> val2;
                    573:                        ty = vtyCnLong;
                    574:                } /* if */
                    575:                break;
                    576:        } /* switch */
                    577:        if (fDidIt) {
                    578:                PushVar(val1, ty);
                    579:                return(psVar);
                    580:        } /* if */
                    581: 
                    582:        if (tk != tkAssign)
                    583:                UError("Unknown operator");
                    584: 
                    585:        cb1 = CbFTy(ty1);
                    586:        if (cb1 <= CBLONG) {
                    587:                PutVal(adr1, ty1, val2);
                    588:        } 
                    589:        else {
                    590:                cb2 = CbFTy(ty2);
                    591:                if (cb1 >= cbAssMax)
                    592:                        Panic("Too many bytes (> %d) moved in assignment", cbAssMax);
                    593:                /* we transfer cb1 bytes, just to be safe */
                    594:                adrShort = adr2;
                    595:                GetBlock(adrShort, spaceData, (ADRT)buf, cb1);
                    596:                adrShort = adr1;
                    597:                PutBlock(adrShort, spaceData, (ADRT)buf, cb1);
                    598:                if (cb1 != cb2) {
                    599:                        printf("WARNING: X=Y: X is %d bytes and Y is %d bytes\n",
                    600:                        cb1, cb2);
                    601:                        printf("  Moving %d bytes\n", cb1);
                    602:                } /* if */
                    603:        } /* if */
                    604:        PushVar(adr1, ty1); /* leave dest on stack, too */
                    605:        return(psVar);
                    606: } /* PsFDoOp */
                    607: 
                    608: 
                    609: /* P S   F   O P E R A T O R */
                    610: 
                    611: local PSE PsFOperator(tk, ps)
                    612: TKE     tk;
                    613: PSE     ps;
                    614: {
                    615:        /* this routine implements the precedence rules */
                    616:        int             prec;
                    617:        TKE         tkStop, tkNew;
                    618:        long    adr;
                    619:        TYR             rgTy[cTyMax];
                    620: 
                    621:        prec = PrecFTk(tk);
                    622:        if (prec == 0)
                    623:                Panic("Bad token in PsFOperator - [%d]", tk);
                    624: 
                    625:        if (ps == psOp) {
                    626:                /* this had better be a unary operator */
                    627:                switch (tk) {
                    628:                case tkSizeof:
                    629:                case tkInside:
                    630:                case tkBang:
                    631:                case tkTilda:
                    632:                case tkBOE:
                    633:                case tkLP:          
                    634:                        PushOp(tk);             
                    635:                        break;
                    636:                        /* these next ones map to something else */
                    637:                case tkAmper:       
                    638:                        PushOp(tkRef);          
                    639:                        break;
                    640:                case tkStar:        
                    641:                        PushOp(tkDeref);        
                    642:                        break;
                    643:                case tkMinus:       
                    644:                        PushOp(tkUMinus);       
                    645:                        break;
                    646:                case tkPlus:        /* ignore it */
                    647:                        break;
                    648:                default:    
                    649:                        UError("Two operators in a row??");
                    650:                } /* switch */
                    651:                return(psOp);
                    652:        } /* if */
                    653: 
                    654:        tkStop = tkNil;
                    655:        switch (tk) {   /* set our stop token for [], (), and (x,y,z) */
                    656:        case tkEOE:     
                    657:                tkStop = tkBOE;         
                    658:                break;
                    659:        case tkRSB:     
                    660:                tkStop = tkLSB;       
                    661:                break;
                    662:        case tkComma:
                    663:        case tkRP:      
                    664:                tkStop = tkLP;          
                    665:                break;
                    666:        } /* switch */
                    667: 
                    668:        /* first process all higher precedence operators */
                    669:        while (prec <= PrecFTk(TOPOP)) {
                    670:                if (TOPOP == tkStop) {
                    671:                        PopOp();    /* eat top op */
                    672:                        return(psVar);      /* by definition, "(x+y)" is a var */
                    673:                } 
                    674:                else if (PrecFTk(TOPOP) == precParen) {
                    675:                        break;  /* we pretend it is higher precedence than the paren */
                    676:                } /* if */
                    677:                if (PsFDoOp() == psFail) {
                    678:                        switch (tk) {
                    679:                        case tkRSB:
                    680:                                UError("Missing '['");
                    681:                        case tkRP:
                    682:                                UError("Missing '('");
                    683:                        case tkComma:
                    684:                                UError("Bad procedure call");
                    685:                        default:
                    686:                                UError("Badly formed expression");
                    687:                        } /* switch */
                    688:                } /* if */
                    689:        } /* while */
                    690: 
                    691:        tkNew = tkNil;
                    692:        switch (tk) {
                    693:        case tkAssPlus:         
                    694:                tkNew = tkPlus;         
                    695:                break;
                    696:        case tkAssMinus:        
                    697:                tkNew = tkMinus;        
                    698:                break;
                    699:        case tkAssMult:         
                    700:                tkNew = tkMul;          
                    701:                break;
                    702:        case tkAssDiv:          
                    703:                tkNew = tkDiv;          
                    704:                break;
                    705:        case tkAssXOR:          
                    706:                tkNew = tkXOR;          
                    707:                break;
                    708:        case tkAssBAND:         
                    709:                tkNew = tkBitAnd;       
                    710:                break;
                    711:        case tkAssBOR:          
                    712:                tkNew = tkBitOr;        
                    713:                break;
                    714:        case tkAssLeft:         
                    715:                tkNew = tkLShift;       
                    716:                break;
                    717:        case tkAssRight:        
                    718:                tkNew = tkRShift;       
                    719:                break;
                    720:        case tkAssMod:          
                    721:                tkNew = tkModulo;       
                    722:                break;
                    723:        } /* switch */
                    724:        if (tkNew != tkNil) {
                    725:                /* this is an 'assign with function' op e.g. *= or += */
                    726:                /* replicate the top of the variable stack */
                    727:                if (!FPopVar(&adr, rgTy))
                    728:                        UError("Bad Syntax");
                    729:                PushVar(adr, rgTy);
                    730:                PushVar(adr, rgTy);
                    731:                PushOp(tkAssign);
                    732:                tk = tkNew;
                    733:        } /* if */
                    734: 
                    735:        PushOp(tk);
                    736:        if (tk == tkLSB)
                    737:                PushOp(tkIndex);        /* we push the tkLSB and then the tkIndex */
                    738:        return(psOp);
                    739: } /* PsFOperator */
                    740: 
                    741: 
                    742: /* T K   F   O P E R A N D */
                    743: 
                    744: export TKE TkFOperand()
                    745: {
                    746:        int             iln, ifd, ipd, cnt;
                    747:        short   valShort;
                    748:        char        sbFloat[30];
                    749:        long        val;
                    750:        TKE         tk;
                    751:        ADRT        adr, fp, ap;
                    752:        TYR         ty[cTyMax];
                    753:        STUFFU      stuff;
                    754: 
                    755:        /* look at the current token and figure out what the hell it is */
                    756:        /* successful cases fall out bottom and return tkAdr */
                    757:        switch (vtk) {
                    758:        default:
                    759:                return(tkNil);  /* nothing of interest */
                    760:        case tkDot:
                    761:                PushVar(vdot, vtyDot);
                    762:                break;
                    763:        case tkColon:   /* they want us to search ONLY global space */
                    764:                tk = TkNext();
                    765:                if (tk != tkStr)
                    766:                        UError("Misformed global name");
                    767:                if ((adr = AdrFGlobal(vsbTok, ty)) == adrNil)
                    768:                        UError("Unknown global - %s", vsbTok);
                    769:                PushVar(lengthen(adr), ty);
                    770:                break;
                    771:        case tkCharConstant:
                    772:                CopyTy(ty, vtyCnChar);
                    773:                val = vsbTok[0];
                    774:                PushVar(val, ty);
                    775:                break;
                    776:        case tkStrConstant:
                    777:                adr = AdrFStore(vsbTok, vcbTok+1);
                    778:                CopyTy(ty, vtyCnChar);  /* it is a constant */
                    779:                FAdjTd(ty, tqPtr);      /* this makes it a 'char *' */
                    780:                PushVar(lengthen(adr), ty);
                    781:                break;
                    782:        case tkNumber:
                    783:                if (vsbTok[0] == '0') {
                    784:                        if (vsbTok[1] == 'x')
                    785:                                sscanf((vsbTok+2), "%X", &val);
                    786:                        else sscanf(vsbTok, "%O", &val);
                    787:                } 
                    788:                else {
                    789:                        tk = TkPeek();
                    790:                        if (tk == tkDot) {
                    791:                                /* looks like a float constant */
                    792:                                strcpy(sbFloat, vsbTok);
                    793:                                TkNext();       /* eat the dot */
                    794:                                strcat(sbFloat, ".");
                    795:                                /* we allow them to say "10." instead of "10.0" */
                    796:                                if (tkNumber == TkPeek()) {
                    797:                                        TkNext();   /* actually get the number */
                    798:                                        strcat(sbFloat, vsbTok); /* get fractional part */
                    799:                                } /* if */
                    800:                                stuff.fl = atof(sbFloat);
                    801:                                PushVar(stuff.lng, vtyCnFloat); /* sorta kludgey */
                    802:                                return(tkNumber);
                    803:                        } 
                    804:                        else {
                    805:                                val = atol(vsbTok);
                    806:                        } /* if */
                    807:                } /* if */
                    808: 
                    809:                TkPeek();
                    810:                /* did they specify long? */
                    811:                if ((vcbPeek == 1)
                    812:                    AND (vsbTokPeek[0] == 'L' OR vsbTokPeek[0] == 'l')) {
                    813:                        TkNext();       /* actually eat the L or l */
                    814:                        PushVar(val, vtyCnLong);
                    815:                } 
                    816:                else {
                    817:                        valShort = val & 0x0000ffff;
                    818:                        PushVar(val, (val==valShort) ? vtyCnInt : vtyCnLong);
                    819:                }
                    820:                return(tkNumber);
                    821:                /* NOTREACHED */
                    822:                break;
                    823:        case tkStr:
                    824:                if ((TOPOP == tkDot) OR (TOPOP == tkPtr)) {
                    825:                        /* we don't do anything until we PROCESS the field.
                    826:                                                                     * so we jam the name in a record.
                    827:                                                                     */
                    828:                        ty[0] = *vtyZeros;
                    829:                        ty[1] = *vtyZeros;
                    830: #ifdef BSD41
                    831:                        ty[0].sbVar = SbSafe(vsbTok);
                    832: #else
                    833:                        strncpy(ty[0].sbVar, vsbTok, cbVarMax);
                    834: #endif
                    835:                        ty[0].td.fConstant = true;
                    836:                        ty[0].td.st = stStruct;
                    837:                        PushVar(0L, ty);
                    838:                        return(psVar);
                    839:                } /* if */
                    840: 
                    841:                /* is it a register or Special variable? */
                    842:                if (vsbTok[0] == '$') {
                    843:                        if (FAdrFSpecial(vsbTok, ty, &adr)) {
                    844:                                PushVar(lengthen(adr), ty);
                    845:                                break;
                    846:                        } /* if */
                    847:                        UError("Unknown special variable `%s'", vsbTok);
                    848:                } /* if */
                    849: 
                    850:                /* is it a local? */
                    851:                if ((vipd != ipdNil)
                    852:                    AND ((adr=AdrFLocal(vipd, -1, vsbTok, ty)) != adrNil)) {
                    853:                        PushVar(lengthen(adr), ty);
                    854:                        break;
                    855:                } /* if */
                    856: 
                    857:                /* is it a global? */
                    858:                if ((adr = AdrFGlobal(vsbTok, ty)) != adrNil) {
                    859:                        PushVar(lengthen(adr), ty);
                    860:                        break;
                    861:                } /* if */
                    862: 
                    863:                /* is it a procedure name? */
                    864:                if ((ipd = IpdFName(vsbTok)) != ipdNil) {
                    865:                        /* it is a procedure name! is there anymore to the name? */
                    866:                        tk = TkPeek();
                    867:                        if (tk == tkDot) {
                    868:                                /* so far we know `procname.' */
                    869:                                TkNext();       /* eat dot */
                    870:                                /* we want full name of a local */
                    871:                                FpApFIpd(&fp, &ap, ipd, -1);
                    872:                                if (fp == 0)
                    873:                                        UError("procedure %s not active",vrgPd[ipd].sbProc);
                    874:                                tk = TkNext();
                    875:                                cnt = -1;       /* default - take first instance */
                    876:                                if (tk == tkNumber) {
                    877:                                        /* we have `proc.3' (or something like that).
                    878:                                                                                                             * they want a SPECIFIC instance of this proc
                    879:                                                                                                             * at backtrace location #.
                    880:                                                                                                             * This is useful for recursive procedures...
                    881:                                                                                                             */
                    882:                                        cnt = atoi(vsbTok);
                    883:                                        if (TkNext() != tkDot)
                    884:                                                UError("Need a `.' after the number");
                    885:                                        ;
                    886:                                        tk = TkNext();
                    887:                                } /* if */
                    888:                                if (tk != tkStr) {
                    889:                                        /* procname.???? */
                    890:                                        UError("Syntax error - bad local name '%s'",vsbTok);
                    891:                                } /* if */
                    892:                                if ((adr = AdrFLocal(ipd,cnt,vsbTok,ty))
                    893:                                    != adrNil) {
                    894:                                        PushVar(lengthen(adr), ty);
                    895:                                        return(tkAdr);
                    896:                                } 
                    897:                                else {
                    898:                                        UError("No such local - %s.%s",
                    899:                                        vrgPd[ipd].sbProc, vsbTok);
                    900:                                } /* if */
                    901:                        } 
                    902:                        else if (tk == tkLP) {
                    903:                                /* we have `procname(' - must be a procedure call */
                    904:                                TkNext();       /* eat ( */
                    905:                                val = DoProc(ipd, ty, adrNil);
                    906:                                PushVar(val, ty);
                    907:                                break;
                    908:                        } 
                    909:                        else if (tk == tkHash) {
                    910:                                TkNext();       /* eat the # */
                    911:                                tk = TkNext();
                    912:                                if (tk != tkNumber)
                    913:                                        UError("'#' should be followed by a decimal line number.");
                    914:                                iln = atoi(vsbTok);
                    915:                                ifd = IfdFIpd(ipd);
                    916:                                adr = AdrFIfdLn(ifd, iln); /* get adr of this line */
                    917:                                PushVar(lengthen(adr), vtyCnInt);
                    918:                        } 
                    919:                        else {
                    920:                                /* proc name followed by ???, give proc adr and type */
                    921:                                TyFLocal(ty, vrgPd[ipd].sbProc, vrgPd[ipd].isym);
                    922:                                PushVar(lengthen(vrgPd[ipd].adrStart), ty);
                    923:                        } /* if */
                    924:                } 
                    925:                else if ((adr=AdrFLabel(vsbTok)) != adrNil) {
                    926:                        /* it is a label */
                    927:                        TkPeek();
                    928:                        if (vtkPeek == tkLP) {
                    929:                                /* we have `label(' - must be a procedure call */
                    930:                                TkNext();       /* eat ( */
                    931:                                val = DoProc(ipdNil, ty, adr);
                    932:                                PushVar(val, ty);
                    933:                        } 
                    934:                        else {
                    935:                                PushVar(lengthen(adr), vtyCnInt);
                    936:                        }
                    937:                } 
                    938:                else {
                    939:                        /* don't what it is, it is NOT something we can handle! */
                    940:                        return(tkNil);
                    941:                } /* if */
                    942:                break;
                    943:        } /* switch */
                    944:        return(tkAdr);
                    945: } /* TkFOperand */
                    946: 
                    947: 
                    948: /* T K   F   E X P R */
                    949: 
                    950: export TKE TkFExpr(pret, ty)
                    951: long    *pret;
                    952: pTYR    ty;
                    953: {
                    954:        int             cbTemp;
                    955:        PSE         ps;
                    956:        TKE         tk, tkRet, tkTemp;
                    957:        char        *sbCmdTemp, sbTokTemp[50];
                    958: 
                    959:        if (vtk == tkNil) {
                    960:                *pret = 0;
                    961:                return(tkNil);
                    962:        } /* if */
                    963: 
                    964:        /* save the token state in case we think it is garbage */
                    965:        cbTemp = vcbTok;
                    966:        sbCmdTemp = vsbCmd;
                    967:        tk = tkTemp = vtk;
                    968:        ps = psOp;
                    969:        strcpy(sbTokTemp, vsbTok);
                    970: 
                    971:        PushOp(tkBOE);  /* push a {ning-of-expression onto the stack */
                    972: 
                    973:        /* we do a little dance here to see if we have a pure number */
                    974:        tkRet = TkFOperand();
                    975:        if (tkRet != tkNil) {
                    976:                ps = psVar;
                    977:                tk = TkNext();
                    978:                if ((tkRet == tkNumber) AND (PrecFTk(tk)==0)) {
                    979:                        tk = PopOp();   /* eat the BOE */
                    980:                        FPopVar(pret, ty);
                    981:                        return(tkNumber);
                    982:                } /* if */
                    983:        } 
                    984:        else if (PrecFTk(tk) == 0) {
                    985:                /* it is neither an operator nor an operand */
                    986:                goto bombout;
                    987:        } /* if */
                    988: 
                    989:        if (tk == tkComma) {
                    990:                PushOp(tkLP);   /* makes procedure call code easier */
                    991:                tk = TkNext();
                    992:        } /* if */
                    993: 
                    994:        while (tk != tkNil) {
                    995:                if ( (PrecFTk(tk) != 0)
                    996:                    AND ((tk != tkDot) OR (ps == psVar)) ) {
                    997:                        /* it is an operator */
                    998:                        ps = PsFOperator(tk, ps);
                    999:                        if (ps == psFail)
                   1000:                                goto bombout;
                   1001:                        if (tk == tkComma)
                   1002:                                break;
                   1003:                } 
                   1004:                else {
                   1005:                        /* it's not an operator, is it an OPERAND?? */
                   1006:                        tk = TkFOperand();
                   1007:                        if (tk == tkNil) {
                   1008:                                ps = psFail;
                   1009:                                break; /* not operand - fall out of loop and see what happens */
                   1010:                        } /* if */
                   1011:                        ps = psVar; /* yup, it was an operand - and it's on the stack */
                   1012:                } /* if */
                   1013:                tk = TkNext();
                   1014:        } /* while */
                   1015: 
                   1016:        /* one way or the other, someone thinks we might be done, try it and see */
                   1017:        if (psFail != PsFOperator(tkEOE, ps)) {
                   1018:                FPopVar(pret, ty);      /* put final stuff in return variables */
                   1019:                return(tkAdr);
                   1020:        } /* if */
                   1021: 
                   1022: bombout:
                   1023:        /* something ain't right - reset the universe */
                   1024:        vcbTok = cbTemp;
                   1025:        vsbCmd = sbCmdTemp;
                   1026:        vtk = tkTemp;
                   1027:        strcpy(vsbTok, sbTokTemp);
                   1028:        vivarMac = 0; /* stack pointer cleanup */
                   1029:        viopMac = 0;
                   1030:        return(tkNil);
                   1031: } /* TkFExpr */
                   1032: 
                   1033: 
                   1034: /* G E T   E X P R */
                   1035: 
                   1036: export long GetExpr(pty, tk)
                   1037: pTYR    *pty;
                   1038: TKE     tk;
                   1039: {
                   1040:        long        adrLong, i;
                   1041:        static TYR  ty[cTyMax];
                   1042:        /* ty is used for callers to GetExp who don't want to be bothered
                   1043:                     * with allocating an ty.
                   1044:                     * NOTE(!): if they want this info for more than a statement or two,
                   1045:                     * they MUST copy it someplace else!!!
                   1046:                     */
                   1047: 
                   1048:        if (tk == tkNil)
                   1049:                TkNext();
                   1050:        if (TkFExpr(&adrLong, ty) != tkNil) {
                   1051:                i = ValFAdr(adrLong, ty);
                   1052:                *pty = ty;
                   1053:        } 
                   1054:        else {
                   1055:                *pty = tyNil;
                   1056:        } /* if */
                   1057:        return(i);
                   1058: } /* GetExpr */

unix.superglobalmegacorp.com

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