Annotation of 43BSD/contrib/icon/operators/subsc.c, revision 1.1

1.1     ! root        1: #include "../h/rt.h"
        !             2: #include "../h/record.h"
        !             3: 
        !             4: /*
        !             5:  * x[y] - access yth character or element of x.
        !             6:  */
        !             7: 
        !             8: subsc(nargs, arg1v, arg2, arg1, arg0)
        !             9: int nargs;
        !            10: struct descrip arg1v, arg2, arg1, arg0;
        !            11:    {
        !            12:    register int i, j;
        !            13:    register union block *bp;
        !            14:    int typ1;
        !            15:    long l1;
        !            16:    struct descrip *dp;
        !            17:    char sbuf[MAXSTRING];
        !            18:    extern char *alcstr();
        !            19:    extern struct b_tvtbl *alctvtbl();
        !            20: 
        !            21:    SetBound;
        !            22:    /*
        !            23:     * Make a copy of x.
        !            24:     */
        !            25:    arg1v = arg1;
        !            26: 
        !            27:    if ((typ1 = cvstr(&arg1, sbuf)) != NULL) {
        !            28:       /*
        !            29:        * x is a string, make sure that y is an integer.
        !            30:        */
        !            31:       if (cvint(&arg2, &l1) == NULL)
        !            32:          runerr(101, &arg2);
        !            33:       /*
        !            34:        * Convert y to a position in x and fail if the position is out
        !            35:        *  of bounds.
        !            36:        */
        !            37:       i = cvpos(l1, STRLEN(arg1));
        !            38:       if (i > STRLEN(arg1))
        !            39:          fail();
        !            40:       if (typ1 == 1) {
        !            41:          /*
        !            42:           * x was converted to a string, so it can't be assigned back into.
        !            43:           *  Just return a string containing the selected character.
        !            44:           */
        !            45:          sneed(1);
        !            46:          STRLEN(arg0) = 1;
        !            47:          STRLOC(arg0) = alcstr(STRLOC(arg1)+i-1, 1);
        !            48:          }
        !            49:       else {
        !            50:          /*
        !            51:           * x is a string, make a substring trapped variable for the one
        !            52:           *  character substring selected and return it.
        !            53:           */
        !            54:          hneed(sizeof(struct b_tvsubs));
        !            55:          mksubs(&arg1v, &arg1, i, 1, &arg0);
        !            56:          }
        !            57:       ClearBound;
        !            58:       return;
        !            59:       }
        !            60: 
        !            61:    /*
        !            62:     * x isn't a string or convertible to one, see if it's an aggregate.
        !            63:     */
        !            64:    DeRef(arg1)
        !            65:    switch (TYPE(arg1)) {
        !            66:       case T_LIST:
        !            67:          /*
        !            68:           * x is a list.  Make sure that y is an integer and that the
        !            69:           *  subscript is in range.
        !            70:           */
        !            71:          if (cvint(&arg2, &l1) == NULL)
        !            72:             runerr(101, &arg2);
        !            73:          i = cvpos(l1, BLKLOC(arg1)->list.cursize);
        !            74:          if (i > BLKLOC(arg1)->list.cursize)
        !            75:             fail();
        !            76:          /*
        !            77:           * Locate the list block containing the desired element.
        !            78:           */
        !            79:          bp = BLKLOC(BLKLOC(arg1)->list.listhead);        
        !            80:          j = 1;
        !            81:          while (i >= j + bp->lelem.nused) {
        !            82:             j += bp->lelem.nused;
        !            83:             if (TYPE(bp->lelem.listnext) != T_LELEM)
        !            84:                syserr("list reference out of bounds in subsc");
        !            85:             bp = BLKLOC(bp->lelem.listnext);
        !            86:             }
        !            87:          /*
        !            88:           * Locate the desired element in the block that contains it and
        !            89:           *  return a pointer to it.
        !            90:           */
        !            91:          i += bp->lelem.first - j;
        !            92:          if (i >= bp->lelem.nelem)
        !            93:             i -= bp->lelem.nelem;
        !            94:          dp = &bp->lelem.lslots[i];
        !            95:          arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !            96:          VARLOC(arg0) = dp;
        !            97:          ClearBound;
        !            98:          return;
        !            99: 
        !           100:       case T_TABLE:
        !           101:          /*
        !           102:           * x is a table.  Dereference y and locate the appropriate bucket
        !           103:           *  based on the hash value.
        !           104:           */
        !           105:          DeRef(arg2)
        !           106:          hneed(sizeof(struct b_tvtbl));
        !           107:          i = hash(&arg2);              /* get hash number of subscript  */
        !           108:          bp = BLKLOC(BLKLOC(arg1)->table.buckets[i % NBUCKETS]);
        !           109:          /*
        !           110:           * Work down the chain of elements for the bucket and if an
        !           111:           *  element with the desired subscript value is found, return
        !           112:           *  a pointer to it.
        !           113:           * Elements are ordered in the chain by hashnumber value
        !           114:           * from smallest to largest.
        !           115:           */
        !           116:          while (bp != NULL) {
        !           117:            if (bp->telem.hashnum > i)          /* past it - not there */
        !           118:                break;
        !           119:             if ((bp->telem.hashnum == i)  &&  (equiv(&bp->telem.tref, &arg2))) {
        !           120:                dp = &bp->telem.tval;
        !           121:                arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !           122:                VARLOC(arg0) = dp;
        !           123:                ClearBound;
        !           124:                return;
        !           125:                }
        !           126:             /* We haven't reached the right hashnumber yet or
        !           127:              *  the element is not the right one.
        !           128:              */
        !           129:             bp = BLKLOC(bp->telem.blink);
        !           130:             }
        !           131:            /*
        !           132:             * x[y] is not in the table, make a table element trapped variable
        !           133:             *  and return it as the result.
        !           134:             */
        !           135:          arg0.type = D_TVTBL;
        !           136:          BLKLOC(arg0) = (union block *) alctvtbl(&arg1, &arg2, i);
        !           137:          ClearBound;
        !           138:          return;
        !           139: 
        !           140:       case T_RECORD:
        !           141:          /*
        !           142:           * x is a record.  Convert y to an integer and be sure that it
        !           143:           *  it is in range as a field number.
        !           144:           */
        !           145:          if (cvint(&arg2, &l1) == NULL)
        !           146:             runerr(101, &arg2);
        !           147:          bp = BLKLOC(arg1);
        !           148:          i = cvpos(l1, bp->record.recptr->nfields);
        !           149:          if (i > bp->record.recptr->nfields)
        !           150:             fail();
        !           151:          /*
        !           152:           * Locate the appropriate field and return a pointer to it.
        !           153:           */
        !           154:          dp = &bp->record.fields[i-1];
        !           155:            arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !           156:          VARLOC(arg0) = dp;
        !           157:          ClearBound;
        !           158:          return;
        !           159: 
        !           160:       default:
        !           161:          /*
        !           162:           * x is of a type that can't be subscripted.
        !           163:           */
        !           164:          runerr(114, &arg1);
        !           165:       }        
        !           166:    ClearBound;
        !           167:    }
        !           168: 
        !           169: Opblockx(subsc,3,"[]",2)

unix.superglobalmegacorp.com

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