home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- }
-