//#include "Unix.h"
#include "stdafx.h"   //MS Windows
#include "Strawberry.h"

DWORD Unregister( DWORD term, DWORD modific)
// pointer * Is this branch contein a head
//         * Is this branch contein an atom
//         * Obseg 1, 2 or 3  1-1 2-0 3-0
//         *                      0    1    0
{
DWORD term1, term2, func, my_buf, my_buf_num=0, creat_m=0, flag;
DWORD pointer, br_buf2, i1, i, j, t, point_last=0;
WORD leaf;

  if (term<TT_START)
    return(term);
  term1=Ufil_c1[term-TT_START];
  term2=Ufil_c2[term-TT_START];
  func=Chfil_c[term-TT_START];
  i1=pointer=br_buf2=0;
  if (term1>=MEMORY_c256 || term1==TT_VAR)
  {
    if (term2>=MEMORY_c256 || term2==TT_VAR)
    {
      my_buf_num=(term1==TT_VAR)?1:Chfil_v[term1-MEMORY_c256];
      my_buf=Ufil_vs[term-MEMORY_c256];
    }
    else
    {
      my_buf_num=(term1==TT_VAR)?1:Chfil_v[term1-MEMORY_c256];
      my_buf=M1;
    }
  }
  else if (term2>=MEMORY_c256 || term2==TT_VAR)
  {
    my_buf_num=0;
    my_buf=M1;
  }
  else
    my_buf=M2;

  while (1)
  {
    i=pointer & MASKA;
    if ((Mtree[i][0] & modific) || (Mtree[i][1+(func%3)] & modific) || (Mtree[i][1+((func+1)%3)] & modific))
      point_last=pointer;
    if ( !((pointer=Mtree[i][func]) & OBSEG1) )
      goto sec_part;
    if (term1>=TT_START)
    {
      bufu7[br_buf2]=i1+1;
      bufu4[br_buf2]=creat_m;
      bufu2[br_buf2++]=term2;
      func=Chfil_c[creat_m=term1-TT_START];
      term2=Ufil_c2[creat_m];
      term1=Ufil_c1[creat_m];
    }
    else if (term1==TT_VAR)
    {
      for (j=0, i=i1; i-->0; )
      {
        if (st_buf[i]!=M1)
          j=Substi[st_buf[i]+j];
        else
          j+=st_buf_num[i];
      }
      term1=TT_VAR+j;
      goto e25u;
    }
    else
    {
e25u: leaf=(WORD)term1;
      i=pointer & MASKA;
      if ((Mtree[i][1] & modific) || (Mtree[i][2] & modific) || (Mtree[i][3] & modific))
        point_last=pointer;
      if ((pointer=Mtree[i][func=0]) & OBSEG1)
      {
e60u:    if (br_buf2 || i1)               /* TRAIL OF SUBSTITUTIOS */
        {
          if (creat_m>=MEMORY_C)
          {
            st_buf[i1]=Ufil_vs[creat_m-MEMORY_C];
            st_buf_num[i1]=(term1>=TT_VAR); // term1 is a constant or variable
          }
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        i1++;
        if (term2>=TT_START)
        {
          func=Chfil_c[creat_m=term2-TT_START];
          term2=Ufil_c2[creat_m];
          term1=Ufil_c1[creat_m];
        }
        else
e49u:        if (term2==TT_VAR)
        {
          for (j=0, i=i1; i-->0; )
          {
            if (st_buf[i]!=M1)
              j=Substi[st_buf[i]+j];
            else
              j+=st_buf_num[i];
          }
          term2=TT_VAR+j;
          goto e26u;
        }
        else
        {
e26u:     leaf=(WORD)term2;
          i=pointer & MASKA;
          if ((Mtree[i][1] & modific) || (Mtree[i][2] & modific) || (Mtree[i][3] & modific))
            point_last=pointer;
          if ((pointer=Mtree[i][func=0]) & OBSEG1)
          {
e61u:        i1=bufu7[--br_buf2];
            term2=bufu2[br_buf2];
            if (br_buf2 || i1>1)               /* TRAIL OF SUBSTITUTIOS */
            {
              if (bufu4[br_buf2]>=MEMORY_C)
              {
                st_buf[i1-1]=Ufil_vs[bufu4[br_buf2]-MEMORY_C];
                st_buf_num[i1-1]=((term1=Ufil_c1[bufu4[br_buf2]]-TT_START)>=MEMORY_C)?
                                                         Chfil_v[term1-MEMORY_C]:0;
              }
            }
            else
            {
              st_buf[0]=my_buf;
              st_buf_num[0]=my_buf_num;
            }
            if (term2>=TT_START)
            {
              func=Chfil_c[creat_m=term2-TT_START];
              term2=Ufil_c2[creat_m];
              term1=Ufil_c1[creat_m];
            }
            else
              goto e49u;
          }
          else
          {
            flag=0;
            break;
          }
        }
      }
      else
      {
        flag=1;
        break;
      }
    }
  }
  if (pointer & OBSEG2)        /* In block */
  {
    for (j=pointer&MASKA, t=Ch_tree[i]; t!=leaf && !(Blocks[j+t] & modific); t=Blocks_next[j+t]);
    if (t==leaf)
    {
      for ( t=Blocks_next[j+t]; t!=SM1 && !(Blocks[j+t] & modific); t=Blocks_next[j+t]);
      if (t!=SM1)
        point_last=pointer;
    }
    else
      point_last=pointer;
    
    pointer=Blocks[j+leaf];
    if (pointer & OBSEG1)
    {
      if (flag) // back in the tree
        goto e60u;
      else
        goto e61u;
    }
    else
      goto sec_part;
  }
  else                    /* Must be the same */
    goto sec_part;

// Second part of this function (dark side of the moon)!!!
// It is a little bit faster with three parts
sec_part:
  term1=Ufil_c1[term-TT_START];
  term2=Ufil_c2[term-TT_START];
  func=Chfil_c[term-TT_START];
  i1=pointer=br_buf2=0;
  while (1)
  {
    i=pointer & MASKA;
    if (point_last==pointer)
      goto st0;
    if ( !((pointer=Mtree[i][func]) & OBSEG1) )
      return(M1);
    if (term1>=TT_START)
    {
      bufu7[br_buf2]=i1+1;
      bufu4[br_buf2]=creat_m;
      bufu2[br_buf2++]=term2;
      func=Chfil_c[creat_m=term1-TT_START];
      term2=Ufil_c2[creat_m];
      term1=Ufil_c1[creat_m];
    }
    else if (term1==TT_VAR)
    {
      for (j=0, i=i1; i-->0; )
      {
        if (st_buf[i]!=M1)
          j=Substi[st_buf[i]+j];
        else
          j+=st_buf_num[i];
      }
      term1=TT_VAR+j;
      goto e25;
    }
    else
    {
e25:  leaf=(WORD)term1;
      if (point_last==pointer)
        goto st1;
      if ((pointer=Mtree[i=pointer & MASKA][func=0]) & OBSEG1)
      {
e60:    if (br_buf2 || i1)               /* TRAIL OF SUBSTITUTIOS */
        {
          if (creat_m>=MEMORY_C)
          {
            st_buf[i1]=Ufil_vs[creat_m-MEMORY_C];
            st_buf_num[i1]=(term1>=TT_VAR); // term1 is a constant or variable
          }
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        i1++;
        if (term2>=TT_START)
        {
          func=Chfil_c[creat_m=term2-TT_START];
          term2=Ufil_c2[creat_m];
          term1=Ufil_c1[creat_m];
        }
        else
e49:         if (term2==TT_VAR)
        {
          for (j=0, i=i1; i-->0; )
          {
            if (st_buf[i]!=M1)
              j=Substi[st_buf[i]+j];
            else
              j+=st_buf_num[i];
          }
          term2=TT_VAR+j;
          goto e26;
        }
        else
        {
e26:      leaf=(WORD)term2;
          if (point_last==pointer)
            goto st2;
          if ((pointer=Mtree[i=pointer & MASKA][func=0]) & OBSEG1)
          {
e61:        i1=bufu7[--br_buf2];
            term2=bufu2[br_buf2];
            if (br_buf2 || i1>1)               /* TRAIL OF SUBSTITUTIOS */
            {
              if (bufu4[br_buf2]>=MEMORY_C)
              {
                st_buf[i1-1]=Ufil_vs[bufu4[br_buf2]-MEMORY_C];
                st_buf_num[i1-1]=((term1=Ufil_c1[bufu4[br_buf2]]-TT_START)>=MEMORY_C)?
                                                         Chfil_v[term1-MEMORY_C]:0;
              }
            }
            else
            {
              st_buf[0]=my_buf;
              st_buf_num[0]=my_buf_num;
            }
            if (term2>=TT_START)
            {
              func=Chfil_c[creat_m=term2-TT_START];
              term2=Ufil_c2[creat_m];
              term1=Ufil_c1[creat_m];
            }
            else
              goto e49;
          }
          else
          {
            flag=0;
            break;
          }
        }
      }
      else
      {
        flag=1;
        break;
      }
    }
  }
  if (pointer & OBSEG2)        /* In block */
  {
    if (point_last==pointer)
      goto st3;
    pointer=Blocks[(pointer&MASKA)+leaf];
    if (pointer & OBSEG1)
    {
      if (flag) // back in the tree
        goto e60;
      else
        goto e61;
    }
    else
      return(M1);
  }
  else                    /* Must be the same */
    return(M1);
// Third part of this function (very dark side of the moon)!!!
// It is a little bit faster with three parts
  while (1)
  {
    i=pointer & MASKA;
st0:if ( !((pointer=Mtree[i][func]^=modific) & OBSEG1) )
      return(TT_START+i);
    if (term1>=TT_START)
    {
      bufu7[br_buf2]=i1+1;
      bufu4[br_buf2]=creat_m;
      bufu2[br_buf2++]=term2;
      func=Chfil_c[creat_m=term1-TT_START];
      term2=Ufil_c2[creat_m];
      term1=Ufil_c1[creat_m];
    }
    else if (term1==TT_VAR)
    {
      for (j=0, i=i1; i-->0; )
      {
        if (st_buf[i]!=M1)
          j=Substi[st_buf[i]+j];
        else
          j+=st_buf_num[i];
      }
      term1=TT_VAR+j;
      goto e25v;
    }
    else
    {
e25v:  leaf=(WORD)term1;
st1:  if ((pointer=Mtree[i=pointer & MASKA][func=0]^=modific) & OBSEG1)
      {
e60v:    if (br_buf2 || i1)               /* TRAIL OF SUBSTITUTIOS */
        {
          if (creat_m>=MEMORY_C)
          {
            st_buf[i1]=Ufil_vs[creat_m-MEMORY_C];
            st_buf_num[i1]=(term1>=TT_VAR); // term1 is a constant or variable
          }
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        i1++;
        if (term2>=TT_START)
        {
          func=Chfil_c[creat_m=term2-TT_START];
          term2=Ufil_c2[creat_m];
          term1=Ufil_c1[creat_m];
        }
        else
e49v:        if (term2==TT_VAR)
        {
          for (j=0, i=i1; i-->0; )
          {
            if (st_buf[i]!=M1)
              j=Substi[st_buf[i]+j];
            else
              j+=st_buf_num[i];
          }
          term2=TT_VAR+j;
          goto e26v;
        }
        else
        {
e26v:     leaf=(WORD)term2;
st2:      if ((pointer=Mtree[i=pointer & MASKA][func=0]^=modific) & OBSEG1)
          {
e61v:       i1=bufu7[--br_buf2];
            term2=bufu2[br_buf2];
            if (br_buf2 || i1>1)               /* TRAIL OF SUBSTITUTIOS */
            {
              if (bufu4[br_buf2]>=MEMORY_C)
              {
                st_buf[i1-1]=Ufil_vs[bufu4[br_buf2]-MEMORY_C];
                st_buf_num[i1-1]=((term1=Ufil_c1[bufu4[br_buf2]]-TT_START)>=MEMORY_C)?
                                                         Chfil_v[term1-MEMORY_C]:0;
              }
            }
            else
            {
              st_buf[0]=my_buf;
              st_buf_num[0]=my_buf_num;
            }
            if (term2>=TT_START)
            {
              func=Chfil_c[creat_m=term2-TT_START];
              term2=Ufil_c2[creat_m];
              term1=Ufil_c1[creat_m];
            }
            else
              goto e49v;
          }
          else
          {
            flag=0;
            break;
          }
        }
      }
      else
      {
        flag=1;
        break;
      }
    }
  }
  if (pointer & OBSEG2)        /* In block */
  {
st3:if (modific==HALF && Blocks_next[(pointer&MASKA)+leaf]!=SM1 && (Blocks_next[(pointer&MASKA)+leaf]&HALF))
    {
      for (j=SM1, t=Ch_tree[i]; t!=leaf; j=t, t=Blocks_next[(pointer&MASKA)+t]); // take out
      if (j==SM1)
        Ch_tree[i]=Blocks_next[(pointer&MASKA)+leaf];
      else
        Blocks_next[(pointer&MASKA)+j]=Blocks_next[(pointer&MASKA)+leaf];
      
      for (j=SM1, t=Ch_tree[i]; t!=SM1 && (Blocks[(pointer&MASKA)+t]&HALF);     // put in
                                                                  j=t, t=Blocks_next[(pointer&MASKA)+t]);
      Blocks_next[(pointer&MASKA)+leaf]=(WORD)t;
      if (j==SM1)
        Ch_tree[i]=leaf;
      else
        Blocks_next[(pointer&MASKA)+j]=leaf;
    }
    pointer=Blocks[(pointer&MASKA)+leaf]^=modific;
    if (pointer & OBSEG1)
    {
      if (flag) // back in the tree
        goto e60v;
      else
        goto e61v;
    }
    else
      return(TT_START+(pointer&MASKA));
  }
  else                    /* Must be the same */
    return(TT_START+(pointer&MASKA));
}
