/* * 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; }