From raghu@ricotta.cs.wisc.edu Fri Jul  9 10:50:17 1993
Received: from ricotta.cs.wisc.edu by quarg.cs.wisc.edu; Fri, 9 Jul 93 10:49:45 -0500
Date: Fri, 9 Jul 93 10:49:21 -0500
From: raghu@ricotta.cs.wisc.edu (Raghu Ramakrishnan)
Message-Id: <9307091549.AA03129@ricotta.cs.wisc.edu>
Received: by ricotta.cs.wisc.edu; Fri, 9 Jul 93 10:49:21 -0500
To: praveen@ricotta.cs.wisc.edu
Subject: coral
Status: RO


first, i can't run it on ricotta (changeover, i guess).  could you
recomplile it please?

second, i can't run it off quarg either.  when i did run it on the foll pgm,
i got an empty .M file.  also, complaints about fileserver ricotta ...

third, following program (from reps) is odd:

module lookup.
  export lookup(ff).

  lookup(X, [X|_]).
  lookup(X, [_|T]) :- lookup(X, T).
end_module.

?lookup(X,[g(a),f(b)]).



Raghu,

Is it a bug that only one answer is reported by the code given below?
Two answers are reported if lookup is declared as "lookup(fb)".

Tom




From raghu@ricotta.cs.wisc.edu Tue Jul 13 14:06:44 1993
Received: from ricotta.cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 14:06:43 -0500
Date: Tue, 13 Jul 93 14:06:42 -0500
From: raghu@ricotta.cs.wisc.edu (Raghu Ramakrishnan)
Message-Id: <9307131906.AA13244@ricotta.cs.wisc.edu>
Received: by ricotta.cs.wisc.edu; Tue, 13 Jul 93 14:06:42 -0500
To: divesh@ricotta.cs.wisc.edu, praveen@ricotta.cs.wisc.edu,
        sudarsha@ricotta.cs.wisc.edu
Subject: bug in subsumption checking
Status: R


tom reps sent the following program.  it generates just g(a) as
an answer, which is a buug, and the reason is a bug
in subs checking:


/**************

Date: Thu, 8 Jul 93 23:18:46 -0500
From: reps@york.cs.wisc.edu (Tom Reps)
To: raghu@york.cs.wisc.edu
Subject: Bug?

Raghu,

Is it a bug that only one answer is reported by the code given below?
Two answers are reported if lookup is declared as "lookup(fb)".

Tom

=== lookup.P ==============================================================

**********/

module lookup.
  export lookup(ff).

  lookup(X, [X|_]).
  lookup(X, [_|T]) :- lookup(X, T).
end_module.

/************

?lookup(X,[g(a),f(b)]).

=====================================================================

1:>consult(lookup.P).
CORAL::Warning : Using underbound method 00 for lookup 01!
X=g(a).
        ... next answer ? (y/n/all)[y](Number of Answers = 1)
2:>

***********/


[Starting to insert lookup(X,[X|_]) - done (env-size:2)]
[Starting to insert lookup(_X0,[_X2,_X0|_X1]) - subsumed]


From sudarsha@research.att.com Tue Jul 13 17:26:23 1993
Received: from cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 17:26:22 -0500
Message-Id: <9307132226.AA20696@cs.wisc.edu>
Received: from research.att.com by cs.wisc.edu; Tue, 13 Jul 93 17:26:11 -0500
Received: by inet; Tue Jul 13 18:25 EDT 1993
From: sudarsha@research.att.com (S. Sudarshan)
Date: Tue, 13 Jul 1993 18:25:18 EDT
X-Mailer: Mail User's Shell (7.1.1 5/02/90)
To: divesh
Subject: FPE!
Cc: raghu, praveen
Status: R


I fixed the bug raghu mailed out, and guess what?  I now get a floating 
point exception!! I've no idea yet where the exception is coming from!

Sudarshan

From sudarsha@research.att.com Tue Jul 13 21:33:13 1993
Received: from cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 21:33:13 -0500
Message-Id: <9307140233.AA22295@cs.wisc.edu>
Received: from research.att.com by cs.wisc.edu; Tue, 13 Jul 93 21:33:03 -0500
Received: by inet; Tue Jul 13 22:32 EDT 1993
From: sudarsha@research.att.com (S. Sudarshan)
Date: Tue, 13 Jul 1993 22:32:09 EDT
X-Mailer: Mail User's Shell (7.1.1 5/02/90)
To: raghu (Raghu Ramakrishnan)
Subject: Re: bug in subsumption checking
Cc: praveen, divesh
Status: R

Your bug fixed (here, not in wisconsin).

I found what was causing the floating point exception -- a very silly bug
introduced when Praveen (or whoever) changed the hashcons hash table
representation to make it more efficient.  Now the first program you sent
works (i.e., produces two answers and loops generating an infinite number
of intermediate facts, as it should).

Sudarshan

From sudarsha@research.att.com Tue Jul 13 21:42:05 1993
Received: from cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 21:42:04 -0500
Message-Id: <9307140242.AA22352@cs.wisc.edu>
Received: from research.att.com by cs.wisc.edu; Tue, 13 Jul 93 21:42:02 -0500
Received: by inet; Tue Jul 13 22:41 EDT 1993
From: sudarsha@research.att.com (S. Sudarshan)
Date: Tue, 13 Jul 1993 22:41:42 EDT
X-Mailer: Mail User's Shell (7.1.1 5/02/90)
To: divesh, raghu, praveen, reps
Subject: Tom Reps' message forwarded by Divesh
Cc: sudarsha@allegra.att.com
Status: R


Both versions of transitive closure meta-interpreted program work correctly
on my copy of the interpreter after fixing a small bug.  Seems to be
the same bug that caused subsumption problems with the other program that 
Tom Reps sent Raghu.

I will send the bug corrections to Divesh, and he will let you know
when he finishes installing them.  Please let me know if you have any
further problems with the code that deals with non-ground facts -- the
code has not been stress tested and Tom/Manuvir may be the first major
users of the code.  

Sudarshan

From sudarsha@research.att.com Tue Jul 13 21:51:04 1993
Received: from cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 21:51:03 -0500
Message-Id: <9307140251.AA22414@cs.wisc.edu>
Received: from research.att.com by cs.wisc.edu; Tue, 13 Jul 93 21:51:02 -0500
Received: by inet; Tue Jul 13 22:49 EDT 1993
Date: Tue, 13 Jul 93 22:49:21 EDT
From: sudarsha@research.att.com (S. Sudarshan)
To: divesh
Subject: bug fix 2
Cc: praveen
Status: R


Here is a new class definition for CoreHashTable (hashtable.h)
The only change is in the defaults for incr_ratio and max_occupancy.
They were both -1 earlier -- I have no idea why.  Praveen, I think
you wrote the code.  The constructor of the hash_cons_table in arg.C
was not changed and used the defaults, which resulted in a floating point
exception, of all errors!

Sudarshan
---------------------------

class CoreHashTable: public GenericHashTable{

        HashEntry *table;

        public:

        CoreHashTable(EqualsFn eqf1, int initsize1=128,
                double incr_ratio1 = 1.0, double max_occupancy1 = 1.0);
        inline void rehash_if_needed() {
                if (cur_size > limit) rehash_bigger();
                }

        virtual void *insert(void *entry, int hashval, int& to_delete);
        void *insert(void *entry, int hashval) {
           int to_delete = 0;
           return insert(entry, hashval, to_delete);
        }
        virtual void *lookup(void *entry, int hashval);
        void rehash_bigger();
};

From sudarsha@research.att.com Tue Jul 13 21:55:10 1993
Received: from cs.wisc.edu by quarg.cs.wisc.edu; Tue, 13 Jul 93 21:55:08 -0500
Message-Id: <9307140255.AA22445@cs.wisc.edu>
Received: from research.att.com by cs.wisc.edu; Tue, 13 Jul 93 21:55:04 -0500
Received: by inet; Tue Jul 13 22:53 EDT 1993
Date: Tue, 13 Jul 93 22:53:48 EDT
From: sudarsha@research.att.com (S. Sudarshan)
To: divesh, praveen
Subject: possible fix 3
Status: R


I think that unknown errors should cause a core dump so we know
where the system was when the error occurred.
I made the following changes to the procs in util.C.  The changes
may need to be polished up.

I've tagged my changes with a comment starting with - SS: ... 

Sudarshan
-------------------------

void exceptionHandler(int recvd_signal)
{
  CORAL_error(COR_SIGNAL_RECEIVED,NULL,NULL) ;

  fprintf(exEnv.error_file, "Received signal no: %d\n", recvd_signal);
  /*
   * Code for recovering from abnormal situation
   */

  if (recvd_signal != SIGINT) {
    fprintf(exEnv.error_file, "Cannot recover from received signal\n");
    fprintf(exEnv.error_file, "Initiating shutdown procedures\n");

#ifdef WITH_PERSISTENCE
  abortTrans();
#endif
    abort(); // SS: Added Jul 13, 93
    exit_coral();
    exit(1);
  }	

  exEnv.C_interrupt_raised = 1;


}


 /*-------------------------------------------------------------------*/

void init_coral(char *pgm)
{

/***************  SS: Commented out (Jul 13, 93)
  #ifndef DEBUG
  // Catch signals that might otherwise cause termination
  for (int i = SIGINT; i < SIGPIPE; i++)
    if (i != SIGKILL && i != SIGABRT)
      signal(i, (SIG_TYP)(exceptionHandler)) ;

#else
*************/

  // for debugging purposes, catch only SIGINT (CTRL-C)
  signal(SIGINT, (SIG_TYP)(exceptionHandler)) ;

/******
#endif
*****/

  // Provide exception handler for new()
  set_new_handler( freeStoreException) ;

  // initialize the module table stack
  TableStack = new TablePtr[exEnv.C_max_recursion_depth_default];
  TableStackCount = 0;

  strcpy(coral_name, (pgm ? pgm : "coral"));

  if (exEnv.C_exec_mode == COR_DOING_INTERPRET) {
    /** Tarun **/
    /* Create debug directory */
    if (fulldir("dump_directory") != -1)
      system("rm -rf dump_directory");   /* hack cause unlink */
    /* doesn't work */
    mkdir("dump_directory", 00755 ); /* set permission to 755 */
  }


  if ((exEnv.C_exec_mode == COR_DOING_INTERPRET) ||
      (exEnv.C_exec_mode == COR_DOING_IMPERATIVE)){
    
    // initialize global stats for CPU and memory usage
    getrusage(RUSAGE_SELF, &startRUsage);
    startMemUsage = (int)sbrk(0);

#ifdef WITH_PERSISTENCE
    // Set up buffers for persistence (to be impl)
    sm_init();
#endif

    // remove the stdin.M file
    unlink("stdin.M");


    // Initialize builtin database.
    initBuiltins();
    CurDB = &BuiltinDB;

    // Add builtin database to the Database Table
    if (!addDBStruct(CurDB)) {
      CORAL_error(COR_MULTIPLE_DB_ERR, "unable to add builtin DB",
		  "init-coral");
      exit(1);
    }

    // Create default database
    DatabaseStruct *db = createDB(EnterSymbol("default_db"));
    if (!db) {
      CORAL_error(COR_MULTIPLE_DB_ERR, "unable to add default DB",
		  "init-coral");
      exit(1);
    }
    CurDB = db ;

    if (exEnv.C_exec_mode == COR_DOING_INTERPRET) {
      // Read .coralrc if it exists, else read input from $(HOME)/.coralrc
      if (!consultFile(".coralrc", ".coralrc")) {
	char *home_path = getenv("HOME") ;
	char *tmp_name = new char[strlen(home_path) + 15] ;
	strcpy(tmp_name, home_path);
	strcat(tmp_name, "/.coralrc");
	consultFile(tmp_name, tmp_name) ;
	delete [] tmp_name ;
      }
    }

  }
  getrusage(RUSAGE_SELF, &SystemUsage);
  beginMem = (int)sbrk(0);
}

/*------------------------------------------------------------------
 Function Behaviour :: Called when quitting coral

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void exit_coral()
{
    if (exEnv.C_exec_mode == COR_DOING_INTERPRET) {
      /** Tarun **/
      /* delete dump directory if empty */
      if (fulldir("dump_directory") == 2)
	system("rm -rf dump_directory"); /* hack cause unlink */
      /* doesn't work! */
    }
    
#ifdef WITH_PERSISTENCE
    if (exEnv.C_exec_mode == COR_DOING_INTERPRET) {
	shutdown_server();
    }
#endif

/*
    if ((exEnv.trace_file) && (exEnv.trace_file != exEnv.error_file))
	 fclose((exEnv.trace_file)) ;

    if ((exEnv.print_file) && (exEnv.print_file != stdout))
	 fclose((exEnv.print_file)) ;

    if ((exEnv.output_file) && (exEnv.output_file != stdout))
	 fclose((exEnv.output_file)) ;
*/
    if ((exEnv.trace_file) && (exEnv.trace_file != stdout)
	&& (exEnv.trace_file != stderr))
      fclose((exEnv.trace_file)) ;

    if ((exEnv.print_file) && (exEnv.print_file != stdout)
	&& (exEnv.print_file != stderr))
      fclose((exEnv.print_file)) ;

    if ((exEnv.output_file) && (exEnv.output_file != stdout)
	&& (exEnv.output_file != stderr))
      fclose((exEnv.output_file)) ;

    if ((exEnv.error_file) && (exEnv.error_file != stdout)
	&& (exEnv.error_file != stderr))
      fclose((exEnv.error_file)) ;
}

/***** Methods for classes declared in globals.h **********/
/*------------------------------------------------------------------
 ExecutionEnv::display(FILE *outf)
 -------------------------------------------------------------------*/
void ExecutionEnv::display(FILE *outf)
{

  fprintf(outf, "\tmode :\t\t\t");
  switch(C_exec_mode) {
  case COR_DOING_INTERPRET : fprintf(outf, "INTERPRETER\n"); break ;
  case COR_DOING_COMPILE : fprintf(outf, "COMPILER\n"); break ;
  case COR_DOING_MAGIC : fprintf(outf, "MAGIC Rewriting\n"); break ;
  case COR_DOING_FACTOR : fprintf(outf, "FACTOR Rewriting\n"); break ;
  case COR_DOING_EXIST : fprintf(outf, "Existential Query Optimization\n"); break ;
  case COR_DOING_IMPERATIVE : fprintf(outf, "Imperative module\n"); break;
  }

  fprintf(outf, "\tinsert_mode : \t\t%s\n",
	  (C_insert_mode_default) ? "on" : "off");
  fprintf(outf, "\tquiet_mode : \t\t%s\n",
	  (C_quiet_mode_default) ? "on" : "off");

  fprintf(outf,"--- Defaults for Rewriting ---\n\n");

  fprintf(outf, "\trewriting : \t\t%s\n",
	  (C_rewriting_default) ? "on" : "off");
  fprintf(outf, "\tsup_magic :\t\t%s\n",
	  (C_use_supplementary_magic_default) ? "on" : "off");
  fprintf(outf, "\tmagic :\t\t\t%s\n",
	  (C_use_magic_default) ? "on" : "off");
  fprintf(outf, "\tsup_magic_indexing :\t%s\n",
	  (C_sup_magic_indexing_default) ? "on" : "off");
  fprintf(outf, "\texistential : \t\t%s\n",
	  (C_use_exist_opt_default) ? "on" : "off");
  fprintf(outf, "\tfactoring : \t\t%s\n\n",
	  (C_use_factoring_default) ? "on" : "off");

  fprintf(outf,"--- Defaults for Execution ---\n\n");

  fprintf(outf, "\tinteractive_mode :\t%s\n",
	  (C_interactive_mode_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t\t%s\n", SymbolString(PredicateSNSymbol),
	  (C_use_predicate_sn_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(UsePipeliningSymbol),
	  (C_use_pipelining_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t%s\n", SymbolString(UseOrdSearchSymbol),
	  (C_use_ordsearch_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(EagerEvalSymbol),
	  (C_use_eager_eval_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(SaveModuleSymbol),
	  (C_save_module_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(MonotonicSymbol),
	  (C_use_monotonic_default) ? "on" : "off");

  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(MultisetSymbol),
	  (C_multisets_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t%s\n", SymbolString(CheckSubsumSymbol),
	  (C_check_subsum_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(IndexDeltaSymbol),
	  (C_index_deltas_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(ReturnUnifySymbol),
	  (C_use_return_unify_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t%s\n", SymbolString(NonGroundFactsSymbol),
	  (C_non_ground_facts_default) ? "on" : "off");

  fprintf(outf, "\n--- Defaults for Output ---\n");
  fprintf(outf, "\tprint_file :\t\t%s\n", print_filename);
  fprintf(outf, "\toutput_file :\t\t%s\n", output_filename);
  fprintf(outf, "\ttrace_file :\t\t%s\n", trace_filename);
  fprintf(outf, "\ttracing :\t\t%s\n",
	 (exEnv.GlobalRelationOptions & REL_DISPLAY_INSERTIONS) ? "on" : "off");
  fprintf(outf, "\tprofiling :\t\t%s\n",
	 (exEnv.GlobalRelationOptions & REL_PROFILE_STATS) ? "on" : "off");
  fprintf(outf, "\texplain :\t\t%s\n",
	 (exEnv.GlobalRelationOptions & REL_EXPLAIN) ? "on" : "off");

  fprintf(outf, "\n--- Defaults for Profiling ---\n");
  fprintf(outf, "\tprofile_module :\t%s\n",
	  (profile_module) ? "on" : "off");
  fprintf(outf, "\tprofile_scc :\t\t%s\n",
	  (profile_scc) ? "on" : "off");
  fprintf(outf, "\tprofile_sn :\t\t%s\n",
	  (profile_sn) ? "on" : "off");

#ifdef DEBUG
  fprintf(outf, "\n--- Defaults at System Level ---\n");

  fprintf(outf, "\tpreprocessing : \t%s\n",
	  (C_preprocessing_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t\t%s\n", SymbolString(SingleSccSymbol),
	  (C_single_scc_default) ? "on" : "off");
  fprintf(outf, "\t%s :\t%s\n", SymbolString(ConvertFunctionsSymbol),
	  (C_convert_functions_default) ? "on" : "off");

  fprintf(outf, "\n--- Defaults for System Debugging ---\n");
  fprintf(outf, "\tdebug_unify :\t\t%s\n",
	  (dbg_unify) ? "on" : "off");
  fprintf(outf, "\tdebug_subsumes :\t%s\n",
	  (dbg_subsumes) ? "on" : "off");
  fprintf(outf, "\tdebug_indexing :\t%s\n",
	  (dbg_indexing) ? "on" : "off");
  fprintf(outf, "\tdebug_aggregates :\t%s\n",
	  (dbg_aggregates) ? "on" : "off");
  fprintf(outf, "\tdebug_sets :\t\t%s\n",
	  (dbg_sets) ? "on" : "off");
  fprintf(outf, "\tdebug_get_next :\t%s\n",
	  (dbg_get_next) ? "on" : "off");
  fprintf(outf, "\tdebug_ordered_search :\t%s\n",
	  (dbg_ordsearch) ? "on" : "off");


  fprintf(outf, "\n--- Defaults for System Tuning ---\n");
  fprintf(outf, "\thash_buckets :\t\t%d\n",C_hash_buckets_default);
  fprintf(outf, "\tdelta_buckets :\t\t%d\n", C_delta_buckets_default);
  fprintf(outf, "\tincr_ratio :\t\t%f\n",C_incr_ratio_default);
  fprintf(outf, "\tmax_occupancy :\t\t%f\n",C_max_occupancy_default);
  fprintf(outf, "\trecursion_depth :\t%d\n", C_max_recursion_depth_default);
#endif 
}

void ExecutionEnv::init()
{
  C_at_end_module = 1;
  C_exec_mode = COR_DOING_INTERPRET ;
  history = new History(MAX_HISTORY_DEPTH);
  C_insert_mode_default = COR_INSERT_MODE_DEFAULT;
  C_quiet_mode_default = 0;
  GlobalRelationOptions = 0;
  dbg_unify= dbg_subsumes= dbg_indexing= dbg_aggregates= dbg_get_next= 0;
  dbg_sets=0;
  dbg_ordsearch=0;
  C_hash_buckets_default = COR_DEFAULT_INDEX_BUCKETS;
  C_delta_buckets_default = COR_DEFAULT_DELTA_BUCKETS;
  C_incr_ratio_default = COR_INDEX_INCR_RATIO;
  C_max_occupancy_default = COR_INDEX_OCCUPANCY;
  C_max_recursion_depth_default = COR_MAX_RECURSION_DEPTH;
  
  profile_sn = COR_PROFILE_SN_DEFAULT;
  profile_scc = COR_PROFILE_SN_DEFAULT;
  profile_module = COR_PROFILE_MODULE_DEFAULT;
  trace_file = stderr;
  trace_filename = "stderr";
  print_file = stdout;
  print_filename = "stdout";
  output_file = stdout;
  output_filename = "stdout";
  
  /*
   * profile_file hasn't been handled yet. for now it is the same as
   * trace_file. also, havent got around to changing all occurrences
   * of exEnv.error_file to exEnv.error_file, but I will some day -- Praveen
   */
  error_file = stderr;
  error_filename = "stderr";
  profile_file = trace_file ;
  profile_filename = trace_filename ;
  
  C_preprocessing_default = COR_PREPROCESSING_DEFAULT;
  C_rewriting_default = COR_REWRITING_DEFAULT;
  C_save_module_default = COR_SAVE_MODULE_DEFAULT;
  C_use_supplementary_magic_default = COR_USE_SUPPLEMENTARY_MAGIC_DEFAULT ;
  C_use_magic_default = COR_USE_MAGIC_DEFAULT;
  C_sup_magic_indexing_default = COR_USE_SUP_MAGIC_INDEXING_DEFAULT;
  C_check_subsum_default = COR_CHECK_SUBSUM_DEFAULT;
  C_single_scc_default = COR_SINGLE_SCC_DEFAULT;
  C_convert_functions_default = COR_CONVERT_FUNCTIONS_DEFAULT;
  C_index_deltas_default = COR_INDEX_DELTA_DEFAULT;
  C_use_factor_magic_default = COR_USE_FACTOR_MAGIC_DEFAULT;
  C_use_return_unify_default = COR_USE_RETURN_UNIFY_DEFAULT;
  C_use_pipelining_default = COR_USE_PIPELINING_DEFAULT;
  C_use_ordsearch_default = COR_USE_ORDSEARCH_DEFAULT;
  C_use_eager_eval_default = COR_USE_EAGER_EVAL_DEFAULT;
  C_use_monotonic_default = COR_USE_MONOTONIC_DEFAULT;
  C_interactive_mode_default = COR_INTERACTIVE_MODE_DEFAULT;
  C_use_exist_opt_default = COR_USE_EXIST_OPT_DEFAULT;
  C_use_factoring_default = COR_USE_FACTORING_DEFAULT;
  C_use_predicate_sn_default = COR_USE_PREDICATE_SEMINAIVE_DEFAULT;
  C_non_ground_facts_default = COR_NON_GROUND_FACTS_DEFAULT;
  
  stackmark = new StackMark ;
  exEnv.coral_path = getenv("CORALROOT");
  if (!exEnv.coral_path) {
#ifdef CORALROOT
    exEnv.coral_path = CORALROOT;
#else
    fprintf(error_file, " Warning ! CORALROOT not set in environment !\n");
    exEnv.coral_path = DEFAULT_CORAL_PATH;
    fprintf(error_file, " Using %s\n", DEFAULT_CORAL_PATH);
#endif

  }

  C_interrupt_raised = 0;
}

void ParserStruct::init()
{
   // Many of these may need to have destructors called on them
   AllPredicates = NULL ;
   Predicates = NULL ;
   rule_list = NULL ;
   init_collection(rules,1) ;
   make_index_annotations = NULL ;
   agg_sel_annotations = NULL;
   prioritize_annotations = NULL;
   AllowedAdornList = NULL ;
   DisallowedAdornList = NULL ;
   MultisetAnnotations = NULL ;
   PredicateTable = NULL ;
   CurModule.init();
   func_setup = 0;
   cur_arg_chain = NULL;
   parameters = new parameter_chain;
   cur_set = NULL;
   lhs_flag = 0;
   nested_index = 0;
   cur_rule = NULL;
}

History::History(int size)
{
  commands = new char* [size];
  counts   = new int [size];
  for (int i = 0; i < size; i++) {
    commands[i] = NULL;
    counts[i] = 0;
  }
  array_size = size;
  cur_pos = 0;
}

History::History()
{
  array_size = MAX_HISTORY_DEPTH;
  commands = new char* [array_size];
  counts   = new int [array_size];
  for (int i = 0; i < array_size; i++) {
    commands[i] = NULL;
    counts[i] = 0;
  }
  cur_pos = 0;
}

void History::addCommand(char *newcommand, int current_count)
{
  if (commands[cur_pos]) delete (commands[cur_pos]);

  commands[cur_pos] = new char[strlen(newcommand) + 1];
  strcpy(commands[cur_pos], newcommand);
  counts[cur_pos] = current_count;
  if ((cur_pos++) >= array_size) cur_pos  = 0;
}

char * History::getCommand(int desired_count)
{
  for (int i = 0; i < array_size; i++) {
    if (counts[i] == desired_count)
      return commands[i];
  }
  return NULL;
}

void History::display(FILE *outf)
{
  int i;
  fprintf(outf, "  Command History\n");
  for (i = cur_pos; i < array_size; i++)
    {
      if (commands[i]) fprintf(outf, "  %d : %s\n", counts[i], commands[i]);
    }
  for (i = 0; i < cur_pos; i++)
    {
      if (commands[i]) fprintf(outf, "  %d : %s\n", counts[i], commands[i]);
    }
  fprintf(outf, "\n");
}

/*------------------------------------------------------------------
 Function Behaviour :: Initializes a collection of rules, and provides
 it with a hash table

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void init_collection(struct collection *collection, int hashable)
{
    collection->chain = NULL;
    collection->lastptr = &collection->chain;
    collection->count = 0;
    collection->hashable = hashable;
    if (hashable)
	InitTab(collection->tab, 20, NULL);
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void alloc_preds(struct rule *rule, int count)
{
    rule->num_preds = count;
    rule->preds = (Literal**)malloc(count * sizeof(Literal*));
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
#ifdef DEBUG
static void check_collection(struct collection *collection)
{
    Link *link, **lptr;
    Name name = NULL;
    int count = 0, diff_count = 0;
    lptr = &collection->chain;
    for ( ; *lptr != NULL; lptr = &(*lptr)->next) {
	if (lptr != (*lptr)->prevptr) abort();
	count++;
	if ((*lptr)->name != name) diff_count++;
	name = (*lptr)->name;
	if (collection->hashable) {
	    Association *hptr = SymbolLookup(collection->tab, (*lptr)->name);
	    if (HashNone(hptr->arg)) abort();
	    for (link= (Link*)hptr->val; link != *lptr; link = link->next)
		if (link == NULL || link->name != (*lptr)->name) abort();
	}
    }
    if (lptr != collection->lastptr) abort();

    if (count != collection->count) abort();
    if (collection->hashable && collection->tab->cur_size != diff_count)
	abort();
}
#endif

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void add_member(Link *member, struct collection *collection)
{
    if (collection->hashable) {
	Association *ptr = SymbolLookup(collection->tab, member->name);
	if (HashNone(ptr->arg)) {
	    ptr->arg = (Pointer)member->name;
	    ptr->val = (Pointer)member;
	    TabInserted(collection->tab, ptr);
	    /* link into linked list */
	    member->next = NULL;
	    member->prevptr = collection->lastptr;
	    *collection->lastptr = member;
	    collection->lastptr = &member->next;
	} else {
	    Link *old_member = (Link*)ptr->val;
	    Link *next_member = old_member->next;
	    /* keep members ordered, for no real reason */
	    while ( next_member && next_member->name == member->name)
		old_member = next_member, next_member = old_member->next;
	    member->next = old_member->next;
	    member->prevptr = &old_member->next;
	    if (old_member->next) old_member->next->prevptr = &member->next;
	    else collection->lastptr = &member->next;
	    old_member->next = member;
	}
    }
    else {
	/* link into linked list */
	member->next = NULL;
	member->prevptr = collection->lastptr;
	*collection->lastptr = member;
	collection->lastptr = &member->next;
    }
    collection->count++;
#ifdef DEBUG
    check_collection(collection);
#endif
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void remove_member(Link *member, struct collection *collection)
{
    if (collection->hashable) abort();
    *member->prevptr = member->next;
    if (member->next) member->next->prevptr = member->prevptr;
    else collection->lastptr = member->prevptr;
    collection->count--;
}

/*------------------------------------------------------------------
 Function Behaviour :: Select some member from 'collection', remove it 
 from the 'collection', and return the removed element.

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
Link * pop_member(struct collection *collection)
{
    Link *member = collection->chain;
    if (member == NULL) return NULL;
    if (collection->hashable) {
	Association *ptr = SymbolLookup(collection->tab, member->name);
	if (HashNone(ptr->arg) || (Link*)ptr->val != member) abort();
	if (member->next && member->next->name == member->name)
	    ptr->val = (Pointer)member->next;
	else {
	    collection->tab->cur_size--;
	    ptr->arg = HashDeleted;
	}
    }
    *member->prevptr = member->next;
    if (member->next) member->next->prevptr = member->prevptr;
    else collection->lastptr = member->prevptr;
    collection->count--;

#ifdef DEBUG
    check_collection(collection);
#endif
    return member;
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void add_rule(struct rule *rule, struct collection *collection)
{
    rule->link.name = collection->hashable ? rule->head->pred : NULL;
    add_member((Link*)rule, collection);
}

/*------------------------------------------------------------------
 Function Behaviour ::  add element x to array a 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void add_to_array(struct array *a, int x)
{
    if (a->length >= a->data_size) {
	if (a->data_size == 0) {
	    a->data_size = 30;
	    a->data = (int *)malloc(a->data_size * sizeof(int));
	}
	else {
	    a->data_size += a->data_size;
	    a->data = (int*)realloc(a->data, a->data_size * sizeof(int));
	}
    }
    a->data[a->length++] = x;
}

/*------------------------------------------------------------------
 Function Behaviour :: Makes a copy of the header fields of the rule, 
 but not the head or body predicates.  Should be called  copy_proto_rule 
 probably.

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
struct rule *copy_rule(struct rule *prototype)
{
    register i;
    register struct rule *rule;
    rule = (struct rule *)malloc(sizeof(struct rule));
    rule->link.next = NULL ;
    rule->link.prevptr = NULL ;
    rule->num_var_names = 0;
    rule->var_names = NULL;
    rule->head = NULL ;
    rule->num_preds = 0 ;
    rule->head_deletes_count = 0;
    rule->head_deletes = NULL;
    rule->preds = NULL ;
    rule->sips = NULL ;
    rule->line_number = -1 ;
    rule->type = COR_NORMALRULE ;
    if (prototype) {
	rule->clause_names = prototype->clause_names;
	if (prototype->num_var_names > 0) {
	    i = prototype->num_var_names;
	    rule->num_var_names = i;
	    rule->var_names = (Name*)malloc(i * sizeof(Name));
	    while (--i >= 0) rule->var_names[i] = prototype->var_names[i];
	    rule->type = prototype->type ;
	}
	rule->line_number = prototype->line_number;
    }
    else {
	rule->clause_names = NULL;
    }
    return rule;
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
Literal *copy_pred(Literal *prototype)
{
    int size = sizeof(Literal) + prototype->args.count() * sizeof(ArgPtr);
    Literal *pred = (Literal*)malloc(size);
    bcopy(prototype, pred, size);
    pred->adorn.init(prototype->adorn); // Fake copy constructor.
    return pred;
}

int pred_arity(Literal *pred)
{
     return pred->arity();
}

/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 
//NOTE: This should be the constructor for Predicate -- PRAVEEN
// Why is malloc being called here instead of new ??
 -------------------------------------------------------------------*/
Predicate *AllocPredicate(ParserStruct& parserStruct, Name name, int arity)
{
    Predicate *pred = (Predicate*)malloc(sizeof(Predicate));
    pred->name = name;
    pred->arity = arity;
    pred->clauses = NULL;
    pred->clause_tail = &pred->clauses;
    pred->work = NULL;
    pred->allprednext = parserStruct.AllPredicates;
    parserStruct.AllPredicates = pred;
    return pred;
}

/*------------------------------------------------------------------
 Function Behaviour :: 
 * Find the (globally unique) Predicate with the given 'name' and 'arity'.
 * Allocate a new one if none is found.

 Oddities/Quirks :: LookupPredicate() is similar, except that it does 
 NOT allocate a new predicate if it is not found.

 -------------------------------------------------------------------*/
Predicate *FindPredicate(ParserStruct& parserStruct, Name name, int arity)
{
    Predicate *pred;
    Association *ptr;
    if (parserStruct.PredicateTable == NULL) {
	parserStruct.PredicateTable = AllocTab(COR_PREDICATE_TABLE_INCR, NULL);
    }

    ptr = SymbolLookup(parserStruct.PredicateTable, name);
    if (HashNone(ptr->arg)) {
	/* No previous Predicate with that name */
	pred = AllocPredicate(parserStruct, name, arity);
	ptr->arg = (Name)name;
	ptr->val = pred;
	TabInserted(parserStruct.PredicateTable, ptr);
	pred->symtabnext = parserStruct.Predicates;
	parserStruct.Predicates = pred;
	return pred;
    }
    /* Check all existing Predicates with same 'name' for given 'arity' */
    pred = (Predicate*)ptr->val;
    for (; ; pred = pred->symtabnext)
	if (pred->arity == arity)
	    return pred;
	else if (pred->symtabnext == NULL || pred->symtabnext->name != name) {
	    /* No such Predicate. Allocate and link in a new one. */
	    Predicate *npred = AllocPredicate(parserStruct, name, arity);
	    npred->symtabnext = pred->symtabnext;
	    pred->symtabnext = npred;
	    return npred;
	}
}

/*------------------------------------------------------------------
 Function Behaviour :: Same as FindPredicate, except that if it is
 not found, a new predicate is NOT created. Instead NULL is returned.

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
Predicate *LookupPredicate(ParserStruct& parserStruct, Name name, int arity)
{
    Predicate *pred;
    Association *ptr;
    if (parserStruct.PredicateTable == NULL) {
	parserStruct.PredicateTable = AllocTab(COR_PREDICATE_TABLE_INCR, NULL);
    }
    ptr = SymbolLookup(parserStruct.PredicateTable, name);
    if (HashNone(ptr->arg)) {
	return NULL;
    }
    /* Check all existing Predicates with same 'name' for given 'arity' */
    pred = (Predicate*)ptr->val;
    for (; ; pred = pred->symtabnext)
	if (pred->arity == arity)
	    return pred;
	else if (pred->symtabnext == NULL || pred->symtabnext->name != name) {
	    /* No such Predicate. */
	    return NULL;
	}
}

/*------------------------------------------------------------------
 Function Behaviour :: Creates a Literal  of the
 specifed predicate

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
Literal * AllocLiteral(ParserStruct& parserStruct, Name name, int arg_count)
{
    Literal *lit =
	(Literal*)malloc(sizeof(Literal) + arg_count * sizeof(ArgPtr));
    lit->predicate = FindPredicate(parserStruct, name, arg_count);
    lit->kind = COR_REGULAR;
    lit->pred = name;
    lit->base_pred = 0;
    lit->negated = 0;
    lit->args.set_count(arg_count);
    lit->adorn.init(arg_count);
    return lit;
}

/*------------------------------------------------------------------
 Function Behaviour :: NOTE: No predicate is specified. Otherwise
 similar to previous function.

 Oddities/Quirks :: Warning : predicate field is NULL

 -------------------------------------------------------------------*/
Literal * AllocLiteral(int arg_count)
{
    Literal *pred =
	(Literal*)malloc(sizeof(Literal) + arg_count * sizeof(ArgPtr));
    pred->predicate = NULL;
    pred->kind = COR_REGULAR;
    pred->pred = NULL;
    pred->base_pred = 0;
    pred->negated = 0;
    pred->args.set_count(arg_count);
    pred->adorn.init(arg_count);
    return pred;
}

/*------------------------------------------------------------------
 Function Behaviour :: Adds a rule(a.k.a. clause) to the list of rules
 defining a predicate.

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
void AddClauseToPredicate(Predicate *predicate, Clause *clause)
{
    clause->pnext = *predicate->clause_tail;
    *predicate->clause_tail = clause;
    predicate->clause_tail = &clause->pnext;
}


/*------------------------------------------------------------------
 Function Behaviour :: 

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
Relation * AllocRelation(Name name, int arity, int delta_indexed)
{
    Relation *rel = hash_relations ?
		new HashSimpleRelation(arity, delta_indexed)
	      : new LinkedRelation(arity);
    rel->name = name;
    return rel;
}

/*------------------------------------------------------------------
 Function Behaviour :: 
   Convert an adornment of the form "bbf" to a BitVector 110.
   Return 0 if ok, -1 otherwise.

 Oddities/Quirks :: 

 -------------------------------------------------------------------*/
int ConvertAdornment(BitVector& bits, char *adorn_string, int adorn_length)
{
    for (int i = 0; i < adorn_length; i++) {
	char adorn_char = *adorn_string++;
	switch (adorn_char) {
	  case 'b':
	    bits.setlen(i+1);
	    bits.set(i, 1);
	    break;
	  case 'f':
	    bits.setlen(i+1);
	    bits.set(i, 0);
	    break;
	  default:
	    return -1;
	}
    }
    return 0;
}

/*------------------------------------------------------------------
 Function Behaviour :: Used to determine if the predicate is a magic
    predicate.

 Oddities/Quirks :: This may not be the right way to do it. Perhaps
 a subclass called MagicPredicate should be defined --- PS

 -------------------------------------------------------------------*/

/** conventions for magic predicates, supplementary predicates, and
  * mp_done predicates below.
**/

int is_magic(Name name)
{
    char *str_name = name->string();
    int len = strlen(str_name);
    if (len > 1) {
        return str_name[0] == 'm' && str_name[1] == '_';
    }
    else return 0;
}

int is_mp_done(Name name)
{
    char *str_name = name->string();
    int len = strlen(str_name);
    if (len > 4) {
        return (str_name[0] == 'd' && str_name[1] == 'o' && str_name[2] == 'n'
			&& str_name[3] == 'e' && str_name[4] == '_') ;
    }
    else return 0;
}

int is_supp(Name name)
{
    char *str_name = name->string();
    int len = strlen(str_name);
    if (len > 3) {
	return (str_name[0] == 's' && str_name[1] == 'u' &&
			str_name[2] == 'p' && str_name[3] == '_') ;
    }
    else return 0;
}

char *make_done_prefix()
{
    return "done_";
}


/* A collecting of various string hashing functions : originally in hash.c */

int StrHash(const char *s, int n)
{
  /* simpler hash function : Praveen */
  int hash = 0;
  for (n -= 1; n >= 0; n--) {
    hash += *s++;
  }
  return hash;
}

int hash_string(const char *text, int len)
{
    return StrHash(text, len);
}

