Annotation of 43BSD/contrib/icon/rt/doasgn.c, revision 1.1.1.1

1.1       root        1: #include "../h/rt.h"
                      2: 
                      3: /*
                      4:  * doasgn - assign value of a2 to variable a1.
                      5:  *  Does the work for asgn, swap, rasgn, and rswap.
                      6:  */
                      7: 
                      8: doasgn(a1, a2)
                      9: struct descrip *a1, *a2;
                     10:    {
                     11:    register int l1, l2;
                     12:    register union block *bp;
                     13:    register struct b_table *tp;
                     14:    union block *hook;
                     15:    long l3;
                     16:    char sbuf1[MAXSTRING], sbuf2[MAXSTRING];
                     17:    extern struct descrip tended[];   /* uses tended[1] through tended[5] */
                     18:    extern struct b_lelem *alclstb();
                     19:    extern char *alcstr();
                     20: 
                     21:    tended[1] = *a1;
                     22:    tended[2] = *a2;
                     23: 
                     24: assign:
                     25: #ifdef DEBUG
                     26:    if (QUAL(tended[1]) || !VAR(tended[1]))
                     27:       syserr("doasgn: variable expected");
                     28: #endif DEBUG
                     29: 
                     30:    if (TVAR(tended[1])) {
                     31:       switch (TYPE(tended[1])) {
                     32:          case T_TVSUBS:
                     33:             /*
                     34:              * An assignment is being made to a substring trapped variable.
                     35:              *  Conceptually, there are three units involved: the value to
                     36:              *  be assigned to the substring, the string containing the
                     37:              *  substring and the substring itself.
                     38:              *
                     39:              * As an example, consider the action of x[2:4] := "xyz" where
                     40:              *  x == "abcd".  The string containing the substring is "abcd",
                     41:              *  the substring is "bc", and the value to be assigned is "xyz".
                     42:              *  A string is allocated for the result, and the portion of the
                     43:              *  string containing the substring up to the substring ("a" in
                     44:              *  this case) is copied into the new string.  Then, the value
                     45:              *  to be assigned, ("xyz"), is added to the new string.
                     46:              *  Finally, the portion of the substrung string to the right
                     47:              *  of the substring ("d") is copied into the new string to
                     48:              *  complete the result ("axyzd").
                     49:              *
                     50:              * The tended descriptors are used as follows:
                     51:              *   tended[1] - the substring trapped variable
                     52:              *   tended[2] - the value to assign
                     53:              *   tended[3] - the string containing the substring
                     54:              *   tended[4] - the substring
                     55:              *   tended[5] - the result string
                     56:              */
                     57:             /*
                     58:              * Be sure that the value to assign is a string.  The result
                     59:              *  is not used, so it seems like it would be much faster to
                     60:              *  see if the value is already a string and only call cvstr
                     61:              *  if necessary.
                     62:              */
                     63:             if (cvstr(&tended[2], sbuf1) == NULL)
                     64:                runerr(103, &tended[2]);
                     65:             /*
                     66:              * Be sure that the string containing the substring is a string.
                     67:              */
                     68:             tended[3] = BLKLOC(tended[1])->tvsubs.ssvar;
                     69:             if (cvstr(&tended[3], sbuf2) == NULL)
                     70:                runerr(103, &tended[3]);
                     71:             /*
                     72:              * Ensure that there is enough string space by checking for
                     73:              *  the worst case size which is the length of the substrung
                     74:              *  string plus the length of the value to be assigned.
                     75:              */
                     76:             sneed(STRLEN(tended[3]) + STRLEN(tended[2]));
                     77:             /*
                     78:              * Get a pointer to the tvsubs block and make l1 a C-style
                     79:              *  index to the character that begins the substring.
                     80:              */
                     81:             bp = BLKLOC(tended[1]);
                     82:             l1 = bp->tvsubs.sspos - 1;
                     83:             /*
                     84:              * Make tended[4] a descriptor for the substring.
                     85:              */
                     86:             STRLEN(tended[4]) = bp->tvsubs.sslen;
                     87:             STRLOC(tended[4]) = STRLOC(tended[3]) + l1;
                     88:             /*
                     89:              * Make l2 a C-style index to the character after the substring.
                     90:              *  If l2 is greater than the length of the substrung string,
                     91:              *  it's an error because the string being assigned won't fit.
                     92:              */
                     93:             l2 = l1 + STRLEN(tended[4]);
                     94:             if (l2 > STRLEN(tended[3]))
                     95:                runerr(205,NULL);
                     96:             /*
                     97:              * Form the result string.  First, copy the portion of the
                     98:              *  substring string to the left of the substring into the string
                     99:              *  space.
                    100:              */
                    101:             STRLOC(tended[5]) = alcstr(STRLOC(tended[3]), l1);
                    102:             /*
                    103:              * Copy the string to be assigned into the string space,
                    104:              *  effectively concatenating it.
                    105:              */
                    106:             alcstr(STRLOC(tended[2]), STRLEN(tended[2]));
                    107:             /*
                    108:              * Copy the portion of the substrung string to the right of
                    109:              *  the substring into the string space, completing the result.
                    110:              */
                    111:             alcstr(STRLOC(tended[3])+l2, STRLEN(tended[3])-l2);
                    112:             /*
                    113:              * Calculate the length of the new string by:
                    114:              *   length of substring string minus
                    115:              *   length of substring (it was replaced) plus
                    116:              *   length of the assigned string.
                    117:              */
                    118:             STRLEN(tended[5]) = STRLEN(tended[3]) - STRLEN(tended[4]) +
                    119:                STRLEN(tended[2]);
                    120:             /*
                    121:              * For this next portion, the parchments left by the Old Ones read
                    122:              *  "tail recursion:"
                    123:              *  "  doasgn(bp->tvsubs.ssvar,tended[5]);"
                    124:              */
                    125:             bp->tvsubs.sslen = STRLEN(tended[2]);
                    126:             tended[1] = bp->tvsubs.ssvar;
                    127:             tended[2] = tended[5];
                    128:             goto assign;
                    129: 
                    130:          case T_TVTBL:
                    131:             /*
                    132:              * An assignment is being made to a table element trapped
                    133:              *  variable.
                    134:              *
                    135:              * Tended descriptors:
                    136:              *  tended[1] - the table element trapped variable
                    137:              *  tended[2] - the value to be assigned
                    138:              *  tended[3] - subscripting value
                    139:              *
                    140:              * Point bp at the trapped variable block; point tended[3]
                    141:              *  at the subscripting value; point tp at the table
                    142:              *  header block.
                    143:              */
                    144:             bp = BLKLOC(tended[1]);
                    145:             if (bp->tvtbl.type == T_TELEM) {
                    146:             /*
                    147:              * It is a converted tvtbl block already in the table
                    148:              *  just assign to it and return.
                    149:              */
                    150:                 bp->telem.tval = tended[2];
                    151:                 clrtend();
                    152:                 return;
                    153:                 }
                    154:             tended[3] = bp->tvtbl.tvtref;
                    155:             tp = (struct b_table *) BLKLOC(bp->tvtbl.tvtable);
                    156:             /*
                    157:              * Get a hash value for the subscripting value and locate the
                    158:              *  element chain on which the element being assigned to will
                    159:              *  be placed.
                    160:              */
                    161:             l1 = bp->tvtbl.hashnum;
                    162:             l2 = l1 % NBUCKETS;   /* bucket number */
                    163:             bp = BLKLOC(tp->buckets[l2]);
                    164:             /*
                    165:              * Look down the bucket chain to see if the value is already
                    166:              *  in the table.  If it's there, just assign to it and return.
                    167:              */
                    168:             hook = bp;
                    169:             while (bp != NULL) {
                    170:               if ( bp->telem.hashnum > l1 ) /* past it - not there */
                    171:                    break;
                    172:               if ((bp->telem.hashnum == l1) &&
                    173:                  (equiv(&bp->telem.tref, &tended[3]))) {
                    174:                        bp->telem.tval = tended[2];
                    175:                        clrtend();
                    176:                        return;
                    177:                        }
                    178:                hook = bp; 
                    179:                bp = BLKLOC(bp->telem.blink);
                    180:                }
                    181:             /*
                    182:              * The value being assigned is new.  Increment the table size,
                    183:              *  and convert the tvtbl to a telem and link it into the chain
                    184:              *  in the table.
                    185:              */
                    186:             tp->cursize++;
                    187:             a1->type = D_VAR | D_TELEM;
                    188:             if (hook == bp) {          /* new element goes at front of chain */
                    189:                bp = BLKLOC(tended[1]);
                    190:                bp->telem.blink = tp->buckets[l2];
                    191:                BLKLOC(tp->buckets[l2]) = bp; 
                    192:                tp->buckets[l2].type = D_TELEM; 
                    193:                }
                    194:             else {                     /* new element follows hook */
                    195:                bp = BLKLOC(tended[1]);
                    196:                bp->telem.blink = hook->telem.blink;
                    197:                BLKLOC(hook->telem.blink) =  bp;
                    198:                hook->telem.blink.type = D_TELEM;
                    199:                }
                    200:             bp->tvtbl.type = T_TELEM;
                    201:             bp->telem.tval = tended[2];
                    202:             clrtend();
                    203:             return;
                    204: 
                    205:          case T_TVPOS:
                    206:             /*
                    207:              * An assignment to &pos is being made.  Be sure that the
                    208:              *  value being assigned is a (non-long) integer.
                    209:              */
                    210:             switch (cvint(&tended[2], &l3)) {
                    211:                case T_INTEGER:  break;
                    212: #ifdef LONGS
                    213:                case T_LONGINT:  clrtend(); fail();
                    214: #endif LONGS
                    215:                default:         runerr(101, &tended[2]);
                    216:                }
                    217:             /*
                    218:              * Convert the value into a position and be sure that it's
                    219:              *  in range.  Note that cvpos fails if the position is past
                    220:              *  the end of the string.
                    221:              */
                    222:             l1 = cvpos(l3, STRLEN(k_subject));
                    223:             if (l1 <= 0) {
                    224:                clrtend();
                    225:                fail();
                    226:                }
                    227:             /*
                    228:              * If all is well, make the assignment to &pos and return.
                    229:              */
                    230:             k_pos = l1;
                    231:             clrtend();
                    232:             return;
                    233: 
                    234:          case T_TVRAND:
                    235:             /*
                    236:              * An assignment to &random is being made.  Be sure that the
                    237:              *  value being assigned is an integer.
                    238:              */
                    239:             switch (cvint(&tended[2], &l3)) {
                    240:                case T_INTEGER:
                    241: #ifdef LONGS
                    242:                case T_LONGINT:
                    243: #endif LONGS
                    244:                                 break;
                    245:                default:         runerr(101, &tended[2]);
                    246:                }
                    247:             k_random = l3;
                    248:             clrtend();
                    249:             return;
                    250: 
                    251:          case T_TVTRACE:
                    252:             /*
                    253:              * An assignment to &trace is being made.  Be sure that the
                    254:              *  value being assigned is an integer.  Should it be a long
                    255:              *  integer, just set &trace to -1.
                    256:              */
                    257:             switch (cvint(&tended[2], &l3)) {
                    258:                case T_INTEGER:  k_trace = (int)l3; break;
                    259: #ifdef LONGS
                    260:                case T_LONGINT:  k_trace = -1; break;
                    261: #endif LONGS
                    262:                default:         runerr(101, &tended[2]);
                    263:                }
                    264:             clrtend();
                    265:             return;
                    266: 
                    267:          default:
                    268:             syserr("doasgn: illegal trapped variable");
                    269:          }
                    270:       }
                    271: 
                    272:    if (VARLOC(tended[1]) == &k_subject) {
                    273:       /*
                    274:        * An assignment is being made to &subject.  Be sure that the value
                    275:        *  being assigned is a string.  If the value is converted to a string,
                    276:        *  allocate it.  Note that &pos is set to 1.
                    277:        */
                    278:       switch (cvstr(&tended[2], sbuf1)) {
                    279:          case NULL:
                    280:             runerr(103, &tended[2]);
                    281:          case 1:
                    282:             sneed(STRLEN(tended[2]));
                    283:             STRLOC(tended[2]) = alcstr(STRLOC(tended[2]), STRLEN(tended[2]));
                    284:          case 2:
                    285:             k_subject = tended[2];
                    286:             k_pos = 1;
                    287:          }
                    288:       }
                    289:    else
                    290:       /*
                    291:        * The easy case, just replace the variable descriptor with the value
                    292:        *  descriptor.
                    293:        */
                    294:       *VARLOC(tended[1]) = tended[2];
                    295:    clrtend();
                    296:    return;
                    297:    }
                    298: 
                    299: /*
                    300:  * clrtend - clear the tended descriptors.
                    301:  */
                    302: clrtend()
                    303:    {
                    304:    register struct descrip *p;
                    305:    extern struct descrip tended[];
                    306: 
                    307:    for (p = &tended[1]; p <= &tended[5]; p++)
                    308:       *p = nulldesc;
                    309:    }

unix.superglobalmegacorp.com

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