/*****************************************************************************
 *
 * FILE : main.c -  program administration
 *
 * programmer - Pawel Cholewinski
 *
 * date 04/19/93, modified 08/10/95
 * modified 19 Apr 1999 by Neil Moore <neil@cs.uky.edu>
 * modified 27 Jul 1999 by Neil Moore <neil@cs.uky.edu>
 * modified 20 Aug 1999 by Neil Moore <neil@cs.uky.edu>
 * modified  5 Sep 1999 by Neil Moore <neil@cs.uky.edu>
 *
 * Part of sderes.  See COPYRIGHT for copyright information.
 *
 *****************************************************************************/

/* FIXME: we want to time each model individually */

#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include "global.h"
#include "default.h"
#include "proto.h"

#ifndef VERSION
#define VERSION "unknown"
#endif

#ifndef LPSMSVER
#define LPSMSVER "unknown"
#endif

clock_t mcu, tcu, last_time;

int err, timex=1, ff, verbosity=1;
char lexbuf[BDRSSIZE];

char def_znak[MAXFILENAME];
long n_extnsns, n_cppcalls, n_candidates;
FILE *finp;
FILE *fdw;
FILE *fstratif;

struct symbolbox *defhashtable[HASHSIZE];

static void version(void);
static void usage(void);
static int to_int(const char *str);

/*
 * ========================================================================
 * main :  logic programming system administration                      
 * ========================================================================
 */
int main(argc, argv)
   int argc;
   char *argv[];
{
   if(setoptions(argc,argv) < 0)
	return 1;
   read_stratification();
   if(verbosity > 1)
	   fprintf(stderr, "\n");
   mcu=last_time=clock();

   stratified_extnsns(1);

   tcu=clock();
   
   /* If we want normal or high verbosity, or if we aren't printing models,
    * we want a count of models.
    */
   if(verbosity != 0)
	   printf("%ld extension%s\n", n_extnsns, n_extnsns==1 ? "" : "s");
	   
   if (timex)
	   print_timing(tcu, mcu);
   return 0;
}


/*
 * ========================================================================
 *  setoptions : parses call line arguments, evaluates options for output 
 *               file, opens input file
 * ========================================================================
 */
/* Rewritten:  NFM, 13 Apr 1999 */

int setoptions(argc, argv)
   int argc;
   char *argv[];
{
	char *filename = NULL;
	(void) argc; /* prevent warnings */

	init_working_memory();

	while (*++argv != NULL) {
		if(!strcmp(*argv, "-v") || !strcmp(*argv, "--version")) {
			version();
			exit(0);
		} else if(!strcmp(*argv, "-h") || !strcmp(*argv, "--help")) {
			usage();
			exit(0);
		} else if(!strcmp(*argv, "-t") || !strcmp(*argv, "--time")) {
			timex = 1;
		} else if(!strcmp(*argv, "-n") || !strcmp(*argv, "--no-time")) {
			timex = 0;
		} else if(!strcmp(*argv, "-V") || !strcmp(*argv, "--verbose")) {
			verbosity = 2;
		} else if(!strcmp(*argv, "-m") || !strcmp(*argv, "--messages")) {
			verbosity = 1;
		} else if(!strcmp(*argv, "-q") || !strcmp(*argv, "--quiet")) {
			verbosity = 0;
		} else if(!strcmp(*argv, "-qq") || !strcmp(*argv, "--very-quiet")) {
			verbosity = -1;
		} else if(!strcmp(*argv, "-1") || !strcmp(*argv, "--single")) {
			extlimit = 1;
		} else if(!strcmp(*argv, "-a") || !strcmp(*argv, "--all")) {
			extlimit = 0;
		} else if(!strcmp(*argv, "-c") || !strcmp(*argv, "--count")) {
			if(*++argv == NULL || (extlimit = to_int(*argv)) < 0) {
				usage();
				exit(1);
			}
		} else if(!strncmp(*argv, "-c", 2)) {
			if((extlimit = to_int(*argv+2)) < 0) {
				usage();
				exit(1);
			}
		} else if(!strncmp(*argv, "--count=", 8)) {
			if((extlimit = to_int(*argv+8)) < 0) {
				usage();
				exit(1);
			}
		} else if((*argv)[0] == '-') {
			usage();
			exit(1);
		} else {
			filename = *argv;
		}		
	}
	
	if (filename != NULL) {
		int retval;
		
		if(verbosity > 1)
			fprintf(stderr, "Loading theory...");
		if((retval = loadtheory(filename))) {
			if(verbosity > 1)
				fprintf(stderr, "\n");
			return retval;
		} else {
			if(verbosity > 1)
				fprintf(stderr, "done.\n");
			return 0;
		}
	}
	
	usage();
	exit(1);
}

void version(void) 
{
	printf("sderes %s, from lpsms %s\n", VERSION, LPSMSVER);
}


void usage(void) 
{
	printf("usage: sderes [options] filename\n");
	printf("Compute stable models of a logic program.\n\n");
	
	printf(" -a, --all             find all stable models (default)\n");
	printf(" -1, --single          find only the first model\n");
	printf(" -c, --count=N         find the first N stable models\n");
	printf(" -t, --time            print timing information to stderr (default)\n");
	printf(" -n, --no-time         do not print timing information\n");
	printf(" -V, --verbose         print additional information to stderr\n");
	printf(" -m, --messages        print status messages to stderr (default)\n");
	printf(" -q, --quiet           do not print status information (other than\n");
	printf("                        timing and models)\n");
	printf(" -qq, --very-quiet     compute models but do not print them\n");
	printf(" -v, --version         print version information to stdout\n");
	printf(" -h, --help            display this message\n\n");

	printf("Input is read from filename.{dt,thc,dc}.\n");
}

int to_int(const char *str)
{
	long result;
	char *end=NULL;
	if(str == NULL)
		return 0;
	
	result = strtol(str, &end, 0);

	if(*str != '\0' && *end == '\0')
		return (int)result;
	else
		return -1;
}


void print_timing(to, frm)
clock_t to, frm;
{
	printf("%f seconds\n",(float)(to - frm)/CLOCKS_PER_SEC);
}

/*
 * ========================================================================
 * init_working_memory : initialize basic shell variables
 * ========================================================================
 */
void init_working_memory(void)
{
   int i;

	timex = 1;
	for (i=0 ; i<HASHSIZE ; i++) 
	   defhashtable[i] = NULL;
	SetProverStructures(w, conc,dttable,
			wno,dno,deffacts,dffno,&n_cppcalls,defatomlex);
        clean_atomtable();
	for (i = 0; i< MAXDSIZE; i++) ad[i] = 0;
}
