#ifdef DOC_BUILD_INTERNAL
#endif
#include "folsubst.h"
TERMSTATE subst_TERMSTATE;
GATOM subst_CreateGAtom(MEMORY Mem, TERMSTATE Termstate, TERM Term, VSUBST Subst, unsigned Vars, BOOL Phase)
{
  GATOM gatom;
  unsigned i;
  gatom = memory_Malloc(Mem, (Vars+2)*sizeof(intptr_t));
  gatom[0] = Vars << 1;
  gatom[0] = gatom[0] | (intptr_t)Phase;
  gatom[1] = (intptr_t)Term;
  gatom = gatom + 2;
  for(i = 0; i < Vars; i++)
    gatom[i] = (intptr_t)Subst[i];
  return gatom;
}
GATOM subst_GatomCopy(MEMORY Mem, GATOM Gatom)
{
  GATOM new;
  unsigned i, Vars;
  Vars = subst_GatomVars(Gatom);
  new = memory_Malloc(Mem, (Vars+2)*sizeof(intptr_t));
  Gatom = Gatom-2;
  new[0] = Gatom[0];
  new[1] = Gatom[1];
  new = new + 2;
  Gatom = Gatom + 2;
  for(i = 0; i < Vars; i++)
    new[i] = (intptr_t)Gatom[i];
  return new;
}
VSUBST subst_GatomSubst(GATOM Gatom)
{
  return Gatom;
}
TERM subst_GatomAtom(GATOM Gatom)
{
  return (TERM)Gatom[-1];
}
BOOL subst_GatomPhasePositive(GATOM Gatom)
{
  return (BOOL)Gatom[-2] & TRUE;
}
void subst_GatomSetPhase(GATOM Gatom, BOOL Phase)
{
  if (Phase)
    Gatom[-2] = Gatom[-2] | Phase;
  else
    Gatom[-2] = Gatom[-2] & Phase;
}
unsigned subst_GatomVars(GATOM Gatom)
{
  return (unsigned)(Gatom[-2] >> 1);
}
void subst_GatomDelete(MEMORY Mem, GATOM Gatom)
{
  Gatom = Gatom -2;
  memory_Free(Mem, Gatom, (2 + (Gatom[0] >> 1))*sizeof(intptr_t));
}
void subst_GatomPrint(SYMBSTATE Symbstate, TERMSTATE Termstate, GATOM Atom)
{
  term_PrintPrefix(Termstate, subst_GatomAtom(Atom));
  printf(" ");
  subst_VPrint(Symbstate, subst_GatomSubst(Atom));
}
void subst_GatomMapUnusedVariablesIdle(SYMBSTATE Symbstate, SUBSTSTATE Subststate, TERMSTATE Termstate, GATOM Gatom)
{
  unsigned i;
  subst_ContextStart(Subststate, Symbstate);
  subst_TermMarkVariables(Subststate, Symbstate, subst_GatomAtom(Gatom));
  for (i=0;i<subst_GatomVars(Gatom); i++) {
    if (!subst_ContextValueIsMarked(Subststate, i))
      subst_VSetValue(subst_GatomSubst(Gatom), i, symbol_GetIdleConstant(Symbstate));
  }
  subst_ContextStop(Subststate);
}
UCONTEXT subst_CreateUContext(MEMORY Mem, int Vars)
{
  UCONTEXT result;
  int i;
  result = (UCONTEXT)memory_Malloc(Mem, ((Vars*3) + 1) * sizeof(intptr_t));
  for (i=0;i<=Vars*3;i++)
    result[i] = 0;
  result++;
  return result;
}
UCONTEXT subst_UContextLeft(SUBSTSTATE SState)
{
  return SState->left;
}
UCONTEXT subst_UContextRight(SUBSTSTATE SState)
{
  return SState->right;
}
void subst_DeleteUContext(MEMORY Mem, UCONTEXT Context, int Vars)
{
  Context = Context -1;
  memory_Free(Mem, Context, ((Vars*3) + 1) * sizeof(intptr_t));
}
void subst_UContextSetTyping(UCONTEXT Context, TYPING Typing)
{
  Context[-1] = (intptr_t)Typing;
}
TYPING subst_UContextGetTyping(UCONTEXT Context)
{
  return (TYPING)Context[-1];
}
void subst_UContextSetValue(SUBSTSTATE SState, UCONTEXT Context, SYMBOL Var, TERM Term, UCONTEXT TContext)
{
  Var = 3 * Var;
  Context[Var] = SState->mark;
  Context[Var+1] = (intptr_t)Term;
  Context[Var+2] = (intptr_t)TContext;
}
void subst_UContextClearMark(UCONTEXT Context, SYMBOL Var)
{
  Context[3*Var] = 0;
}
BOOL subst_UContextValueIsMarked(SUBSTSTATE SState, UCONTEXT Context, SYMBOL Var)
{
  return (SState->mark == Context[(3*Var)]);
}
TERM subst_UContextGetTerm(SUBSTSTATE SState, UCONTEXT Context, SYMBOL Var)
{
  return (TERM)Context[(3*Var)+1];
}
UCONTEXT subst_UContextGetContext(SUBSTSTATE SState, UCONTEXT Context, SYMBOL Var)
{
  return (UCONTEXT)Context[(3*Var)+2];
}
SUBSTSTATE subst_StateCreate(MEMORY Mem, unsigned Vars)
{
  SUBSTSTATE sstate;
  CONTEXT context;
  UCONTEXT ulcontext,urcontext;
  unsigned i;
  sstate = memory_Malloc(Mem, sizeof(SUBSTSTATE_NODE));
  sstate->memory = Mem;
  sstate->vars = Vars;
  context = memory_Malloc(Mem, sizeof(intptr_t)*Vars*4);
  sstate->mark = 1;
  sstate->active = FALSE;
  sstate->context = context;
  for (i=0; i<Vars*4;i++) {
    context[i] = 0;
  }
  sstate->stack = array_Create(Mem, Vars*10);
  sstate->matchs = array_Create(Mem, Vars/2);
  sstate->sactive = FALSE;
  ulcontext = subst_CreateUContext(Mem, Vars);
  urcontext = subst_CreateUContext(Mem, Vars);
  for (i=0; i<Vars*3;i++) {
    ulcontext[i] = 0;
    urcontext[i] = 0;
  }
  sstate->left = ulcontext;
  sstate->right = urcontext;
  return sstate;
}
void subst_StateUpdate(MEMORY Mem, SYMBSTATE Symbstate, SUBSTSTATE State, unsigned Vars)
{
  if (Vars > State->vars) {
    unsigned i;
    CONTEXT context;
    UCONTEXT ulcontext,urcontext;
    memory_Free(Mem, State->context, sizeof(intptr_t)*State->vars*4);
    subst_DeleteUContext(Mem, State->left, State->vars);
    subst_DeleteUContext(Mem, State->right, State->vars);
    array_Delete(Mem, State->stack);
    array_Delete(Mem, State->matchs);
    Vars = 2 * Vars;
    State->vars = Vars;
    context = memory_Malloc(Mem, sizeof(intptr_t)*Vars*4);
    State->mark = 1;
    State->active = FALSE;
    State->context = context;
    for (i=0; i<Vars*4;i++) {
      context[i] = 0;
    }
    State->stack = array_Create(Mem, Vars);
    State->matchs = array_Create(Mem, Vars/2);
    State->sactive = FALSE;
    ulcontext = subst_CreateUContext(Mem, Vars);
    urcontext = subst_CreateUContext(Mem, Vars);
    for (i=0; i<Vars*3;i++) {
      ulcontext[i] = 0;
      urcontext[i] = 0;
    }
    State->left = ulcontext;
    State->right = urcontext;
    symbol_AdjustStateMaxVarsLimit(Symbstate, Vars);
  }
}
void subst_HotStateUpdate(MEMORY Mem, SYMBSTATE Symbstate, SUBSTSTATE State, unsigned Vars)
{
  if (Vars > State->vars) {
    unsigned i;
    CONTEXT context;
    UCONTEXT ulcontext,urcontext;
    subst_DeleteUContext(Mem, State->left, State->vars);
    subst_DeleteUContext(Mem, State->right, State->vars);
    Vars = 2 * Vars;
    context = memory_Malloc(Mem, sizeof(intptr_t)*Vars*4);
    for (i=0; i<State->vars*4;i++) {
      context[i] = State->context[i];
    }
    for (i=State->vars*4; i < Vars*4;i++) {
      context[i] = 0;
    }
    memory_Free(Mem, State->context, sizeof(intptr_t)*State->vars*4);
    State->vars = Vars;
    State->context = context;
    ulcontext = subst_CreateUContext(Mem, Vars);
    urcontext = subst_CreateUContext(Mem, Vars);
    for (i=0; i<Vars*3;i++) {
      ulcontext[i] = 0;
      urcontext[i] = 0;
    }
    State->left = ulcontext;
    State->right = urcontext;
    symbol_AdjustStateMaxVarsLimit(Symbstate, Vars);
  }
}
void subst_StateDelete(MEMORY Mem, SUBSTSTATE SState)
{
  memory_Free(Mem, SState->context, sizeof(intptr_t)*SState->vars*4);
  array_Delete(Mem, SState->stack);
  array_Delete(Mem, SState->matchs);
  subst_DeleteUContext(Mem, SState->left, SState->vars);
  subst_DeleteUContext(Mem, SState->right, SState->vars);
  memory_Free(Mem, SState, sizeof(SUBSTSTATE_NODE));
}
unsigned subst_MaxVars(SUBSTSTATE SState)
{
  return SState->vars;
}
BOOL subst_ContextValueIsMarked(SUBSTSTATE SState, SYMBOL Var)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
  if (Var >= SState->vars) {
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Variable larger than maximal variable. Var is %u and maxvar is %u.", __func__, Var, SState->vars);
    misc_FinishUserErrorReport();
  }
#endif
  return (SState->mark == SState->context[(Var<<2)+1]);
}
intptr_t subst_ContextGetValue(SUBSTSTATE SState, SYMBOL Var)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  return (SState->context[(Var<<2)]);
}
void subst_ContextSetValue(SUBSTSTATE SState, SYMBOL Var, intptr_t Put)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
  if (Var >= SState->vars) {
    misc_StartErrorReport();
    misc_ErrorReport("\n%s: Var range byond max var: %d.\n",__func__, Var);
    misc_FinishErrorReport();
  }
#endif
  SState->context[(Var<<2)] = Put;
  SState->context[(Var<<2)+1] = SState->mark;
}
void subst_ContextSetValueStack(SUBSTSTATE SState, SYMBOL Var, intptr_t Put)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
  if (Var >= SState->vars) {
    misc_StartErrorReport();
    misc_ErrorReport("\n%s: Var range byond max var: %d.\n",__func__, Var);
    misc_FinishErrorReport();
  }
#endif
  subst_ContextSetValue(SState, Var, Put);
  SState->stack = array_Add(SState->memory, SState->stack, Var);
}
void subst_ContextUnsetValue(SUBSTSTATE SState, SYMBOL Var)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartErrorReport();
    misc_ErrorReport("%s: Context not in use.",__func__);
    misc_FinishErrorReport();
  }
#endif
  SState->context[(Var<<2)+1] = 0;
}
intptr_t subst_ContextGetExtraValue(SUBSTSTATE SState, SYMBOL Var)
{
  return SState->context[(Var<<2)+2];
}
void subst_ContextSetExtraValue(SUBSTSTATE SState, SYMBOL Var, intptr_t Put)
{
#ifdef SPASS_CHECK
  if (Var >= SState->vars) {
    misc_StartErrorReport();
    misc_ErrorReport("\n%s: Var range byond max var: %d.\n",__func__, Var);
    misc_FinishErrorReport();
  }
#endif
  SState->context[(Var<<2)+2] = Put;
}
void subst_ContextSetSecondExtraValue(SUBSTSTATE SState, SYMBOL Var, intptr_t Put)
{
#ifdef SPASS_CHECK
  if (Var >= SState->vars) {
    misc_StartErrorReport();
    misc_ErrorReport("\n%s: Var range byond max var: %d.\n",__func__, Var);
    misc_FinishErrorReport();
  }
#endif
  SState->context[(Var<<2)+3] = Put;
}
intptr_t subst_ContextGetSecondExtraValue(SUBSTSTATE SState, SYMBOL Var)
{
  return SState->context[(Var<<2)+3];
}
void subst_ContextSetExtraValueWithMark(SUBSTSTATE SState, SYMBOL Var, intptr_t Put)
{
  SState->context[(Var<<2)+2] = Put;
  SState->context[(Var<<2)+3] = SState->mark;
}
BOOL subst_ContextExtraValueIsMarked(SUBSTSTATE SState, SYMBOL Var)
{
  return (SState->mark == SState->context[(Var<<2)+3]);
}
TERM subst_UContextGetValueFollowSymbolChain(SUBSTSTATE SState, SYMBSTATE Symbstate, UCONTEXT *Context, TERM Term)
{
  SYMBOL Top;
  Top = term_TopSymbol(Term);
  if (!symbol_IsVariable(Symbstate, Top) || !subst_UContextValueIsMarked(SState, *Context, Top))
     return Term;
   else {
     Term = subst_UContextGetTerm(SState, *Context, Top);
     *Context = subst_UContextGetContext(SState, *Context, Top);
     return subst_UContextGetValueFollowSymbolChain(SState, Symbstate, Context, Term);
   }
}
SYMBOL subst_ContextGetValueFollowSymbolChain(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL Top)
{
  if (!symbol_IsVariable(Symbstate, Top) || !subst_ContextValueIsMarked(SState, Top))
    return Top;
  else
    return subst_ContextGetValueFollowSymbolChain(SState, Symbstate, (SYMBOL)subst_ContextGetValue(SState, Top));
}
TERM subst_ContextGetTermValueFollowSymbolChain(SUBSTSTATE SState, SYMBSTATE Symbstate, TERM Term)
{
  SYMBOL Top;
  Top = term_TopSymbol(Term);
  if (!symbol_IsVariable(Symbstate, Top) || !subst_ContextValueIsMarked(SState, Top))
    return Term;
  else
    return subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, (TERM)subst_ContextGetValue(SState, Top));
}
void subst_ContextFlattenTerms(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL Maxvar)
{
  unsigned i;
  for (i=0;i<Maxvar;i++) {
    if (subst_ContextValueIsMarked(SState, i))
      subst_ContextSetValue(SState, i, (intptr_t)subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, (TERM)subst_ContextGetValue(SState, i)));
  }
}
SYMBOL subst_ContextGetValueFollowSymbolChainLeft(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL Top)
{
  if (!symbol_IsVariable(Symbstate, Top) || !subst_ContextValueIsMarked(SState, Top))
    return Top;
  else
    return subst_ContextGetValueFollowSymbolChainRight(SState, Symbstate, (SYMBOL)subst_ContextGetValue(SState, Top));
}
SYMBOL subst_ContextGetValueFollowSymbolChainRight(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL Top)
{
  if (!symbol_IsVariable(Symbstate, Top) || !subst_ContextExtraValueIsMarked(SState, Top))
    return Top;
  else
    return subst_ContextGetValueFollowSymbolChainLeft(SState, Symbstate, (SYMBOL)subst_ContextGetExtraValue(SState, Top));
}
void subst_ContextFlattenTermChainDisjoint(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL Var)
{
  if (subst_ContextValueIsMarked(SState, Var) && symbol_IsVariable(Symbstate, (SYMBOL)subst_ContextGetValue(SState, Var))) {
    subst_ContextFlattenTermChainDisjoint(SState, Symbstate, (SYMBOL)subst_ContextGetValue(SState, Var));
    subst_ContextSetValue(SState, Var, (intptr_t)subst_ContextGetValueFollowSymbolChain(SState, Symbstate, (SYMBOL)subst_ContextGetValue(SState, Var)));
  }
}
TERM subst_UContextFlattenTermChainDisjointTerm(SUBSTSTATE SState, TERMSTATE Termstate, UCONTEXT Context, TERM Term)
{
  SYMBOL top;
  Term = subst_UContextGetValueFollowSymbolChain(SState, term_GetSymbstate(Termstate), &Context, Term);
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(term_GetSymbstate(Termstate), top) || symbol_IsConstant(top))
    return term_Copy(Termstate, Term);
  else {
    unsigned i;
    Term = term_CopyShallow(Termstate, Term);
    for (i = 0; i < term_GetArity(Term); i++)
      Term[i] = (intptr_t)subst_UContextFlattenTermChainDisjointTerm(SState, Termstate, Context, (TERM)Term[i]);
    return Term;
  }
}
void subst_UContextFlattenTermChainDisjoint(SUBSTSTATE SState, TERMSTATE Termstate, SYMBOL Var)
{
  if (subst_UContextValueIsMarked(SState, subst_UContextLeft(SState), Var))
    subst_UContextSetValue(SState, subst_UContextLeft(SState),
      Var,
      subst_UContextFlattenTermChainDisjointTerm(SState, Termstate, subst_UContextLeft(SState), subst_UContextGetTerm(SState, subst_UContextLeft(SState), Var)),
      subst_UContextLeft(SState));
}
void subst_ContextStart(SUBSTSTATE SState, SYMBSTATE Symbstate)
{
#ifdef SPASS_CHECK
  if (SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context already in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  SState->active = TRUE;
  SState->mark++;
  if (SState->mark == INT_MAX) {
    unsigned i;
    for(i=0;i<SState->vars*4;i++)
      SState->context[i] = 0;
    for(i=0;i<SState->vars*3;i++) {
      SState->left[i] = 0;
      SState->right[i] = 0;
    }
    SState->mark = 1;
  }
}
void subst_ContextStackStart(SUBSTSTATE SState)
{
#ifdef SPASS_CHECK
  if (!SState->active || SState->sactive){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use or stack in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  SState->sactive = TRUE;
  array_SetSize(SState->stack,0);
  array_SetSize(SState->matchs,0);
}
void subst_ContextStackStop(SUBSTSTATE SState)
{
#ifdef SPASS_CHECK
  if (!SState->active || !SState->sactive){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use or stack not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  SState->sactive = FALSE;
}
void subst_ContextStackPush(SUBSTSTATE SState)
{
#ifdef SPASS_CHECK
  if (!SState->active || !SState->sactive){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use or stack not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  SState->matchs = array_Add(SState->memory, SState->matchs, array_GetSize(SState->stack));
}
void subst_ContextStackPop(SUBSTSTATE SState)
{
  int i, size;
#ifdef SPASS_CHECK
  if (!SState->active || !SState->sactive){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use or stack not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  size = array_Pop(SState->matchs);
  for (i = array_GetSize(SState->stack) - 1; i >= size; i--)
    subst_ContextUnsetValue(SState, SState->stack[i]);
  array_SetSize(SState->stack, size);
}
void subst_ContextPrint(SUBSTSTATE SState, TERMSTATE Termstate, BOOL Symbol)
{
  intptr_t i;
  BOOL first;
  SYMBSTATE symbstate;
  first = TRUE;
  symbstate = term_GetSymbstate(Termstate);
  printf("{");
  for(i=0;i<SState->vars;i++) {
    if (subst_ContextValueIsMarked(SState, i)) {
      if (first)
 first = FALSE;
      else
 printf(",");
      symbol_Print(symbstate, i);
      printf(" -> ");
      if (Symbol)
 symbol_Print(symbstate, (SYMBOL)subst_ContextGetValue(SState, i));
      else
 term_PrintPrefix(Termstate, (TERM)subst_ContextGetValue(SState, i));
    }
  }
  printf("}");
}
void subst_TermMarkVariables(SUBSTSTATE SState, SYMBSTATE Symbstate, TERM Term)
{
  SYMBOL top;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top))
    subst_ContextSetValue(SState, top, top);
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_TermMarkVariables(SState, Symbstate, term_GetArgument(Term,i));
  }
}
void subst_VUndefineVariablesInTerm(SYMBSTATE Symbstate, TERM Term, VSUBST Subst)
{
  SYMBOL top;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top))
    subst_VSetValue(Subst, top, symbol_GetDummyConstant(Symbstate));
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_VUndefineVariablesInTerm(Symbstate, term_GetArgument(Term,i), Subst);
  }
}
void subst_VarNormalize(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, ARRAY Vartypes, TYPE Type)
{
  SYMBOL top,new;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top) && !term_AlreadyVisited(Termstate, Term)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
    else {
      new = symbol_GetNextStandardVar(Symbstate);
      term_RplacTop(Term, new);
      subst_ContextSetValue(SState, top, new);
      if (Type != (TYPE)((intptr_t)NULL))
 subst_ContextSetExtraValue(SState, new, Type);
      else {
 if (Vartypes != (ARRAY)NULL) {
   subst_ContextSetExtraValue(SState, new, Vartypes[top]);
 }
      }
    }
    term_SetTermStamp(Termstate, Term);
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_VarNormalize(SState, Termstate, Symbstate, term_GetArgument(Term,i), Vartypes, Type);
  }
}
void subst_VVarNormalizeIntern(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, VSUBST Subst)
{
  SYMBOL top,new;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top) && !term_AlreadyVisited(Termstate, Term)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
    else {
      new = symbol_GetNextStandardVar(Symbstate);
      term_RplacTop(Term, new);
      subst_ContextSetValue(SState, top, new);
      subst_VSetValue(Subst, new, top);
    }
    term_SetTermStamp(Termstate, Term);
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_VVarNormalizeIntern(SState, Termstate, Symbstate, term_GetArgument(Term,i), Subst);
  }
}
VSUBST subst_VVarNormalize(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, unsigned Vars)
{
  SYMBOL top,new;
  VSUBST subst;
  top = term_TopSymbol(Term);
  subst = subst_VCreate(symbol_GetStateMemory(Symbstate), Symbstate, Vars);
  if (symbol_IsVariable(Symbstate, top) && !term_AlreadyVisited(Termstate, Term)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
    else {
      new = symbol_GetNextStandardVar(Symbstate);
      term_RplacTop(Term, new);
      subst_ContextSetValue(SState, top, new);
      subst_VSetValue(subst, new, top);
    }
    term_SetTermStamp(Termstate, Term);
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_VVarNormalizeIntern(SState, Termstate, Symbstate, term_GetArgument(Term,i), subst);
  }
  return subst;
}
void subst_ContextStop(SUBSTSTATE SState)
{
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  SState->active = FALSE;
}
void subst_VContextUpdateSubst(SUBSTSTATE SState, SYMBSTATE Symbstate, VSUBST Subst)
{
  unsigned i, vars;
  SYMBOL map;
  vars = subst_VNumberOfVariables(Subst);
  for (i=0; i<vars; i++) {
    if (subst_VVarDefined(Symbstate, Subst, i)) {
      map = subst_VGetValue(Subst, i);
      if (subst_ContextValueIsMarked(SState, map))
 subst_VSetValue(Subst, i, (SYMBOL)subst_ContextGetValue(SState, map));
    }
    else {
      if (subst_ContextValueIsMarked(SState, i))
 subst_VSetValue(Subst, i, (SYMBOL)subst_ContextGetValue(SState, i));
    }
  }
}
void subst_BSContextApplyToTerm(SUBSTSTATE SState, SYMBSTATE Symbstate, TERM Term)
{
  SYMBOL top;
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top)) {
    if (subst_ContextValueIsMarked(SState, top))
      term_RplacTop(Term, (SYMBOL)subst_ContextGetValue(SState, top));
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++)
      subst_BSContextApplyToTerm(SState, Symbstate, term_GetArgument(Term,i));
  }
}
TERM subst_UContextApplyToTerm(SUBSTSTATE SState, TERMSTATE Termstate, TERM Term)
{
  SYMBOL top;
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(term_GetSymbstate(Termstate), top)) {
    if (subst_UContextValueIsMarked(SState, subst_UContextLeft(SState), top))
      return term_Copy(Termstate, subst_UContextGetTerm(SState, subst_UContextLeft(SState), top));
    else
      return term_Copy(Termstate, Term);
  }
  else {
    unsigned i;
    Term = term_CopyShallow(Termstate, Term);
    for (i=0; i<term_GetArity(Term); i++)
      Term[i] = (intptr_t)subst_UContextApplyToTerm(SState, Termstate, (TERM)Term[i]);
    return Term;
  }
}
TERM subst_ContextTermApplyToTerm(SUBSTSTATE SState, TERMSTATE Termstate, TERM Term)
{
  SYMBOL top;
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(term_GetSymbstate(Termstate), top)) {
    if (subst_ContextValueIsMarked(SState, top))
      return term_Copy(Termstate, (TERM)subst_ContextGetValue(SState, top));
    else
      return term_Copy(Termstate, Term);
  }
  else {
    unsigned i;
    Term = term_CopyShallow(Termstate, Term);
    for (i=0; i<term_GetArity(Term); i++)
      Term[i] = (intptr_t)subst_ContextTermApplyToTerm(SState, Termstate, (TERM)Term[i]);
    return Term;
  }
}
TERM subst_ContextFlattenTermApplyToTerm(SUBSTSTATE SState, TERMSTATE Termstate, TERM Term)
{
  SYMBOL top;
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(term_GetSymbstate(Termstate), top)) {
    if (subst_ContextValueIsMarked(SState, top))
      return subst_ContextFlattenTermApplyToTerm(SState, Termstate, (TERM)subst_ContextGetValue(SState, top));
    else
      return term_Copy(Termstate, Term);
  }
  else {
    unsigned i;
    Term = term_CopyShallow(Termstate, Term);
    for (i=0; i<term_GetArity(Term); i++)
      Term[i] = (intptr_t)subst_ContextFlattenTermApplyToTerm(SState, Termstate, (TERM)Term[i]);
    return Term;
  }
}
void subst_UContextClean(SUBSTSTATE SState, TERMSTATE Termstate)
{
  UCONTEXT Context;
  unsigned i;
  Context = subst_UContextLeft(SState);
  for (i=0;i < SState->vars ; i++) {
    if (subst_UContextValueIsMarked(SState, Context, i)) {
      term_Delete(Termstate, subst_UContextGetTerm(SState,Context,i));
      subst_UContextClearMark(Context, i);
    }
  }
}
VSUBST subst_VCreate(MEMORY Mem, SYMBSTATE Symbstate, unsigned Vars)
{
  VSUBST new;
  SYMBOL dummy;
  unsigned i;
  new = memory_Malloc(Mem, sizeof(TERM)*(Vars+1));
  new[0] = (intptr_t)(long unsigned)Vars;
  new++;
  dummy = symbol_GetDummyConstant(Symbstate);
  for (i=0;i<Vars;i++)
    new[i] = dummy;
  return new;
}
unsigned subst_VNumberOfVariables(VSUBST Subst)
{
  return (unsigned)(intptr_t)Subst[-1];
}
void subst_VClean(SYMBSTATE Symbstate, VSUBST Subst)
{
  SYMBOL dummy;
  unsigned i, vars;
  vars = subst_VNumberOfVariables(Subst);
  dummy = symbol_GetDummyConstant(Symbstate);
  for (i=0;i<vars;i++)
    Subst[i] = dummy;
}
VSUBST subst_VCopy(MEMORY Mem, VSUBST Subst)
{
  VSUBST new;
  unsigned i, vars;
  vars = subst_VNumberOfVariables(Subst);
  new = memory_Malloc(Mem, sizeof(TERM)*(vars+1));
  new[0] = vars;
  new++;
  for (i=0;i<vars;i++)
    new[i] = Subst[i];
  return new;
}
BOOL subst_VIsTotal(SYMBSTATE Symbstate, VSUBST Subst)
{
  unsigned i, vars;
  vars = subst_VNumberOfVariables(Subst);
  for (i=0; i<vars; i++) {
    if (!subst_VVarDefined(Symbstate, Subst, i))
      return FALSE;
  }
  return TRUE;
}
unsigned subst_VGetFirstUndefinedVar(SYMBSTATE Symbstate, VSUBST Subst)
{
  unsigned i, vars;
  vars = subst_VNumberOfVariables(Subst);
  for (i=0; i<vars && subst_VVarDefined(Symbstate, Subst, i); i++);
  return i;
}
void subst_VDelete(MEMORY Mem, VSUBST Subst)
{
  memory_Free(Mem, (Subst-1), sizeof(TERM)*(subst_VNumberOfVariables(Subst)+1));
}
BOOL subst_VVarDefined(SYMBSTATE Symbstate, VSUBST Subst, SYMBOL Var)
{
  return (Subst[Var] != symbol_GetDummyConstant(Symbstate));
}
void subst_VSetValue(VSUBST Subst, SYMBOL Var, SYMBOL Symbol)
{
  Subst[Var] = Symbol;
}
SYMBOL subst_VGetValue(VSUBST Subst, SYMBOL Var)
{
  return Subst[Var];
}
void subst_VPrint(SYMBSTATE Symbstate, VSUBST Subst)
{
  unsigned i, vars;
  BOOL cont;
  printf("{");
  cont = FALSE;
  vars = subst_VNumberOfVariables(Subst);
  for (i=0;i<vars;i++)
    if (subst_VVarDefined(Symbstate, Subst, i)) {
      if (cont)
 printf(", ");
      else
 cont = TRUE;
      symbol_Print(Symbstate,i);
      printf(" -> ");
      symbol_Print(Symbstate, subst_VGetValue(Subst, i));
    }
  printf("}");
}
void subst_VTermPrintPrefix(TERMSTATE Termstate, TERM Term, VSUBST Subst)
{
  unsigned i;
  if (term_IsComplex(Term)) {
    symbol_Print(term_GetSymbstate(Termstate),
   term_TopSymbol(Term));
    putchar('(');
    for (i = 0; i < term_GetArity(Term); i++) {
      subst_VTermPrintPrefix(Termstate, term_GetArgument(Term, i), Subst);
      if (i < term_GetArity(Term)-1)
 putchar(',');
    }
    putchar(')');
  } else {
    if (term_IsValueConstant(Termstate, Term))
      symbol_GetPrintFunc(term_GetSymbstate(Termstate), term_TopSymbol(Term))(stdout, term_GetValue(Termstate, Term));
    else {
      if (symbol_IsVariable(term_GetSymbstate(Termstate), term_TopSymbol(Term)) && subst_VVarDefined(term_GetSymbstate(Termstate), Subst, term_TopSymbol(Term)))
 symbol_Print(term_GetSymbstate(Termstate), subst_VGetValue(Subst, term_TopSymbol(Term)));
      else
 symbol_Print(term_GetSymbstate(Termstate), term_TopSymbol(Term));
    }
  }
}
void subst_VSubstApplyTerm(SYMBSTATE Symbstate, TERM Term, VSUBST Subst)
{
  unsigned i;
  if (Subst == NULL)
    return;
  if (term_IsComplex(Term)) {
    for (i = 0; i < term_GetArity(Term); i++)
      subst_VSubstApplyTerm(Symbstate, (TERM)Term[i], Subst);
  }
  else {
    if (symbol_IsVariable(Symbstate, term_TopSymbol(Term)) && subst_VVarDefined(Symbstate, Subst, term_TopSymbol(Term)))
      term_RplacTop(Term, subst_VGetValue(Subst, term_TopSymbol(Term)));
  }
}
BOOL subst_FolTermMatchTerms(SUBSTSTATE SState, SYMBSTATE Symbstate, TERMSTATE Termstate, FOLSTATE Folstate, TERM Term1, TYPING Types1, TERM Term2, TYPING Types2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_FolTermMatchTerms(SState, Symbstate, Termstate, Folstate, (TERM)Term1[i], Types1, (TERM)Term2[i], Types2))
 return FALSE;
    }
    return TRUE;
  }
  else {
    if (symbol_IsVariable(Symbstate, top1)) {
      if (subst_ContextValueIsMarked(SState, top1)) {
 return term_Equal(Termstate, (TERM)subst_ContextGetValue(SState, top1), Term2);
      }
      else {
 if (Types1 != (TYPING)NULL &&
     symbol_GetVarTypingType(Types1, top1) != fol_TypeTop(Folstate) &&
     symbol_GetVarTypingType(Types1, top1) != symbol_GetVarTypingType(Types2, top2))
   return FALSE;
 subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
 return TRUE;
      }
    }
    else
      return term_Equal(Termstate, Term1,Term2);
  }
  misc_StartUserErrorReport();
  misc_UserErrorReport("%s: Ill defined Matching function, substs or terms.",__func__);
  misc_FinishUserErrorReport();
  return FALSE;
}
BOOL subst_FolTermMatchTermsSubsts(SUBSTSTATE SState, SYMBSTATE Symbstate, TERMSTATE Termstate, FOLSTATE Folstate, TERM Term1, TYPING Types1, SUBST Subst1, TERM Term2, TYPING Types2, SUBST Subst2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_FolTermMatchTermsSubsts(SState, Symbstate, Termstate, Folstate, (TERM)Term1[i], Types1, Subst1, (TERM)Term2[i], Types2, Subst2))
 return FALSE;
    }
    return TRUE;
  }
  else {
    if (symbol_IsVariable(Symbstate, top1)) {
      if (subst_ContextValueIsMarked(SState, top1)) {
 if (Subst2 && symbol_IsVariable(Symbstate, top2) && subst_VarDefined(Subst2, top2))
   return term_Equal(Termstate, (TERM)subst_ContextGetValue(SState, top1), subst_GetValue(Subst2, top2));
 else
   return term_Equal(Termstate, (TERM)subst_ContextGetValue(SState, top1), Term2);
      }
      else {
 if (Subst1 && subst_VarDefined(Subst1, top1)) {
   return subst_FolTermMatchTermsSubsts(SState, Symbstate, Termstate, Folstate, subst_GetValue(Subst1, top1), Types1, NULL, Term2, Types2, Subst2);
 }
 if (Types1 != (TYPING)NULL && Types2 != (TYPING)NULL &&
     symbol_GetVarTypingType(Types1, top1) != fol_TypeTop(Folstate) &&
     (symbol_IsVariable(Symbstate, top2) && symbol_GetVarTypingType(Types1, top1) != symbol_GetVarTypingType(Types2, top2)))
   return FALSE;
 if (Subst2 && symbol_IsVariable(Symbstate, top2) && subst_VarDefined(Subst2, top2))
   subst_ContextSetValue(SState, top1, (uintptr_t)subst_GetValue(Subst2, top2));
 else {
   subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
 }
 return TRUE;
      }
    }
    else {
      if (Subst2 && symbol_IsVariable(Symbstate, top2) && subst_VarDefined(Subst2, top2))
 return term_Equal(Termstate, Term1, subst_GetValue(Subst2, top2));
      else
 return term_Equal(Termstate, Term1,Term2);
    }
  }
  misc_StartUserErrorReport();
  misc_UserErrorReport("%s: Ill defined Matching function, substs or terms.",__func__);
  misc_FinishUserErrorReport();
  return FALSE;
}
BOOL subst_VTermEqual(SYMBSTATE Symbstate, TERM Term1, VSUBST Subst1, TERM Term2, VSUBST Subst2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_VTermEqual(Symbstate, (TERM)Term1[i], Subst1, (TERM)Term2[i], Subst2))
 return FALSE;
    }
    return TRUE;
  }
  else {
    if (symbol_IsVariable(Symbstate, top1)) {
      if (subst_VVarDefined(Symbstate, Subst1, top1)) {
 if (symbol_IsVariable(Symbstate, top2) && subst_VVarDefined(Symbstate, Subst2, top2))
   return symbol_Equal(Subst1[top1], Subst2[top2]);
 else
   return symbol_Equal(Subst1[top1], top2);
      }
      else {
 if (symbol_IsVariable(Symbstate, top2) && subst_VVarDefined(Symbstate, Subst2, top2))
   return symbol_Equal(top1, Subst2[top2]);
 else
   return symbol_Equal(top1, top2);
      }
    }
    else {
      if (symbol_IsVariable(Symbstate, top2) && subst_VVarDefined(Symbstate, Subst2, top2))
 return symbol_Equal(top1, Subst2[top2]);
      else
 return symbol_Equal(top1, top2);
    }
  }
  misc_StartUserErrorReport();
  misc_UserErrorReport("%s: Ill defined Equal function, substs or terms.",__func__);
  misc_FinishUserErrorReport();
}
void subst_BSTermUnifyDisjoint(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term1, TERM Term2)
{
  unsigned i;
  SYMBOL top1, top2;
  if (term_IsComplex(Term1)) {
#ifdef SPASS_CHECK
    if (!symbol_Equal(term_TopSymbol(Term1), term_TopSymbol(Term2)) || term_GetArity(Term1) != term_GetArity(Term2)) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: terms are not unifiable.", __func__);
      misc_FinishErrorReport();
    }
#endif
    for (i=0; i<term_GetArity(Term1); i++)
      subst_BSTermUnifyDisjoint(SState, Termstate, Symbstate, (TERM)Term1[i], (TERM)Term2[i]);
  }
  else {
    top1 = subst_ContextGetValueFollowSymbolChain(SState, Symbstate, term_TopSymbol(Term1));
    top2 = subst_ContextGetValueFollowSymbolChain(SState, Symbstate, term_TopSymbol(Term2));
    if (!symbol_Equal(top1, top2)) {
      if (symbol_IsVariable(Symbstate, top1))
 subst_ContextSetValue(SState, top1, (uintptr_t)top2);
      else {
 if (symbol_IsVariable(Symbstate, top2))
   subst_ContextSetValue(SState, top2, (uintptr_t)top1);
 else {
   misc_StartErrorReport();
   misc_ErrorReport("\n In %s: terms are not unifiable.", __func__);
   misc_FinishErrorReport();
 }
      }
    }
  }
}
BOOL subst_OccurCheck(SUBSTSTATE SState, SYMBSTATE Symbstate, SYMBOL var, TERM Term)
{
  SYMBOL top;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top)) {
    if (top == var)
      return TRUE;
    else {
      if (subst_ContextValueIsMarked(SState, top)) {
        Term = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term);
 return subst_OccurCheck(SState, Symbstate, var, Term);
      }
      return FALSE;
    }
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++) {
      if (subst_OccurCheck(SState, Symbstate, var, (TERM)Term[i]))
 return TRUE;
    }
  }
  return FALSE;
}
BOOL subst_OccurCheckSubst(SUBSTSTATE SState, SYMBSTATE Symbstate, SUBST Subst, SYMBOL var, TERM Term)
{
  SYMBOL top;
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top) && subst_VarDefined(Subst, top)) {
    Term = subst_GetValue(Subst, top);
    top = term_TopSymbol(Term);
  }
  if (symbol_IsVariable(Symbstate, top)) {
    if (top == var)
      return TRUE;
    else {
      if (subst_ContextValueIsMarked(SState, top)) {
        Term = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term);
 return subst_OccurCheckSubst(SState, Symbstate, Subst, var, Term);
      }
      return FALSE;
    }
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++) {
      if (subst_OccurCheckSubst(SState, Symbstate, Subst, var, (TERM)Term[i]))
 return TRUE;
    }
  }
  return FALSE;
}
SUBST subst_ContextFlattenExtractSubst(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, SYMBOL Maxvar)
{
  unsigned i;
  SUBST result;
  result = subst_Create(term_GetMemory(Termstate), Maxvar);
  for (i=0;i<Maxvar;i++) {
    if (subst_ContextValueIsMarked(SState, i)) {
      subst_SetValue(result, i, subst_ContextFlattenTermApplyToTerm(SState, Termstate, (TERM)subst_ContextGetValue(SState, i)));
    }
  }
  return result;
}
SUBST subst_ContextExtractSubst(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, SYMBOL Maxvar)
{
  unsigned i;
  SUBST result;
  result = subst_Create(term_GetMemory(Termstate), Maxvar);
  for (i=0;i<Maxvar;i++) {
    if (subst_ContextValueIsMarked(SState, i))
      subst_SetValue(result, i, subst_ContextTermApplyToTerm(SState, Termstate, (TERM)subst_ContextGetValue(SState, i)));
  }
  return result;
}
SUBST subst_ContextExtractSubstShallow(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, SYMBOL Maxvar)
{
  unsigned i;
  SUBST result;
  result = subst_Create(term_GetMemory(Termstate), Maxvar);
  for (i=0;i<Maxvar;i++) {
    if (subst_ContextValueIsMarked(SState, i)) {
         subst_SetValue(result, i, (TERM)subst_ContextGetValue(SState, i));
    }
  }
  return result;
}
BOOL subst_FolTermUnifyIdenticalVars(SUBSTSTATE SState, FOLSTATE Folstate, TERMSTATE Termstate, SYMBSTATE Symbstate, TYPING Types, TERM Term1, TERM Term2, BOOL OccurCheck)
{
  unsigned i;
  SYMBOL top1, top2;
  TERM tswap;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) && subst_ContextValueIsMarked(SState, top1)) {
    Term1 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term1);
    top1 = term_TopSymbol(Term1);
  }
  if (symbol_IsVariable(Symbstate, top2) && subst_ContextValueIsMarked(SState, top2)) {
    Term2 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term2);
    top2 = term_TopSymbol(Term2);
  }
  if (!symbol_IsVariable(Symbstate, top1) && symbol_IsVariable(Symbstate, top2)) {
    tswap = Term1;
    Term1 = Term2;
    top1 = top2;
    Term2 = tswap;
    top2 = term_TopSymbol(tswap);
  }
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (!symbol_Equal(top1, top2)) {
 if (symbol_GetVarTypingType(Types, top2) == fol_TypeTop(Folstate)) {
   subst_ContextSetValue(SState, top2, (uintptr_t)Term1);
 }
 else {
   subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
 }
      }
      return TRUE;
    }
    else {
      if (OccurCheck && subst_OccurCheck(SState, Symbstate, top1, Term2))
 return FALSE;
      subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
      return TRUE;
    }
  }
  else {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_FolTermUnifyIdenticalVars(SState, Folstate, Termstate, Symbstate, Types, (TERM)Term1[i], (TERM)Term2[i], OccurCheck))
 return FALSE;
    }
    return TRUE;
  }
  return TRUE;
}
BOOL subst_TermUnifyIdenticalVarsNoTypes(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term1, TERM Term2, BOOL OccurCheck)
{
  unsigned i;
  SYMBOL top1, top2;
  TERM tswap;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) && subst_ContextValueIsMarked(SState, top1)) {
    Term1 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term1);
    top1 = term_TopSymbol(Term1);
  }
  if (symbol_IsVariable(Symbstate, top2) && subst_ContextValueIsMarked(SState, top2)) {
    Term2 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term2);
    top2 = term_TopSymbol(Term2);
  }
  if (!symbol_IsVariable(Symbstate, top1) && symbol_IsVariable(Symbstate, top2)) {
    tswap = Term1;
    Term1 = Term2;
    top1 = top2;
    Term2 = tswap;
    top2 = term_TopSymbol(tswap);
  }
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (!symbol_Equal(top1, top2)) {
 subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
      }
      return TRUE;
    }
    else {
      if (OccurCheck && subst_OccurCheck(SState, Symbstate, top1, Term2))
 return FALSE;
      subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
      return TRUE;
    }
  }
  else {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_TermUnifyIdenticalVarsNoTypes(SState, Termstate, Symbstate, (TERM)Term1[i], (TERM)Term2[i], OccurCheck))
 return FALSE;
    }
    return TRUE;
  }
  return TRUE;
}
BOOL subst_TermUnifyIdenticalVarsNoTypesStack(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term1, TERM Term2, BOOL OccurCheck)
{
  unsigned i;
  SYMBOL top1, top2;
  TERM tswap;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) && subst_ContextValueIsMarked(SState, top1)) {
    Term1 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term1);
    top1 = term_TopSymbol(Term1);
  }
  if (symbol_IsVariable(Symbstate, top2) && subst_ContextValueIsMarked(SState, top2)) {
    Term2 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term2);
    top2 = term_TopSymbol(Term2);
  }
  if (!symbol_IsVariable(Symbstate, top1) && symbol_IsVariable(Symbstate, top2)) {
    tswap = Term1;
    Term1 = Term2;
    top1 = top2;
    Term2 = tswap;
    top2 = term_TopSymbol(tswap);
  }
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (!symbol_Equal(top1, top2)) {
 subst_ContextSetValueStack(SState, top1, (uintptr_t)Term2);
      }
      return TRUE;
    }
    else {
      if (OccurCheck && subst_OccurCheck(SState, Symbstate, top1, Term2))
 return FALSE;
      subst_ContextSetValueStack(SState, top1, (uintptr_t)Term2);
      return TRUE;
    }
  }
  else {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_TermUnifyIdenticalVarsNoTypesStack(SState, Termstate, Symbstate, (TERM)Term1[i], (TERM)Term2[i], OccurCheck))
 return FALSE;
    }
    return TRUE;
  }
  return TRUE;
}
BOOL subst_FolTermUnifyIdenticalVarsSubst(SUBSTSTATE SState, FOLSTATE Folstate, TERMSTATE Termstate, SYMBSTATE Symbstate, TYPING Types, SUBST Subst, TERM Term1, TERM Term2, BOOL OccurCheck)
{
  unsigned i;
  SYMBOL top1, top2;
  TERM tswap;
  if (Subst == NULL)
    return subst_FolTermUnifyIdenticalVars(SState, Folstate, Termstate, Symbstate, Types, Term1, Term2, OccurCheck);
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) && subst_VarDefined(Subst, top1)) {
    Term1 = subst_GetValue(Subst, top1);
    top1 = term_TopSymbol(Term1);
  }
  if (symbol_IsVariable(Symbstate, top2) && subst_VarDefined(Subst, top2)) {
    Term2 = subst_GetValue(Subst, top2);
    top2 = term_TopSymbol(Term2);
  }
  if (symbol_IsVariable(Symbstate, top1) && subst_ContextValueIsMarked(SState, top1)) {
    Term1 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term1);
    top1 = term_TopSymbol(Term1);
  }
  if (symbol_IsVariable(Symbstate, top2) && subst_ContextValueIsMarked(SState, top2)) {
    Term2 = subst_ContextGetTermValueFollowSymbolChain(SState, Symbstate, Term2);
    top2 = term_TopSymbol(Term2);
  }
  if (!symbol_IsVariable(Symbstate, top1) && symbol_IsVariable(Symbstate, top2)) {
    tswap = Term1;
    Term1 = Term2;
    top1 = top2;
    Term2 = tswap;
    top2 = term_TopSymbol(tswap);
  }
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (!symbol_Equal(top1, top2)) {
 if (symbol_GetVarTypingType(Types, top2) == fol_TypeTop(Folstate)) {
   subst_ContextSetValue(SState, top2, (uintptr_t)Term1);
 }
 else {
   subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
 }
      }
      return TRUE;
    }
    else {
      if (OccurCheck && subst_OccurCheckSubst(SState, Symbstate, Subst, top1, Term2))
 return FALSE;
      subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
      return TRUE;
    }
  }
  else {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_FolTermUnifyIdenticalVarsSubst(SState, Folstate, Termstate, Symbstate, Types, Subst, (TERM)Term1[i], (TERM)Term2[i], OccurCheck))
 return FALSE;
    }
    return TRUE;
  }
  return TRUE;
}
BOOL subst_BSTermUnify(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term1, TERM Term2)
{
  unsigned i;
  SYMBOL top1, top2;
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(term_TopSymbol(Term1), term_TopSymbol(Term2)) || term_GetArity(Term1) != term_GetArity(Term2)) {
      return FALSE;
    }
    for (i=0; i<term_GetArity(Term1); i++)
      if (!subst_BSTermUnify(SState, Termstate, Symbstate, (TERM)Term1[i], (TERM)Term2[i]))
 return FALSE;
  }
  else {
    top1 = subst_ContextGetValueFollowSymbolChainLeft(SState, Symbstate, term_TopSymbol(Term1));
    top2 = subst_ContextGetValueFollowSymbolChainRight(SState, Symbstate, term_TopSymbol(Term2));
    if (!symbol_Equal(top1, top2)) {
      if (symbol_IsVariable(Symbstate, top1))
 subst_ContextSetValue(SState, top1, (uintptr_t)top2);
      else {
 if (symbol_IsVariable(Symbstate, top2))
   subst_ContextSetExtraValueWithMark(SState, top2, (uintptr_t)top1);
 else {
   return FALSE;
 }
      }
    }
  }
  return TRUE;
}
BOOL subst_UOccurCheck(SUBSTSTATE SState, SYMBSTATE Symbstate, UCONTEXT Uc1, SYMBOL var, UCONTEXT Uc2, TERM Term)
{
  SYMBOL top;
  Term = subst_UContextGetValueFollowSymbolChain(SState, Symbstate, &Uc2, Term);
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(Symbstate, top)) {
    if (top == var && Uc1 == Uc2)
      return TRUE;
    else
      return FALSE;
  }
  else {
    unsigned i;
    for (i=0; i<term_GetArity(Term); i++) {
      if (subst_UOccurCheck(SState, Symbstate, Uc1, var, Uc2, (TERM)Term[i]))
     return TRUE;
    }
  }
  return FALSE;
}
void subst_FolUCreateVariableBinding(SUBSTSTATE SState, FOLSTATE Folstate, UCONTEXT Uc1, TERM Term1, UCONTEXT Uc2, TERM Term2)
{
  TYPING Typing2;
  SYMBOL top1, top2;
  Typing2 = subst_UContextGetTyping(Uc2);
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_GetVarTypingType(Typing2, top2) == fol_TypeTop(Folstate))
    subst_UContextSetValue(SState, Uc2, top2, Term1, Uc1);
  else
    subst_UContextSetValue(SState, Uc1, top1, Term2, Uc2);
}
void subst_UCreateVariableBindingNoTypes(SUBSTSTATE SState, UCONTEXT Uc1, TERM Term1, UCONTEXT Uc2, TERM Term2)
{
  subst_UContextSetValue(SState, Uc1, term_TopSymbol(Term1), Term2, Uc2);
}
BOOL subst_FolUTermUnifyTypesIntern(SUBSTSTATE SState, FOLSTATE Folstate, SYMBSTATE Symbstate, UCONTEXT Uc1, TERM Term1, UCONTEXT Uc2, TERM Term2, BOOL OccurCheck)
{
  SYMBOL top1, top2;
  TERM tswap;
  UCONTEXT uswap;
  Term1 = subst_UContextGetValueFollowSymbolChain(SState, Symbstate, &Uc1, Term1);
  top1 = term_TopSymbol(Term1);
  Term2 = subst_UContextGetValueFollowSymbolChain(SState, Symbstate, &Uc2, Term2);
  top2 = term_TopSymbol(Term2);
  if (!symbol_IsVariable(Symbstate, top1) && symbol_IsVariable(Symbstate, top2)) {
    tswap = Term1;
    uswap = Uc1;
    Term1 = Term2;
    top1 = top2;
    Uc1 = Uc2;
    Term2 = tswap;
    top2 = term_TopSymbol(tswap);
    Uc2 = uswap;
  }
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (symbol_Equal(top1, top2) && Uc1 == Uc2)
 return TRUE;
      else {
 subst_FolUCreateVariableBinding(SState, Folstate, Uc1, Term1, Uc2, Term2);
 return TRUE;
      }
    }
    else
      if (OccurCheck && subst_UOccurCheck(SState, Symbstate, Uc1, top1, Uc2, Term2))
 return FALSE;
      else {
 subst_UContextSetValue(SState, Uc1, top1, Term2, Uc2);
 return TRUE;
      }
  }
  else {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2)) {
      return FALSE;
    }
    else {
      unsigned i;
      for (i=0; i<term_GetArity(Term1); i++)
 if (!subst_FolUTermUnifyTypesIntern(SState, Folstate, Symbstate, Uc1, (TERM)Term1[i], Uc2, (TERM)Term2[i], OccurCheck))
   return FALSE;
    }
  }
  return TRUE;
}
BOOL subst_FolUTermUnifyTypes(SUBSTSTATE SState, FOLSTATE Folstate, SYMBSTATE Symbstate, TERM Term1, TYPING Types1, TERM Term2, TYPING Types2, BOOL OccurCheck)
{
  subst_UContextSetTyping(subst_UContextLeft(SState), Types1);
  subst_UContextSetTyping(subst_UContextRight(SState), Types2);
  return subst_FolUTermUnifyTypesIntern(SState, Folstate, Symbstate, subst_UContextLeft(SState), Term1, subst_UContextRight(SState), Term2, OccurCheck);
}
BOOL subst_TermUnifyDisjointVarsNoTypesIntern(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, UCONTEXT Uc1, TERM Term1, UCONTEXT Uc2, TERM Term2, BOOL OccurCheck)
{
  SYMBOL top1, top2;
  subst_TERMSTATE = Termstate;
  Term1 = subst_UContextGetValueFollowSymbolChain(SState, Symbstate, &Uc1, Term1);
  top1 = term_TopSymbol(Term1);
  Term2 = subst_UContextGetValueFollowSymbolChain(SState, Symbstate, &Uc2, Term2);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1)) {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (symbol_Equal(top1, top2) && Uc1 == Uc2)
   return TRUE;
 else {
   subst_UCreateVariableBindingNoTypes(SState, Uc1, Term1, Uc2, Term2);
   return TRUE;
 }
    }
    else
      if (OccurCheck && subst_UOccurCheck(SState, Symbstate, Uc1, top1, Uc2, Term2)) {
 return FALSE;
      }
      else {
 subst_UContextSetValue(SState, Uc1, top1, Term2, Uc2);
      }
  }
  else {
    if (symbol_IsVariable(Symbstate, top2)) {
      if (OccurCheck && subst_UOccurCheck(SState, Symbstate, Uc2, top2, Uc1, Term1)) {
 return FALSE;
      }
      else {
 subst_UContextSetValue(SState, Uc2, top2, Term1, Uc1);
 return TRUE;
      }
    }
    else {
      if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2)) {
 return FALSE;
      }
      else {
 unsigned i;
 for (i=0; i<term_GetArity(Term1); i++)
   if (!subst_TermUnifyDisjointVarsNoTypesIntern(SState, Termstate, Symbstate, Uc1, (TERM)Term1[i], Uc2, (TERM)Term2[i], OccurCheck))
     return FALSE;
      }
    }
  }
  return TRUE;
}
BOOL subst_TermUnifyDisjointVarsNoTypes(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term1, TERM Term2, BOOL OccurCheck)
{
  return subst_TermUnifyDisjointVarsNoTypesIntern(SState, Termstate, Symbstate, subst_UContextLeft(SState), Term1, subst_UContextRight(SState), Term2, OccurCheck);
}
VSUBST subst_VIdentitySubst(MEMORY Memory, SYMBSTATE Symbstate, unsigned Vars)
{
  unsigned i;
  VSUBST subst;
  subst = subst_VCreate(Memory,Symbstate,Vars);
  for(i = 0; i < Vars; i++){
    subst_VSetValue(subst,(SYMBOL)i,(SYMBOL)i);
  }
  return subst;
}
SUBST subst_Create(MEMORY Mem, unsigned Vars)
{
  SUBST new;
  unsigned i;
  new = memory_Malloc(Mem, sizeof(TERM)*(Vars+1));
  new[0] = (TERM)(long unsigned)Vars;
  new++;
  for (i=0;i<Vars;i++)
    new[i] = (TERM)NULL;
  return new;
}
unsigned subst_NumberOfVariables(SUBST Subst)
{
  if (Subst == NULL)
    return 0;
  else
    return (unsigned)(intptr_t)Subst[-1];
}
void subst_Clean(SUBST Subst)
{
  unsigned i, vars;
  vars = subst_NumberOfVariables(Subst);
  for (i=0;i<vars;i++)
    Subst[i] = (TERM)NULL;
}
SUBST subst_Copy(MEMORY Mem, SUBST Subst)
{
  SUBST new;
  unsigned i, Vars;
  Vars = subst_NumberOfVariables(Subst);
  new = memory_Malloc(Mem, sizeof(TERM)*(Vars+1));
  new[0] = (TERM)(long unsigned)subst_NumberOfVariables(Subst);
  new++;
  for (i=0;i<Vars;i++)
    new[i] = Subst[i];
  return new;
}
SUBST subst_CopyWitTerms(TERMSTATE Termstate, SUBST Subst, unsigned Vars)
{
  SUBST new;
  unsigned i;
  new = memory_Malloc(term_GetMemory(Termstate), sizeof(TERM)*(Vars+1));
  new[0] = (TERM)(long unsigned)subst_NumberOfVariables(Subst);
  new++;
  for (i=0;i<Vars;i++) {
    if (Subst[i])
      new[i] = term_Copy(Termstate, (TERM)Subst[i]);
  }
  return new;
}
SUBST subst_ApplyToSubst(TERMSTATE Termstate, SUBST Subst1, SUBST Subst2, BOOL Concat)
{
  SUBST new;
  unsigned i, vars1, vars2, vars;
  vars1 = subst_NumberOfVariables(Subst1);
  vars2 = subst_NumberOfVariables(Subst2);
  if (vars1 < vars2 || !Concat)
    vars = vars2;
  else
    vars = vars1;
  new = subst_Create(term_GetMemory(Termstate), vars);
  for (i=0;i<vars;i++) {
    if (i < vars1 && Subst1[i])
      new[i] = subst_SubstApplyTerm(Termstate, term_Copy(Termstate, (TERM)Subst1[i]), Subst2, TRUE);
    else {
      if (Concat && i < vars2 && Subst2[i])
 new[i] = term_Copy(Termstate, (TERM)Subst2[i]);
    }
  }
  return new;
}
SUBST subst_ContextApplyToSubst(SUBSTSTATE SState, TERMSTATE Termstate, SUBST Subst, BOOL Concat)
{
  SUBST new;
  unsigned i, vars1, vars2, vars;
  vars1 = subst_NumberOfVariables(Subst);
  vars2 = 0;
  for (i=0;i<SState->vars;i++) {
    if (subst_ContextValueIsMarked(SState, i))
      vars2 = i;
  }
  vars2++;
  if (vars1 < vars2 || !Concat)
    vars = vars2;
  else
    vars = vars1;
  new = subst_Create(term_GetMemory(Termstate), vars);
  for (i=0;i<vars;i++) {
    if (i < vars1 && Subst[i])
      new[i] = subst_ContextTermApplyToTerm(SState, Termstate, (TERM)Subst[i]);
    else {
      if (Concat && i < vars2 && subst_ContextValueIsMarked(SState, i))
 new[i] = term_Copy(Termstate, (TERM)subst_ContextGetValue(SState, i));
    }
  }
  return new;
}
TERM subst_ContextFlattenTermApplyToTermSubst(SUBSTSTATE SState, TERMSTATE Termstate, SUBST Subst, unsigned Vars, TERM Term)
{
  SYMBOL top;
#ifdef SPASS_CHECK
  if (!SState->active){
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: Context not in use.",__func__);
    misc_FinishUserErrorReport();
  }
#endif
  top = term_TopSymbol(Term);
  if (symbol_IsVariable(term_GetSymbstate(Termstate), top)) {
    if (subst_ContextValueIsMarked(SState, top))
      return subst_ContextFlattenTermApplyToTermSubst(SState, Termstate, Subst, Vars, (TERM)subst_ContextGetValue(SState, top));
    else {
      if (top < Vars && Subst[top])
 return subst_ContextFlattenTermApplyToTermSubst(SState, Termstate, Subst, Vars, (TERM)Subst[top]);
      else
 return term_Copy(Termstate, Term);
    }
  }
  else {
    unsigned i;
    Term = term_CopyShallow(Termstate, Term);
    for (i=0; i<term_GetArity(Term); i++)
      Term[i] = (intptr_t)subst_ContextFlattenTermApplyToTermSubst(SState, Termstate, Subst, Vars, (TERM)Term[i]);
    return Term;
  }
  return Term;
}
SUBST subst_ContextFlattenApplyToSubst(SUBSTSTATE SState, TERMSTATE Termstate, SUBST Subst, BOOL Concat)
{
  SUBST new;
  unsigned i, vars1, vars2, vars;
  vars1 = subst_NumberOfVariables(Subst);
  vars2 = 0;
  for (i=0;i<SState->vars;i++) {
    if (subst_ContextValueIsMarked(SState, i))
      vars2 = i;
  }
  vars2++;
  if (vars1 < vars2 || !Concat)
    vars = vars2;
  else
    vars = vars1;
  new = subst_Create(term_GetMemory(Termstate), vars);
  for (i=0;i<vars;i++) {
    if (i < vars1 && Subst[i])
      new[i] = subst_ContextFlattenTermApplyToTermSubst(SState, Termstate, Subst, vars1, (TERM)Subst[i]);
    else {
      if (Concat && i < vars2 && subst_ContextValueIsMarked(SState, i))
 new[i] = subst_ContextFlattenTermApplyToTermSubst(SState, Termstate, Subst, vars1, (TERM)subst_ContextGetValue(SState, i));
    }
  }
  return new;
}
BOOL subst_IsTotal(SUBST Subst)
{
  unsigned i, vars;
  vars = subst_NumberOfVariables(Subst);
  for (i=0; i<vars; i++) {
    if (!subst_VarDefined(Subst, i))
      return FALSE;
  }
  return TRUE;
}
unsigned subst_GetFirstUndefinedVar(SUBST Subst)
{
  unsigned i, vars;
  vars = subst_NumberOfVariables(Subst);
  for (i=0; i<vars && subst_VarDefined(Subst, i); i++);
  return i;
}
void subst_Delete(MEMORY Mem, SUBST Subst)
{
  memory_Free(Mem, (Subst-1), sizeof(TERM)*(subst_NumberOfVariables(Subst)+1));
}
void subst_DeleteWithTerms(TERMSTATE Termstate, MEMORY Mem, SUBST Subst)
{
  unsigned i, Vars;
  Vars = subst_NumberOfVariables(Subst);
  for (i=0; i<Vars; i++) {
    if (subst_VarDefined(Subst, i))
      term_Delete(Termstate, (TERM)Subst[i]);
  }
  memory_Free(Mem, (Subst-1), sizeof(TERM)*(Vars+1));
}
BOOL subst_VarDefined(SUBST Subst, SYMBOL Var)
{
  return (Subst != NULL && Subst[Var] != (TERM)NULL);
}
void subst_SetValue(SUBST Subst, SYMBOL Var, TERM Term)
{
  Subst[Var] = Term;
}
TERM subst_GetValue(SUBST Subst, SYMBOL Var)
{
  return Subst[Var];
}
 void subst_Print(TERMSTATE Termstate, SYMBSTATE Symbstate, SUBST Subst)
{
  unsigned i, Vars;
  BOOL cont;
  Vars = subst_NumberOfVariables(Subst);
  printf("{");
  cont = FALSE;
  for (i=0;i<Vars;i++)
    if (subst_VarDefined(Subst, i)) {
      if (cont)
 printf(", ");
      else
 cont = TRUE;
      symbol_Print(Symbstate,i);
      printf(" -> ");
      term_PrintPrefix(Termstate, subst_GetValue(Subst, i));
    }
  printf("}");
}
void subst_TermPrintPrefix(TERMSTATE Termstate, TERM Term, SUBST Subst)
{
  unsigned i;
  if (term_IsComplex(Term)) {
    symbol_Print(term_GetSymbstate(Termstate),
   term_TopSymbol(Term));
    putchar('(');
    for (i = 0; i < term_GetArity(Term); i++) {
      subst_TermPrintPrefix(Termstate, term_GetArgument(Term, i), Subst);
      if (i < term_GetArity(Term)-1)
 putchar(',');
    }
    putchar(')');
  } else {
    if (term_IsValueConstant(Termstate, Term))
      symbol_GetPrintFunc(term_GetSymbstate(Termstate), term_TopSymbol(Term))(stdout, term_GetValue(Termstate, Term));
    else {
      if (symbol_IsVariable(term_GetSymbstate(Termstate), term_TopSymbol(Term)) && subst_VarDefined(Subst, term_TopSymbol(Term)))
 term_PrintPrefix(Termstate, subst_GetValue(Subst, term_TopSymbol(Term)));
      else
 symbol_Print(term_GetSymbstate(Termstate), term_TopSymbol(Term));
    }
  }
}
void subst_SubstApplyTermIntern(TERMSTATE Termstate, TERM Term, unsigned j, SUBST Subst, BOOL Copy)
{
  TERM ActTerm;
  unsigned i;
  ActTerm = (TERM)Term[j];
  if (term_IsComplex(ActTerm)) {
    for (i = 0; i < term_GetArity(ActTerm); i++)
      subst_SubstApplyTermIntern(Termstate, ActTerm, i, Subst, Copy);
  }
  else {
    SYMBOL top;
    top = term_TopSymbol(ActTerm);
    if (symbol_IsVariable(term_GetSymbstate(Termstate), top) && subst_VarDefined(Subst, top)) {
      term_Delete(Termstate, ActTerm);
      if (Copy)
 term_SetArgument(Term, j, term_Copy(Termstate, subst_GetValue(Subst, top)));
      else
 term_SetArgument(Term, j, subst_GetValue(Subst, top));
    }
  }
}
TERM subst_SubstApplyTerm(TERMSTATE Termstate, TERM Term, SUBST Subst, BOOL Copy)
{
  unsigned i;
  if (Subst == NULL)
    return Term;
  if (term_IsComplex(Term)) {
    for (i = 0; i < term_GetArity(Term); i++)
      subst_SubstApplyTermIntern(Termstate, Term, i, Subst, Copy);
  }
  else {
    SYMBOL top;
    top = term_TopSymbol(Term);
    if (symbol_IsVariable(term_GetSymbstate(Termstate), top) && subst_VarDefined(Subst, top)) {
      term_Delete(Termstate, Term);
      if (Copy)
 return term_Copy(Termstate, subst_GetValue(Subst, top));
      else
 return subst_GetValue(Subst, top);
    }
  }
  return Term;
}
SUBST subst_BSSubstApplyContext(SUBSTSTATE SState, TERMSTATE Termstate, SYMBSTATE Symbstate, SUBST Subst)
{
  unsigned i, vars;
  SUBST new;
  vars = subst_NumberOfVariables(Subst);
  new = subst_Create(symbol_GetStateMemory(Symbstate), vars);
  for (i=0;i<vars;i++) {
    if (Subst[i] != (TERM)NULL) {
      new[i] = term_Copy(Termstate, subst_GetValue(Subst,i));
      subst_BSContextApplyToTerm(SState, Symbstate, subst_GetValue(new,i));
    }
  }
  return new;
}
SUBST subst_SubstApplyUContext(SUBSTSTATE SState, TERMSTATE Termstate, SUBST Subst)
{
  unsigned i, vars;
  SUBST new;
  vars = subst_NumberOfVariables(Subst);
  new = subst_Create(term_GetMemory(Termstate), vars);
  for (i=0;i<vars;i++) {
    if (Subst[i] != (TERM)NULL) {
      new[i] = subst_UContextApplyToTerm(SState, Termstate, subst_GetValue(Subst,i));
    }
  }
  return new;
}
BOOL subst_TermIsGroundedIntern(TERMSTATE Termstate, SYMBSTATE Symbstate, TERM Term, SUBST Subst, unsigned Mark)
{
  unsigned i;
  if (term_IsComplex(Term)) {
    for (i = 0; i < term_GetArity(Term); i++)
      if (!subst_TermIsGroundedIntern(Termstate, Symbstate, (TERM)Term[i], Subst, Mark)) {
 return FALSE;
      }
  }
  else {
    SYMBOL top;
    top = term_TopSymbol(Term);
    if (symbol_IsVariable(Symbstate, top) && !symbol_VarIsMarked(Symbstate, top, Mark)) {
      if (subst_GetValue(Subst, top) != (TERM)NULL) {
 if (term_IsGround(Termstate, subst_GetValue(Subst, top)))
   symbol_SetBindingMark(Symbstate, top, Mark);
 else
   return FALSE;
      }
      else
 return FALSE;
    }
  }
  return TRUE;
}
BOOL subst_TermIsGrounded(TERMSTATE Termstate, TERM Term, SUBST Subst)
{
  unsigned i, mark;
  SYMBSTATE symbstate;
  symbstate = term_GetSymbstate(Termstate);
  symbol_StartBinding(symbstate);
  mark = symbol_NewMark(symbstate);
  if (Subst == NULL) {
    symbol_StopBinding(symbstate);
    return term_IsGround(Termstate, Term);
  }
  if (term_IsComplex(Term)) {
    for (i = 0; i < term_GetArity(Term); i++)
      if (!subst_TermIsGroundedIntern(Termstate, symbstate, (TERM)Term[i], Subst, mark)) {
 symbol_StopBinding(symbstate);
 return FALSE;
      }
  }
  else {
    SYMBOL top;
    top = term_TopSymbol(Term);
    if (symbol_IsVariable(symbstate, top) && !symbol_VarIsMarked(symbstate, top, mark)) {
      if (subst_GetValue(Subst, top) != (TERM)NULL) {
 if (!term_IsGround(Termstate, subst_GetValue(Subst, top))) {
   symbol_StopBinding(symbstate);
   return FALSE;
 }
      }
    }
  }
  symbol_StopBinding(symbstate);
  return TRUE;
}
BOOL subst_TermEqualModuloSubsts(SYMBSTATE Symbstate, TERM Term1, SUBST Subst1, TERM Term2, SUBST Subst2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) &&
      Subst1 != NULL && subst_VarDefined(Subst1, top1)) {
    Term1 = subst_GetValue(Subst1,top1);
    top1 = term_TopSymbol(Term1);
    Subst1 = NULL;
  }
  if (symbol_IsVariable(Symbstate, top2) &&
      Subst2 != NULL && subst_VarDefined(Subst2, top2)) {
    Term2 = subst_GetValue(Subst2,top2);
    top2 = term_TopSymbol(Term2);
    Subst2 = NULL;
  }
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_TermEqualModuloSubsts(Symbstate, (TERM)Term1[i], Subst1, (TERM)Term2[i], Subst2))
 return FALSE;
    }
    return TRUE;
  }
  else {
    return symbol_Equal(top1, top2);
  }
  misc_StartErrorReport();
  misc_ErrorReport("%s: Ill defined Equal function, substs or terms.",__func__);
  misc_FinishErrorReport();
}
BOOL subst_TermEqualModuloSubstsAndTypes(SYMBSTATE Symbstate, TERM Term1, SUBST Subst1, TYPING Types1, TERM Term2, SUBST Subst2, TYPING Types2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (symbol_IsVariable(Symbstate, top1) &&
      Subst1 != NULL && subst_VarDefined(Subst1, top1)) {
    Term1 = subst_GetValue(Subst1,top1);
    top1 = term_TopSymbol(Term1);
    Subst1 = NULL;
  }
  if (symbol_IsVariable(Symbstate, top2) &&
      Subst2 != NULL && subst_VarDefined(Subst2, top2)) {
    Term2 = subst_GetValue(Subst2,top2);
    top2 = term_TopSymbol(Term2);
    Subst2 = NULL;
  }
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_TermEqualModuloSubstsAndTypes(Symbstate, (TERM)Term1[i], Subst1, Types1, (TERM)Term2[i], Subst2, Types2))
        return FALSE;
    }
    return TRUE;
  }
  else if (symbol_IsVariable(Symbstate, top1)){
    return symbol_Equal(top1, top2) && (Types1 == NULL || (Types2 != NULL && symbol_GetVarTypingType(Types1, top1) == symbol_GetVarTypingType(Types2, top2)));
  }else{
    return symbol_Equal(top1, top2);
  }
  misc_StartErrorReport();
  misc_ErrorReport("%s: Ill defined Equal function, substs or terms.",__func__);
  misc_FinishErrorReport();
}
BOOL subst_MatchTerms(SUBSTSTATE SState, SYMBSTATE Symbstate, TERMSTATE Termstate, TERM Term1, TERM Term2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_MatchTerms(SState, Symbstate, Termstate, (TERM)Term1[i], (TERM)Term2[i]))
 return FALSE;
    }
    return TRUE;
  }
  else {
    if (symbol_IsVariable(Symbstate, top1)) {
      if (subst_ContextValueIsMarked(SState, top1)) {
 return term_Equal(Termstate, (TERM)subst_ContextGetValue(SState, top1), Term2);
      }
      else {
 subst_ContextSetValue(SState, top1, (uintptr_t)Term2);
 return TRUE;
      }
    }
    else
      return term_Equal(Termstate, Term1,Term2);
  }
  misc_StartUserErrorReport();
  misc_UserErrorReport("%s: Ill defined Matching function, substs or terms.",__func__);
  misc_FinishUserErrorReport();
  return FALSE;
}
BOOL subst_IsInstance(SUBSTSTATE Subststate, SYMBSTATE Symbstate, TERMSTATE Termstate, SUBST Subst, SUBST Instance)
{
  unsigned i, svars, ivars;
  SYMBOL vtop;
  if (Subst == NULL)
    return TRUE;
  svars = subst_NumberOfVariables(Subst);
  ivars = subst_NumberOfVariables(Instance);
  subst_ContextStart(Subststate, Symbstate);
  for (i=0; i<svars; i++) {
    if (subst_VarDefined(Subst, i)) {
      if (i>ivars || !subst_VarDefined(Instance, i)) {
 vtop = term_TopSymbol(subst_GetValue(Subst,i));
 if (!symbol_IsVariable(Symbstate, vtop) ||
     (vtop != i && (vtop>ivars || !subst_VarDefined(Instance, vtop) || !symbol_Equal(i, term_TopSymbol(subst_GetValue(Instance, vtop)))))) {
   subst_ContextStop(Subststate);
   return FALSE;
 }
      }
      else {
 if (!subst_MatchTerms(Subststate, Symbstate, Termstate, subst_GetValue(Subst, i), subst_GetValue(Instance, i))) {
   subst_ContextStop(Subststate);
   return FALSE;
 }
      }
    }
  }
  subst_ContextStop(Subststate);
  return TRUE;
}
BOOL subst_TermMatchTermsStackFol(SUBSTSTATE SState, SYMBSTATE Symbstate, TERMSTATE Termstate, FOLSTATE Folstate, TERM Term1, TYPING Types1, TERM Term2, TYPING Types2)
{
  unsigned i;
  SYMBOL top1, top2;
  top1 = term_TopSymbol(Term1);
  top2 = term_TopSymbol(Term2);
  if (term_IsComplex(Term1)) {
    if (!symbol_Equal(top1, top2) || term_GetArity(Term1) != term_GetArity(Term2))
      return FALSE;
    for (i=0; i<term_GetArity(Term1); i++) {
      if (!subst_TermMatchTermsStackFol(SState, Symbstate, Termstate, Folstate, (TERM)Term1[i], Types1, (TERM)Term2[i], Types2))
 return FALSE;
    }
    return TRUE;
  }
  else {
    if (symbol_IsVariable(Symbstate, top1)) {
      if (subst_ContextValueIsMarked(SState, top1)) {
 return term_Equal(Termstate, (TERM)subst_ContextGetValue(SState, top1), Term2);
      }
      else {
 if (Types1 != (TYPING)NULL && Types2 != (TYPING)NULL &&
     symbol_GetVarTypingType(Types1, top1) != fol_TypeTop(Folstate) &&
     (symbol_IsVariable(Symbstate, top2) && symbol_GetVarTypingType(Types1, top1) != symbol_GetVarTypingType(Types2, top2)))
   return FALSE;
 subst_ContextSetValueStack(SState, top1, (uintptr_t)Term2);
 return TRUE;
      }
    }
    else
      return term_Equal(Termstate, Term1,Term2);
  }
  misc_StartUserErrorReport();
  misc_UserErrorReport("%s: Ill defined Matching function, substs or terms.",__func__);
  misc_FinishUserErrorReport();
  return FALSE;
}
