while (q != (struct tavl_node *) &tree->tavl_root)
  {
    struct tavl_node *y = q;

    q = find_parent (tree, y);

    if (dir == 0)
      {
        dir = q->tavl_link[0] != y;
        y->tavl_balance++;
        if (y->tavl_balance == +1)
          break;
        else if (y->tavl_balance == +2)
          {
            struct tavl_node *x = y->tavl_link[1];

            assert (x != NULL);
            if (x->tavl_balance == -1)
              {
                struct tavl_node *w;

                assert (x->tavl_balance == -1);
                w = x->tavl_link[0];
                x->tavl_link[0] = w->tavl_link[1];
                w->tavl_link[1] = x;
                y->tavl_link[1] = w->tavl_link[0];
                w->tavl_link[0] = y;
                if (w->tavl_balance == +1)
                  x->tavl_balance = 0, y->tavl_balance = -1;
                else if (w->tavl_balance == 0)
                  x->tavl_balance = y->tavl_balance = 0;
                else /* |w->tavl_balance == -1| */
                  x->tavl_balance = +1, y->tavl_balance = 0;
                w->tavl_balance = 0;
                if (w->tavl_tag[0] == TAVL_THREAD)
                  {
                    y->tavl_tag[1] = TAVL_THREAD;
                    y->tavl_link[1] = w;
                    w->tavl_tag[0] = TAVL_CHILD;
                  }
                if (w->tavl_tag[1] == TAVL_THREAD)
                  {
                    x->tavl_tag[0] = TAVL_THREAD;
                    x->tavl_link[0] = w;
                    w->tavl_tag[1] = TAVL_CHILD;
                  }
                q->tavl_link[dir] = w;
              }
            else
              {
                q->tavl_link[dir] = x;

                if (x->tavl_balance == 0)
                  {
                    y->tavl_link[1] = x->tavl_link[0];
                    x->tavl_link[0] = y;
                    x->tavl_balance = -1;
                    y->tavl_balance = +1;
                    break;
                  }
                else /* |x->tavl_balance == +1| */
                  {
                    if (x->tavl_tag[0] == TAVL_CHILD)
                      y->tavl_link[1] = x->tavl_link[0];
                    else
                      {
                        y->tavl_tag[1] = TAVL_THREAD;
                        x->tavl_tag[0] = TAVL_CHILD;
                      }
                    x->tavl_link[0] = y;
                    y->tavl_balance = x->tavl_balance = 0;
                  }
              }
          }
      }
    else
      {
        dir = q->tavl_link[0] != y;
        y->tavl_balance--;
        if (y->tavl_balance == -1)
          break;
        else if (y->tavl_balance == -2)
          {
            struct tavl_node *x = y->tavl_link[0];
            assert (x != NULL);
            if (x->tavl_balance == +1)
              {
                struct tavl_node *w;

                assert (x->tavl_balance == +1);
                w = x->tavl_link[1];
                x->tavl_link[1] = w->tavl_link[0];
                w->tavl_link[0] = x;
                y->tavl_link[0] = w->tavl_link[1];
                w->tavl_link[1] = y;
                if (w->tavl_balance == -1)
                  x->tavl_balance = 0, y->tavl_balance = +1;
                else if (w->tavl_balance == 0)
                  x->tavl_balance = y->tavl_balance = 0;
                else /* |w->tavl_balance == +1| */
                  x->tavl_balance = -1, y->tavl_balance = 0;
                w->tavl_balance = 0;
                if (w->tavl_tag[0] == TAVL_THREAD)
                  {
                    x->tavl_tag[1] = TAVL_THREAD;
                    x->tavl_link[1] = w;
                    w->tavl_tag[0] = TAVL_CHILD;
                  }
                if (w->tavl_tag[1] == TAVL_THREAD)
                  {
                    y->tavl_tag[0] = TAVL_THREAD;
                    y->tavl_link[0] = w;
                    w->tavl_tag[1] = TAVL_CHILD;
                  }
                q->tavl_link[dir] = w;
              }
            else
              {
                q->tavl_link[dir] = x;

                if (x->tavl_balance == 0)
                  {
                    y->tavl_link[0] = x->tavl_link[1];
                    x->tavl_link[1] = y;
                    x->tavl_balance = +1;
                    y->tavl_balance = -1;
                    break;
                  }
                else /* |x->tavl_balance == -1| */
                  {
                    if (x->tavl_tag[1] == TAVL_CHILD)
                      y->tavl_link[0] = x->tavl_link[1];
                    else
                      {
                        y->tavl_tag[0] = TAVL_THREAD;
                        x->tavl_tag[1] = TAVL_CHILD;
                      }
                    x->tavl_link[1] = y;
                    y->tavl_balance = x->tavl_balance = 0;
                  }
              }
          }
      }
  }

tree->tavl_count--;
return (void *) item;
