/* * File: oasgn.c * Contents: asgn, rasgn, rswap, swap */ #include "..\h\config.h" #include "..\h\rt.h" #include "rproto.h" /* * x := y - assign y to x. */ OpDcl(asgn,2,":=") { /* * Make sure that Arg1 is a variable. */ if (!Var(Arg1)) RunErr(111, &Arg1); /* * The returned result is the variable to which assignment is being * made. */ Arg0 = Arg1; /* * All the work is done by doasgn. Note that Arg1 is known * to be a variable. */ switch (doasgn(&Arg1, &Arg2)) { case Success: Return; case Failure: Fail; case Error: RunErr(0, NULL); } } /* * x <- y - assign y to x. * Reverses assignment if resumed. */ OpDcl(rasgn,2,"<-") { /* * Arg1 must be a variable. */ if (!Var(Arg1)) RunErr(111, &Arg1); /* * The return value is the variable Arg1, so make a copy of it before * it is dereferenced. */ Arg0 = Arg1; if (DeRef(Arg1) == Error) RunErr(0, NULL); /* * Assign Arg2 to Arg1 and suspend. */ switch (doasgn(&Arg0, &Arg2)) { case Success: Suspend; break; case Failure: Fail; case Error: RunErr(0, NULL); } /* * Reverse the assignment by assigning the old value * of back and fail. */ if (doasgn(&Arg0, &Arg1) == Error) RunErr(0, NULL); Fail; } /* * x <-> y - swap values of x and y. * Reverses swap if resumed. */ OpDcl(rswap,2,"<->") { register union block *bp1, *bp2; word adj1, adj2; /* * Arg1 and Arg2 must be variables. */ if (!Var(Arg1)) { RunErr(111, &Arg1); } if (!Var(Arg2)) { RunErr(111, &Arg2); } /* * Make copies of Arg1 and Arg2 as variables in Arg0 and Arg3. */ Arg0 = Arg1; Arg3 = Arg2; adj1 = adj2 = 0; if (Arg1.dword == D_Tvsubs && Arg2.dword == D_Tvsubs) { bp1 = BlkLoc(Arg1); bp2 = BlkLoc(Arg2); if (VarLoc(bp1->tvsubs.ssvar) == VarLoc(bp2->tvsubs.ssvar) && Offset(bp1->tvsubs.ssvar) == Offset(bp2->tvsubs.ssvar)) { /* * Arg1 and Arg2 are both substrings of the same string; set * adj1 and adj2 for use in locating the substrings after * an assignment has been made. If Arg1 is to the right of Arg2, * set adj1 := *Arg1 - *Arg2, otherwise if Arg2 is to the right of * Arg1, set adj2 := *Arg2 - *Arg1. 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; } } if (DeRef(Arg1) == Error) { RunErr(0, NULL); } if (DeRef(Arg2) == Error) { RunErr(0, NULL); } /* * Do Arg1 := Arg2 */ switch (doasgn(&Arg0, &Arg2)) { case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj2 != 0) /* * Arg2 is to the right of Arg1 and the assignment Arg := Arg2 has * shifted the position of Arg2. Add adj2 to the position of Arg2 * to account for the replacement of Arg1 by Arg2. */ BlkLoc(Arg3)->tvsubs.sspos += adj2; /* * Do Arg2 := Arg1 */ switch (doasgn(&Arg3, &Arg1)) { case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj1 != 0) /* * Arg1 is to the right of Arg2 and the assignment Arg2 := Arg1 has * shifted the position of Arg1. Add adj2 to the position of Arg1 * to account for the replacement of Arg2 by Arg1. */ BlkLoc(Arg0)->tvsubs.sspos += adj1; /* * Suspend Arg1 with the assignment in effect. */ Suspend; /* * If resumed, the assignments are undone. Note that the string position * adjustments are opposite those done earlier. */ switch (doasgn(&Arg0, &Arg1)) { /* restore Arg1 */ case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj2 != 0) BlkLoc(Arg3)->tvsubs.sspos -= adj2; switch (doasgn(&Arg3, &Arg2)) { /* restore Arg2 */ case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj1 != 0) BlkLoc(Arg0)->tvsubs.sspos -= adj1; Fail; } /* * x :=: y - swap values of x and y. */ OpDcl(swap,2,":=:") { register union block *bp1, *bp2; word adj1, adj2; /* * Arg1 and Arg2 must be variables. */ if (!Var(Arg1)) { RunErr(111, &Arg1); } if (!Var(Arg2)) { RunErr(111, &Arg2); } /* * Make copies of Arg1 and Arg2 as variables in Arg0 and Arg3. */ Arg0 = Arg1; Arg3 = Arg2; adj1 = adj2 = 0; if (Arg1.dword == D_Tvsubs && Arg2.dword == D_Tvsubs) { bp1 = BlkLoc(Arg1); bp2 = BlkLoc(Arg2); if (VarLoc(bp1->tvsubs.ssvar) == VarLoc(bp2->tvsubs.ssvar) && Offset(bp1->tvsubs.ssvar) == Offset(bp2->tvsubs.ssvar)) { /* * Arg1 and Arg2 are both substrings of the same string, set * adj1 and adj2 for use in locating the substrings after * an assignment has been made. If Arg1 is to the right of Arg2, * set adj1 := *Arg1 - *Arg2, otherwise if Arg2 is to the right of * Arg1, set adj2 := *Arg2 - *Arg1. 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; } } if (DeRef(Arg1) == Error) { RunErr(0, NULL); } if (DeRef(Arg2) == Error) { RunErr(0, NULL); } /* * Do Arg1 := Arg2 */ switch (doasgn(&Arg0, &Arg2)) { case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj2 != 0) /* * Arg2 is to the right of Arg1 and the assignment Arg1 := Arg2 has * shifted the position of Arg2. Add adj2 to the position of Arg2 * to account for the replacement of Arg1 by Arg2. */ BlkLoc(Arg3)->tvsubs.sspos += adj2; /* * Do Arg2 := Arg1 */ switch (doasgn(&Arg3, &Arg1)) { case Success: break; case Failure: Fail; case Error: RunErr(0, NULL); } if (adj1 != 0) /* * Arg1 is to the right of Arg2 and the assignment Arg2 := Arg1 has * shifted the position of Arg1. Add adj2 to the position of Arg1 to * account for the replacement of Arg2 by Arg1. */ BlkLoc(Arg0)->tvsubs.sspos += adj1; Return; }