Annotation of researchv10dc/cmd/icon/src/iconx/omisc.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * File: omisc.c
        !             3:  *  Contents: random, refresh, size, tabmat, toby
        !             4:  */
        !             5: 
        !             6: 
        !             7: #include "../h/rt.h"
        !             8: #define RandVal (RanScale*(k_random=(RandA*k_random+RandC)&MaxLong))
        !             9: 
        !            10: /*
        !            11:  * ?x - produce a randomly selected element of x.
        !            12:  */
        !            13: 
        !            14: OpDclV(random,1,"?")
        !            15:    {
        !            16:    register word val, i, j;
        !            17:    register union block *bp;
        !            18:    long r1;
        !            19:    char sbuf[MaxCvtLen];
        !            20:    union block *ep;
        !            21:    struct descrip *dp;
        !            22:    double rval;
        !            23:    extern char *alcstr();
        !            24: 
        !            25:    Arg2 = Arg1;
        !            26:    DeRef(Arg1);
        !            27: 
        !            28:    if (Qual(Arg1)) {
        !            29:       /*
        !            30:        * x is a string, produce a random character in it as the result.
        !            31:        *  Note that a substring trapped variable is returned.
        !            32:        */
        !            33:       if ((val = StrLen(Arg1)) <= 0)
        !            34:          Fail;
        !            35:       blkreq((word)sizeof(struct b_tvsubs));
        !            36:       rval = RandVal;                  /* This form is used to get around */
        !            37:       rval *= val;                     /* a bug in a certain C compiler */
        !            38:       mksubs(&Arg2, &Arg1, (word)rval + 1, (word)1, &Arg0);
        !            39:       Return;
        !            40:       }
        !            41: 
        !            42:    switch (Type(Arg1)) {
        !            43:       case T_Cset:
        !            44:          /*
        !            45:           * x is a cset.  Convert it to a string, select a random character
        !            46:           *  of that string and return it.  Note that a substring trapped
        !            47:           *  variable is not needed.
        !            48:           */
        !            49:          cvstr(&Arg1, sbuf);
        !            50:          if ((val = StrLen(Arg1)) <= 0)
        !            51:             Fail;
        !            52:          strreq((word)1);
        !            53:          StrLen(Arg0) = 1;
        !            54:          rval = RandVal;
        !            55:          rval *= val;
        !            56:          StrLoc(Arg0) = alcstr(StrLoc(Arg1)+(word)rval, (word)1);
        !            57:          Return;
        !            58: 
        !            59: 
        !            60:       case T_List:
        !            61:          /*
        !            62:           * x is a list.  Set i to a random number in the range [1,*x],
        !            63:           *  failing if the list is empty.
        !            64:           */
        !            65:          bp = BlkLoc(Arg1);
        !            66:          val = bp->list.size;
        !            67:          if (val <= 0)
        !            68:             Fail;
        !            69:          rval = RandVal;
        !            70:          rval *= val;
        !            71:          i = (word)rval + 1;
        !            72:          j = 1;
        !            73:          /*
        !            74:           * Work down chain list of list blocks and find the block that
        !            75:           *  contains the selected element.
        !            76:           */
        !            77:          bp = BlkLoc(BlkLoc(Arg1)->list.listhead);
        !            78:          while (i >= j + bp->lelem.nused) {
        !            79:             j += bp->lelem.nused;
        !            80:             if ((bp->lelem.listnext).dword != D_Lelem)
        !            81:             syserr("list reference out of bounds in random");
        !            82:             bp = BlkLoc(bp->lelem.listnext);
        !            83:             }
        !            84:          /*
        !            85:           * Locate the appropriate element and return a variable
        !            86:           * that points to it.
        !            87:           */
        !            88:          i += bp->lelem.first - j;
        !            89:          if (i >= bp->lelem.nelem)
        !            90:             i -= bp->lelem.nelem;
        !            91:          dp = &bp->lelem.lslots[i];
        !            92:          Arg0.dword = D_Var + ((word *)dp - (word *)bp);
        !            93:          VarLoc(Arg0) = dp;
        !            94:          Return;
        !            95: 
        !            96:       case T_Table:
        !            97:           /*
        !            98:            * x is a table.  Set i to a random number in the range [1,*x],
        !            99:            *  failing if the table is empty.
        !           100:            */
        !           101:          bp = BlkLoc(Arg1);
        !           102:          val = bp->table.size;
        !           103:          if (val <= 0)
        !           104:             Fail;
        !           105:          rval = RandVal;
        !           106:          rval *= val;
        !           107:          i = (word)rval + 1;
        !           108:          /*
        !           109:           * Work down the chain of elements in each bucket and return
        !           110:           *  a variable that points to the i'th element encountered.
        !           111:           */
        !           112:          for (j = 0; j < TSlots; j++) {
        !           113:             for (ep = BlkLoc(bp->table.buckets[j]); ep != NULL;
        !           114:                     ep = BlkLoc(ep->telem.clink)) {
        !           115:                if (--i <= 0) {
        !           116:                   dp = &ep->telem.tval;
        !           117:                   Arg0.dword = D_Var + ((word *)dp - (word *)bp);
        !           118:                   VarLoc(Arg0) = dp;
        !           119:                   Return;
        !           120:                   }
        !           121:                }
        !           122:              }
        !           123:       case T_Set:
        !           124:          /*
        !           125:           * x is a set.  Set i to a random number in the range [1,*x],
        !           126:           *  failing if the set is empty.
        !           127:           */
        !           128:          bp = BlkLoc(Arg1);
        !           129:          val = bp->set.size;
        !           130:          if (val <= 0)
        !           131:             Fail;
        !           132:          rval = RandVal;
        !           133:          rval *= val;
        !           134:          i = (word)rval + 1;
        !           135:          /*
        !           136:           * Work down the chain of elements in each bucket and return
        !           137:           *  the value of the ith element encountered.
        !           138:           */
        !           139:          for (j = 0; j < SSlots; j++) {
        !           140:             for (ep = BlkLoc(bp->set.sbucks[j]); ep != NULL;
        !           141:                ep = BlkLoc(ep->selem.clink)) {
        !           142:                  if (--i <= 0) {
        !           143:                     Arg0 = ep->selem.setmem;
        !           144:                     Return;
        !           145:                     }
        !           146:                 }
        !           147:              }
        !           148: 
        !           149:       case T_Record:
        !           150:          /*
        !           151:           * x is a record.  Set val to a random number in the range [1,*x]
        !           152:           *  (*x is the number of fields), failing if the record has no
        !           153:           *  fields.
        !           154:           */
        !           155:          bp = BlkLoc(Arg1);
        !           156:          val = BlkLoc(bp->record.recdesc)->proc.nfields;
        !           157:          if (val <= 0)
        !           158:             Fail;
        !           159:          /*
        !           160:           * Locate the selected element and return a variable
        !           161:           * that points to it
        !           162:           */
        !           163:             rval = RandVal;
        !           164:             rval *= val;
        !           165:             dp = &bp->record.fields[(word)rval];
        !           166:             Arg0.dword = D_Var + ((word *)dp - (word *)bp);
        !           167:             VarLoc(Arg0) = dp;
        !           168:             Return;
        !           169: 
        !           170:       default:
        !           171:          /*
        !           172:           * Try converting it to an integer
        !           173:           */
        !           174:       switch (cvint(&Arg1, &r1)) {
        !           175: 
        !           176:          case T_Longint:
        !           177:             runerr(205, &Arg1);
        !           178: 
        !           179:          case T_Integer:
        !           180:             /*
        !           181:              * x is an integer, be sure that it's non-negative.
        !           182:              */
        !           183:             val = (word)r1;
        !           184:             if (val < 0)
        !           185:                runerr(205, &Arg1);
        !           186:          getrand:
        !           187:             /*
        !           188:              * val contains the integer value of x.  If val is 0, return
        !           189:              * a real in the range [0,1), else return an integer in the
        !           190:              * range [1,val].
        !           191:              */
        !           192:             if (val == 0) {
        !           193:                rval = RandVal;
        !           194:                mkreal(rval, &Arg0);
        !           195:                }
        !           196:             else {
        !           197:                rval = RandVal;
        !           198:                rval *= val;
        !           199:                Mkint((long)rval + 1, &Arg0);
        !           200:                }
        !           201:             Return;
        !           202: 
        !           203:          default:
        !           204:             /*
        !           205:              * x is of a type for which random generation is not supported
        !           206:              */
        !           207:             runerr(113, &Arg1);
        !           208:             }
        !           209:          }
        !           210:    }
        !           211: 
        !           212: 
        !           213: /*
        !           214:  * ^x - return an entry block for co-expression x from the refresh block.
        !           215:  */
        !           216: 
        !           217: OpDcl(refresh,1,"^")
        !           218:    {
        !           219:    register struct b_coexpr *sblkp;
        !           220:    register struct b_refresh *rblkp;
        !           221:    register struct descrip *dp, *dsp;
        !           222:    register word *newsp;
        !           223:    int na, nl, i;
        !           224:    extern struct b_coexpr *alcstk();
        !           225:    extern struct b_refresh *alceblk();
        !           226: 
        !           227:    /*
        !           228:     * Be sure a co-expression is being refreshed.
        !           229:     */
        !           230:    if (Qual(Arg1) || Arg1.dword != D_Coexpr)
        !           231:       runerr(118, &Arg1);
        !           232: 
        !           233:    /*
        !           234:     * Get a new co-expression stack and initialize.
        !           235:     */
        !           236:    sblkp = alcstk();
        !           237:    sblkp->activator = nulldesc;
        !           238:    sblkp->size = 0;
        !           239:    sblkp->nextstk = stklist;
        !           240:    stklist = sblkp;
        !           241:    sblkp->freshblk = BlkLoc(Arg1)->coexpr.freshblk;
        !           242:    /*
        !           243:     * Icon stack starts at word after co-expression stack block.  C stack
        !           244:     *  starts at end of stack region on machines with down-growing C stacks
        !           245:     *  and somewhere in the middle of the region.
        !           246:     *
        !           247:     * The C stack is aligned on a doubleword boundary. For upgrowing
        !           248:     *  stacks, the C stack starts in the middle of the stack portion
        !           249:     *  of the static block.  For downgrowing stacks, the C stack starts
        !           250:     *  at the last word of the static block.
        !           251:     */
        !           252:    newsp = (word *)((char *)sblkp + sizeof(struct b_coexpr));
        !           253: #ifdef UpStack
        !           254:    sblkp->cstate[0] =
        !           255:       ((word)((char *)sblkp + (stksize - sizeof(*sblkp))/2)
        !           256:        &~(WordSize*2-1));
        !           257: #else
        !           258:    sblkp->cstate[0] =
        !           259:        ((word)((char *)sblkp + stksize - WordSize)&~(WordSize*2-1));
        !           260: #endif UpStack
        !           261:    sblkp->es_argp = (struct descrip *)newsp;
        !           262:    /*
        !           263:     * Get pointer to refresh block and get number of arguments and locals.
        !           264:     */
        !           265:    rblkp = (struct b_refresh *)BlkLoc(sblkp->freshblk);
        !           266:    na = (rblkp->pfmkr).pf_nargs + 1;
        !           267:    nl = rblkp->numlocals;
        !           268: 
        !           269:    /*
        !           270:     * Copy arguments onto new stack.
        !           271:     */
        !           272:    dp = &rblkp->elems[0];
        !           273:    dsp = (struct descrip *)newsp;
        !           274:    for (i = 1; i <= na; i++)
        !           275:       *dsp++ = *dp++;
        !           276: 
        !           277:    /*
        !           278:     * Copy procedure frame to new stack and point dsp to word after frame.
        !           279:     */
        !           280:    *((struct pf_marker *)dsp) = rblkp->pfmkr;
        !           281:    sblkp->es_pfp = (struct pf_marker *)dsp;
        !           282:    dsp = (struct descrip *)((word *)dsp + Vwsizeof(*pfp));
        !           283:    sblkp->es_ipc = rblkp->ep;
        !           284:    sblkp->es_gfp = 0;
        !           285:    sblkp->es_efp = 0;
        !           286:    sblkp->tvalloc = NULL;
        !           287:    sblkp->es_ilevel = 0;
        !           288: 
        !           289:    /*
        !           290:     * Copy locals to new stack and refresh block.
        !           291:     */
        !           292:    for (i = 1; i <= nl; i++)
        !           293:       *dsp++ = *dp++;
        !           294: 
        !           295:    /*
        !           296:     * Push two null descriptors on the stack.
        !           297:     */
        !           298:    *dsp++ = nulldesc;
        !           299:    *dsp++ = nulldesc;
        !           300: 
        !           301:    sblkp->es_sp = (word *)dsp - 1;
        !           302: 
        !           303:    /*
        !           304:     * Establish line and file values and clear location for transmitted value.
        !           305:     */
        !           306:    sblkp->es_line = line;
        !           307: 
        !           308:    /*
        !           309:     * Return the new co-expression.
        !           310:     */
        !           311:    Arg0.dword = D_Coexpr;
        !           312:    BlkLoc(Arg0) = (union block *) sblkp;
        !           313:    Return;
        !           314:    }
        !           315: 
        !           316: 
        !           317: /*
        !           318:  * *x - return size of string or object x.
        !           319:  */
        !           320: 
        !           321: /* >size */
        !           322: OpDcl(size,1,"*")
        !           323:    {
        !           324:    char sbuf[MaxCvtLen];
        !           325: 
        !           326:    Arg0.dword = D_Integer;
        !           327:    if (Qual(Arg1)) {
        !           328:       /*
        !           329:        * If Arg1 is a string, return the length of the string.
        !           330:        */
        !           331:       IntVal(Arg0) = StrLen(Arg1);
        !           332:       }
        !           333:    else {
        !           334:       /*
        !           335:        * Arg1 is not a string.  For most types, the size is in the size
        !           336:        *  field of the block.  For records, it is in an auxiliary
        !           337:        *  structure.
        !           338:        */
        !           339:       switch (Type(Arg1)) {
        !           340:          case T_List:
        !           341:             IntVal(Arg0) = BlkLoc(Arg1)->list.size;
        !           342:             break;
        !           343: 
        !           344:          case T_Table:
        !           345:             IntVal(Arg0) = BlkLoc(Arg1)->table.size;
        !           346:             break;
        !           347: 
        !           348:          case T_Set:
        !           349:             IntVal(Arg0) = BlkLoc(Arg1)->set.size;
        !           350:             break;
        !           351: 
        !           352:          case T_Cset:
        !           353:             IntVal(Arg0) = BlkLoc(Arg1)->cset.size;
        !           354:             break;
        !           355: 
        !           356:          case T_Record:
        !           357:             IntVal(Arg0) = BlkLoc(BlkLoc(Arg1)->record.recdesc)->proc.nfields;
        !           358:             break;
        !           359: 
        !           360:          case T_Coexpr:
        !           361:             IntVal(Arg0) = BlkLoc(Arg1)->coexpr.size;
        !           362:             break;
        !           363: 
        !           364:          default:
        !           365:             /*
        !           366:              * Try to convert it to a string.
        !           367:              */
        !           368:             if (cvstr(&Arg1, sbuf) == NULL)
        !           369:                runerr(112, &Arg1);             /* no notion of size */
        !           370:             IntVal(Arg0) = StrLen(Arg1);
        !           371:          }
        !           372:       }
        !           373:    Return;
        !           374:    }
        !           375: /* <size */
        !           376: 
        !           377: /*
        !           378:  * =x - tab(match(x)).
        !           379:  * Reverses effects if resumed.
        !           380:  */
        !           381: 
        !           382: OpDcl(tabmat,1,"=")
        !           383:    {
        !           384:    register word l;
        !           385:    register char *s1, *s2;
        !           386:    word i, j;
        !           387:    char sbuf[MaxCvtLen];
        !           388: 
        !           389:    /*
        !           390:     * x must be a string.
        !           391:     */
        !           392:    if (cvstr(&Arg1,sbuf) == NULL)
        !           393:       runerr(103, &Arg1);
        !           394: 
        !           395:    /*
        !           396:     * Make a copy of &pos.
        !           397:     */
        !           398:    i = k_pos;
        !           399: 
        !           400:    /*
        !           401:     * Fail if &subject[&pos:0] is not of sufficient length to contain x.
        !           402:     */
        !           403:    j = StrLen(k_subject) - i + 1;
        !           404:    if (j < StrLen(Arg1))
        !           405:       Fail;
        !           406: 
        !           407:    /*
        !           408:     * Get pointers to x (s1) and &subject (s2).  Compare them on a bytewise
        !           409:     *  basis and fail if s1 doesn't match s2 for *s1 characters.
        !           410:     */
        !           411:    s1 = StrLoc(Arg1);
        !           412:    s2 = StrLoc(k_subject) + i - 1;
        !           413:    l = StrLen(Arg1);
        !           414:    while (l-- > 0) {
        !           415:       if (*s1++ != *s2++)
        !           416:          Fail;
        !           417:       }
        !           418: 
        !           419:    /*
        !           420:     * Increment &pos to tab over the matched string and suspend the
        !           421:     *  matched string.
        !           422:     */
        !           423:    l = StrLen(Arg1);
        !           424:    k_pos += l;
        !           425:    Arg0 = Arg1;
        !           426:    Suspend;
        !           427: 
        !           428:    /*
        !           429:     * tabmat has been resumed, restore &pos and fail.
        !           430:     */
        !           431:    k_pos = i;
        !           432:    if (k_pos > StrLen(k_subject) + 1)
        !           433:       runerr(205, &tvky_pos.kyval);
        !           434:    Fail;
        !           435:    }
        !           436: 
        !           437: 
        !           438: /*
        !           439:  * i to j by k - generate successive values.
        !           440:  */
        !           441: 
        !           442: /* >toby */
        !           443: OpDcl(toby,3,"toby")
        !           444:    {
        !           445:    long from, to, by;
        !           446: 
        !           447:    /*
        !           448:     * Arg1 (from), Arg2 (to), and Arg3 (by) must be integers.
        !           449:     *  Also, Arg3 must not be zero.
        !           450:     */
        !           451:    if (cvint(&Arg1, &from) == NULL)
        !           452:       runerr(101, &Arg1);
        !           453:    if (cvint(&Arg2, &to) == NULL)
        !           454:       runerr(101, &Arg2);
        !           455:    if (cvint(&Arg3, &by) == NULL)
        !           456:       runerr(101, &Arg3);
        !           457:    if (by == 0)
        !           458:       runerr(211, &Arg3);
        !           459: 
        !           460:    /*
        !           461:     * Count up or down (depending on relationship of from and to) and
        !           462:     *  suspend each value in sequence, failing when the limit has been
        !           463:     *  exceeded.
        !           464:     */
        !           465:    while ((from <= to && by > 0) || (from >= to && by < 0)) {
        !           466:       Mkint(from, &Arg0);
        !           467:       Suspend;
        !           468:       from += by;
        !           469:       }
        !           470:    Fail;
        !           471:    }
        !           472: /* <toby */

unix.superglobalmegacorp.com

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