/*****************************************************************************

	ExeO()

	This function executes an O command.

*****************************************************************************/

#include "ZPort.h"		/* define portability identifiers */
#include "DefTeco.h"		/* define general identifiers */
#include "DefChars.h"		/* define identifiers for characters */
#include "DefError.h"		/* define identifiers for error messages */

extern	DEFAULT	BldStr();	/* build a string */
extern	VOID	ErrMsg();	/* display an error message on the terminal */
extern	DEFAULT	FindES();	/* find end of string */
extern	DEFAULT	SkpCmd();	/* skip a command */
extern	VOID	ZDspCh();	/* display a character */

EXTERN	char	*ArgPtr;	/* beginning of text argument */
EXTERN	char	*CStEnd;	/* pointer to last char of command string */
EXTERN	char	*CStBeg;	/* command string beginning */
EXTERN	char	*CBfPtr;	/* command buffer pointer */
EXTERN	BYTE	CmdMod;		/* command modifiers flags for @, :, etc. */
EXTERN	WORD	LStBot;		/* bottom of loop stack */
EXTERN	struct	LStck LStack[];	/* loop stack */
EXTERN	WORD	LStTop;		/* top of loop stack */
EXTERN	BOOLEAN	TraceM;		/* trace mode flag */

DEFAULT ExeO()			/* execute an O command */
{
	LOCAL	BOOLEAN	Found;			/* has the tag been found? */
	LOCAL	char	TBfBeg[TBFINIT];	/* beginning of O buffer */
	LOCAL	char	*TBfEnd;		/* end of O buffer */
	LOCAL	char	*TBfPtr;		/* pointer into O buffer */
	LOCAL	char	*TagPtr;		/* pointer into O buffer */

#if DEBUGGING
DbgInd+=2;if(DbgLvl>=1){DbgMsg();DbgDBf("ExeO: called.\015\012");DbgROf();}
#endif

	TBfEnd = TBfBeg + TBFINIT;
	if (BldStr(TBfBeg, TBfEnd, &TBfPtr) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(FAILURE);
#if DEBUGGING
}
#endif

#if DEBUGGING
if(DbgLvl>=1){DbgMsg();DbgDBf("ExeO: searching for tag \"");
TypBuf(TBfBeg,TBfPtr);DbgDBf("\"\015\012");DbgROf();}
#endif

/*
  reset CBfPtr to point to the front of the command string,  or the front
   of the loop if we're in a loop.
*/

	CBfPtr = (LStTop == LStBot) ? CStBeg : LStack[LStTop].LAddr + 1L;

	Found = NO;
	CmdMod = '\0';				/* clear modifiers flags */
	while (!Found)
		{
		while (*CBfPtr != '!')
			{
			if (CBfPtr == CStEnd)
				{
				ErrMsg(ERR_UTC);/* unterminated command */
#if DEBUGGING
{if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
#if DEBUGGING
}
#endif
				}
			switch (*CBfPtr) {
				case '!':
					break;
				case '<':
					if (++LStTop >= LPS_SIZE)
						{
						ErrMsg(ERR_PDO);
#if DEBUGGING
if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
						return(FAILURE);
						}
					LStack[LStTop].LIndex = INFINITE;
					LStack[LStTop].LAddr = CBfPtr;
					CmdMod = '\0';
					break;
				case '>':
					if (LStTop == LStBot)
						{
						ErrMsg(ERR_BNI);
#if DEBUGGING
if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
						return(FAILURE);
						}
					--LStTop;
					CmdMod = '\0';
					break;
				default:
					if (SkpCmd() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
						return(FAILURE);
#if DEBUGGING
}
#endif
				}			/* end of switch */
			++CBfPtr;
		}					/* end of while */

/*
  if tracing is on,  display the closing exclamation point
*/

		if (TraceM)			/* if trace mode is on */
			{
			if (CmdMod & ATSIGN)		/* if it was @O */
				ZDspCh('@');
			ZDspCh('!');
			}

		if (FindES('!') == FAILURE)	/* find end of tag */
#if DEBUGGING
{if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(FAILURE);
#if DEBUGGING
}
#endif

#if DEBUGGING
if(DbgLvl>=1){DbgMsg();DbgDBf("ExeO: found tag \"");
TypBuf(ArgPtr,CBfPtr);DbgDBf("\"\015\012");DbgROf();}
#endif

/*
  compare found tag to tag from O command and set Found to YES or NO
*/

		TagPtr = TBfBeg;
		Found = YES;
		while (TagPtr < TBfPtr)
			if (*ArgPtr == *TagPtr)
				{
				++ArgPtr;
				++TagPtr;
				}
			else
				{
				Found = NO;
				break;
				}
		++CBfPtr;
	}					/* end of while */

	--CBfPtr;
	CmdMod = '\0';				/* clear modifiers flags */
#if DEBUGGING
if(DbgLvl>=1)
{DbgMsg();DbgDBf("ExeO: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
return(SUCCESS);
}
