#include "../h/rt.h" /* * x <-> y - swap values of x and y. * Reverses swap if resumed. */ rswap(nargs, arg2v, arg2, arg1, arg0) int nargs; struct descrip arg2v, arg2, arg1, arg0; { register union block *bp1, *bp2; int adj1, adj2; SetBound; /* * x and y must be variables. */ if (QUAL(arg1) || !VAR(arg1)) runerr(111, &arg1); if (QUAL(arg2) || !VAR(arg2)) runerr(111, &arg2); /* * Make copies of x and y as variables in arg0 and arg2v. */ arg0 = arg1; arg2v = arg2; adj1 = adj2 = 0; if (arg1.type == D_TVSUBS && arg2.type == D_TVSUBS) { bp1 = BLKLOC(arg1); bp2 = BLKLOC(arg2); if (VARLOC(bp1->tvsubs.ssvar) == VARLOC(bp2->tvsubs.ssvar)) { /* * x and y are both substrings of the same string, set * adj1 and adj2 for use in locating the substrings after * an assignment has been made. If x is to the right of y, * set adj1 := *x - *y, otherwise if y is to the right of x, * set adj2 := *y - *x. Note that the adjustment values may * be negative. */ if (bp1->tvsubs.sspos > bp2->tvsubs.sspos) adj1 = bp1->tvsubs.sslen - bp2->tvsubs.sslen; else if (bp2->tvsubs.sspos > bp1->tvsubs.sspos) adj2 = bp2->tvsubs.sslen - bp1->tvsubs.sslen; } } DeRef(arg1) DeRef(arg2) /* * Do x := y */ doasgn(&arg0, &arg2); if (adj2 != 0) /* * y is to the right of x and the assignment x := y has shifted * the position of y. Add adj2 to the position of y to account * for the replacement of x by y. */ BLKLOC(arg2)->tvsubs.sspos += adj2; doasgn(&arg2v, &arg1); /* * Do y := x */ if (adj1 != 0) /* * x is to the right of y and the assignment y := x has shifted * the position of x. Add adj2 to the position of x to account * for the replacement of y by x. */ BLKLOC(arg1)->tvsubs.sspos += adj1; /* * Suspend x with the assignment in effect. */ suspend(); /* * If resumed, the assignments are undone. Note that the string position * adjustments are identical to those done earlier. */ doasgn(&arg0, &arg1); /* restore x */ if (adj2 != 0) BLKLOC(arg2)->tvsubs.sspos += adj2; doasgn(&arg2v, &arg2); /* restore y */ if (adj1 != 0) BLKLOC(arg1)->tvsubs.sspos += adj1; fail(); } Opblockx(rswap,3,"<->",2)