/*
	dfatest

	A not-particularly-fast-nor-comprehensive (NPFNC) test program
	for the dfa library.
*/
#include <ncbi.h>
#include <gishlib.h>
#include <dfa.h>

unsigned char PNTR strings[] = {
			(unsigned char *)"AAAAAAG",
			(unsigned char *)"GCGATCC",
			(unsigned char *)"GCGATGC",
			(unsigned char *)"GCGACGC",
			(unsigned char *)"GCGTCGC",
			(unsigned char *)"GCATCGC",
			(unsigned char *)"GGATCGC",
			(unsigned char *)"CGATCGC",
			NULL };

int		report PROTO((long, DFA_AcceptPtr));
int		gettoken PROTO((Nlm_VoidPtr stream));
Nlm_VoidPtr	memget PROTO((size_t size));
void	memfree PROTO((Nlm_VoidPtr));
long	lineno = 1;
long	linechr = 0;

main(ac, av)
	int	ac;
	char	**av;
{
	register DFA_StatePtr	S;
	register CharPtr	query;
	register DFA_AcceptPtr	ap;
	CharPtr	query0;
	DFAPtr	dp;
	unsigned char PNTR sp;
	FILE	*fp = stdin;
	int	i;
	CharPtr	cp;

	if (ac > 1) {
		fp = fopen(av[1], "r");
		if (fp == NULL) {
			perror(av[1]);
			exit(1);
		}
	}


	dfa_memalloc(memget);
	dfa_memincr(20*1024);
	dfa_memfree(memfree);

	dp = dfa_new(CHAR_MIN, CHAR_MAX);
	if (dp == NULL || dfaerrno != dfaErrNone) {
		dfa_perror("dfa_open");
		exit(dfaerrno);
	}

	dfa_halton(dp, '\0'); /* Halt on C-string terminators */
	dfa_begin(dp);
	if (dfaerrno != dfaErrNone) {
		dfa_perror(NULL);
		exit(dfaerrno);
	}

	for (i=0, sp=strings[0]; sp; sp = strings[i]) {
		DFA_PatID	pi;
		pi.i = ++i;
		if (dfa_add(dp, sp, strlen((char *)sp), pi) == NULL) {
			dfa_perror("dfa_add");
			exit(dfaerrno);
		}
	}


	if (dfa_close(dp) != dfaErrNone) {
		dfa_perror("dfa_close");
		exit(dfaerrno);
	}

#ifndef OS_DOS
#define NK 256
#else
#define NK 31
#endif

	printf("Buffer size = %d KB\n", NK);
	cp = memget(NK*1024);
	for (i=0; i<NK*1024; ++i)
		cp[i] = 'A';
	cp[NK*1024-2] = 'G';
	cp[NK*1024-1] = NULLB;

	/* Do the search */
	query0 = cp;
	for (i=0; i<100; ++i) {
		if (i%10 == 0)
			printf("Search %d\n", i);
		query = query0;
		S = dp->state0;
		for (;;) {
			while (!DFA_ISACCEPTING(S = S->next[*query++]))
				;
			if ((ap = (DFA_AcceptPtr)DFA_UNMUNGED(S)) == NULL)
				break;
			S = ap->retState;
			if (report(query-query0, ap) != 0)
				break;
		}
	}

	printf("\nDoing strchr() searches\n");
	for (i=0; i<100; ++i)
		strchr((char *)query0, 'C');

	exit(dfa_destruct(dp));
}

int
report(off, ap)
	long	off;
	DFA_AcceptPtr	ap;
{
	register DFA_PatlistPtr	pp = &ap->pl;

	do {
		printf("Matched pattern %lu at line %d, char %d\n",
				pp->patID.u, lineno, linechr);
	} while ((pp = pp->chain) != NULL);
	return 0;
}

int
gettoken(stream)
	Nlm_VoidPtr	stream;
{
	static int	lastch;

	if (lastch == '\n') {
		++lineno;
		linechr = 0;
	}
	++linechr;
	return lastch = fgetc((FILE *)stream);
}

Nlm_VoidPtr
memget(size)
	size_t	size;
{
	return (Nlm_VoidPtr)malloc(size);
}

void
memfree(p)
	Nlm_VoidPtr	p;
{
	(void) free((CharPtr)p);
}

