if (p->tbst_tag[1] == TBST_THREAD)
  {
    if (p->tbst_tag[0] == TBST_CHILD)
      {
        struct tbst_node *t = p->tbst_link[0];
        while (t->tbst_tag[1] == TBST_CHILD)
          t = t->tbst_link[1];
        t->tbst_link[1] = p->tbst_link[1];
        q->tbst_link[dir] = p->tbst_link[0];
      }
    else
      {
        q->tbst_link[dir] = p->tbst_link[dir];
        if (q != (struct tbst_node *) &tree->tbst_root)
          q->tbst_tag[dir] = TBST_THREAD;
      }
  }
else
  {
    struct tbst_node *r = p->tbst_link[1];
    if (r->tbst_tag[0] == TBST_THREAD)
      {
        r->tbst_link[0] = p->tbst_link[0];
        r->tbst_tag[0] = p->tbst_tag[0];
        if (r->tbst_tag[0] == TBST_CHILD)
          {
            struct tbst_node *t = r->tbst_link[0];
            while (t->tbst_tag[1] == TBST_CHILD)
              t = t->tbst_link[1];
            t->tbst_link[1] = r;
          }
        q->tbst_link[dir] = r;
      }
    else
      {
        struct tbst_node *s;

        for (;;)
          {
            s = r->tbst_link[0];
            if (s->tbst_tag[0] == TBST_THREAD)
              break;

            r = s;
          }

        if (s->tbst_tag[1] == TBST_CHILD)
          r->tbst_link[0] = s->tbst_link[1];
        else
          {
            r->tbst_link[0] = s;
            r->tbst_tag[0] = TBST_THREAD;
          }

        s->tbst_link[0] = p->tbst_link[0];
        if (p->tbst_tag[0] == TBST_CHILD)
          {
            struct tbst_node *t = p->tbst_link[0];
            while (t->tbst_tag[1] == TBST_CHILD)
              t = t->tbst_link[1];
            t->tbst_link[1] = s;

            s->tbst_tag[0] = TBST_CHILD;
          }

        s->tbst_link[1] = p->tbst_link[1];
        s->tbst_tag[1] = TBST_CHILD;

        q->tbst_link[dir] = s;
      }
  }

