/***************************************************************************** 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; }