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

/***************************************************************************
*	dfa_accepts(dp, pattern, patlen)
*
*	Determine whether a given pattern is accepted by the DFA.
*	Only callable while the DFA is in the operational state dfaOpstateOpen.
*
*	Return Values:  pointer to the linked list of patIDs when found
*					NULL when pattern was not found.
***************************************************************************/
DFA_PatlistPtr _cdecl
dfa_accepts(dp, pattern, patlen)
	DFAPtr	dp;			/* the initialized DFA structure */
	unsigned char PNTR pattern;	/* the pattern to look for in the DFA */
	size_t	patlen;	/* length of the pattern (in DFA_Letters) */
{
	DFA_StatePtr	S;
	DFA_AcceptPtr	A;
	int	i;
	DFA_StatePtr	state0;

#ifndef DFA_THENEED4SPEED
	unsigned char	patChr;

	if (dp == NULL || dp->magic != DFA_MAGIC) {
		dfaerrno = dfaErrBadPtr;
		return NULL;
	}
	if (dp->opstate != dfaOpstateOpen) {
		dfaerrno = dfaErrOpstate;
		return NULL;
	}
	if (patlen == 0) {
		dfaerrno = dfaErrPatlen;
		return NULL;
	}
#endif

	S = state0 = dp->state0;
	for (i=0; i<patlen-1; ++i) {
#ifndef DFA_THENEED4SPEED
		if ((int)(patChr = *pattern++) < dp->amin || (int)patChr > dp->amax)
			goto BadLetter;
		S = S->next[patChr];
#else
		S = S->next[*pattern++];
#endif
		if (S == state0)
			goto NotFound;
		if (!DFA_ISACCEPTING(S))
			continue;
		A = (DFA_AcceptPtr)DFA_UNMUNGED(S);
		S = A->retState;
		if (S == state0)
			goto NotFound;
	}

#ifndef DFA_THENEED4SPEED
	if ((int)(patChr = *pattern) < dp->amin || (int)patChr > dp->amax)
		goto BadLetter;
	if (!DFA_ISACCEPTING(S = S->next[patChr]))
		goto NotFound;
#else
	if (!DFA_ISACCEPTING(S = S->next[*pattern]))
		goto NotFound;
#endif

	A = (DFA_AcceptPtr)DFA_UNMUNGED(S);
	return &A->pl;

NotFound:
	dfaerrno = dfaErrNotFound;
	return NULL;

BadLetter:
	dfaerrno = dfaErrNonAlpha;
	return NULL;
}
