Annotation of researchv10dc/cmd/icon/src/iconx/omisc.c, revision 1.1.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.