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

/*************************************************************************
 *	dfa_pscanf(dp, gettoken, stream, report)
 *
 *	Use the specified DFA to scan a stream of tokens and report matches.
 *************************************************************************/
DFA_Error _cdecl
dfa_pscanf(dp, gettoken, stream, report)
	DFAPtr	dp;
	/* Call-back function to get each token */
	int	(_cdecl *gettoken) PROTO((Nlm_VoidPtr _stream));
	Nlm_VoidPtr	stream;
	/* Call-back function to report matches */
	int	(_cdecl *report) PROTO((size_t off, DFA_PatID patID));
{
	DFA_StatePtr	S;
	DFA_AcceptPtr	ap;
	DFA_PatlistPtr	plp;
	size_t	off = 0;
	int	ch;

	if (dp == NULL || dp->magic != DFA_MAGIC)
		return dfaerrno = dfaErrBadPtr;
	if (dfa_opstate(dp) != dfaOpstateClosed)
		return dfaerrno = dfaErrOpstate;
	if (dp->xlen != 0)
		return dfaerrno = dfaErrIncompat;

	if (gettoken == NULL || report == NULL)
		return dfaerrno = dfaErrNullParm;

	S = dp->state0;

	for (;; ++off) {
		while (!DFA_ISACCEPTING(S = S->next[ch = (*gettoken)(stream)])) {
			++off;
			if (ch == EOF)
				return dfaErrNone;
		}
		if ((ap = (DFA_AcceptPtr)DFA_UNMUNGED(S)) == NULL)
			return dfaErrNone;
		S = ap->retState;
		plp = &ap->pl;
		do {
			if ((*report)(off, plp->patID) != 0)
				return dfaerrno = dfaErrReport;
		} while ((plp = plp->chain) != NULL);
	}
	/*NOTREACHED*/
}

