NT4/private/windows/diamond/format.c
2020-09-30 17:12:29 +02:00

186 lines
6.3 KiB
C

/*** format.c - Parameter Formatter
*
* Microsoft Confidential
* Copyright (C) Microsoft Corporation 1994
* All Rights Reserved.
*
* Author:
* Benjamin W. Slivka
*
* History:
* 28-Apr-1994 bens Initial version
* 10-May-1994 bens Add braces support
*/
#include <memory.h>
#include <string.h>
#include "types.h"
#include "asrt.h"
#include "error.h"
#include "message.h"
#include "misc.h"
#include "inf.h"
#include "format.h"
#include "format.msg"
/*** SubstituteFormatString - Do parameter substitution
*
* NOTE: See format.h for entry/exit conditions.
*/
BOOL SubstituteFormatString(char *pszDst,
int cbDst,
char *pszSrc,
PFNFORMATPARM pfnfp,
void *pv,
PERROR perr)
{
char achParmName[cbPARM_NAME_MAX];
int cb;
int cch;
BOOL fParmSeen; // TRUE => parm seen in {braces}
BOOL fParmEmpty; // TRUE => all parms were empty in {opt}
char *pch;
char *pszAfterParm; // Points to first char after var subst.
char *pszOptStart; // Start of optional text
char *pszParmStart; // Points to first * in var substitution
//** Not in conditional test
pszOptStart = NULL;
//** Process string for parameters and conditional text
while (*pszSrc != '\0') {
switch (*pszSrc) {
case chFP_LBRACE:
pszSrc++; // Eat the left brace
if (*pszSrc == chFP_LBRACE) { // Have "{{"
//** Collapse two {{ into one {
if (!copyBounded(&pszDst,&cbDst,&pszSrc,1)) {
goto error_copying;
}
}
else {
//** Make sure we're not already in a brace section
if (pszOptStart) {
ErrSet(perr,pszFMTERR_NESTED_BRACES,"%c%s",
chFP_LBRACE,pszSrc);
return FALSE;
}
pszOptStart = pszDst; // Save start of conditional text
fParmSeen = FALSE; // No parm seen, yet
fParmEmpty = TRUE; // Assume parm was empty
}
break;
case chFP_RBRACE:
pszSrc++; // Eat the right brace
if (*pszSrc == chFP_RBRACE) { // Have "}}"
//** Collapse two }} into one }
if (!copyBounded(&pszDst,&cbDst,&pszSrc,1)) {
goto error_copying;
}
}
else {
//** Make sure we are in a brace section
if (!pszOptStart) {
ErrSet(perr,pszFMTERR_RIGHT_WITH_NO_LEFT,"%c%c%s",
chFP_RBRACE,chFP_LBRACE,pszSrc);
return FALSE;
}
//** Omit text if we need to
if (fParmSeen && fParmEmpty) { // All parms were empty
//** Remove optional text
Assert(pszDst >= pszOptStart);
cbDst += pszDst - pszOptStart;
pszDst = pszOptStart;
}
//** Reset state variables
pszOptStart = NULL;
}
break;
case chFP_MARKER:
pszParmStart = pszSrc; // Save start for error messgages
pszSrc++; // Skip first *
if (*pszSrc == chFP_MARKER) { // Have "**"
//** Collapse two ** into one *
if (!copyBounded(&pszDst,&cbDst,&pszSrc,1)) {
goto error_copying;
}
}
else {
//** Attempt parameter substitution
pch = strchr(pszSrc,chFP_MARKER); // Finding ending *
if (!pch) { // No terminating *
ErrSet(perr,pszFMTERR_MISSING_SUBST,"%c%s",
chFP_MARKER,pszParmStart);
return FALSE;
}
pszAfterParm = pch+1; // Point after ending *
//** Extract parameter name
cch = pch - pszSrc; // Length of parameter name
if (cch >= sizeof(achParmName)) {
ErrSet(perr,pszFMTERR_PARM_NAME_TOO_LONG,"%d%s",
sizeof(achParmName)-1,pszParmStart);
return FALSE;
}
memcpy(achParmName,pszSrc,cch); // Copy it
achParmName[cch] = '\0'; // Terminate it
//** Get parameter value
if (-1 == (cb = (*pfnfp)(pszDst, // Destination
cbDst, // Space remaining
achParmName, // Parm name
pv, // Context
perr))) {
return FALSE; // Error already filled in
}
//** Adjust output buffer and space remaining
// NOTE: Don't count NUL byte, as we do that at the very end
Assert(cbDst >= cb);
pszDst += cb;
cbDst -= cb;
//** Remember we saw a parm, and if it was not empty
fParmSeen = TRUE;
if (cb > 0) {
fParmEmpty = FALSE; // At least one parm not empty
}
//** Skip over parameter name
pszSrc = pszAfterParm;
}
break;
default:
//** Just copy the character
if (!copyBounded(&pszDst,&cbDst,&pszSrc,1)) {
goto error_copying;
}
}
} /* while */
//** Make sure we didn't leave an open optional text section
if (pszOptStart) {
ErrSet(perr,pszFMTERR_MISSING_RIGHT_BRACE,"%c",chFP_RBRACE);
return FALSE;
}
//** Terminate processed string
if (cbDst == 0) { // No room for terminator
goto error_copying;
}
*pszDst++ = '\0'; // Terminate string
//** Success
return TRUE;
error_copying:
ErrSet(perr,pszFMTERR_COPYING_OVERFLOW,"%s",pszSrc);
return FALSE;
} /* SubstituteFormatString() */