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

DWORD creat_p( DWORD fun, DWORD term_1, DWORD term_2, DWORD sub_1, DWORD sub_2)
// pointer * Is this branch contein a head
//         * Is this branch contein an atom
//         * Obseg 1 - in the tree
//         * Obseg 2 - in the blocks
//         * not Obseg 1 and not Obseg 2 - concrete term

// br_buf2 - turns in left
// bufu1 (br_buf2) - turns in right between that in left
// bufu2 "            - term2 / bufu4 - father of bufu2 / bufu3 - the same for creator
// bufu7 "           - saves i1

// i1               - turns in right on curent deep (for variables)
// st_buf      (i1) - Ufil_vs / bufu5 - from it we obtein the same for creator
// st_buf_num "       - haw many variables in the left term

// sv_tr (Mtree) nulira=MASKA, izpolzva, uvelichava++, proveriava>=MEMORY_rt
// Ch_tree - not Obseg 2 - the constant 
// Ch_tree -     Obseg 2 - the first marked with Unique flag if it is only
{
DWORD term1, term2, func, my_buf, my_buf_num, creator, creat_l, creat_m=0, where_flag;
DWORD pointer, point_l, br_buf2, i1, p1, t, m, blue_flag=127; // TR
DWORD i, j, p, n, q, pt; // temporal
WORD leaf;

  term2=term_2;
  term1=term_1;
  func=HALFM & fun;
  i1=pointer=br_buf2=0;
  bufu1[0]=0;
  if (term_1>=MEMORY_c256 || term_1==TT_VAR)
  {
    if (term_2>=MEMORY_c256 || term_2==TT_VAR)
    {
      t=(term_2==TT_VAR)?1:Chfil_v[term_2-MEMORY_c256];
      p=p1=(term_1==TT_VAR)?1:Chfil_v[term_1-MEMORY_c256];
      if (status_fl&256)  // from exe file
      {
        p1=Chfil_v[sv_v];
        my_buf=Ufil_vs[sv_v];
        my_buf_num=p;
        m=t;
      }
      else if (sub_1==M1) // for make ReadyLists
      {
        p1=t+p;
        my_buf_num=p;
        my_buf=M1;
      }
      else
      {
        if (sv_subT+p1+t>MEMORY_STemp && correct_MEM_STemp(p1+t))
        {
          MitiText("Small MEMORY_STemp!\r\n");
          // exit(1);
        }
        tt_sub=sv_subT;
        for (i=0; i<p1; i++)
          SubstiT[sv_subT+i]=SubstiT[sub_1+i];
        sv_subT+=i;
        for (m=0; m<t; m++)
        {
          for (n=0; SubstiT[sub_1+n]!=SubstiT[sub_2+m] && n<p; n++);
          if (n==p)
          {
            Substi[sv_sub+m]=(WORD)p1++;
            SubstiT[sv_subT++]=SubstiT[sub_2+m];
          }
          else
            Substi[sv_sub+m]=(WORD)n;
        }
        my_buf_num=p;
        if (m+p==p1)
          my_buf=M1;
        else
          my_buf=sv_sub;
      }
    }
    else
    {
      tt_sub=sub_1;
      p1=my_buf_num=(term_1==TT_VAR)?1:Chfil_v[term_1-MEMORY_c256];
      my_buf=M1;
    }
  }
  else if (term_2>=MEMORY_c256 || term_2==TT_VAR)
  {
    p1=(term_2==TT_VAR)?1:Chfil_v[term_2-MEMORY_c256];
    tt_sub=sub_2;                       /* unusless */
    my_buf_num=0;
    my_buf=M1;
  }
  else
  {
    my_buf_num=0;
    my_buf=M2;
  }
  while ((pointer=Mtree[point_l=pointer & MASKA][func]) & OBSEG1)
  {
    if (term1>=TT_START)
    {
      bufu7[br_buf2]=i1+1;
      bufu4[br_buf2]=creat_m;
      bufu2[br_buf2++]=term2;
      bufu1[br_buf2]=0;
      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 ((pointer=Mtree[point_l=pointer & MASKA][func=0]) & OBSEG1)
      {
        if (term1!=Ch_tree[point_l])
        {
          blue_flag=pointer & THREE_Q;
          goto e59;
        }
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_num[i1]=0;
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        i1++;
        if (term2>=TT_START)
        {
          bufu1[br_buf2]++;
          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 ((pointer=Mtree[point_l=pointer & MASKA][func=0]) & OBSEG1)
          {
            if (term2!=Ch_tree[point_l])
            {
              blue_flag=pointer & THREE_Q;
e59:          if (fun&HALF)
                return(M1);
              // create block (new one)
              for (q=sv_blocks2, i=0; i<4; q=(q + PRIME_2)%sv_blocks, i++)
                if (Blocks_val[q]==SM1 && Blocks_val[q+leaf]==SM1 && Blocks_val[q+Ch_tree[point_l]]==SM1)
                {
                  sv_blocks2=q+1;
                  goto e45;
                }
              sv_blocks2=q;
              for (q=sv_blocks+1; 1; q += PRIME_1)
              {
                if (q >= BLOCKS && correct_BLOCKS() )
                  MitiText("Small BLOCKS!\r\n");
                if (Blocks_val[q]==SM1 && Blocks_val[q+leaf]==SM1 && Blocks_val[q+Ch_tree[point_l]]==SM1)
                {
                  sv_blocks=q;
                  goto e45;
                }
              }
e45:          Mtree[point_l][0]= q | blue_flag | OBSEG2;
              
              Blocks_val[q]= SM2; // maybe will be coverd by one of the next two
              Blocks_val[q+Ch_tree[point_l]]=Ch_tree[point_l];
              Blocks_val[q+leaf]=leaf;
              
              Blocks[q+Ch_tree[point_l]]=pointer | blue_flag;
              Blocks[q+leaf]=(my_buf!=M2)?(MEMORY_C + sv_v):sv_c;
              
              Blocks_next[q+Ch_tree[point_l]]=leaf;
              Blocks_next[q+leaf]=SM1;

              if (my_buf!=M2)
                goto e33;
              else
                goto e3;              
            }
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_num[i1-1]=0;
            }
            else
            {
              st_buf[0]=my_buf;
              st_buf_num[0]=my_buf_num;
            }
            bufu1[br_buf2]++;
            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
          {
            where_flag=0;
            break;
          }
        }
      }
      else
      {
        where_flag=1;
        break;
      }
    }
  }
  if (pointer==MASKA)
  {
    if (fun&HALF)
      return(M1);
    if (func==0) //?
      Ch_tree[point_l]=leaf;
e23:if (my_buf!=M2)
    {
      Mtree[point_l][func]=MEMORY_C+sv_v;
e33:  if (sv_v>=MEMORY_V && correct_MEM_V() )
      {
        MitiText("Small MEMORY_V!\r\n");
       // exit(1);
      }
      Chfil_v[sv_v]=(WORD)p1;
      Ufil_vs[sv_v]=my_buf;
      Chfil_c[MEMORY_C+sv_v]=(BYTE)fun;
      Ufil_c1[MEMORY_C+sv_v]=term_1;
      Ufil_c2[MEMORY_C+sv_v]=term_2;
      if (my_buf!=M1)
      {
        if ((sv_sub+=m)>MEMORY_S && correct_MEM_S())
        {
          MitiText("Small MEMORY_S!\r\n");
        // exit(1);
        }
      }
      return(MEMORY_c256+sv_v++);
    }
    else
    {
      Mtree[point_l][func]=sv_c;
e3:   if (sv_c>=MEMORY_C-1 && correct_MEM_C() ) // -1 is the min
      {
        MitiText("Small MEMORY_C!\r\n");
       // exit(1);
      }
      Chfil_c[sv_c]=(BYTE)fun;
      Ufil_c1[sv_c]=term_1;
      Ufil_c2[sv_c]=term_2;
      return(TT_START+sv_c++);
    }
  }
  else if (pointer & OBSEG2)        /* In block */
  {
#if TR
    if (func>0)
      MitiText("It can't be. !unfinished\r\n");
#endif      
    pt=point_l;
    pointer=Blocks[(point_l=pointer&MASKA)+leaf];
    if (Blocks_val[point_l+leaf]!=leaf)
    {
      if (fun&HALF)
        return(M1);
      if (Blocks_val[point_l+leaf]==SM1)
        goto e66;
      else
      {
        // create block (move old)
        for (q=sv_blocks2, i=0; i<2; q=(q + PRIME_2)%sv_blocks, i++)
          if (Blocks_val[q]==SM1 && Blocks_val[q+leaf]==SM1)
          {
            for (j=Ch_tree[pt]; Blocks_val[q+j]==SM1; )
              if ((j=Blocks_next[point_l+j])==SM1)
              {
                sv_blocks2=q+1;
                goto e99;
              }
          }
        sv_blocks2=q;
        for (q=sv_blocks+1; 1; q += PRIME_1)
        {
          if (q >= BLOCKS && correct_BLOCKS() )
            MitiText("Small BLOCKS!\r\n");
          if (Blocks_val[q]==SM1 && Blocks_val[q+leaf]==SM1)
          {
            for (j=Ch_tree[pt]; Blocks_val[q+j]==SM1; )
              if ((j=Blocks_next[point_l+j])==SM1)
              {
                sv_blocks=q;
                goto e99;
              }
          }
        }
e99:    if (Blocks_val[point_l]!=0) // !=0 => ==SM2
        {
          Blocks_val[point_l]=SM1;
          Blocks_val[q]= SM2;
        }
        j=Ch_tree[pt];
        do
        {
          Blocks[q+j]=Blocks[point_l+j];
          Blocks_val[q+j]=Blocks_val[point_l+j];
          Blocks_next[q+j]=Blocks_next[point_l+j];
          Blocks_val[point_l+j]=SM1;
        }
        while ((j=Blocks_next[point_l+j])!=SM1);
        point_l=q;
        Mtree[pt][0]= point_l | (Mtree[pt][0] & THREE_Q) | OBSEG2;
          
e66:    Blocks_val[point_l+leaf]=leaf;
        Blocks[point_l+leaf]=(my_buf!=M2)?(MEMORY_C + sv_v):sv_c;
        
        for (j=Ch_tree[pt], i=Blocks_next[point_l+j]; i!=SM1 && (Blocks[point_l+i]&HALF); j=i, i=Blocks_next[point_l+i]);
        Blocks_next[point_l+j]=leaf;
        Blocks_next[point_l+leaf]=(WORD)i;
        
        if (my_buf!=M2)
          goto e33;
        else
          goto e3;              
      }
    }
    else if (pointer & OBSEG1)
    {
      if (where_flag) // back in the tree
        goto e60;
      else
        goto e61;
    }
    else
    {
      blue_flag=pointer & THREE_Q;
      if (term_2==Ufil_c2[pointer&=MASKA] && term_1==Ufil_c1[pointer])
      {                             /* The same */
        if (my_buf!=M2)
        {
          if (my_buf==M1 || Ufil_vs[pointer-MEMORY_C]==M1)
          {
            if (my_buf!=Ufil_vs[pointer-MEMORY_C])
              goto e100;
          }
          else
          {
            for(i=0; i<t && Substi[my_buf+i]==Substi[Ufil_vs[pointer-MEMORY_C]+i]; i++);
            if (i<t)
              goto e100;
          }
        }
        return(TT_START+pointer);
      }
      else
      {
e100:   if (fun&HALF)
          return(M1);
        Blocks[point_l+leaf]= sv_tr | blue_flag | OBSEG1; //jump
        point_l=0; // send in the black hole
        goto e21;
      }
    }
  }
  else // concrete term
  {
    blue_flag=pointer & THREE_Q;
    if (term_2==Ufil_c2[pointer&=MASKA] && term_1==Ufil_c1[pointer])
    {                             /* The same */
      if (my_buf!=M2)
      {
        if (my_buf==M1 || Ufil_vs[pointer-MEMORY_C]==M1)
        {
          if (my_buf!=Ufil_vs[pointer-MEMORY_C])
            goto e7;
        }
        else
        {
          for(i=0; i<t && Substi[my_buf+i]==Substi[Ufil_vs[pointer-MEMORY_C]+i]; i++);
          if ( i<t)
            goto e7;
        }
      }
      return(TT_START+pointer);
    }
    else
    {
e7:   if (fun&HALF)
        return(M1);
      if (!func && leaf!=Ch_tree[point_l])
        goto e59;
e21:  creator=pointer+TT_START;
      for (n=i=0; i<br_buf2; i++)
      {
        for(j=bufu1[i]; j--; bufu5[n++]=creator, creator=Ufil_c2[creator-TT_START]);
        bufu3[i]=creator;
        creator=Ufil_c1[creator-TT_START];
      }
      for( j=bufu1[i]; j--; bufu5[n++]=creator, creator=Ufil_c2[creator-TT_START]);                                 /* losing buf2! */
      if (!br_buf2 && !func && !where_flag)              /* if structure is finised */
      {
        creator=Ufil_c2[creator-TT_START];
        goto e30;
      }
      if (func)                /* Two terms, 1 or 2 - no shoes */
      {
e5:     creator=Ufil_c1[(creat_l=creator)-TT_START];
        if ( ((creator>=TT_START)+(term1>=TT_START))%2 ||
                   (term1>=TT_START && Chfil_c[creator-TT_START]!=Chfil_c[term1-TT_START]) )
        {    // different
          term2=term1; // no problem, this is the end
e63:      Mtree[point_l][func]=sv_tr | blue_flag | OBSEG1;
          Mtree[sv_tr][0]=Mtree[sv_tr][1]=Mtree[sv_tr][2]=Mtree[sv_tr][3]=MASKA;
          if (creator>=TT_START)
            Mtree[sv_tr][Chfil_c[creator-TT_START]]=pointer | blue_flag; //  not in pointer
          else
          {
            Mtree[sv_tr][0]=pointer | blue_flag; // not in pointer
            if (creator==TT_VAR)
            {
              for (j=0, n=i1; n-->0; )
              {
                if (Ufil_vs[bufu5[n]-MEMORY_c256]!=M1)
                  j=Substi[Ufil_vs[bufu5[n]-MEMORY_c256]+j];
                else
                  j+=st_buf_num[n];
              }
              creator=TT_VAR+j;
            }
            Ch_tree[sv_tr]=(WORD)creator;
          }
          if (term2>=TT_START)
            func=Chfil_c[term2-TT_START];
          else
          {
            func=0;
            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;
            }
            Ch_tree[sv_tr]=(WORD)term2;
          }
          point_l=sv_tr++;
          if (sv_tr>=MEMORY_tr && correct_MEM_tr() )
          {
e46:        MitiText("Small MEMORY_tr!\r\n");
            return(M1);
          }
          goto e23;
        }
        else
        {
          if (creator>=TT_START)
          {
            Mtree[point_l][func]=sv_tr | blue_flag | OBSEG1;
            Mtree[sv_tr][0]=Mtree[sv_tr][1]=Mtree[sv_tr][2]=Mtree[sv_tr][3]=MASKA;
            func=Chfil_c[creator-TT_START];
            point_l=sv_tr++;
            if (sv_tr>=MEMORY_tr && correct_MEM_tr() )
              goto e46;
            bufu7[br_buf2]=i1+1;
            bufu4[br_buf2]=creat_m;
            bufu2[br_buf2]=term2;
            bufu3[br_buf2++]=creat_l;
            term2=Ufil_c2[creat_m=term1-TT_START];
            term1=Ufil_c1[creat_m];
            goto e5;
          }
          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;
          }
          if (creator==TT_VAR)
          {
            for (j=0, n=i1; n-->0; )
            {
              if (Ufil_vs[bufu5[n]-MEMORY_c256]!=M1)
                j=Substi[Ufil_vs[bufu5[n]-MEMORY_c256]+j];
              else
                j+=st_buf_num[n];
            }
            creator=TT_VAR+j;
          }
          leaf=(WORD)term1;
          Mtree[point_l][func]=sv_tr | blue_flag | OBSEG1;
          Mtree[sv_tr][1]=Mtree[sv_tr][2]=Mtree[sv_tr][3]=MASKA;    // for 0 is OK
          func=0;
          point_l=sv_tr++;
          if (sv_tr>=MEMORY_tr && correct_MEM_tr() )
            goto e46;
          Ch_tree[point_l]=(WORD)creator;
          if (term1!=creator)
            goto e59;
          creator=creat_l;
          goto e4;
        }
      }
      else if (where_flag)
      {                                                /* two terms, FUNC - one shose */
e4:     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_num[i1]=0;
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        bufu5[i1++]=creator;
        creator=Ufil_c2[creator-TT_START];
        if ( ((creator>=TT_START)+(term2>=TT_START))%2 || (term2>=TT_START &&
                                Chfil_c[creator-TT_START]!=Chfil_c[term2-TT_START]) )
          goto e63; // different
        else
        {
          Mtree[point_l][0]=sv_tr | blue_flag | OBSEG1;
          Mtree[sv_tr][0]=Mtree[sv_tr][1]=Mtree[sv_tr][2]=Mtree[sv_tr][3]=MASKA;
          point_l=sv_tr++;
          if (sv_tr>=MEMORY_tr && correct_MEM_tr() )
            goto e46;
          if (creator>=TT_START)
          {
            func=Chfil_c[creator-TT_START];
            term2=Ufil_c2[creat_m=term2-TT_START];
            term1=Ufil_c1[creat_m];
            goto e5;
          }
e30:      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;
          }
          if (creator==TT_VAR)
          {
            for (j=0, n=i1; n-->0; )
            {
              if (Ufil_vs[bufu5[n]-MEMORY_c256]!=M1)
                j=Substi[Ufil_vs[bufu5[n]-MEMORY_c256]+j];
              else
                j+=st_buf_num[n];
            }
            creator=TT_VAR+j;
          }
          Ch_tree[point_l]=(WORD)creator;
          if (term2==creator)
            goto e6;
          leaf=(WORD)term2;
          goto e59;
        }
      }
      else                       /* two teerms, 0 - two shose */
      {
e6:     creator=Ufil_c2[bufu3[--br_buf2]-TT_START];
        i1=bufu7[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_num[i1-1]=0;
        }
        else
        {
          st_buf[0]=my_buf;
          st_buf_num[0]=my_buf_num;
        }
        bufu5[i1-1]=bufu3[br_buf2];
        if ( ((creator>=TT_START)+((term2=bufu2[br_buf2])>=TT_START))%2 || (creator>=TT_START &&
                                Chfil_c[creator-TT_START]!=Chfil_c[term2-TT_START]) )
          goto e63; //different
        else
        {
          Mtree[point_l][0]=sv_tr | blue_flag | OBSEG1;
          Mtree[sv_tr][0]=Mtree[sv_tr][1]=Mtree[sv_tr][2]=Mtree[sv_tr][3]=MASKA;
          point_l=sv_tr++;
          if (sv_tr>=MEMORY_tr && correct_MEM_tr() )
            goto e46;
          if (creator>=TT_START)
          {
            func=Chfil_c[creator-TT_START];
            term2=Ufil_c2[creat_m=term2-TT_START];
            term1=Ufil_c1[creat_m];
            goto e5;
          }
          goto e30;
        }
      }
    }
  }
}
