168 lines
5.0 KiB
C
168 lines
5.0 KiB
C
|
/*****************************************************************************
|
||
|
ExeO()
|
||
|
This function executes an O command.
|
||
|
Otag Goto label
|
||
|
nOtag0,tag1 Computed goto
|
||
|
*****************************************************************************/
|
||
|
#include "zport.h" /* define portability identifiers */
|
||
|
#include "tecoc.h" /* define general identifiers */
|
||
|
#include "defext.h" /* define external global variables */
|
||
|
#include "dchars.h" /* define identifiers for characters */
|
||
|
#include "deferr.h" /* define identifiers for error messages */
|
||
|
DEFAULT ExeO() /* execute an O command */
|
||
|
{
|
||
|
BOOLEAN Found; /* has the tag been found? */
|
||
|
unsigned char TBfBeg[TBFINIT]; /* tag buffer */
|
||
|
charptr TBfEnd; /* end of tag buffer */
|
||
|
charptr TBfPtr; /* end of tag in tag buffer */
|
||
|
charptr TagPtr; /* pointer into tag buffer */
|
||
|
charptr TmpPtr; /* temp pointer for shuffling in Tbf */
|
||
|
DBGFEN(1,"ExeO",NULL);
|
||
|
/*
|
||
|
* ??? Pete,
|
||
|
* given "O^EQq$" we simply use BldStr to build the string
|
||
|
* before looking for the tag in q-reg q. What do we do if
|
||
|
* given "nOtag0,^EQq,tag2$", especially if q-reg q contains a
|
||
|
* comma? if we BldStr first, the comma in the q-reg will
|
||
|
* change the number of tags, maybe changing the nth tag.
|
||
|
* If we BldStr after finding the tag we want, we don't take
|
||
|
* into account the list of tags which may be in q-reg q.
|
||
|
*
|
||
|
* After implementing it the second way (search/Bldstr), I find
|
||
|
* it is much easier to do it the first way (BldStr/search). One
|
||
|
* disadvantage to doing it this way is BldStr is probably building
|
||
|
* much more than it needs to, potentially overrunning TBf?
|
||
|
*/
|
||
|
TBfEnd = TBfBeg + TBFINIT;
|
||
|
if (BldStr(TBfBeg, TBfEnd, &TBfPtr) == FAILURE) {
|
||
|
DBGFEX(1,DbgFNm,"FAILURE, BldStr() failed");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
/*
|
||
|
* If there's something on the expression stack, then we have a computed
|
||
|
* goto, so figure out which tag in TBf they want.
|
||
|
*
|
||
|
* TBf: "TAG0,TAG1,TAG2........"
|
||
|
* ^ ^ ^
|
||
|
* TBfBeg TBfPtr TBfEnd
|
||
|
*/
|
||
|
if (EStTop > EStBot) {
|
||
|
if (GetNmA () == FAILURE) { /* get NArgmt */
|
||
|
DBGFEX(1,DbgFNm,"FAILURE, GetNmA() failed");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
if (NArgmt < 0) { /* n is out of range */
|
||
|
TagPtr = TBfPtr; /* say we ran into end of tag list */
|
||
|
} else { /* find the nth tag */
|
||
|
TagPtr = TBfBeg;
|
||
|
if (NArgmt > 0) { /* n==0 is already done */
|
||
|
while (TagPtr < TBfPtr) {
|
||
|
if (*TagPtr++ == ',') {
|
||
|
if (--NArgmt == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* If we ran into the end of the tag list, or the tag we found is null
|
||
|
* (",,"), then flow past nO command.
|
||
|
*/
|
||
|
if (TagPtr == TBfPtr || *TagPtr == ',') {
|
||
|
DBGFEX(1,DbgFNm,"SUCCESS");
|
||
|
CmdMod = '\0'; /* clear modifiers flags */
|
||
|
return SUCCESS;
|
||
|
}
|
||
|
/*
|
||
|
* shuffle tag we found to beginning of TBf for searching.
|
||
|
*/
|
||
|
TmpPtr = TBfBeg;
|
||
|
while (TagPtr < TBfPtr && *TagPtr != ',') {
|
||
|
*TmpPtr++ = *TagPtr++;
|
||
|
}
|
||
|
TBfPtr = TmpPtr;
|
||
|
}
|
||
|
#if DEBUGGING
|
||
|
*TBfPtr = '\0';
|
||
|
sprintf(DbgSBf,"searching for tag \"%s\"", TBfBeg);
|
||
|
DbgFMs(1,DbgFNm,DbgSBf);
|
||
|
#endif
|
||
|
/*
|
||
|
* reset CBfPtr to point to the front of the command string, or the front
|
||
|
* of the loop if we're in a loop, then search for the tag in TBf, keeping
|
||
|
* track of nested <> loops.
|
||
|
*/
|
||
|
CBfPtr = (LStTop == LStBot) ? CStBeg : LStack[LStTop].LAddr + 1;
|
||
|
Found = FALSE;
|
||
|
CmdMod = '\0'; /* clear modifiers flags */
|
||
|
while (!Found) {
|
||
|
while (*CBfPtr != '!') {
|
||
|
if (CBfPtr == CStEnd) {
|
||
|
ErrPSt(ERR_TAG, TBfBeg, TBfPtr);
|
||
|
DBGFEX(1,DbgFNm,"FAILURE, missing tag");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
switch (*CBfPtr) {
|
||
|
case '<':
|
||
|
if (++LStTop >= LPS_SIZE) {
|
||
|
ErrMsg(ERR_PDO);
|
||
|
DBGFEX(1,DbgFNm,"FAILURE");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
LStack[LStTop].LIndex = INFINITE;
|
||
|
LStack[LStTop].LAddr = CBfPtr;
|
||
|
CmdMod = '\0';
|
||
|
break;
|
||
|
case '>':
|
||
|
if (LStTop == LStBot) {
|
||
|
ErrMsg(ERR_BNI);
|
||
|
DBGFEX(1,DbgFNm,"FAILURE");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
--LStTop;
|
||
|
CmdMod = '\0';
|
||
|
break;
|
||
|
default:
|
||
|
if (SkpCmd() == FAILURE) {
|
||
|
DBGFEX(1,DbgFNm,"FAILURE, SkpCmd() failed");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
} /* end of switch */
|
||
|
++CBfPtr;
|
||
|
} /* end of while (!='!')*/
|
||
|
/*
|
||
|
* At this point, we've found an '!'. if tracing is on, display 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 */
|
||
|
DBGFEX(1,DbgFNm,"FAILURE, FindES() failed");
|
||
|
return FAILURE;
|
||
|
}
|
||
|
#if DEBUGGING
|
||
|
sprintf(DbgSBf,"found tag \"%.*s\"\n",(int)(CBfPtr-ArgPtr), ArgPtr);
|
||
|
DbgFMs(1,DbgFNm,DbgSBf);
|
||
|
#endif
|
||
|
/*
|
||
|
* compare found tag (in ArgPtr) to O command tag (in TBf).
|
||
|
*/
|
||
|
TagPtr = TBfBeg;
|
||
|
while ((TagPtr < TBfPtr) && (*ArgPtr == *TagPtr)) {
|
||
|
++ArgPtr;
|
||
|
++TagPtr;
|
||
|
}
|
||
|
Found = ((TagPtr == TBfPtr) && (*ArgPtr == '!'));
|
||
|
++CBfPtr;
|
||
|
} /* end of while (!Found) */
|
||
|
--CBfPtr;
|
||
|
CmdMod = '\0'; /* clear modifiers flags */
|
||
|
DBGFEX(1,DbgFNm,"SUCCESS");
|
||
|
return SUCCESS;
|
||
|
}
|