Annotation of cci/usr/src/bin/cdb/expr.c, revision 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.