1800 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1800 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*********************************************
 | 
						|
  File:     core_tries.c
 | 
						|
  Author:   Ricardo Rocha
 | 
						|
  Comments: Tries core module for Yap Prolog
 | 
						|
  version:  $ID$
 | 
						|
*********************************************/
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*          Includes          */
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
#include <YapInterface.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "core_tries.h"
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*      Local Procedures      */
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
static TrNode   put_entry(TrNode node, YAP_Term entry);
 | 
						|
static TrNode   check_entry(TrNode node, YAP_Term entry);
 | 
						|
static YAP_Term get_entry(TrNode node, YAP_Term *stack_list, TrNode *cur_node);
 | 
						|
static void     remove_entry(TrNode node);
 | 
						|
static void     remove_child_nodes(TrNode node);
 | 
						|
static TrNode   copy_child_nodes(TrNode parent_dest, TrNode node_source);
 | 
						|
static void     traverse_and_add(TrNode parent_dest, TrNode parent_source);
 | 
						|
static void     traverse_and_join(TrNode parent_dest, TrNode parent_source);
 | 
						|
static void     traverse_and_intersect(TrNode parent_dest, TrNode parent_source);
 | 
						|
static YAP_Int  traverse_and_count_common_entries(TrNode parent1, TrNode parent2);
 | 
						|
static YAP_Int  traverse_and_count_entries(TrNode node);
 | 
						|
static void     traverse_and_get_usage(TrNode node, YAP_Int depth);
 | 
						|
static void     traverse_and_save(TrNode node, FILE *file, int float_block);
 | 
						|
static void     traverse_and_load(TrNode parent, FILE *file);
 | 
						|
static void     traverse_and_print(TrNode node, int *arity, char *str, int str_index, int mode);
 | 
						|
 | 
						|
static YAP_Term trie_to_list(TrNode node);
 | 
						|
static YAP_Term trie_to_list_node(TrNode node);
 | 
						|
static YAP_Term trie_to_list_floats(TrNode node);
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*       Local Variables      */
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
static TrEngine CURRENT_TRIE_ENGINE;
 | 
						|
 | 
						|
static YAP_Int USAGE_ENTRIES, USAGE_NODES, USAGE_VIRTUAL_NODES;
 | 
						|
static YAP_Int CURRENT_AUXILIARY_TERM_STACK_SIZE, CURRENT_TRIE_MODE, CURRENT_LOAD_VERSION, CURRENT_DEPTH, CURRENT_INDEX;
 | 
						|
static YAP_Term *AUXILIARY_TERM_STACK;
 | 
						|
YAP_Term *stack_args, *stack_args_base, *stack_vars, *stack_vars_base;
 | 
						|
static YAP_Functor FunctorComma;
 | 
						|
static void (*DATA_SAVE_FUNCTION)(TrNode, FILE *);
 | 
						|
static void (*DATA_LOAD_FUNCTION)(TrNode, YAP_Int, FILE *);
 | 
						|
static void (*DATA_PRINT_FUNCTION)(TrNode);
 | 
						|
static void (*DATA_ADD_FUNCTION)(TrNode, TrNode);
 | 
						|
static void (*DATA_COPY_FUNCTION)(TrNode, TrNode);
 | 
						|
static void (*DATA_DESTRUCT_FUNCTION)(TrNode);
 | 
						|
 | 
						|
static YAP_Int TRIE_DISABLE_HASH_TABLE = 0;
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*     Inline Procedures      */
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
static
 | 
						|
TrNode trie_node_check_insert(TrNode parent, YAP_Term t) {
 | 
						|
  TrNode child;
 | 
						|
 | 
						|
  CURRENT_DEPTH++;
 | 
						|
  child = TrNode_child(parent);
 | 
						|
  if (child == NULL) {
 | 
						|
    new_trie_node(child, t, parent, NULL, NULL, NULL);
 | 
						|
    TrNode_child(parent) = child;
 | 
						|
  } else if (IS_HASH_NODE(child)) {
 | 
						|
    TrHash hash;
 | 
						|
    TrNode *bucket;
 | 
						|
    int count;
 | 
						|
    hash = (TrHash) child;
 | 
						|
    bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash)));
 | 
						|
    child = *bucket;
 | 
						|
    count = 0;
 | 
						|
    while (child) {
 | 
						|
      if ((TrNode_entry(child) == t) || (((TrNode_entry(child) == PairEndTermTag) || (TrNode_entry(child) == PairEndEmptyTag)) && ((CURRENT_TRIE_MODE & TRIE_MODE_MINIMAL) == TRIE_MODE_MINIMAL)))
 | 
						|
        return child;
 | 
						|
      count++;
 | 
						|
      child = TrNode_next(child);
 | 
						|
    } while (child);
 | 
						|
    TrHash_num_nodes(hash)++;
 | 
						|
    new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket));
 | 
						|
    if (*bucket)
 | 
						|
      TrNode_previous(*bucket) = child;
 | 
						|
    *bucket = child;
 | 
						|
    if (count > MAX_NODES_PER_BUCKET && TrHash_num_nodes(hash) > TrHash_num_buckets(hash)) {
 | 
						|
      /* expand trie hash */
 | 
						|
      TrNode chain, next, *first_bucket, *new_bucket;
 | 
						|
      int seed;
 | 
						|
      first_bucket = TrHash_buckets(hash);
 | 
						|
      bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
      TrHash_num_buckets(hash) *= 2;
 | 
						|
      new_hash_buckets(hash, TrHash_num_buckets(hash)); 
 | 
						|
      seed = TrHash_num_buckets(hash) - 1;
 | 
						|
      do {
 | 
						|
        if (*--bucket) {
 | 
						|
          chain = *bucket;
 | 
						|
          do {
 | 
						|
            new_bucket = TrHash_bucket(hash, HASH_TERM(TrNode_entry(chain), seed));
 | 
						|
            next = TrNode_next(chain);
 | 
						|
            TrNode_next(chain) = *new_bucket;
 | 
						|
            TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket);
 | 
						|
            if (*new_bucket)
 | 
						|
              TrNode_previous(*new_bucket) = chain;
 | 
						|
            *new_bucket = chain;
 | 
						|
            chain = next;
 | 
						|
          } while (chain);
 | 
						|
        }
 | 
						|
      } while (bucket != first_bucket);
 | 
						|
      free_hash_buckets(first_bucket, TrHash_num_buckets(hash) / 2);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    int count = 0;
 | 
						|
    do {
 | 
						|
      if ((TrNode_entry(child) == t) || (((TrNode_entry(child) == PairEndTermTag) || (TrNode_entry(child) == PairEndEmptyTag)) && ((CURRENT_TRIE_MODE & TRIE_MODE_MINIMAL) == TRIE_MODE_MINIMAL)))
 | 
						|
        return child;
 | 
						|
      count++;
 | 
						|
      child = TrNode_next(child);
 | 
						|
    } while (child);
 | 
						|
    new_trie_node(child, t, parent, NULL, TrNode_child(parent), NULL);
 | 
						|
    TrNode_previous(TrNode_child(parent)) = child;
 | 
						|
    if ((++count > MAX_NODES_PER_TRIE_LEVEL) && (TRIE_DISABLE_HASH_TABLE == 0)) {
 | 
						|
      /* alloc a new trie hash */
 | 
						|
      TrHash hash;
 | 
						|
      TrNode chain, next, *bucket;
 | 
						|
      new_trie_hash(hash, count, BASE_HASH_BUCKETS);
 | 
						|
      chain = child;
 | 
						|
      do {
 | 
						|
        bucket = TrHash_bucket(hash, HASH_TERM(TrNode_entry(chain), BASE_HASH_BUCKETS - 1));
 | 
						|
        next = TrNode_next(chain);
 | 
						|
        TrNode_next(chain) = *bucket;
 | 
						|
        TrNode_previous(chain) = AS_TR_NODE_NEXT(bucket);
 | 
						|
        if (*bucket)
 | 
						|
          TrNode_previous(*bucket) = chain;
 | 
						|
        *bucket = chain;
 | 
						|
        chain = next;
 | 
						|
      } while (chain);
 | 
						|
      TrNode_child(parent) = (TrNode) hash;
 | 
						|
    } else
 | 
						|
      TrNode_child(parent) = child;
 | 
						|
  }
 | 
						|
  return child;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
TrNode trie_node_insert(TrNode parent, YAP_Term t, TrHash hash) {
 | 
						|
  TrNode child;
 | 
						|
 | 
						|
  CURRENT_DEPTH++;
 | 
						|
  if (hash) {
 | 
						|
    /* is trie hash */
 | 
						|
    TrNode *bucket;
 | 
						|
    TrHash_num_nodes(hash)++;
 | 
						|
    bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash)));
 | 
						|
    new_trie_node(child, t, parent, NULL, *bucket, AS_TR_NODE_NEXT(bucket));
 | 
						|
    if (*bucket)
 | 
						|
      TrNode_previous(*bucket) = child;
 | 
						|
    *bucket = child;
 | 
						|
  } else {
 | 
						|
    new_trie_node(child, t, parent, NULL, TrNode_child(parent), NULL);
 | 
						|
    if (TrNode_child(parent))
 | 
						|
      TrNode_previous(TrNode_child(parent)) = child;
 | 
						|
    TrNode_child(parent) = child;
 | 
						|
  }
 | 
						|
  return child;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
TrNode trie_node_check(TrNode parent, YAP_Term t) {
 | 
						|
  TrNode child;
 | 
						|
 | 
						|
  child = TrNode_child(parent);
 | 
						|
  if (IS_HASH_NODE(child)) {
 | 
						|
    TrHash hash;
 | 
						|
    TrNode *bucket;
 | 
						|
    hash = (TrHash) child;
 | 
						|
    bucket = TrHash_bucket(hash, HASH_TERM(t, TrHash_seed(hash)));
 | 
						|
    child = *bucket;
 | 
						|
    if (!child)
 | 
						|
      return NULL;
 | 
						|
  }
 | 
						|
  do {
 | 
						|
    if (TrNode_entry(child) == t)
 | 
						|
      return child;
 | 
						|
    child = TrNode_next(child);
 | 
						|
  } while (child);
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list_create_simple(const char *atom_name, TrNode node) {
 | 
						|
  YAP_Functor f = YAP_MkFunctor(YAP_LookupAtom(atom_name), 1);
 | 
						|
  YAP_Term child = trie_to_list(TrNode_child(node));  
 | 
						|
 | 
						|
  return YAP_MkApplTerm(f, 1, &child);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list_create_simple_end(const char *atom_name, TrNode node) {
 | 
						|
  YAP_Atom atom = YAP_LookupAtom(atom_name);
 | 
						|
  
 | 
						|
  if (IS_LEAF_TRIE_NODE(node)) {
 | 
						|
    return YAP_MkAtomTerm(atom);
 | 
						|
  } else {
 | 
						|
    YAP_Functor f = YAP_MkFunctor(atom, 1);
 | 
						|
    YAP_Term child = trie_to_list(TrNode_child(node));    
 | 
						|
    return YAP_MkApplTerm(f, 1, &child);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list_create_two(const char *atom_name, TrNode node, YAP_Term operand) {
 | 
						|
  YAP_Atom atom = YAP_LookupAtom(atom_name);
 | 
						|
  
 | 
						|
  if(IS_LEAF_TRIE_NODE(node)) {
 | 
						|
    YAP_Functor f = YAP_MkFunctor(atom, 1);
 | 
						|
    return YAP_MkApplTerm(f, 1, &operand);
 | 
						|
  } else {
 | 
						|
    YAP_Functor f = YAP_MkFunctor(atom, 2);
 | 
						|
    YAP_Term args[2] = {
 | 
						|
      operand, trie_to_list(TrNode_child(node))
 | 
						|
    };
 | 
						|
    return YAP_MkApplTerm(f, 2, args);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*            API             */     
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
TrEngine core_trie_init_module(void) {
 | 
						|
  static int init_once = 1;
 | 
						|
  TrEngine engine;
 | 
						|
 | 
						|
  if (init_once) {
 | 
						|
    new_struct(AUXILIARY_TERM_STACK, YAP_Term, BASE_AUXILIARY_TERM_STACK_SIZE * sizeof(YAP_Term));
 | 
						|
    CURRENT_AUXILIARY_TERM_STACK_SIZE = BASE_AUXILIARY_TERM_STACK_SIZE;
 | 
						|
    CURRENT_TRIE_MODE = TRIE_MODE_STANDARD;
 | 
						|
    FunctorComma = YAP_MkFunctor(YAP_LookupAtom(","), 2);
 | 
						|
    init_once = 0;
 | 
						|
  }
 | 
						|
  new_trie_engine(engine);
 | 
						|
  return engine;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
TrNode core_trie_open(TrEngine engine) {
 | 
						|
  TrNode node;
 | 
						|
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  new_trie_node(node, 0, NULL, NULL, TrEngine_trie(engine), AS_TR_NODE_NEXT(&TrEngine_trie(engine)));
 | 
						|
  if (TrEngine_trie(engine))
 | 
						|
    TrNode_previous(TrEngine_trie(engine)) = node;
 | 
						|
  TrEngine_trie(engine) = node;
 | 
						|
  INCREMENT_TRIES(CURRENT_TRIE_ENGINE);
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) {
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  DATA_DESTRUCT_FUNCTION = destruct_function;
 | 
						|
  if (TrNode_child(node))
 | 
						|
    remove_child_nodes(TrNode_child(node));
 | 
						|
  if (TrNode_next(node)) {
 | 
						|
    TrNode_previous(TrNode_next(node)) = TrNode_previous(node);
 | 
						|
    TrNode_next(TrNode_previous(node)) = TrNode_next(node);
 | 
						|
  } else
 | 
						|
    TrNode_next(TrNode_previous(node)) = NULL;
 | 
						|
  free_trie_node(node);  
 | 
						|
  DECREMENT_TRIES(CURRENT_TRIE_ENGINE);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)) {
 | 
						|
  while (TrEngine_trie(engine))
 | 
						|
    core_trie_close(engine, TrEngine_trie(engine), destruct_function);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_set_mode(YAP_Int mode) {
 | 
						|
  CURRENT_TRIE_MODE = mode;
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
YAP_Int core_trie_get_mode(void) {
 | 
						|
  return CURRENT_TRIE_MODE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
TrNode core_trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth) {
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  CURRENT_DEPTH = 0;
 | 
						|
  stack_args_base = stack_args = AUXILIARY_TERM_STACK;
 | 
						|
  stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1;
 | 
						|
  node = put_entry(node, entry);
 | 
						|
  if (!IS_LEAF_TRIE_NODE(node)) {
 | 
						|
    MARK_AS_LEAF_TRIE_NODE(node);
 | 
						|
    INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
  }
 | 
						|
  /* reset var terms */
 | 
						|
  while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) {
 | 
						|
    (void) POP_DOWN(stack_vars);
 | 
						|
    *((YAP_Term *)*stack_vars) = *stack_vars;
 | 
						|
  }
 | 
						|
  if (depth)
 | 
						|
    *depth = CURRENT_DEPTH;
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
TrNode core_trie_check_entry(TrNode node, YAP_Term entry) {
 | 
						|
  if (!TrNode_child(node))
 | 
						|
    return NULL;
 | 
						|
  stack_args_base = stack_args = AUXILIARY_TERM_STACK;
 | 
						|
  stack_vars_base = stack_vars = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1;
 | 
						|
  node = check_entry(node, entry);
 | 
						|
  /* reset var terms */
 | 
						|
  while (STACK_NOT_EMPTY(stack_vars++, stack_vars_base)) {
 | 
						|
    (void) POP_DOWN(stack_vars);
 | 
						|
    *((YAP_Term *)*stack_vars) = *stack_vars;
 | 
						|
  }
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
YAP_Term core_trie_get_entry(TrNode node) {
 | 
						|
  CURRENT_INDEX = -1;
 | 
						|
  stack_vars_base = stack_vars = AUXILIARY_TERM_STACK;
 | 
						|
  stack_args_base = stack_args = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1;
 | 
						|
  return get_entry(node, stack_args, &node);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) {
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  DATA_DESTRUCT_FUNCTION = destruct_function;
 | 
						|
  if (DATA_DESTRUCT_FUNCTION)
 | 
						|
    (*DATA_DESTRUCT_FUNCTION)(node);
 | 
						|
  DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
  remove_entry(node);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) {
 | 
						|
  TrNode parent;
 | 
						|
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  DATA_DESTRUCT_FUNCTION = destruct_function;
 | 
						|
  parent = TrNode_parent(node);
 | 
						|
  remove_child_nodes(TrNode_child(parent));
 | 
						|
  remove_entry(parent);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)) {
 | 
						|
  DATA_ADD_FUNCTION = add_function;
 | 
						|
  if (TrNode_child(node_dest) && TrNode_child(node_source))
 | 
						|
    traverse_and_add(node_dest, node_source);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*copy_function)(TrNode, TrNode)) {
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  DATA_ADD_FUNCTION = add_function;
 | 
						|
  DATA_COPY_FUNCTION = copy_function;
 | 
						|
  if (TrNode_child(node_dest)) {
 | 
						|
    if (TrNode_child(node_source))
 | 
						|
      traverse_and_join(node_dest, node_source);
 | 
						|
  } else if (TrNode_child(node_source))
 | 
						|
    TrNode_child(node_dest) = copy_child_nodes(node_dest, TrNode_child(node_source));
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)) {
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  DATA_ADD_FUNCTION = add_function;
 | 
						|
  DATA_DESTRUCT_FUNCTION = destruct_function;
 | 
						|
  if (TrNode_child(node_dest)) {
 | 
						|
    if (TrNode_child(node_source))
 | 
						|
      traverse_and_intersect(node_dest, node_source);
 | 
						|
    else {
 | 
						|
      remove_child_nodes(TrNode_child(node_dest));
 | 
						|
      TrNode_child(node_dest) = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
YAP_Int core_trie_count_join(TrNode node1, TrNode node2) {
 | 
						|
  YAP_Int count = 0;
 | 
						|
 | 
						|
  if (TrNode_child(node1)) {
 | 
						|
    count += traverse_and_count_entries(TrNode_child(node1));
 | 
						|
    if (TrNode_child(node2)) {
 | 
						|
      count += traverse_and_count_entries(TrNode_child(node2));
 | 
						|
      count -= traverse_and_count_common_entries(node1, node2);
 | 
						|
    }
 | 
						|
  } else if (TrNode_child(node2))
 | 
						|
    count += traverse_and_count_entries(TrNode_child(node2));
 | 
						|
  return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
YAP_Int core_trie_count_intersect(TrNode node1, TrNode node2) {
 | 
						|
  YAP_Int count = 0;
 | 
						|
 | 
						|
  if (TrNode_child(node1))
 | 
						|
    if (TrNode_child(node2))
 | 
						|
      count = traverse_and_count_common_entries(node1, node2);
 | 
						|
  return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)) {
 | 
						|
  CURRENT_INDEX = -1;
 | 
						|
  DATA_SAVE_FUNCTION = save_function;
 | 
						|
  if (TrNode_child(node)) {
 | 
						|
    fprintf(file, "BEGIN_TRIE_v2 ");
 | 
						|
    traverse_and_save(TrNode_child(node), file, 0);
 | 
						|
    fprintf(file, "END_TRIE_v2");
 | 
						|
    fflush(file);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
TrNode core_trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)) {
 | 
						|
  TrNode node;
 | 
						|
  char version[15];
 | 
						|
  fpos_t curpos;
 | 
						|
  int n;
 | 
						|
 | 
						|
  n = fscanf(file, "%14s", version);
 | 
						|
  if (fgetpos(file, &curpos))
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  if (!strcmp(version, "BEGIN_TRIE_v2")) {
 | 
						|
    fseek(file, -11, SEEK_END);
 | 
						|
    n = fscanf(file, "%s", version);
 | 
						|
    if (strcmp(version, "END_TRIE_v2")) {
 | 
						|
      fprintf(stderr, "******************************************\n");
 | 
						|
      fprintf(stderr, "  Tries core module: trie file corrupted\n");
 | 
						|
      fprintf(stderr, "******************************************\n");  
 | 
						|
      fflush(stderr);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
    if (fsetpos(file, &curpos))
 | 
						|
      return NULL;
 | 
						|
    CURRENT_LOAD_VERSION = 2;
 | 
						|
  } else if (!strcmp(version, "BEGIN_TRIE")) {
 | 
						|
    fseek(file, -8, SEEK_END);
 | 
						|
    n = fscanf(file, "%s", version);
 | 
						|
    if (strcmp(version, "END_TRIE")) {
 | 
						|
      fprintf(stderr, "******************************************\n");
 | 
						|
      fprintf(stderr, "  Tries core module: trie file corrupted\n");
 | 
						|
      fprintf(stderr, "******************************************\n");  
 | 
						|
      fflush(stderr);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
    if (fsetpos(file, &curpos))
 | 
						|
      return NULL;
 | 
						|
    CURRENT_LOAD_VERSION = 1;
 | 
						|
  } else {
 | 
						|
    fprintf(stderr, "****************************************\n");
 | 
						|
    fprintf(stderr, "  Tries core module: invalid trie file\n");
 | 
						|
    fprintf(stderr, "****************************************\n");  
 | 
						|
    fflush(stderr);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  CURRENT_TRIE_ENGINE = engine;
 | 
						|
  CURRENT_INDEX = -1;
 | 
						|
  CURRENT_DEPTH = 0;
 | 
						|
  DATA_LOAD_FUNCTION = load_function;
 | 
						|
  node = core_trie_open(engine);
 | 
						|
  traverse_and_load(node, file);
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) {
 | 
						|
  *memory = TrEngine_memory(engine);
 | 
						|
  *tries = TrEngine_tries(engine);
 | 
						|
  *entries = TrEngine_entries(engine);
 | 
						|
  *nodes = TrEngine_nodes(engine);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes) {
 | 
						|
  *memory = TrEngine_memory_max(engine);
 | 
						|
  *tries = TrEngine_tries_max(engine);
 | 
						|
  *entries = TrEngine_entries_max(engine);
 | 
						|
  *nodes = TrEngine_nodes_max(engine);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes) {
 | 
						|
  USAGE_ENTRIES = 0;
 | 
						|
  USAGE_NODES = 0;
 | 
						|
  USAGE_VIRTUAL_NODES = 0;
 | 
						|
  if (TrNode_child(node))
 | 
						|
    traverse_and_get_usage(TrNode_child(node), 0);
 | 
						|
  *entries = USAGE_ENTRIES;
 | 
						|
  *nodes = USAGE_NODES;
 | 
						|
  *virtual_nodes = USAGE_VIRTUAL_NODES;
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_trie_print(TrNode node, void (*print_function)(TrNode)) {
 | 
						|
  DATA_PRINT_FUNCTION = print_function;
 | 
						|
  if (TrNode_child(node)) {
 | 
						|
    int arity[1000];
 | 
						|
    char str[10000];
 | 
						|
    arity[0] = 0;
 | 
						|
    traverse_and_print(TrNode_child(node), arity, str, 0, TRIE_PRINT_NORMAL);
 | 
						|
  } else
 | 
						|
    fprintf(stdout, "(empty)\n");
 | 
						|
  fflush(stdout);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_disable_hash_table(void) {
 | 
						|
  TRIE_DISABLE_HASH_TABLE = 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void core_enable_hash_table(void) {
 | 
						|
  TRIE_DISABLE_HASH_TABLE = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
YAP_Term core_trie_to_list(TrNode node) {
 | 
						|
  TrNode root = TrNode_child(node);
 | 
						|
  
 | 
						|
  if (root)
 | 
						|
    return trie_to_list(root);
 | 
						|
  else
 | 
						|
    return YAP_MkAtomTerm(YAP_LookupAtom("empty"));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* -------------------------- */
 | 
						|
/*      Local Procedures      */
 | 
						|
/* -------------------------- */
 | 
						|
 | 
						|
static
 | 
						|
TrNode put_entry(TrNode node, YAP_Term entry) {
 | 
						|
  YAP_Term t = YAP_Deref(entry);
 | 
						|
  if (YAP_IsVarTerm(t)) {
 | 
						|
    if (IsTrieVar(t, stack_vars, stack_vars_base)) {
 | 
						|
      node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - 1 - (YAP_Term *)t) / 2));
 | 
						|
    } else {
 | 
						|
      node = trie_node_check_insert(node, MkTrieVar((stack_vars_base - stack_vars) / 2));
 | 
						|
      PUSH_UP(stack_vars, t, stack_args);
 | 
						|
      *((YAP_Term *)t) = (YAP_Term)stack_vars;
 | 
						|
      PUSH_UP(stack_vars, stack_vars, stack_args);
 | 
						|
    }
 | 
						|
  } else if (YAP_IsAtomTerm(t)) {
 | 
						|
    node = trie_node_check_insert(node, t);
 | 
						|
  } else if (YAP_IsIntTerm(t)) {
 | 
						|
    node = trie_node_check_insert(node, t);
 | 
						|
  } else if (YAP_IsFloatTerm(t)) {
 | 
						|
    volatile union {
 | 
						|
      double f;
 | 
						|
      YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
    } tf;  /* to avoid gcc warning */
 | 
						|
    tf.f = YAP_FloatOfTerm(t);
 | 
						|
    node = trie_node_check_insert(node, FloatInitTag);
 | 
						|
    node = trie_node_check_insert(node, tf.p[0]);
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
    node = trie_node_check_insert(node, tf.p[1]);
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
    node = trie_node_check_insert(node, FloatEndTag);
 | 
						|
  } else if (YAP_IsPairTerm(t)) {
 | 
						|
    node = trie_node_check_insert(node, PairInitTag);
 | 
						|
    if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) {
 | 
						|
      do {
 | 
						|
        node = put_entry(node, YAP_HeadOfTerm(t));
 | 
						|
        t = YAP_Deref(YAP_TailOfTerm(t));
 | 
						|
      } while (YAP_IsPairTerm(t));
 | 
						|
      if (t == YAP_TermNil()) {
 | 
						|
        node = trie_node_check_insert(node, PairEndEmptyTag);
 | 
						|
      } else {
 | 
						|
        node = put_entry(node, t);
 | 
						|
        node = trie_node_check_insert(node, PairEndTermTag);
 | 
						|
      }
 | 
						|
    } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */
 | 
						|
      YAP_Term *stack_list = stack_args;
 | 
						|
      do {
 | 
						|
        PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars);
 | 
						|
        t = YAP_Deref(YAP_TailOfTerm(t));
 | 
						|
      } while (YAP_IsPairTerm(t));
 | 
						|
      if (t == YAP_TermNil()) {
 | 
						|
        while (STACK_NOT_EMPTY(stack_args, stack_list))
 | 
						|
          node = put_entry(node, POP_UP(stack_args));
 | 
						|
        node = trie_node_check_insert(node, PairEndEmptyTag);
 | 
						|
      } else {
 | 
						|
        PUSH_DOWN(stack_args, t, stack_vars);
 | 
						|
        while (STACK_NOT_EMPTY(stack_args, stack_list))
 | 
						|
          node = put_entry(node, POP_UP(stack_args));
 | 
						|
        node = trie_node_check_insert(node, PairEndTermTag);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (YAP_IsApplTerm(t)) {
 | 
						|
    YAP_Functor f = YAP_FunctorOfTerm(t);
 | 
						|
    if (f == FunctorComma) {
 | 
						|
      node = trie_node_check_insert(node, CommaInitTag);
 | 
						|
      do {
 | 
						|
        node = put_entry(node, YAP_ArgOfTerm(1, t));
 | 
						|
        t = YAP_Deref(YAP_ArgOfTerm(2, t));
 | 
						|
      } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma);
 | 
						|
      node = put_entry(node, t);
 | 
						|
      node = trie_node_check_insert(node, CommaEndTag);
 | 
						|
    } else {
 | 
						|
      int i;
 | 
						|
      node = trie_node_check_insert(node, ApplTag | ((YAP_Term) f));
 | 
						|
      for (i = 1; i <= YAP_ArityOfFunctor(f); i++)
 | 
						|
        node = put_entry(node, YAP_ArgOfTerm(i, t));
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fprintf(stderr, "  Tries core module: unknown type tag\n");
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fflush(stderr);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
TrNode check_entry(TrNode node, YAP_Term entry) {
 | 
						|
  YAP_Term t = YAP_Deref(entry);
 | 
						|
  if (YAP_IsVarTerm(t)) {
 | 
						|
    if (IsTrieVar(t, stack_vars, stack_vars_base)) {
 | 
						|
      if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - 1 - (YAP_Term *)t) / 2))))
 | 
						|
        return NULL;
 | 
						|
    } else {
 | 
						|
      if (!(node = trie_node_check(node, MkTrieVar((stack_vars_base - stack_vars) / 2))))
 | 
						|
        return NULL;
 | 
						|
      PUSH_UP(stack_vars, t, stack_args);
 | 
						|
      *((YAP_Term *)t) = (YAP_Term)stack_vars;
 | 
						|
      PUSH_UP(stack_vars, stack_vars, stack_args);
 | 
						|
    }
 | 
						|
  } else if (YAP_IsAtomTerm(t)) {
 | 
						|
    if (!(node = trie_node_check(node, t)))
 | 
						|
      return NULL;
 | 
						|
  } else if (YAP_IsIntTerm(t)) {
 | 
						|
    if (!(node = trie_node_check(node, t)))
 | 
						|
      return NULL;
 | 
						|
  } else if (YAP_IsFloatTerm(t)) {
 | 
						|
    volatile union {
 | 
						|
      double f;
 | 
						|
      YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
    } tf;  /* to avoid gcc warning */
 | 
						|
    tf.f = YAP_FloatOfTerm(t);
 | 
						|
    if (!(node = trie_node_check(node, FloatInitTag)))
 | 
						|
      return NULL;
 | 
						|
    if (!(node = trie_node_check(node, tf.p[0])))
 | 
						|
      return NULL;
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
    if (!(node = trie_node_check(node, tf.p[1])))
 | 
						|
      return NULL;
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
    if (!(node = trie_node_check(node, FloatEndTag)))
 | 
						|
      return NULL;
 | 
						|
  } else if (YAP_IsPairTerm(t)) {
 | 
						|
    if (!(node = trie_node_check(node, PairInitTag)))
 | 
						|
      return NULL;
 | 
						|
    if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) {
 | 
						|
      do {
 | 
						|
        if (!(node = check_entry(node, YAP_HeadOfTerm(t))))
 | 
						|
          return NULL;
 | 
						|
        t = YAP_Deref(YAP_TailOfTerm(t));
 | 
						|
      } while (YAP_IsPairTerm(t));
 | 
						|
      if (t == YAP_TermNil()) {
 | 
						|
        if (!(node = trie_node_check(node, PairEndEmptyTag)))
 | 
						|
          return NULL;
 | 
						|
      } else {
 | 
						|
        if (!(node = check_entry(node, t)))
 | 
						|
          return NULL;
 | 
						|
        if (!(node = trie_node_check(node, PairEndTermTag)))
 | 
						|
          return NULL;
 | 
						|
      }
 | 
						|
    } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */
 | 
						|
      YAP_Term *stack_list = stack_args;
 | 
						|
      do {
 | 
						|
        PUSH_DOWN(stack_args, YAP_HeadOfTerm(t), stack_vars);
 | 
						|
        t = YAP_Deref(YAP_TailOfTerm(t));
 | 
						|
      } while (YAP_IsPairTerm(t));
 | 
						|
      if (t == YAP_TermNil()) {
 | 
						|
        while (STACK_NOT_EMPTY(stack_args, stack_list))
 | 
						|
          if (!(node = check_entry(node, POP_UP(stack_args))))
 | 
						|
            return NULL;
 | 
						|
        if (!(node = trie_node_check(node, PairEndEmptyTag)))
 | 
						|
          return NULL;
 | 
						|
      } else {
 | 
						|
        PUSH_DOWN(stack_args, t, stack_vars);
 | 
						|
        while (STACK_NOT_EMPTY(stack_args, stack_list))
 | 
						|
          if (!(node = check_entry(node, POP_UP(stack_args))))
 | 
						|
            return NULL;
 | 
						|
        if (!(node = trie_node_check(node, PairEndTermTag)))
 | 
						|
          return NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (YAP_IsApplTerm(t)) {
 | 
						|
    YAP_Functor f = YAP_FunctorOfTerm(t);
 | 
						|
    if (f == FunctorComma) {
 | 
						|
      if (!(node = trie_node_check(node, CommaInitTag)))
 | 
						|
        return NULL;
 | 
						|
      do {
 | 
						|
        if (!(node = check_entry(node, YAP_ArgOfTerm(1, t))))
 | 
						|
          return NULL;
 | 
						|
        t = YAP_Deref(YAP_ArgOfTerm(2, t));
 | 
						|
      } while (YAP_IsApplTerm(t) && YAP_FunctorOfTerm(t) == FunctorComma);
 | 
						|
      if (!(node = check_entry(node, t)))
 | 
						|
        return NULL;
 | 
						|
      if (!(node = trie_node_check(node, CommaEndTag)))
 | 
						|
        return NULL;
 | 
						|
    } else {
 | 
						|
      int i;
 | 
						|
      if (!(node = trie_node_check(node, ApplTag | ((YAP_Term) f))))
 | 
						|
        return NULL;
 | 
						|
      for (i = 1; i <= YAP_ArityOfFunctor(f); i++)
 | 
						|
        if (!(node = check_entry(node, YAP_ArgOfTerm(i, t))))
 | 
						|
          return NULL;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fprintf(stderr, "  Tries core module: unknown type tag\n");
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fflush(stderr);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term get_entry(TrNode node, YAP_Term *stack_mark, TrNode *cur_node) {
 | 
						|
  YAP_Term t = (YAP_Term) &t;
 | 
						|
  while (TrNode_parent(node)) {
 | 
						|
    t = TrNode_entry(node);
 | 
						|
    if (YAP_IsVarTerm(t)) {
 | 
						|
      int index = TrieVarIndex(t);
 | 
						|
      if (index > CURRENT_INDEX) {
 | 
						|
        int i;
 | 
						|
        stack_vars = &stack_vars_base[index + 1];
 | 
						|
        if (stack_vars > stack_args + 1) {
 | 
						|
          fprintf(stderr, "**************************************\n");
 | 
						|
          fprintf(stderr, "  Tries core module: term stack full\n");
 | 
						|
          fprintf(stderr, "**************************************\n");
 | 
						|
	  fflush(stderr);
 | 
						|
        }
 | 
						|
        for (i = index; i > CURRENT_INDEX; i--)
 | 
						|
          stack_vars_base[i] = 0;
 | 
						|
        CURRENT_INDEX = index;
 | 
						|
      }
 | 
						|
      if (stack_vars_base[index]) {
 | 
						|
        t = stack_vars_base[index];
 | 
						|
      } else {
 | 
						|
        t = YAP_MkVarTerm();
 | 
						|
        stack_vars_base[index] = t;
 | 
						|
      }
 | 
						|
      PUSH_UP(stack_args, t, stack_vars);
 | 
						|
    } else if (YAP_IsAtomTerm(t)) {
 | 
						|
      PUSH_UP(stack_args, t, stack_vars);
 | 
						|
    } else if (YAP_IsIntTerm(t)) {
 | 
						|
      PUSH_UP(stack_args, t, stack_vars);
 | 
						|
    } else if (YAP_IsPairTerm(t)) {
 | 
						|
      if (t == PairInitTag) {
 | 
						|
        YAP_Term t2;
 | 
						|
        if ((CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) == TRIE_MODE_STANDARD) {
 | 
						|
          YAP_Term *stack_aux = stack_mark;
 | 
						|
          t = *stack_aux--;
 | 
						|
          while (STACK_NOT_EMPTY(stack_aux, stack_args)) {
 | 
						|
            t2 = *stack_aux--;
 | 
						|
            t = YAP_MkPairTerm(t2, t);
 | 
						|
          }
 | 
						|
        } else if (CURRENT_TRIE_MODE & TRIE_MODE_REVERSE) { /* TRIE_MODE_REVERSE */
 | 
						|
          YAP_Term *stack_aux = stack_mark;
 | 
						|
          t = *stack_aux;
 | 
						|
          if (t == YAP_TermNil())
 | 
						|
            stack_aux--;
 | 
						|
          else
 | 
						|
            t = POP_DOWN(stack_args);
 | 
						|
          while (STACK_NOT_EMPTY(stack_args, stack_aux)) {
 | 
						|
            t2 = POP_DOWN(stack_args);
 | 
						|
            t = YAP_MkPairTerm(t2, t);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        stack_args = stack_mark;
 | 
						|
        *cur_node = node;
 | 
						|
        return t;
 | 
						|
      } else if (t == PairEndEmptyTag) {
 | 
						|
        t = YAP_TermNil();
 | 
						|
        PUSH_UP(stack_args, t, stack_vars);
 | 
						|
        node = TrNode_parent(node);
 | 
						|
        t = get_entry(node, &stack_args[1], &node);
 | 
						|
        PUSH_UP(stack_args, t, stack_vars);
 | 
						|
      } else if (t == PairEndTermTag) {
 | 
						|
        node = TrNode_parent(node);
 | 
						|
        t = get_entry(node, stack_args, &node);
 | 
						|
        PUSH_UP(stack_args, t, stack_vars);
 | 
						|
      } else if (t == CommaEndTag) {
 | 
						|
        node = TrNode_parent(node);
 | 
						|
        t = get_entry(node, stack_args, &node);
 | 
						|
        PUSH_UP(stack_args, t, stack_vars);
 | 
						|
      } else if (t == CommaInitTag) {
 | 
						|
        YAP_Term *stack_aux = stack_mark;
 | 
						|
        stack_aux--;
 | 
						|
        while (STACK_NOT_EMPTY(stack_aux, stack_args)) {
 | 
						|
          t = YAP_MkApplTerm(FunctorComma, 2, stack_aux);
 | 
						|
          *stack_aux = t;
 | 
						|
          stack_aux--;
 | 
						|
        }
 | 
						|
        stack_args = stack_mark;
 | 
						|
        *cur_node = node;
 | 
						|
        return t;
 | 
						|
      } else if (t == FloatEndTag) {
 | 
						|
	volatile union {
 | 
						|
	  double f;
 | 
						|
	  YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
	} tf;  /* to avoid gcc warning */
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
        node = TrNode_parent(node);
 | 
						|
        tf.p[1] = TrNode_entry(node);
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
        node = TrNode_parent(node);
 | 
						|
        tf.p[0] = TrNode_entry(node);
 | 
						|
        node = TrNode_parent(node); /* ignore FloatInitTag */
 | 
						|
        t = YAP_MkFloatTerm(tf.f);
 | 
						|
        PUSH_UP(stack_args, t, stack_vars);
 | 
						|
      } else if (t == FloatInitTag) {
 | 
						|
      }
 | 
						|
    } else if (ApplTag & t) {
 | 
						|
      YAP_Functor f = (YAP_Functor)(~ApplTag & t);
 | 
						|
      int arity = YAP_ArityOfFunctor(f);
 | 
						|
      t = YAP_MkApplTerm(f, arity, &stack_args[1]);
 | 
						|
      stack_args += arity;
 | 
						|
      PUSH_UP(stack_args, t, stack_vars);
 | 
						|
    } else {
 | 
						|
      fprintf(stderr, "***************************************\n");
 | 
						|
      fprintf(stderr, "  Tries core module: unknown type tag\n");
 | 
						|
      fprintf(stderr, "***************************************\n");
 | 
						|
      fflush(stderr);
 | 
						|
    }
 | 
						|
    node = TrNode_parent(node);
 | 
						|
  }
 | 
						|
  *cur_node = node;
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void remove_entry(TrNode node) {
 | 
						|
  TrNode parent = TrNode_parent(node);
 | 
						|
  while (parent) {
 | 
						|
    if (TrNode_previous(node)) {
 | 
						|
      if (IS_HASH_NODE(TrNode_child(parent))) {
 | 
						|
	TrHash hash = (TrHash) TrNode_child(parent);
 | 
						|
	TrHash_num_nodes(hash)--;
 | 
						|
	if (TrHash_num_nodes(hash)) {
 | 
						|
	  if (TrNode_next(node)) {
 | 
						|
	    TrNode_next(TrNode_previous(node)) = TrNode_next(node);
 | 
						|
	    TrNode_previous(TrNode_next(node)) = TrNode_previous(node);
 | 
						|
	  } else {
 | 
						|
	    TrNode_next(TrNode_previous(node)) = NULL;
 | 
						|
	  }
 | 
						|
	  free_trie_node(node);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
	free_hash_buckets(TrHash_buckets(hash), TrHash_num_buckets(hash));
 | 
						|
	free_trie_hash(hash);
 | 
						|
      } else {
 | 
						|
	if (TrNode_next(node)) {
 | 
						|
	  TrNode_next(TrNode_previous(node)) = TrNode_next(node);
 | 
						|
	  TrNode_previous(TrNode_next(node)) = TrNode_previous(node);
 | 
						|
	} else {
 | 
						|
	  TrNode_next(TrNode_previous(node)) = NULL;
 | 
						|
	}
 | 
						|
	free_trie_node(node);
 | 
						|
	return;
 | 
						|
      }
 | 
						|
    } else if (TrNode_next(node)) {
 | 
						|
      TrNode_child(parent) = TrNode_next(node);
 | 
						|
      TrNode_previous(TrNode_next(node)) = NULL;
 | 
						|
      free_trie_node(node);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    free_trie_node(node);
 | 
						|
    node = parent;
 | 
						|
    parent = TrNode_parent(node);
 | 
						|
  }
 | 
						|
  TrNode_child(node) = NULL;
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void remove_child_nodes(TrNode node) {
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash = (TrHash) node;
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      if (*--bucket)
 | 
						|
	remove_child_nodes(*bucket);
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    free_hash_buckets(first_bucket, TrHash_num_buckets(hash));
 | 
						|
    free_trie_hash(hash);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  if (TrNode_next(node))
 | 
						|
    remove_child_nodes(TrNode_next(node));
 | 
						|
  if (!IS_LEAF_TRIE_NODE(node))
 | 
						|
    remove_child_nodes(TrNode_child(node));
 | 
						|
  else {
 | 
						|
    if (DATA_DESTRUCT_FUNCTION)
 | 
						|
      (*DATA_DESTRUCT_FUNCTION)(node);
 | 
						|
    DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
  }
 | 
						|
  free_trie_node(node);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
TrNode copy_child_nodes(TrNode parent_dest, TrNode child_source) {
 | 
						|
  TrNode child_dest, next_dest;
 | 
						|
 | 
						|
  if (IS_HASH_NODE(child_source)) {
 | 
						|
    TrNode *bucket_dest, *first_bucket_source, *bucket_source;
 | 
						|
    TrHash hash_dest, hash_source;
 | 
						|
    hash_source = (TrHash) child_source;
 | 
						|
    first_bucket_source = TrHash_buckets(hash_source);
 | 
						|
    bucket_source = first_bucket_source + TrHash_num_buckets(hash_source);
 | 
						|
    new_trie_hash(hash_dest, TrHash_num_nodes(hash_source), TrHash_num_buckets(hash_source));
 | 
						|
    bucket_dest = TrHash_buckets(hash_dest) + TrHash_num_buckets(hash_dest);
 | 
						|
    do {
 | 
						|
      bucket_dest--;
 | 
						|
      if (*--bucket_source) {
 | 
						|
	*bucket_dest = copy_child_nodes(parent_dest, *bucket_source);
 | 
						|
	TrNode_previous(*bucket_dest) = AS_TR_NODE_NEXT(bucket_dest);
 | 
						|
      } else
 | 
						|
	*bucket_dest = NULL;
 | 
						|
    } while (bucket_source != first_bucket_source);
 | 
						|
    return (TrNode) hash_dest;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TrNode_next(child_source))
 | 
						|
    next_dest = copy_child_nodes(parent_dest, TrNode_next(child_source));
 | 
						|
  else
 | 
						|
    next_dest = NULL;
 | 
						|
  new_trie_node(child_dest, TrNode_entry(child_source), parent_dest, NULL, next_dest, NULL);
 | 
						|
  if (next_dest)
 | 
						|
    TrNode_previous(next_dest) = child_dest;
 | 
						|
  if (IS_LEAF_TRIE_NODE(child_source)) {
 | 
						|
    MARK_AS_LEAF_TRIE_NODE(child_dest);
 | 
						|
    INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
    if (DATA_COPY_FUNCTION)
 | 
						|
      (*DATA_COPY_FUNCTION)(child_dest, child_source);
 | 
						|
  } else
 | 
						|
    TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source));
 | 
						|
  return child_dest;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_add(TrNode parent_dest, TrNode parent_source) {
 | 
						|
  TrNode child_dest, child_source;
 | 
						|
 | 
						|
  /* parent_source is not a leaf node */
 | 
						|
  child_source = TrNode_child(parent_source);
 | 
						|
  if (IS_HASH_NODE(child_source)) {
 | 
						|
    TrNode *first_bucket_source, *bucket_source;
 | 
						|
    TrHash hash_source;
 | 
						|
    hash_source = (TrHash) child_source;
 | 
						|
    first_bucket_source = TrHash_buckets(hash_source);
 | 
						|
    bucket_source = first_bucket_source + TrHash_num_buckets(hash_source);
 | 
						|
    do {
 | 
						|
      child_source = *--bucket_source;
 | 
						|
      while (child_source) {
 | 
						|
	/* parent_dest is not a leaf node */
 | 
						|
	child_dest = trie_node_check(parent_dest, TrNode_entry(child_source));
 | 
						|
	if (child_dest) {
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	    /* child_source is a leaf node */
 | 
						|
	    if (DATA_ADD_FUNCTION)
 | 
						|
	      (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
	  } else
 | 
						|
	    /* child_dest and child_source are not leaf nodes */
 | 
						|
	    traverse_and_add(child_dest, child_source);
 | 
						|
	}
 | 
						|
	child_source = TrNode_next(child_source);
 | 
						|
      }
 | 
						|
    } while (bucket_source != first_bucket_source);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  while (child_source) {
 | 
						|
    /* parent_dest is not a leaf node */
 | 
						|
    child_dest = trie_node_check(parent_dest, TrNode_entry(child_source));
 | 
						|
    if (child_dest) {
 | 
						|
      if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	/* child_source is a leaf node */
 | 
						|
	if (DATA_ADD_FUNCTION)
 | 
						|
	  (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
      } else
 | 
						|
	/* child_dest and child_source are not leaf nodes */
 | 
						|
	traverse_and_add(child_dest, child_source);
 | 
						|
    }
 | 
						|
    child_source = TrNode_next(child_source);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_join(TrNode parent_dest, TrNode parent_source) {
 | 
						|
  TrNode child_dest, child_source;
 | 
						|
 | 
						|
  /* parent_source is not a leaf node */
 | 
						|
  child_source = TrNode_child(parent_source);
 | 
						|
  if (IS_HASH_NODE(child_source)) {
 | 
						|
    TrNode *first_bucket_source, *bucket_source;
 | 
						|
    TrHash hash_source;
 | 
						|
    hash_source = (TrHash) child_source;
 | 
						|
    first_bucket_source = TrHash_buckets(hash_source);
 | 
						|
    bucket_source = first_bucket_source + TrHash_num_buckets(hash_source);
 | 
						|
    do {
 | 
						|
      child_source = *--bucket_source;
 | 
						|
      while (child_source) {
 | 
						|
	/* parent_dest is not a leaf node */
 | 
						|
	child_dest = trie_node_check(parent_dest, TrNode_entry(child_source));
 | 
						|
	if (child_dest) {
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	    /* child_source is a leaf node */
 | 
						|
	    if (DATA_ADD_FUNCTION)
 | 
						|
	      (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
	  } else
 | 
						|
	    /* child_dest and child_source are not leaf nodes */
 | 
						|
	    traverse_and_join(child_dest, child_source);
 | 
						|
	} else {
 | 
						|
	  child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source));
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child_source)) {
 | 
						|
	    MARK_AS_LEAF_TRIE_NODE(child_dest);
 | 
						|
	    INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
	    if (DATA_COPY_FUNCTION)
 | 
						|
	      (*DATA_COPY_FUNCTION)(child_dest, child_source);
 | 
						|
	  } else
 | 
						|
            TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source));
 | 
						|
	}
 | 
						|
	child_source = TrNode_next(child_source);
 | 
						|
      }
 | 
						|
    } while (bucket_source != first_bucket_source);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  while (child_source) {
 | 
						|
    /* parent_dest is not a leaf node */
 | 
						|
    child_dest = trie_node_check(parent_dest, TrNode_entry(child_source));
 | 
						|
    if (child_dest) {
 | 
						|
      if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	/* child_source is a leaf node */
 | 
						|
	if (DATA_ADD_FUNCTION)
 | 
						|
	  (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
      } else
 | 
						|
	/* child_dest and child_source are not leaf nodes */
 | 
						|
	traverse_and_join(child_dest, child_source);
 | 
						|
    } else {
 | 
						|
      child_dest = trie_node_check_insert(parent_dest, TrNode_entry(child_source));
 | 
						|
      if (IS_LEAF_TRIE_NODE(child_source)) {
 | 
						|
	MARK_AS_LEAF_TRIE_NODE(child_dest);
 | 
						|
	INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
	if (DATA_COPY_FUNCTION)
 | 
						|
	  (*DATA_COPY_FUNCTION)(child_dest, child_source);
 | 
						|
      } else
 | 
						|
        TrNode_child(child_dest) = copy_child_nodes(child_dest, TrNode_child(child_source));
 | 
						|
    }
 | 
						|
    child_source = TrNode_next(child_source);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_intersect(TrNode parent_dest, TrNode parent_source) {
 | 
						|
  TrNode child_dest, child_source, child_next;
 | 
						|
 | 
						|
  /* parent_dest is not a leaf node */
 | 
						|
  child_dest = TrNode_child(parent_dest);
 | 
						|
  if (IS_HASH_NODE(child_dest)) {
 | 
						|
    TrNode *first_bucket_dest, *bucket_dest;
 | 
						|
    TrHash hash_dest;
 | 
						|
    hash_dest = (TrHash) child_dest;
 | 
						|
    first_bucket_dest = TrHash_buckets(hash_dest);
 | 
						|
    bucket_dest = first_bucket_dest + TrHash_num_buckets(hash_dest);
 | 
						|
    do {
 | 
						|
      child_dest = *--bucket_dest;
 | 
						|
      while (child_dest) {
 | 
						|
	child_next = TrNode_next(child_dest);
 | 
						|
	/* parent_source is not a leaf node */
 | 
						|
	child_source = trie_node_check(parent_source, TrNode_entry(child_dest));
 | 
						|
	if (child_source) {
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	    /* child_source is a leaf node */
 | 
						|
	    if (DATA_ADD_FUNCTION)
 | 
						|
	      (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
	  } else
 | 
						|
	    /* child_dest and child_source are not leaf nodes */
 | 
						|
	    traverse_and_intersect(child_dest, child_source);
 | 
						|
	} else {
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	    if (DATA_DESTRUCT_FUNCTION)
 | 
						|
	      (*DATA_DESTRUCT_FUNCTION)(child_dest);
 | 
						|
	    DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
	  } else
 | 
						|
	    remove_child_nodes(TrNode_child(child_dest));
 | 
						|
	  remove_entry(child_dest);
 | 
						|
	}
 | 
						|
	child_dest = child_next;
 | 
						|
      }
 | 
						|
    } while (bucket_dest != first_bucket_dest);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  while (child_dest) {
 | 
						|
    child_next = TrNode_next(child_dest);
 | 
						|
    /* parent_source is not a leaf node */
 | 
						|
    child_source = trie_node_check(parent_source, TrNode_entry(child_dest));
 | 
						|
    if (child_source) {
 | 
						|
      if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	/* child_source is a leaf node */
 | 
						|
	if (DATA_ADD_FUNCTION)
 | 
						|
	  (*DATA_ADD_FUNCTION)(child_dest, child_source);
 | 
						|
      } else
 | 
						|
	/* child_dest and child_source are not leaf nodes */
 | 
						|
	traverse_and_intersect(child_dest, child_source);
 | 
						|
    } else {
 | 
						|
      if (IS_LEAF_TRIE_NODE(child_dest)) {
 | 
						|
	if (DATA_DESTRUCT_FUNCTION)
 | 
						|
	  (*DATA_DESTRUCT_FUNCTION)(child_dest);
 | 
						|
	DECREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
      } else
 | 
						|
	remove_child_nodes(TrNode_child(child_dest));
 | 
						|
      remove_entry(child_dest);
 | 
						|
    }
 | 
						|
    child_dest = child_next;
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Int traverse_and_count_common_entries(TrNode parent1, TrNode parent2) {
 | 
						|
  TrNode child1, child2;
 | 
						|
  YAP_Int count = 0;
 | 
						|
 | 
						|
  /* parent1 is not a leaf node */
 | 
						|
  child1 = TrNode_child(parent1);
 | 
						|
  if (IS_HASH_NODE(child1)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash;
 | 
						|
    hash = (TrHash) child1;
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      child1 = *--bucket;
 | 
						|
      while (child1) {
 | 
						|
	/* parent2 is not a leaf node */
 | 
						|
	child2 = trie_node_check(parent2, TrNode_entry(child1));
 | 
						|
	if (child2) {
 | 
						|
	  if (IS_LEAF_TRIE_NODE(child1))
 | 
						|
	    /* child2 is a leaf node */
 | 
						|
	    count++;
 | 
						|
	  else
 | 
						|
	    /* child1 and child2 are not leaf nodes */
 | 
						|
	    count += traverse_and_count_common_entries(child1, child2);
 | 
						|
	}
 | 
						|
	child1 = TrNode_next(child1);
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
  while (child1) {
 | 
						|
    /* parent2 is not a leaf node */
 | 
						|
    child2 = trie_node_check(parent2, TrNode_entry(child1));
 | 
						|
    if (child2) {
 | 
						|
      if (IS_LEAF_TRIE_NODE(child1))
 | 
						|
	/* child2 is a leaf node */
 | 
						|
	count++;
 | 
						|
      else
 | 
						|
	/* child1 and child2 are not leaf nodes */
 | 
						|
	count += traverse_and_count_common_entries(child1, child2);
 | 
						|
    }
 | 
						|
    child1 = TrNode_next(child1);
 | 
						|
  }
 | 
						|
  return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Int traverse_and_count_entries(TrNode node) {
 | 
						|
  YAP_Int count = 0;
 | 
						|
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash;
 | 
						|
    hash = (TrHash) node;
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        count += traverse_and_count_entries(node);
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TrNode_next(node))
 | 
						|
    count += traverse_and_count_entries(TrNode_next(node));
 | 
						|
  if (!IS_LEAF_TRIE_NODE(node))
 | 
						|
    count += traverse_and_count_entries(TrNode_child(node));
 | 
						|
  else
 | 
						|
    count++;
 | 
						|
  return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_get_usage(TrNode node, YAP_Int depth) {
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash;
 | 
						|
    hash = (TrHash) node;
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        traverse_and_get_usage(node, depth);
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  USAGE_NODES++;
 | 
						|
  if (TrNode_next(node))
 | 
						|
    traverse_and_get_usage(TrNode_next(node), depth);
 | 
						|
  depth++;
 | 
						|
  if (!IS_LEAF_TRIE_NODE(node)) {
 | 
						|
    traverse_and_get_usage(TrNode_child(node), depth);
 | 
						|
  } else {
 | 
						|
    USAGE_ENTRIES++;
 | 
						|
    USAGE_VIRTUAL_NODES+= depth;
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_save(TrNode node, FILE *file, int float_block) {
 | 
						|
  YAP_Term t;
 | 
						|
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash;
 | 
						|
    hash = (TrHash) node;
 | 
						|
    fprintf(file, "%lu %d ", HASH_SAVE_MARK, TrHash_num_buckets(hash));
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
	traverse_and_save(node, file, float_block);
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TrNode_next(node))
 | 
						|
    traverse_and_save(TrNode_next(node), file, float_block);
 | 
						|
 | 
						|
  t = TrNode_entry(node);
 | 
						|
  if (float_block) {
 | 
						|
    float_block--;
 | 
						|
    fprintf(file, "%lu %lu ", FLOAT_SAVE_MARK, t);
 | 
						|
  } else if (YAP_IsPairTerm(t)) {
 | 
						|
    if (t == FloatInitTag) {
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
      float_block++;
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
      float_block ++;
 | 
						|
    }
 | 
						|
    fprintf(file, "%lu ", t);
 | 
						|
  } else if (YAP_IsVarTerm(t) || YAP_IsIntTerm(t))
 | 
						|
    fprintf(file, "%lu ", t);
 | 
						|
  else {
 | 
						|
    int index;
 | 
						|
    for (index = 0; index <= CURRENT_INDEX; index++)
 | 
						|
      if (AUXILIARY_TERM_STACK[index] == t)
 | 
						|
	break;
 | 
						|
    if (index > CURRENT_INDEX) {
 | 
						|
      CURRENT_INDEX = index;
 | 
						|
      if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE)
 | 
						|
	expand_auxiliary_term_stack();
 | 
						|
      AUXILIARY_TERM_STACK[CURRENT_INDEX] = t;
 | 
						|
      if (YAP_IsAtomTerm(t))
 | 
						|
	  fprintf(file, "%lu %d %s%c ", ATOM_SAVE_MARK, index, YAP_AtomName(YAP_AtomOfTerm(t)), '\0');
 | 
						|
      else  /* (ApplTag & t) */
 | 
						|
	fprintf(file, "%lu %d %s %lu ", FUNCTOR_SAVE_MARK, index,
 | 
						|
		YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t))),
 | 
						|
		YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t)));
 | 
						|
    } else
 | 
						|
      if (YAP_IsAtomTerm(t))
 | 
						|
	fprintf(file, "%lu %d ", ATOM_SAVE_MARK, index);
 | 
						|
      else
 | 
						|
	fprintf(file, "%lu %d ", FUNCTOR_SAVE_MARK, index);
 | 
						|
  }
 | 
						|
  if (IS_LEAF_TRIE_NODE(node)) {
 | 
						|
    fprintf(file, "- ");
 | 
						|
    if (DATA_SAVE_FUNCTION)
 | 
						|
      (*DATA_SAVE_FUNCTION)(node, file);
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    traverse_and_save(TrNode_child(node), file, float_block);
 | 
						|
    fprintf(file, "- ");
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_load(TrNode parent, FILE *file) {
 | 
						|
  TrHash hash = NULL;
 | 
						|
  YAP_Term t;
 | 
						|
  int n;
 | 
						|
 | 
						|
  if (!fscanf(file, "%lu", &t)) {
 | 
						|
    MARK_AS_LEAF_TRIE_NODE(parent);
 | 
						|
    INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
 | 
						|
    if (DATA_LOAD_FUNCTION)
 | 
						|
      (*DATA_LOAD_FUNCTION)(parent, CURRENT_DEPTH, file);
 | 
						|
    CURRENT_DEPTH--;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  if (t == HASH_SAVE_MARK) {
 | 
						|
    /* alloc a new trie hash */
 | 
						|
    int num_buckets;
 | 
						|
    n = fscanf(file, "%d", &num_buckets);
 | 
						|
    new_trie_hash(hash, 0, num_buckets);
 | 
						|
    TrNode_child(parent) = (TrNode) hash;
 | 
						|
    n = fscanf(file, "%lu", &t);
 | 
						|
  }
 | 
						|
  do {
 | 
						|
    TrNode child;
 | 
						|
    if (t == ATOM_SAVE_MARK) {
 | 
						|
      int index;
 | 
						|
      n = fscanf(file, "%d", &index);
 | 
						|
      if (index > CURRENT_INDEX) {
 | 
						|
	char atom[1000];
 | 
						|
	if (CURRENT_LOAD_VERSION == 2) {
 | 
						|
	  char *ptr, ch;
 | 
						|
	  ptr = atom;
 | 
						|
	  fgetc(file);  /* skip the first empty space */
 | 
						|
	  while ((ch = fgetc(file)))
 | 
						|
	    *ptr++ = ch;
 | 
						|
	  *ptr = '\0';
 | 
						|
	} else if (CURRENT_LOAD_VERSION == 1) {
 | 
						|
	  n = fscanf(file, "%s", atom);
 | 
						|
	}
 | 
						|
	CURRENT_INDEX = index;
 | 
						|
	if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE)
 | 
						|
	  expand_auxiliary_term_stack();
 | 
						|
	AUXILIARY_TERM_STACK[CURRENT_INDEX] = YAP_MkAtomTerm(YAP_LookupAtom(atom));
 | 
						|
      }
 | 
						|
      t = AUXILIARY_TERM_STACK[index];
 | 
						|
    } else if (t == FUNCTOR_SAVE_MARK) {
 | 
						|
      int index;
 | 
						|
      n = fscanf(file, "%d", &index);
 | 
						|
      if (index > CURRENT_INDEX) {
 | 
						|
	char atom[1000];
 | 
						|
	int arity;
 | 
						|
	n = fscanf(file, "%s %d", atom, &arity);
 | 
						|
	CURRENT_INDEX = index;
 | 
						|
	if (CURRENT_INDEX == CURRENT_AUXILIARY_TERM_STACK_SIZE)
 | 
						|
	  expand_auxiliary_term_stack();
 | 
						|
	AUXILIARY_TERM_STACK[CURRENT_INDEX] = ApplTag | ((YAP_Term) YAP_MkFunctor(YAP_LookupAtom(atom), arity));
 | 
						|
      }
 | 
						|
      t = AUXILIARY_TERM_STACK[index];
 | 
						|
    } else if (t == FLOAT_SAVE_MARK)
 | 
						|
      n = fscanf(file, "%lu", &t);
 | 
						|
    child = trie_node_insert(parent, t, hash);
 | 
						|
    traverse_and_load(child, file);
 | 
						|
  } while (fscanf(file, "%lu", &t));
 | 
						|
  CURRENT_DEPTH--;
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
void traverse_and_print(TrNode node, int *arity, char *str, int str_index, int mode) {
 | 
						|
  YAP_Term t;
 | 
						|
  int last_pair_mark = -arity[arity[0]];
 | 
						|
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    int *current_arity = (int *) malloc(sizeof(int) * (arity[0] + 1));
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash;
 | 
						|
    hash = (TrHash) node;
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    memcpy(current_arity, arity, sizeof(int) * (arity[0] + 1));
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        traverse_and_print(node, arity, str, str_index, mode);
 | 
						|
	memcpy(arity, current_arity, sizeof(int) * (current_arity[0] + 1));
 | 
						|
	if (mode != TRIE_PRINT_FLOAT2 && arity[arity[0]] < 0) {
 | 
						|
	  /* restore possible PairEndEmptyTag/PairEndTermTag/CommaEndTag side-effect */
 | 
						|
	  if (str_index > 0 && str[str_index - 1] != '[')
 | 
						|
	    str[str_index - 1] = ',';
 | 
						|
	  /* restore possible PairEndTermTag side-effect */
 | 
						|
	  if (str[last_pair_mark] == '|')
 | 
						|
	    str[last_pair_mark] = ',';
 | 
						|
	}
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
    free(current_arity);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TrNode_next(node)) {
 | 
						|
    int *current_arity = (int *) malloc(sizeof(int) * (arity[0] + 1));
 | 
						|
    memcpy(current_arity, arity, sizeof(int) * (arity[0] + 1));
 | 
						|
    traverse_and_print(TrNode_next(node), arity, str, str_index, mode);
 | 
						|
    memcpy(arity, current_arity, sizeof(int) * (current_arity[0] + 1));
 | 
						|
    if (mode != TRIE_PRINT_FLOAT2 && arity[arity[0]] < 0) {
 | 
						|
      /* restore possible PairEndEmptyTag/PairEndTermTag/CommaEndTag side-effect */
 | 
						|
      if (str_index > 0 && str[str_index - 1] != '[')
 | 
						|
	str[str_index - 1] = ',';
 | 
						|
      /* restore possible PairEndTermTag side-effect */
 | 
						|
      if (str[last_pair_mark] == '|')
 | 
						|
	str[last_pair_mark] = ',';
 | 
						|
    }
 | 
						|
    free(current_arity);
 | 
						|
  }
 | 
						|
 | 
						|
  /* update position for possible PairEndTermTag side-effect */
 | 
						|
  if (mode != TRIE_PRINT_FLOAT2 && arity[arity[0]] < 0 && str_index > 1)
 | 
						|
    arity[arity[0]] = -str_index + 1;
 | 
						|
 | 
						|
  t = TrNode_entry(node);
 | 
						|
  if (mode == TRIE_PRINT_FLOAT) {
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
    arity[arity[0]] = (YAP_Int) t;
 | 
						|
    mode = TRIE_PRINT_FLOAT2;
 | 
						|
  } else if (mode == TRIE_PRINT_FLOAT2) {
 | 
						|
    volatile union {
 | 
						|
      double f;
 | 
						|
      YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
    } tf;  /* to avoid gcc warning */
 | 
						|
    tf.p[1] = t;
 | 
						|
    tf.p[0] = (YAP_Term) arity[arity[0]];
 | 
						|
    arity[arity[0]] = -1;
 | 
						|
#else /* TAG_64BITS */
 | 
						|
    volatile union {
 | 
						|
      double f;
 | 
						|
      YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
    } tf;  /* to avoid gcc warning */
 | 
						|
    tf.p[0] = t;
 | 
						|
#endif /* TAG_SCHEME */
 | 
						|
    str_index += sprintf(& str[str_index], "%.15g", tf.f);
 | 
						|
    mode = TRIE_PRINT_FLOAT_END;
 | 
						|
  } else if (mode == TRIE_PRINT_FLOAT_END) {
 | 
						|
    arity[0]--;
 | 
						|
    while (arity[0]) {
 | 
						|
      if (arity[arity[0]] == 1) {
 | 
						|
	str_index += sprintf(& str[str_index], ")");
 | 
						|
	arity[0]--;
 | 
						|
      } else {
 | 
						|
	if (arity[arity[0]] > 1)
 | 
						|
	  arity[arity[0]]--;
 | 
						|
	str_index += sprintf(& str[str_index], ",");
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    mode = TRIE_PRINT_NORMAL;
 | 
						|
  } else if (YAP_IsVarTerm(t)) {
 | 
						|
    str_index += sprintf(& str[str_index], "VAR%ld", TrieVarIndex(t));
 | 
						|
    while (arity[0]) {
 | 
						|
      if (arity[arity[0]] == 1) {
 | 
						|
	str_index += sprintf(& str[str_index], ")");
 | 
						|
	arity[0]--;
 | 
						|
      } else {
 | 
						|
	if (arity[arity[0]] > 1)
 | 
						|
	  arity[arity[0]]--;
 | 
						|
	str_index += sprintf(& str[str_index], ",");
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (YAP_IsAtomTerm(t)) {
 | 
						|
    str_index += sprintf(& str[str_index], "%s", YAP_AtomName(YAP_AtomOfTerm(t)));
 | 
						|
    while (arity[0]) {
 | 
						|
      if (arity[arity[0]] == 1) {
 | 
						|
	str_index += sprintf(& str[str_index], ")");
 | 
						|
	arity[0]--;
 | 
						|
      } else {
 | 
						|
	if (arity[arity[0]] > 1)
 | 
						|
	  arity[arity[0]]--;
 | 
						|
	str_index += sprintf(& str[str_index], ",");
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (YAP_IsIntTerm(t)) {
 | 
						|
    str_index += sprintf(& str[str_index], "%ld", YAP_IntOfTerm(t));
 | 
						|
    while (arity[0]) {
 | 
						|
      if (arity[arity[0]] == 1) {
 | 
						|
	str_index += sprintf(& str[str_index], ")");
 | 
						|
	arity[0]--;
 | 
						|
      } else {
 | 
						|
	if (arity[arity[0]] > 1)
 | 
						|
	  arity[arity[0]]--;
 | 
						|
	str_index += sprintf(& str[str_index], ",");
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (YAP_IsPairTerm(t)) {
 | 
						|
    if (t == FloatInitTag) {
 | 
						|
      mode = TRIE_PRINT_FLOAT;
 | 
						|
      arity[0]++;
 | 
						|
      arity[arity[0]] = -1;
 | 
						|
    } else if (t == PairInitTag) {
 | 
						|
      str_index += sprintf(& str[str_index], "[");
 | 
						|
      arity[0]++;
 | 
						|
      arity[arity[0]] = -1;
 | 
						|
    } else if (t == CommaInitTag) {
 | 
						|
      str_index += sprintf(& str[str_index], "(");
 | 
						|
      arity[0]++;
 | 
						|
      arity[arity[0]] = -1;
 | 
						|
    } else {
 | 
						|
      if (t == PairEndEmptyTag)
 | 
						|
	str[str_index - 1] = ']';
 | 
						|
      else if (t == PairEndTermTag) {
 | 
						|
	str[last_pair_mark] = '|';
 | 
						|
	str[str_index - 1] = ']';
 | 
						|
      } else /*   (t == CommaEndTag)   */
 | 
						|
	str[str_index - 1] = ')';
 | 
						|
      arity[0]--;
 | 
						|
      while (arity[0]) {
 | 
						|
	if (arity[arity[0]] == 1) {
 | 
						|
	  str_index += sprintf(& str[str_index], ")");
 | 
						|
	  arity[0]--;
 | 
						|
	} else {
 | 
						|
	  if (arity[arity[0]] > 1)
 | 
						|
	    arity[arity[0]]--;
 | 
						|
	  str_index += sprintf(& str[str_index], ",");
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (ApplTag & t) {
 | 
						|
    str_index += sprintf(& str[str_index], "%s(", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & t))));
 | 
						|
    arity[0]++;
 | 
						|
    arity[arity[0]] = YAP_ArityOfFunctor((YAP_Functor)(~ApplTag & t));
 | 
						|
  } else {
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fprintf(stderr, "  Tries core module: unknown type tag\n");
 | 
						|
    fprintf(stderr, "***************************************\n");
 | 
						|
    fflush(stderr);
 | 
						|
  }
 | 
						|
 | 
						|
  if (arity[0]) {
 | 
						|
    traverse_and_print(TrNode_child(node), arity, str, str_index, mode);
 | 
						|
  } else {
 | 
						|
    str[str_index] = 0;
 | 
						|
    fprintf(stdout, "%s\n", str);
 | 
						|
    if (DATA_PRINT_FUNCTION)
 | 
						|
      (*DATA_PRINT_FUNCTION)(node);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list(TrNode node) {
 | 
						|
  YAP_Term tail = YAP_MkAtomTerm(YAP_LookupAtom("[]"));
 | 
						|
 | 
						|
#define CONSUME_NODE_LIST                                  \
 | 
						|
  do {                                                     \
 | 
						|
    /* add node result to list */                          \
 | 
						|
    tail = YAP_MkPairTerm(trie_to_list_node(node), tail);  \
 | 
						|
  } while((node = TrNode_next(node)));
 | 
						|
  
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash = (TrHash) node;
 | 
						|
    
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    
 | 
						|
    /* iterate through valid hash positions and consume each list */
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        CONSUME_NODE_LIST;
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
  } else {
 | 
						|
    CONSUME_NODE_LIST;
 | 
						|
  }  
 | 
						|
#undef CONSUME_NODE_LIST
 | 
						|
 | 
						|
  /* return list of trie options at this level */
 | 
						|
  return tail;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list_node(TrNode node) {
 | 
						|
  YAP_Term t = TrNode_entry(node);
 | 
						|
  
 | 
						|
  if(YAP_IsIntTerm(t) || YAP_IsAtomTerm(t)) {
 | 
						|
    return trie_to_list_create_two(YAP_IsIntTerm(t) ? "int" : "atom", node, t);
 | 
						|
  } else if (YAP_IsVarTerm(t)) {
 | 
						|
    int index = TrieVarIndex(t);
 | 
						|
    YAP_Term index_term = YAP_MkIntTerm((YAP_Int)index);
 | 
						|
    return trie_to_list_create_two("var", node, index_term);
 | 
						|
  } else if (YAP_IsPairTerm(t)) {
 | 
						|
    if(t == FloatInitTag) {
 | 
						|
      node = TrNode_child(node); /* consume FloatInitTag */      
 | 
						|
      YAP_Functor f = YAP_MkFunctor(YAP_LookupAtom("floats"), 1);
 | 
						|
      YAP_Term child = trie_to_list_floats(node);
 | 
						|
      return YAP_MkApplTerm(f, 1, &child);
 | 
						|
    } else if(t == PairInitTag) {
 | 
						|
      return trie_to_list_create_simple("list", node);
 | 
						|
    } else if (t == PairEndEmptyTag) {
 | 
						|
      return trie_to_list_create_simple_end("endlist", node);
 | 
						|
    } else if (t == CommaInitTag) {
 | 
						|
      return trie_to_list_create_simple("comma", node);
 | 
						|
    } else if (t == CommaEndTag) {
 | 
						|
      return trie_to_list_create_simple_end("endcomma", node);
 | 
						|
    }
 | 
						|
  } else if (ApplTag & t) {
 | 
						|
    YAP_Functor f = (YAP_Functor)(~ApplTag & t);
 | 
						|
    int arity = YAP_ArityOfFunctor(f);
 | 
						|
    YAP_Functor new_f = YAP_MkFunctor(YAP_LookupAtom("functor"), 3);
 | 
						|
    YAP_Term args[3] = {
 | 
						|
      YAP_MkAtomTerm(YAP_NameOfFunctor(f)),
 | 
						|
      YAP_MkIntTerm((YAP_Int)arity),
 | 
						|
      trie_to_list(TrNode_child(node))
 | 
						|
    };
 | 
						|
    return YAP_MkApplTerm(new_f, 3, args);
 | 
						|
  }
 | 
						|
  fprintf(stderr, "***************************************\n");
 | 
						|
  fprintf(stderr, "  Tries core module: unknown type tag\n");
 | 
						|
  fprintf(stderr, "***************************************\n");
 | 
						|
  fflush(stderr);
 | 
						|
  
 | 
						|
  return YAP_MkAtomTerm(YAP_LookupAtom("fail"));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#define PUSH_NEW_FLOAT_TERM(val)                                                     \
 | 
						|
        result = YAP_MkPairTerm(                                                     \
 | 
						|
        trie_to_list_create_two("float", TrNode_child(node), YAP_MkFloatTerm(val)),  \
 | 
						|
        result);
 | 
						|
 | 
						|
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
 | 
						|
YAP_Term trie_to_list_floats_tag_low_32(YAP_Term result, TrNode node, volatile YAP_Term *p, volatile double *f) {
 | 
						|
  if(IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash = (TrHash) node;
 | 
						|
    
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    
 | 
						|
    do {
 | 
						|
      if(*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        do {
 | 
						|
          p[1] = TrNode_entry(node);
 | 
						|
          PUSH_NEW_FLOAT_TERM(*f);
 | 
						|
        } while((node = TrNode_next(node)));
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
  } else {
 | 
						|
    do {
 | 
						|
      p[1] = TrNode_entry(node);
 | 
						|
      PUSH_NEW_FLOAT_TERM(*f);
 | 
						|
    } while((node = TrNode_next(node)));
 | 
						|
  }
 | 
						|
  
 | 
						|
  return result;
 | 
						|
}
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
 | 
						|
 | 
						|
static
 | 
						|
YAP_Term trie_to_list_floats(TrNode node) {
 | 
						|
  volatile union {
 | 
						|
    double f;
 | 
						|
    YAP_Term p[SIZE_FLOAT_AS_TERM];
 | 
						|
  } tf;  /* to avoid gcc warning */
 | 
						|
  YAP_Term result = YAP_MkAtomTerm(YAP_LookupAtom("[]"));
 | 
						|
 | 
						|
  if (IS_HASH_NODE(node)) {
 | 
						|
    TrNode *first_bucket, *bucket;
 | 
						|
    TrHash hash = (TrHash) node;    
 | 
						|
    first_bucket = TrHash_buckets(hash);
 | 
						|
    bucket = first_bucket + TrHash_num_buckets(hash);
 | 
						|
    do {
 | 
						|
      if (*--bucket) {
 | 
						|
        node = *bucket;
 | 
						|
        do {
 | 
						|
          tf.p[0] = TrNode_entry(node);
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
          result = trie_to_list_floats_tag_low_32(result, TrNode_child(node), &tf.p, &tf.f);
 | 
						|
#else
 | 
						|
          PUSH_NEW_FLOAT_TERM(tf.f);
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
        } while((node = TrNode_next(node)));
 | 
						|
      }
 | 
						|
    } while (bucket != first_bucket);
 | 
						|
  } else {
 | 
						|
    do {
 | 
						|
      tf.p[0] = TrNode_entry(node);
 | 
						|
#ifdef TAG_LOW_BITS_32
 | 
						|
      result = trie_to_list_floats_tag_low_32(result, TrNode_child(node), &tf.p, &tf.f);
 | 
						|
#else
 | 
						|
      PUSH_NEW_FLOAT_TERM(tf.f);
 | 
						|
#endif /* TAG_LOW_BITS_32 */
 | 
						|
    } while((node = TrNode_next(node)));
 | 
						|
  }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
#undef PUSH_NEW_FLOAT_TERM
 | 
						|
 | 
						|
 | 
						|
#include "core_dbtries.c"
 |