#include <ncbi.h>
#include <dfa.h>
#include <gishlib.h>


/**************************************************************************
*	dfa_dump(dp, fp)
*
*	Dump the contents of the DFA to the file pointer fp.
**************************************************************************/
DFA_Error _cdecl
dfa_dump(dp, fp)
	DFAPtr	dp;
	FILE	*fp;
{
	DFA_StatePtr	state0, S;
	int		i;
	int		ilim;
	DFA_BufPtr	dbp;
	char	buf[1024];
	CharPtr	cp;

	if (dp == NULL || dp->magic != DFA_MAGIC)
		return dfaerrno = dfaErrBadPtr;

	if (fp == NULL)
		return dfaerrno = dfaErrNullParm;

	if (ferror(fp) != 0)
		return dfaerrno = dfaErrFileIO;

	(void) fprintf(fp, "Dumping DFA beginning @(0x%lx)\n", (long)dp);
	(void) fprintf(fp, "Current operational state:  ");
	switch (dp->opstate) {
	case dfaOpstateInit:
		cp = "dfaOpstateInit";
		break;
	case dfaOpstateMemInit:
		cp = "dfaOpstateMemInit";
		break;
	case dfaOpstateVirgin:
		cp = "dfaOpstateVirgin";
		break;
	case dfaOpstateAlphaInit:
		cp = "dfaOpstateAlphaInit";
		break;
	case dfaOpstateOpen:
		cp = "dfaOpstateOpen";
		break;
	case dfaOpstateBuilding:
		cp = "dfaOpstateBuilding";
		break;
	case dfaOpstateClosing:
		cp = "dfaOpstateClosing";
		break;
	case dfaOpstateClosed:
		cp = "dfaOpstateClosed";
		break;
	case dfaOpstateZombie:
		cp = "dfaOpstateZombie";
		break;
	case dfaOpstateDestroyed:
		cp = "dfaOpstateDestroyed";
		break;
	default:
		cp = "dfaOpstateUnknown";
		break;
	}
	(void) fprintf(fp, "DFA_%s\n", cp);
	if (*cp == 'U' || dp->opstate <= dfaOpstateMemInit ||
				dp->opstate == dfaOpstateDestroyed) {
		(void) fprintf(fp, "Unable to dump a DFA in this state\n");
		return dfaErrNone;
	}

	(void) fprintf(fp, "DFA statistics:\n");
	(void) fprintf(fp, "\tAlphabet = %d...%d\n", dp->amin, dp->amax);
	(void) fprintf(fp, "\tAlphabet size = %ld letters\n", (long)dp->asize);
	(void) fprintf(fp, "\tNo. of States in DFA = %ld\n", (long)dp->nstates);
	(void) fprintf(fp, "\tNo. of Accepting Transitions in DFA = %ld\n",
					(long)dp->naccepts);
	(void) fprintf(fp, "\tStorage required = %ld bytes\n",
			(long)sizeof(*dp) +
			dp->nstates * dp->statesize +
			dp->naccepts * sizeof(DFA_Accept)
			);
	fflush(fp);

	state0 = dp->state0;

	dbp = &dp->buf0;
	while (dbp != NULL) {
		/* Check for error condition (this function could easily fill a disk) */
		if (ferror(fp) != 0 || feof(fp) != 0)
			return dfaerrno = dfaErrFileIO;
		(void) fprintf(fp, "\n\nStart of buffer @(0x%lx)\n", (long)dbp);
		fflush(fp);
		if (dbp == &dp->buf0)
			S = dp->state0;
		else
			S = (DFA_StatePtr)dbp->buf;
		if (dbp == dp->lastbuf)
			ilim = dbp->bsize - dp->memavail;
		else
			ilim = dbp->bused;
		ilim /= sizeof(S);
		for (i=0; i<ilim; ++i) {
			if (i%4 == 0) {
				sprintf(buf, "0x%08lx", (long)S);
				(void) fprintf(fp, "\n%10s:  ", buf);
			}
			if (S->next[0] == state0)
				(void) fprintf(fp, "  State0 ");
			else
				if (S->next[0] == (DFA_StatePtr)DFA_MUNGED(state0))
					(void) fprintf(fp, " *State0 ");
				else
					(void) fprintf(fp, " %08lx", (long)S->next[0]);
			++S;
		}
		dbp = dbp->chain;
	}
	(void) fputc('\n', fp);
	if (ferror(fp) != 0)
		return dfaerrno = dfaErrFileIO;
	return dfaErrNone;
}
