244 lines
7.5 KiB
C
244 lines
7.5 KiB
C
/*****************************************************************************
|
|
BldStr()
|
|
This function "builds" a string. This means converting string
|
|
build constructs in the input string into their intended equivalents
|
|
in the output string. The string build constructs are as follows:
|
|
^Q use next character literally, not as a string build char
|
|
^R use next character literally, not as a string build char
|
|
^V lowercase the next character
|
|
^V^V lowercase all following characters
|
|
^W uppercase the next character
|
|
^W^W uppercase all following characters
|
|
^EQq use string in q-register q here
|
|
^EUq use ASCII char for number in q-register q here
|
|
When this function is called, CBfPtr points to the first character
|
|
of the input string. It is assumed that the string is terminated by an ESCAPE
|
|
character (or something else if the calling command was @-modified). If the
|
|
string is not properly terminated this function will die with "unterminated
|
|
command" when it encounters CStEnd while looking for the terminator character.
|
|
When this function returns, CBfPtr points to the ESCAPE which
|
|
terminates the string, the built string is in the buffer pointed to by
|
|
XBfBeg, and XBfPtr points to the character after the last character in
|
|
the built string.
|
|
The commands which contain a filename (EB, EI, EN, ER and
|
|
EW) use this function. The EG command, which exits with an operating system
|
|
command line, uses this function. The O command, which jumps to a tag, uses
|
|
this function. The search commands (E_, FK, FN, FS, F_, N, S and _) use this
|
|
function.
|
|
*****************************************************************************/
|
|
#include "zport.h" /* define portability identifiers */
|
|
#include "tecoc.h" /* define general identifiers */
|
|
#include "defext.h" /* define external global variables */
|
|
#include "deferr.h" /* define identifiers for error messages */
|
|
#include "dchars.h" /* define identifiers for characters */
|
|
#include "chmacs.h" /* define character processing macros */
|
|
#if USE_PROTOTYPES
|
|
static DEFAULT DoCtVW(charptr EndArg, unsigned char TmpChr);
|
|
static DEFAULT DoCtE(charptr EndArg, charptr XBfEnd);
|
|
#endif
|
|
static charptr BBfPtr; /* pointer into XBf */
|
|
static int CaseCv; /* case conversion */
|
|
static unsigned char WVFlag; /* ^W or ^V flag */
|
|
static DEFAULT DoCtVW(EndArg, TmpChr) /* do a control-V or control-W */
|
|
charptr EndArg; /* ptr to end of string argument */
|
|
unsigned char TmpChr; /* temporary character */
|
|
{
|
|
DBGFEN(3,"DoCtVW",NULL);
|
|
WVFlag = TmpChr;
|
|
if (++CBfPtr == EndArg) { /* move past ^W or ^V, too far? */
|
|
ErrMsg(ERR_ISS); /* yes, illegal search string */
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
if ((*CBfPtr == '^') && ((EdFlag & ED_CARET_OK) == 0)) {
|
|
if (++CBfPtr == EndArg) {
|
|
ErrMsg(ERR_ISS);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
TmpChr = To_Upper(*CBfPtr);
|
|
if ((TmpChr < '@') || (TmpChr > '_')) {
|
|
ErrChr(ERR_IUC, *CBfPtr);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
TmpChr &= '\077';
|
|
} else {
|
|
TmpChr = *CBfPtr;
|
|
}
|
|
if (WVFlag == CTRL_V) {
|
|
if (TmpChr == CTRL_V) {
|
|
CaseCv = LOWER;
|
|
} else {
|
|
*BBfPtr++ = To_Lower(TmpChr);
|
|
}
|
|
} else {
|
|
if (TmpChr == CTRL_W) {
|
|
CaseCv = UPPER;
|
|
} else {
|
|
*BBfPtr++ = To_Upper(TmpChr);
|
|
}
|
|
}
|
|
WVFlag = '\0';
|
|
DBGFEX(2,DbgFNm,"SUCCESS");
|
|
return SUCCESS;
|
|
}
|
|
static DEFAULT DoCtE(EndArg, XBfEnd) /* do a control-E */
|
|
charptr EndArg; /* ptr to end of string argument */
|
|
charptr XBfEnd; /* end of build-string buffer */
|
|
{
|
|
DEFAULT Status; /* returned from FindQR */
|
|
charptr TCStEn; /* temporary holder of CStEnd */
|
|
DBGFEN(3,"DoCtE",NULL);
|
|
if (++CBfPtr == EndArg) { /* move past ^E, too far? */
|
|
ErrMsg(ERR_ICE); /* yes, illegal ^E command */
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
if ((*CBfPtr == 'Q') || (*CBfPtr == 'q')) {
|
|
if (++CBfPtr == EndArg) {
|
|
ErrMsg(ERR_ISS);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
/*
|
|
* handle filespec buffer and search string buffer
|
|
*/
|
|
if (*CBfPtr=='*' || *CBfPtr=='_') {
|
|
charptr BufPtr, BufBeg;
|
|
if (*CBfPtr=='*') {
|
|
BufPtr=FBfPtr;
|
|
BufBeg=FBfBeg;
|
|
} else {
|
|
BufPtr=SBfPtr;
|
|
BufBeg=SBfBeg;
|
|
}
|
|
if ((BufPtr-BufBeg) > (XBfEnd-BBfPtr)) {
|
|
ErrMsg(ERR_STL);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
MEMMOVE(BBfPtr, BufBeg, (SIZE_T)(BufPtr - BufBeg));
|
|
BBfPtr += BufPtr-BufBeg;
|
|
} else {
|
|
/*
|
|
* it really must be a Q reg reference after all
|
|
*/
|
|
TCStEn = CStEnd; /* save CStEnd */
|
|
CStEnd = EndArg;
|
|
Status = FindQR();
|
|
CStEnd = TCStEn; /* restore CStEnd */
|
|
if (Status == FAILURE) {
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
if ((QR->End_P1-QR->Start) > (XBfEnd-BBfPtr)) {
|
|
ErrMsg(ERR_STL);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
MEMMOVE(BBfPtr, QR->Start, (SIZE_T)(QR->End_P1 - QR->Start));
|
|
BBfPtr += QR->End_P1 - QR->Start;
|
|
}
|
|
} else if ((*CBfPtr == 'U') || (*CBfPtr == 'u')) {
|
|
if (++CBfPtr == EndArg) {
|
|
ErrMsg(ERR_ISS);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
TCStEn = CStEnd; /* save CStEnd */
|
|
CStEnd = EndArg;
|
|
Status = FindQR();
|
|
CStEnd = TCStEn; /* restore CStEnd */
|
|
if (Status == FAILURE) {
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
*BBfPtr++ = (char)QR->Number;
|
|
} else {
|
|
*BBfPtr++ = CTRL_E;
|
|
*BBfPtr++ = *CBfPtr;
|
|
}
|
|
DBGFEX(2,DbgFNm,"SUCCESS");
|
|
return SUCCESS;
|
|
}
|
|
DEFAULT BldStr(XBfBeg, XBfEnd, XBfPtr) /* build a string */
|
|
charptr XBfBeg; /* beginning of build-string buffer */
|
|
charptr XBfEnd; /* end of build-string buffer */
|
|
charptr (*XBfPtr); /* pointer into build-string buffer */
|
|
{
|
|
charptr EndArg; /* end of input string, plus 1 */
|
|
unsigned char TmpChr; /* temporary character */
|
|
DBGFEN(2,"BldStr",NULL);
|
|
if (FindES(ESCAPE) == FAILURE) { /* move CBfPtr to end of argument */
|
|
DBGFEX(2,DbgFNm,"FAILURE, FindES(ESCAPE) failed");
|
|
return FAILURE;
|
|
}
|
|
WVFlag = '\0'; /* initialize ^W and ^V flag */
|
|
CaseCv = IniSrM; /* initialize internal search mode */
|
|
BBfPtr = XBfBeg; /* initialize ptr into build-string buffer */
|
|
EndArg = CBfPtr; /* save pointer to end of argument */
|
|
CBfPtr = ArgPtr; /* reset to beginning of argument */
|
|
while (CBfPtr < EndArg) {
|
|
if ((*CBfPtr == '^') && ((EdFlag & ED_CARET_OK) == 0)) {
|
|
if (++CBfPtr == EndArg) {
|
|
ErrMsg(ERR_ISS);
|
|
DBGFEX(2,DbgFNm,"FAILURE, no char after ^");
|
|
return FAILURE;
|
|
}
|
|
TmpChr = To_Upper(*CBfPtr);
|
|
if ((TmpChr < '@') || (TmpChr > '_')) {
|
|
ErrChr(ERR_IUC, *CBfPtr);
|
|
DBGFEX(2,DbgFNm,"FAILURE, bad char after ^");
|
|
return FAILURE;
|
|
}
|
|
TmpChr &= '\077';
|
|
} else {
|
|
TmpChr = *CBfPtr;
|
|
}
|
|
switch (TmpChr) {
|
|
case CTRL_R:
|
|
case CTRL_Q:
|
|
if (++CBfPtr == EndArg) {
|
|
ErrMsg(ERR_ISS);
|
|
DBGFEX(2,DbgFNm,"FAILURE");
|
|
return FAILURE;
|
|
}
|
|
*BBfPtr++ = *CBfPtr;
|
|
break;
|
|
case CTRL_V:
|
|
case CTRL_W:
|
|
if (DoCtVW(EndArg, TmpChr) == FAILURE) {
|
|
DBGFEX(2,DbgFNm,"FAILURE, DoCtVW failed");
|
|
return FAILURE;
|
|
}
|
|
break;
|
|
case CTRL_E:
|
|
if (DoCtE(EndArg, XBfEnd) == FAILURE) {
|
|
DBGFEX(2,DbgFNm,"FAILURE, DoCtE failed");
|
|
return FAILURE;
|
|
}
|
|
break;
|
|
default:
|
|
if (CaseCv == LOWER) {
|
|
TmpChr = To_Lower(TmpChr);
|
|
} else if (CaseCv == UPPER) {
|
|
TmpChr = To_Upper(TmpChr);
|
|
}
|
|
*BBfPtr++ = TmpChr;
|
|
}
|
|
if (BBfPtr > XBfEnd) {
|
|
ErrMsg(ERR_STL); /* string too long */
|
|
DBGFEX(2,DbgFNm,"FAILURE, string too long");
|
|
return FAILURE;
|
|
}
|
|
++CBfPtr;
|
|
}
|
|
*XBfPtr = BBfPtr;
|
|
#if DEBUGGING
|
|
sprintf(DbgSBf,"string = \"%.*s\"", (int)(BBfPtr-XBfBeg), XBfBeg);
|
|
DbgFEx(2,DbgFNm,DbgSBf);
|
|
#endif
|
|
return SUCCESS;
|
|
}
|