home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: rdoasgn.c
- * Contents: doasgn.c
- */
-
- #include "../h/config.h"
- #include "../h/rt.h"
- #include "rproto.h"
-
- /*
- * doasgn - assign value of dp2 to variable dp1.
- * Does the work for asgn, swap, rasgn, and rswap.
- */
-
- int doasgn(dp1, dp2)
- dptr dp1, dp2;
- {
- register word i1, i2;
- register union block *bp;
- register struct b_table *tp;
- register uword hn;
- int (*putf)();
- int ret_code;
- union block *hook, **slot;
- char sbuf1[MaxCvtLen];
-
- tended[1] = *dp1;
- tended[2] = *dp2;
- ntended = 2;
-
- assign:
-
- if (!Tvar(tended[1]))
- *(dptr)((word *)VarLoc(tended[1]) + Offset(tended[1])) = tended[2];
- else switch (Type(tended[1])) {
- case T_Tvsubs:
- /*
- * An assignment is being made to a substring trapped
- * variable. The tended descriptors are used as
- * follows:
- *
- * tended[1] - the substring trapped variable
- * tended[2] - the value to assign
- * tended[3] - the string containing the substring
- * tended[4] - the substring
- * tended[5] - the result string
- */
-
- /*
- * Be sure that the value to be assigned is a string.
- */
- ntended = 5;
- if (DeRef(tended[2]) == Error) {
- ntended = 0;
- return Error;
- }
- if (cvstr(&tended[2], sbuf1) == CvtFail) {
- ntended = 0;
- RetError(103, tended[2]);
- }
-
- /*
- * Be sure that the variable in the trapped variable points
- * to a string.
- */
- tended[3] = BlkLoc(tended[1])->tvsubs.ssvar;
- if (DeRef(tended[3]) == Error) {
- ntended = 0;
- return Error;
- }
- if (!Qual(tended[3])) {
- ntended = 0;
- RetError(103, tended[3]);
- }
- if (strreq(StrLen(tended[3]) + StrLen(tended[2])) == Error)
- return Error;
-
- /*
- * Get a pointer to the substring trapped-variable block and
- * make i1 a C-style index to the character that begins the
- * substring.
- */
- bp = BlkLoc(tended[1]);
- i1 = bp->tvsubs.sspos - 1;
-
- /*
- * Make tended[4] a descriptor for the substring.
- */
- StrLen(tended[4]) = bp->tvsubs.sslen;
- StrLoc(tended[4]) = StrLoc(tended[3]) + i1;
-
- /*
- * Make i2 a C-style index to the character after the
- * substring. If i2 is greater than the length of the
- * substring, it is an error because the string being
- * assigned will not fit.
- */
- i2 = i1 + StrLen(tended[4]);
- if (i2 > StrLen(tended[3])) {
- ntended = 0;
- RetError(-205, nulldesc);
- }
-
- /*
- * Form the result string. First, copy the portion of the
- * substring string to the left of the substring into the
- * string space.
- */
- StrLoc(tended[5]) = alcstr(StrLoc(tended[3]), i1);
-
- /*
- * Copy the string to be assigned into the string space,
- * effectively concatenating it.
- */
- alcstr(StrLoc(tended[2]), StrLen(tended[2]));
-
- /*
- * Copy the portion of the substring to the right of
- * the substring into the string space, completing the
- * result.
- */
- alcstr(StrLoc(tended[3]) + i2, StrLen(tended[3]) - i2);
-
- /*
- * Calculate the length of the new string.
- */
- StrLen(tended[5]) = StrLen(tended[3]) - StrLen(tended[4]) +
- StrLen(tended[2]);
- bp->tvsubs.sslen = StrLen(tended[2]);
- tended[1] = bp->tvsubs.ssvar;
- tended[2] = tended[5];
-
- /*
- * Everything is set up for the actual assignment. Go
- * back to the beginning of the routine to do it.
- */
- goto assign;
-
- case T_Tvtbl:
- /*
- *
- * The tended descriptors are used as follows:
- *
- * tended[1] - the table element trapped variable
- * tended[2] - the value to be assigned
- * tended[3] - subscripting value
- */
-
- /*
- * Point bp to the trapped-variable block, point tended[3]
- * to the subscripting value, and point tp to the table-
- * header block.
- */
- ntended = 3;
- bp = BlkLoc(tended[1]);
-
- if (bp->tvtbl.title == T_Telem) {
- /*
- * The trapped-variable block already has been
- * converted to a table-element block. Just assign
- * to it and return.
- */
- bp->telem.tval = tended[2];
- ntended = 0;
- return Success;
- }
- tended[3] = bp->tvtbl.tref;
- tp = (struct b_table *)bp->tvtbl.clink;
-
- /*
- * Get the hash number for the subscripting value and
- * locate the chain that contains the element to which
- * assignment is to be made.
- */
- hn = bp->tvtbl.hashnum;
- slot = hchain((union block *)tp, hn);
- bp = *slot;
-
- /*
- * Traverse the chain to see if the value is already in the
- * table. If it is there, assign to it and return.
- */
- hook = bp;
- while (bp != NULL && bp->telem.hashnum <= hn) {
- if (bp->telem.hashnum == hn &&
- equiv(&bp->telem.tref, &tended[3])) {
- bp->telem.tval = tended[2];
- ntended = 0;
- return Success;
- }
- hook = bp;
- bp = bp->telem.clink;
- }
-
- /*
- * The value being assigned is new. Increment the table
- * size, convert the table-element trapped-variable block
- * to a table-element block, and link it into the chain.
- */
- tp->size++;
- if (hook == bp) { /* it goes at front of chain */
- bp = BlkLoc(tended[1]);
- bp->telem.clink = *slot;
- *slot = bp;
- }
-
- else { /* it follows hook */
- bp = BlkLoc(tended[1]);
- bp->telem.clink = hook->telem.clink;
- hook->telem.clink = bp;
- }
-
- bp->tvtbl.title = T_Telem;
- bp->telem.tval = tended[2];
- tended[1].dword = D_Telem;
- MMShow(&tended[1], "r");
- if (TooCrowded(tp)) {
- tended[1].dword = D_Table;
- BlkLoc(tended[1]) = (union block *)tp;
- hgrow(&tended[1]);
- }
- ntended = 0;
- return Success;
-
- case T_Tvkywd:
- ntended = 2;
- putf = BlkLoc(tended[1])->tvkywd.putval;
- ret_code = (*putf)(&tended[2], BlkLoc(tended[1]));
- ntended = 0;
- return ret_code;
-
- default:
- syserr("doasgn: illegal trapped variable");
- }
-
- ntended = 0;
- return Success;
- }
-