4.3BSD/usr/contrib/icon/operators/rswap.c

Compare this file to the similar file:
Show the results in this format:

#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)