Windows NT 4.0 source code leak
 
 
 
 
 
 

1890 lines
52 KiB

/*** debfmt.c - expression evaluator formatting routines
*
* GLOBAL
*
*
* LOCAL
*
*
*
* DESCRIPTION
* Expression evaluator formatting routines
*
*/
extern char Suffix;
typedef enum FMT_ret {
FMT_error,
FMT_none,
FMT_ok
} FMT_ret;
LOCAL void NEAR PASCAL Format (peval_t, uint, char FAR * FAR *, uint FAR *);
LOCAL void PASCAL EvalString (peval_t, char FAR * FAR *, uint FAR *);
LOCAL void NEAR PASCAL FormatExpand (peval_t, char FAR * FAR *, uint FAR *, char FAR * FAR *, ulong, PHDR_TYPE);
LOCAL void NEAR PASCAL FormatClass (peval_t, uint, char FAR * FAR * , uint FAR *);
LOCAL bool_t NEAR PASCAL FormatUDT (peval_t, char FAR * FAR *, uint FAR *);
LOCAL char FAR *NEAR PASCAL FormatVirtual (char FAR *, CV_typ_t, peval_t, PEEHSTR);
LOCAL FMT_ret NEAR PASCAL VerifyFormat (peval_t, PEEFORMAT, char FAR * FAR *, uint FAR *);
BOOL UseUnicode( peval_t pv );
BOOL BaseIs16Bit( CV_typ_t utype );
static char accessstr[4][4] = {" ", "PV ", "PR ", "PB "};
struct typestr {
CV_typ_t typ;
uchar len;
#ifdef WIN32
char *name;
#else
char _based (_segname("_CODE")) *name;
#endif
};
#ifdef WIN32
//#define FMTSTR(name, type, mode, len, str) static char S##name[] = str;
#define FMTSTR(name, type, mode, len, str) static char name[] = str;
#else
#define FMTSTR(name, type, mode, len, str) static char _based(_segname("_CODE")) S##name[] = str;
#endif
#define PTRNAME(name, str)
#include "fmtstr.h"
#undef FMTSTR
#undef PTRNAME
#ifdef WIN32
static struct typestr nametype[] = {
#else
static struct typestr _based(_segname("_CODE")) nametype[] = {
#endif
//#define FMTSTR(name, type, mode, len, str) {(type | (mode << CV_MSHIFT)), len, S##name},
#define FMTSTR(name, type, mode, len, str) {(type | (mode << CV_MSHIFT)), len, name},
#define PTRNAME(name, str)
#include "fmtstr.h"
#undef FMTSTR
#undef PTRNAME
};
#define FMTSTR(name, type, mode, len, str)
#ifdef WIN32
//#define PTRNAME(name, str) static char S##name[] = str;
#define PTRNAME(name, str) static char name[] = str;
#else
#define PTRNAME(name, str) static char _based(_segname("_CODE")) S##name[] = str;
#endif
#include "fmtstr.h"
#undef FMTSTR
#undef PTRNAME
#ifdef WIN32
static char * ptrname[] = {
#else
static char _based(_segname("_CODE")) *_based(_segname("_CODE")) ptrname[] = {
#endif
#define FMTSTR(name, type, mode, len, str)
//#define PTRNAME(name, str) S##name,
#define PTRNAME(name, str) name,
#include "fmtstr.h"
#undef FMTSTR
#undef PTRNAME
};
#define typecount (sizeof (nametype) / sizeof (nametype[0]))
bool_t fPtrAndString; // true if pointer AND string to be displayed
char *fmt_char[] = {
"0o%03.03o",
"%d",
"0x%02.02x"
};
char *fmt_uchar[] = {
"0o%03.03o",
"%u",
"0x%02.02x"
};
char *fmt_short[] = {
"0o%06.06ho",
"%hd",
"0x%04.04hx"
};
char *fmt_ushort[] = {
"0o%06.06ho",
"%hu",
"0x%04.04hx"
};
char *fmt_long[] = {
"0o%011.011lo",
"%ld",
"0x%08.08lx"
};
char *fmt_ulong[] = {
"0o%011.011lo",
"%lu",
"0x%08.08lx"
};
char *bailout = "\x006""??? * ";
/** FormatCXT - format context packet
*
* status = FormatCXT (pCXT, ppbuf, pbuflen);
*
* Entry pCXT = pointer to context
* ppbuf = pointer pointer to buffer
* pbuflen = pointer to buffer length
*
* Exit context formatted into buffer as a context operator
* *pcount = space remaining in buffer
*
* Returns EENONE if no error
* EEGENERAL if error
*/
ushort PASCAL FormatCXT (PCXT pCXT, PEEHSTR phStr, BOOL fAbbreviated)
{
HMOD hMod;
HPROC hProc;
HSF hsf;
HEXE hExe;
SYMPTR pProc;
char FAR *pFile;
char FAR *pExe;
char FAR *pStr;
uint len = 6;
hMod = SHHMODFrompCXT (pCXT);
hProc = SHHPROCFrompCXT (pCXT);
if ((hMod == 0) && (hProc == 0)) {
if ((*phStr = MHMemAllocate (10)) != 0) {
pStr = MHMemLock (*phStr);
*pStr = 0;
MHMemUnLock (*phStr);
return (EENOERROR);
}
}
hsf = SLHsfFromPcxt (pCXT);
hExe = SHHexeFromHmod (hMod);
if (fAbbreviated) {
pExe = SHGetModNameFromHexe( hExe );
} else {
pExe = SHGetExeName( hExe );
}
if (!pExe) {
//
// we can't generate a CXT if we can't get the exe name
//
return EECATASTROPHIC;
}
pFile = SLNameFromHsf (hsf) ;
// it is possible to get the exe name, but not source
// file/line information (ex. a public) In this case we will use
// pExe instead of pFile (ie. {,,foob.exe} )
if (hProc != 0) {
switch ((pProc = (SYMPTR)MHOmfLock ((HDEP)hProc))->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
len += ((PROCPTR16)pProc)->name[0];
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED)
case S_LPROC32:
case S_GPROC32:
len += ((PROCPTR32)pProc)->name[0];
break;
#endif
case S_LPROCMIPS:
case S_GPROCMIPS:
len += ((PROCPTRMIPS)pProc)->name[0];
break;
default:
DASSERT (FALSE);
MHOmfUnLock ((HDEP)hProc);
return (EECATASTROPHIC);
}
}
if ( pFile ) {
len += *pFile + (int)_fstrlen (pExe) ;
}
else {
len += (int)_fstrlen (pExe) ;
}
if (fAbbreviated) {
len = max( 16, len );
}
if ((*phStr = MHMemAllocate (len)) != 0) {
pStr = MHMemLock (*phStr);
if (fAbbreviated) {
strcpy(pStr,pExe);
#ifdef DBCS
CharUpper(pStr);
#else
_strupr(pStr);
#endif
strcat (pStr,"!");
MHMemUnLock (*phStr);
} else {
_fstrcpy (pStr, "{");
if (hProc != 0) {
switch (pProc->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
_fstrncat (pStr, &((PROCPTR16)pProc)->name[1],
((PROCPTR16)pProc)->name[0]);
break;
#endif
case S_LPROC32:
case S_GPROC32:
_fstrncat (pStr, &((PROCPTR32)pProc)->name[1],
((PROCPTR32)pProc)->name[0]);
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
_fstrncat (pStr, &((PROCPTRMIPS)pProc)->name[1],
((PROCPTRMIPS)pProc)->name[0]);
break;
}
}
_fstrcat (pStr, ",");
if ( pFile ) {
_fstrncat (pStr, pFile + 1, *pFile);
}
_fstrcat (pStr, ",");
_fstrcat (pStr, pExe);
_fstrcat (pStr, "}");
MHMemUnLock (*phStr);
}
}
else {
MHOmfUnLock ((HDEP)hProc);
return (EECATASTROPHIC);
}
MHOmfUnLock ((HDEP)hProc);
return (EENOERROR);
}
/** FormatType - format type string
*
* FormatType (pv, ppbuf, pcount, ppName, select, pHdr);
*
* Entry pv = pointer to value node
* ppbuf = pointer pointer to buffer
* pcount = pointer to buffer length
* ppName = pointer to name if not null
* select = selection mask
* pHdr = pointer to structure describing formatting
*
* Exit type formatted into buffer
* *pcount = space remaining in buffer
* *pHdr updated
*
* Returns none
*/
void PASCAL FormatType (peval_t pv, char FAR * FAR *buf, uint FAR *buflen,
char FAR * FAR *ppName, ulong select, PHDR_TYPE pHdr)
{
eval_t evalT;
peval_t pvT = &evalT;
uint skip = 1;
int len;
int i;
char FAR *tname;
CV_typ_t type;
#if defined (NEVR)
#if !defined (C_ONLY)
if (EVAL_ACCESS (pv) != 0) {
len = min (*buflen, ( uint ) 3);
_fstrncpy (*buf, accessstr[EVAL_ACCESS (pv)], len);
*buf += len;
*buflen -= len;
}
#endif
#endif
if (EVAL_IS_CONST (pv)) {
len = min (*buflen, 6);
_fstrncpy (*buf, "const ", len);
*buf += len;
*buflen -= len;
}
else if (EVAL_IS_VOLATILE (pv)) {
len = min (*buflen, 9);
_fstrncpy (*buf, "volatile ", len);
*buf += len;
*buflen -= len;
}
if (CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
switch (EVAL_TYP (pv)) {
default:
for (i = 0; i < typecount - 1; i++) {
if (nametype[i].typ == EVAL_TYP (pv))
break;
}
// copy type string and add blank afterwards
len = min (*buflen, (uint)(nametype[i].len));
_fstrncpy (*buf, nametype[i].name, len);
*buf += len;
*buflen -= len;
break;
case T_NCVPTR:
tname = "\x007""near * ";
goto formatmode;
case T_HCVPTR:
tname = "\x007""huge * ";
goto formatmode;
case T_FCVPTR:
tname = "\x006""far * ";
formatmode:
*pvT = *pv;
SetNodeType (pvT, PTR_UTYPE (pv));
type = EVAL_TYP (pvT);
if ((type == T_NCVPTR) || (type == T_FCVPTR) ||
(type == T_HCVPTR)) {
// we are in a bind here. The type generator messed
// up and generated a created type pointing to a created
// type. we are going to bail out here.
len = min (*buflen, (uint) *bailout);
_fstrncpy (*buf, bailout + 1, len);
*buflen -= len;
*buf += len;
}
else {
FormatType (pvT, buf, buflen, 0, select, pHdr);
}
len = min (*buflen, (uint) *tname);
_fstrncpy (*buf, tname + 1, len);
*buflen -= len;
*buf += len;
break;
}
}
else {
if (FormatUDT (pv, buf, buflen) == FALSE) {
FormatExpand (pv, buf, buflen, ppName, select, pHdr);
}
}
if (ppName != NULL && *ppName != NULL) {
len = (int)_fstrlen (*ppName);
len = min (len, (int) *buflen);
pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
pHdr->lenname = len;
_fstrncpy (*buf, *ppName, len);
*buflen -= len;
*buf += len;
*ppName = NULL;
}
}
/** FormatExpand - format expanded type definition
*
* FormatExpand (pv, ppbuf, pbuflen, ppName, select)
*
* Entry pv = pointer to value node
* ppbuf = pointer to pointer to buffer
* pbuflen = pointer to space remaining in buffer
* ppName = pointer to name to insert after type if not null
* select = selection mask
* pHdr = pointer to type formatting header
*
* Exit buffer contains formatted type
* ppbuf = end of formatted string
* pbuflen = space remaining in buffer
*
* Returns none
*/
LOCAL void NEAR PASCAL FormatExpand (peval_t pv, char FAR * FAR *buf,
uint FAR *buflen, char FAR * FAR *ppName, ulong select, PHDR_TYPE pHdr)
{
eval_t evalT;
peval_t pvT = &evalT;
uint skip = 1;
int len;
HTYPE hType;
plfEasy pType;
ushort model;
ulong count;
char tempbuf[33];
CV_typ_t rvtype;
CV_typ_t mclass;
CV_call_e call;
ushort cparam;
CV_typ_t parmtype;
CV_typ_t thistype;
char FAR *movestart;
int movelen;
int movedist;
if ((hType = THGetTypeFromIndex (EVAL_MOD (pv), EVAL_TYP (pv))) == 0) {
return;
}
pType = (plfEasy)(&((TYPPTR)(MHOmfLock ((HDEP)hType)))->leaf);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
skip = offsetof (lfClass, data[0]);
RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
len = *(((char FAR *)&(pType->leaf)) + skip);
len = min (len, (int) *buflen);
_fstrncpy (*buf, ((char FAR *)pType) + skip + 1, len);
*buflen -= len;
*buf += len;
if (*buflen > 1) {
**buf = ' ';
(*buf)++;
(*buflen)--;
}
MHOmfUnLock ((HDEP)hType);
break;
case LF_UNION:
skip = offsetof (lfUnion, data[0]);
RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
len = *(((char FAR *)&(pType->leaf)) + skip);
len = min (len, (int) *buflen);
_fstrncpy (*buf, ((char FAR *)pType) + skip + 1, len);
*buflen -= len;
*buf += len;
if (*buflen > 1) {
**buf = ' ';
(*buf)++;
(*buflen)--;
}
MHOmfUnLock ((HDEP)hType);
break;
case LF_ENUM:
skip = offsetof (lfEnum, Name[0]);
len = ((plfEnum)pType)->Name[0];
len = min (len, (int) *buflen);
_fstrncpy (*buf, &((plfEnum)pType)->Name[1], len);
*buflen -= len;
*buf += len;
if (*buflen > 1) {
**buf = ' ';
(*buf)++;
(*buflen)--;
}
MHOmfUnLock ((HDEP)hType);
break;
case LF_POINTER:
// set up a node to evaluate this field
model = ((plfPointer)pType)->attr.ptrtype;
if (((plfPointer)pType)->attr.ptrmode == (uchar)CV_PTR_MODE_REF) {
model = CV_PTR_UNUSEDPTR;
}
// format the underlying type
*pvT = *pv;
EVAL_TYP (pvT) = ((plfPointer)pType)->utype;
MHOmfUnLock ((HDEP)hType);
SetNodeType (pvT, EVAL_TYP (pvT));
FormatType (pvT, buf, buflen, 0, select, pHdr);
len = min (*buflen, (uint) *ptrname[model]);
_fstrncpy (*buf, ptrname[model] + 1, len);
*buflen -= len;
*buf += len;
break;
case LF_ARRAY:
*pvT = *pv;
EVAL_TYP (pvT) = ((plfArray)(&pType->leaf))->elemtype;
skip = offsetof (lfArray, data[0]);
count = RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
MHOmfUnLock ((HDEP)hType);
SetNodeType (pvT, EVAL_TYP (pvT));
// continue down until the underlying type is reached
FormatType (pvT, buf, buflen, ppName, select, pHdr);
if ((ppName != NULL) && (*ppName != NULL)) {
len = (int)_fstrlen (*ppName);
len = min (len, (int) *buflen);
_fstrncpy (*buf, *ppName, len);
pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
pHdr->lenname = len;
*buflen -= len;
*buf += len;
*ppName = NULL;
}
// display size of array or * if size unknown. We have to
// move the trailing part of the string down if it already
// set so that the array dimensions come out in the proper
// order
if (count != 0) {
_ultoa (count / TypeSize (pvT), tempbuf, 10);
len = _fstrlen (tempbuf);
}
else {
*tempbuf = '?';
*(tempbuf + 1) = 0;
len = 1;
}
if (*buflen >= 2) {
if (pHdr->offtrail == 0) {
pHdr->offtrail = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
movestart = (char FAR *)pHdr + sizeof (HDR_TYPE) +
pHdr->offtrail;
movelen = 0;
movedist = 0;
}
else {
movestart = (char FAR *)pHdr + sizeof (HDR_TYPE) +
pHdr->offtrail;
movelen = _fstrlen (movestart);
movedist = _fstrlen (tempbuf) + 2;
movelen = min ((int) *buflen, movelen);
_fmemmove (movestart + movedist, movestart, movelen);
}
*movestart++ = '[';
_fmemmove (movestart, tempbuf, len);
movestart += len;
*movestart++ = ']';
*buf += len + 2;
*buflen -= len + 2;
}
break;
case LF_PROCEDURE:
mclass = 0;
rvtype = ((plfProc)pType)->rvtype;
call = ((plfProc)pType)->calltype;
cparam = ((plfProc)pType)->parmcount;
parmtype = ((plfProc)pType)->arglist;
MHOmfUnLock ((HDEP)hType);
FormatProc (pv, buf, buflen, ppName, rvtype, mclass, call,
cparam, parmtype, select, pHdr);
break;
#if !defined (C_ONLY)
case LF_MFUNCTION:
rvtype = ((plfMFunc)pType)->rvtype;
mclass = ((plfMFunc)pType)->classtype;
call = ((plfMFunc)pType)->calltype;
thistype = ((plfMFunc)pType)->thistype;
cparam = ((plfMFunc)pType)->parmcount;
parmtype = ((plfMFunc)pType)->arglist;
MHOmfUnLock ((HDEP)hType);
FormatProc (pv, buf, buflen, ppName, rvtype, mclass, call,
cparam, parmtype, select, pHdr);
break;
#else
Unreferenced(thistype);
#endif
case LF_MODIFIER:
if (*buflen >= 6) {
if (((plfModifier)pType)->attr.MOD_const == TRUE) {
_fstrncpy (*buf, "const ", 6);
*buf += 6;
*buflen -= 6;
}
}
if (*buflen >= 9) {
if (((plfModifier)pType)->attr.MOD_volatile == TRUE) {
_fstrncpy (*buf, "volatile ", 9);
*buf += 9;
*buflen -= 9;
}
}
EVAL_TYP (pv) = ((plfModifier)pType)->type;
MHOmfUnLock ((HDEP)hType);
FormatType (pv, buf, buflen, ppName, select, pHdr);
break;
case LF_LABEL:
break;
default:
MHOmfUnLock ((HDEP)hType);
break;
}
}
LOCAL bool_t NEAR PASCAL FormatUDT (peval_t pv, char FAR * FAR *buf,
uint FAR *buflen)
{
search_t Name;
UDTPTR pUDT;
uint len;
// Slow ineffective search disabled jsg 2/1/92
//
// This code would search all symbols for typedefs to the current type index.
// This was making the local window repaint too sluggish, since 'FormatUDT'
// can be called many times per line.
//
Unreferenced( Name );
Unreferenced( len );
Unreferenced( pUDT );
Unreferenced( pv );
Unreferenced( buf );
Unreferenced( buflen );
pExState->err_num = ERR_NONE;
return (FALSE);
}
/** FormatProc - format proc or member function
*
* FormatProc (pv. buf, buflen, ppName, rvtype, mclass, call,
* cparam, paramtype, select)
*/
void NEAR PASCAL
FormatProc (
peval_t pv,
char FAR * FAR * buf,
uint FAR * buflen,
char FAR * FAR * ppName,
CV_typ_t rvtype,
CV_typ_t mclass,
CV_call_e call,
ushort cparam,
CV_typ_t paramtype,
ulong select,
PHDR_TYPE pHdr
)
{
eval_t evalT;
peval_t pvT;
HTYPE hArg;
plfArgList pArg;
ushort noffset = 1;
short len;
bool_t farcall;
ushort argCnt;
Unreferenced( mclass );
pvT = &evalT;
*pvT = *pv;
if (GettingChild == FALSE && (select & 1) == 0 ) {
// output function return type if we are not getting a child TM.
// If we are getting a child tm and the function type is included,
// the subsequent parse of the generated expression will fail
// because the parse cannot handle
// type fcn (..........
// OR...
// if select == 0x1 then this is a request to format procs
// without the return type (for BPs etc)
EVAL_TYP (pvT) = (rvtype == 0)? T_VOID: rvtype;
FormatType (pvT, buf, buflen, NULL, select, pHdr);
//M00KLUDGE - need to output call and model here
switch (call) {
case CV_CALL_NEAR_C:
//near C call - caller pops stack
call = FCN_C;
farcall = FALSE;
break;
case CV_CALL_FAR_C:
// far C call - caller pops stack
call = FCN_C;
farcall = TRUE;
break;
case CV_CALL_NEAR_PASCAL:
// near pascal call - callee pops stack
call = FCN_PASCAL;
farcall = FALSE;
break;
case CV_CALL_FAR_PASCAL:
// far pascal call - callee pops stack
call = FCN_PASCAL;
farcall = TRUE;
break;
case CV_CALL_NEAR_FAST:
// near fast call - callee pops stack
call = FCN_FAST;
farcall = FALSE;
break;
case CV_CALL_FAR_FAST:
// far fast call - callee pops stack
call = FCN_FAST;
farcall = TRUE;
break;
case CV_CALL_NEAR_STD:
// near fast call - callee pops stack
call = FCN_STD;
farcall = FALSE;
break;
case CV_CALL_FAR_STD:
// far fast call - callee pops stack
call = FCN_STD;
farcall = TRUE;
break;
default:
DASSERT (FALSE);
call = 0;
farcall = FALSE;
break;
}
}
// output function name
if ((ppName != NULL) && (*ppName != NULL)) {
len = (int)_fstrlen (*ppName);
len = min (( uint ) len, *buflen);
pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
pHdr->lenname = len;
_fstrncpy (*buf, *ppName, len);
*buflen -= len;
*buf += len;
*ppName = NULL;
}
if (*buflen > 1) {
pHdr->offtrail = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
**buf = '(';
(*buf)++;
(*buflen)--;
}
if (cparam == 0) {
EVAL_TYP (pvT) = T_VOID;
FormatType (pvT, buf, buflen, NULL, select, pHdr);
}
else {
if ((hArg = THGetTypeFromIndex (EVAL_MOD (pv), paramtype)) == 0) {
return;
}
argCnt = 0;
while (argCnt < cparam) {
pArg = (plfArgList)((&((TYPPTR)MHOmfLock ((HDEP)hArg))->leaf));
EVAL_TYP (pvT) = pArg->arg[argCnt];
MHOmfUnLock ((HDEP)hArg);
FormatType (pvT, buf, buflen, NULL, select, pHdr);
(*buf)--; (*buflen)--;
argCnt++;
if ((argCnt < cparam) && (*buflen > 2)) {
// insert a comma if there are further arguments
**buf = ',';
(*buf)++;
(*buflen)--;
**buf = ' ';
(*buf)++;
(*buflen)--;
}
}
}
if (*buflen > 1) {
**buf = ')';
(*buf)++;
(*buflen)--;
}
}
/** FormatNode - format node according to format string
*
* retval = FormatNode (phTM, radix, pFormat, phValue);
*
* Entry phTM = pointer to handle to TM
* radix = default radix for formatting
* pFormat = pointer to format string
* phValue = pointer to handle for display string
*
* Exit evaluation result formatted
*
* Returns EENOERROR if no error in formatting
* error number if error
*/
EESTATUS PASCAL FormatNode (PHTM phTM, uint Radix, PEEFORMAT pFormat,
PEEHSTR phszValue)
{
char islong = FALSE;
char fc = 0;
char FAR *buf;
uint buflen = FMTSTRMAX - 1;
eval_t evalT;
peval_t pv = &evalT;
char FAR *pExStr;
ushort retval = EECATASTROPHIC;
DASSERT (*phTM != 0);
if (*phTM == 0) {
return (retval);
}
if ((*phszValue = MHMemAllocate (FMTSTRMAX)) == 0) {
// unable to allocate memory for formatting
return (retval);
}
buf = (char FAR *)MHMemLock (*phszValue);
_fmemset (buf, 0, FMTSTRMAX);
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTM);
// Get expression string
pExStr = (char FAR *)MHMemLock (pExState->hExStr);
if (pExState->state.eval_ok == TRUE) {
*pv = pExState->result;
if ((EVAL_STATE (pv) == EV_lvalue) ||
(EVAL_STATE (pv) == EV_type) ||
(EVAL_STATE (pv) == EV_rvalue && EVAL_IS_PTR (pv))) {
// do nothing
}
else {
// this handles the case were the return result is a large
// structure.
pv = &pExState->result;
}
if (EVAL_IS_REF (pv)) {
if (!LoadSymVal (pv)) {
// unable to load value
goto formatexit;
}
EVAL_IS_REF (pv) = FALSE;
EVAL_STATE (pv) = EV_lvalue;
EVAL_SYM_OFF (pv) = EVAL_PTR_OFF (pv);
EVAL_SYM_SEG (pv) = EVAL_PTR_SEG (pv);
SetNodeType (pv, PTR_UTYPE (pv));
}
if (EVAL_IS_CLASS (pv)) {
// For structures and classes ignore format string and format
// according to element data types
EVAL_STATE (pv) = EV_rvalue;
goto format;
}
else if (EVAL_IS_ENUM (pv)) {
SetNodeType (pv, CLASS_UTYPE (pv));
}
// load value and format according to format string
if ((EVAL_STATE (pv) == EV_type) || !LoadSymVal (pv)) {
// unable to load value
retval = EEGENERAL;
if (pExState->err_num == ERR_NONE) {
pExState->err_num = ERR_NOTEVALUATABLE;
}
goto formatexit;
}
else {
switch (VerifyFormat (pv, pFormat, &buf, &buflen)) {
case FMT_error:
retval = EEGENERAL;
pExState->err_num = ERR_FORMAT;
goto formatexit;
case FMT_none:
goto format;
case FMT_ok:
retval = EENOERROR;
goto formatexit;
}
}
}
else {
// not evaluated, fail
retval = EEGENERAL;
pExState->err_num = ERR_NOTEVALUATABLE;
goto formatexit;
}
format:
retval = EENOERROR;
Format (pv, Radix, &buf, &buflen);
formatexit:
MHMemUnLock (pExState->hExStr);
pExState = NULL;
MHMemUnLock (*phszValue);
MHMemUnLock (*phTM);
return (retval);
}
/** VerifyFormat -
*
*
*/
LOCAL FMT_ret NEAR PASCAL VerifyFormat (peval_t pv, PEEFORMAT pFmtIn,
char FAR * FAR *buf, uint FAR *buflen)
{
char tempbuf[41];
char prefix = 0;
char fmtchar = 0;
char fmtcnt = 0;
char fmtcnt2 = 0;
ushort size = 0;
char FAR *pf;
char fmtstr[10];
ADDR addr;
ushort cnt;
DASSERT (*buflen > 40);
if (EVAL_TYP (pv) == T_VOID) {
// if the value is void, ignore all formatting
_fstrcpy (*buf, "<void>");
*buflen -= 6;
*buf += 6;
return (FMT_ok);
}
if (pFmtIn == NULL) {
pf = &pExStr[pExState->strIndex];
} else {
/*
* p is a special format character. It turns off string following
* pointers and is generally used for call stack code.
*/
if (*pFmtIn == 'p') {
fPtrAndString = FALSE;
return (FMT_none);
}
pf = pFmtIn;
}
if (*pf == ',') {
pf++;
}
while ((*pf != 0) && ((*pf == ' ') || (*pf == '\t'))) {
pf++;
}
if (*pf == 0) {
// add string to pointer display
fPtrAndString = TRUE;
return (FMT_none);
}
fPtrAndString = FALSE;
size = (ushort)TypeSize (pv);
if (*pf != 0) {
// extract the prefix character if it exists
switch (*pf) {
case 'h':
case 'l':
case 'L':
prefix = *pf++;
break;
}
// extract the format character
switch (*pf) {
case 'd':
if ((prefix != 'h') && (size > 2)) {
prefix = 'l';
}
fmtchar = *pf++;
break;
case 'i':
if ((prefix != 'h') && (size > 2)) {
prefix = 'l';
}
fmtchar = *pf++;
break;
case 'u':
if ((prefix != 'h') && (size > 2)) {
prefix = 'l';
}
fmtchar = *pf++;
break;
case 'o':
if ((prefix != 'h') && (size > 2)) {
fmtcnt = '1';
fmtcnt2 = '1';
prefix = 'l';
} else {
fmtcnt = '6';
}
fmtchar = *pf++;
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
/*
* Ensure that the value is of type float
*/
if (!CV_TYP_IS_REAL( EVAL_TYP( pv ))) {
return FMT_error;
}
/*
* Validate for legal prefix character
*/
if (prefix == 0) {
;
} else if (prefix == 'h') {
return (FMT_error);
} else if (prefix == 'l') {
fmtcnt = '#';
} else if (prefix == 'L') {
#ifdef LONG_DOUBLE_64
prefix = 'l';
fmtcnt = '#';
#endif
#ifdef LONG_DOUBLE_80
/*
* Hack since we don't have code for 'Lf' convert
* to lf
*/
if ((fmtchar == 'f') || (fmtchar == 'F')) {
EVAL_DOUBLE(pv) = R10CastToDouble(EVAL_LDOUBLE(pv));
prefix = 'l';
fmtcnt = '#';
}
#endif
} else {
return FMT_error;
}
fmtchar = *pf++;
break;
case 'c':
case 's':
switch ( prefix ) {
case 0:
if ( ((size == 2) && (*pf == 'c')) ||
UseUnicode(pv) ) {
prefix = 'l';
} else {
prefix = 'h';
}
break;
case 'l':
case 'h':
break;
default:
return (FMT_error);
}
fmtchar = *pf++;
break;
case 'x':
case 'X':
if ((prefix != 'h') && (size > 2)) {
// note that only the first 8 bytes of a long double
// will be displayed
fmtcnt = '8';
prefix = 'l';
}
else {
fmtcnt = '4';
}
fmtchar = *pf++;
break;
default:
return (FMT_error);
}
if ((*pf != 0) && !isspace (*pf)) {
return (FMT_error);
}
pf = fmtstr;
*pf++ = '%';
if (fmtcnt != 0) {
*pf++ = fmtcnt;
if (fmtcnt2 != 0) {
*pf++ = fmtcnt2;
}
}
if (prefix != 0) {
*pf++ = prefix;
}
*pf++ = fmtchar;
*pf = 0;
switch (fmtchar) {
case 'd':
case 'i':
case 'u':
cnt = sprintf (tempbuf, fmtstr, EVAL_LONG (pv));
break;
case 'o':
pf = fmtstr;
*pf++ = '0';
*pf++ = 'o';
*pf++ = '%';
*pf++ = '0';
if (fmtcnt != 0) {
*pf++ = fmtcnt;
if (fmtcnt2 != 0) {
*pf++ = fmtcnt2;
}
}
if (prefix != 0) {
*pf++ = prefix;
}
*pf++ = fmtchar;
*pf = 0;
cnt = sprintf (tempbuf, fmtstr, EVAL_LONG (pv));
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
if (prefix == 'l') {
cnt = _snprintf (tempbuf, sizeof(tempbuf), fmtstr, EVAL_DOUBLE (pv));
} else if (prefix == 'L') {
#ifdef LONG_DOUBLE_80
_uldtoa((_ULDOUBLE *) &EVAL_LDOUBLE( pv ), 25, tempbuf);
cnt = strlen(tempbuf);
if ((fmtchar == 'E') || (fmtchar == 'G')) {
_strupr(tempbuf);
}
#endif
#ifdef LONG_DOUBLE_64
DASSERT(FALSE);
#endif
} else {
cnt = _snprintf (tempbuf, sizeof(tempbuf), fmtstr, EVAL_FLOAT (pv));
}
break;
case 'c':
{
unsigned short s;
pf = fmtstr;
*pf++ = '\'';
if ( prefix == 'l' ) {
s = EVAL_USHORT(pv);
} else {
s = (unsigned short)EVAL_CHAR(pv);
}
if (s != 0) {
// if the value is not zero, then display it.
// otherwise, display ''
*pf++ = '%';
*pf++ = fmtchar;
}
*pf++ = '\'';
*pf = 0;
//
// NOTENOTE ramonsa - Convert unicode if necessary.
//
cnt = sprintf (tempbuf, fmtstr, s);
}
break;
case 's':
if (EVAL_IS_ADDR (pv)) {
// Need to set Evaluating to 1 to force Normalization
// of based ptrs in CastNode (and reset to 0 immediately
// afterwards
Evaluating = TRUE;
if ( prefix == 'l' ) {
CastNode (pv, T_PFWCHAR, T_PFWCHAR);
} else {
CastNode (pv, T_PFCHAR, T_PFCHAR);
}
EvalString (pv, buf, buflen);
Evaluating = FALSE;
return (FMT_ok);
}
else {
return (FMT_error);
}
break;
case 'x':
case 'X':
if (EVAL_IS_PTR (pv)) {
addr = EVAL_PTR (pv);
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
/*
* Treat near pointers the same as far pointers
* for formatting purposes. Thus if you would
* display a segment for the far pointer then
* also display it for the near pointer.
*/
if ((EVAL_IS_NPTR32(pv)) || (EVAL_IS_FPTR32(pv))) {
DASSERT( ADDR_IS_FLAT( addr ) );
}
EEFormatAddr(&addr, tempbuf, sizeof(tempbuf),
(fmtchar == 'x') ? EEFMT_LOWER : 0);
cnt = strlen(tempbuf);
}
else {
pf = fmtstr;
*pf++ = '0';
*pf++ = fmtchar;
*pf++ = '%';
*pf++ = '.';
if (fmtcnt != 0) {
*pf++ = fmtcnt;
}
if (prefix != 0) {
*pf++ = prefix;
}
*pf++ = fmtchar;
*pf = 0;
cnt = sprintf (tempbuf, fmtstr, EVAL_ULONG (pv));
}
break;
}
if ((cnt == -1) || (cnt > (ushort)*buflen)) {
strcpy(tempbuf, "******");
cnt = 6;
}
_fstrncpy (*buf, tempbuf, cnt + 1);
*buf += cnt;
*buflen -= cnt;
return (FMT_ok);
}
}
/* Format - format data
*
*/
LOCAL void NEAR PASCAL Format (peval_t pv, uint radix, char FAR * FAR *buf,
uint FAR *plen)
{
char tempbuf[FMTSTRMAX];
char FAR *pTempBuf = tempbuf;
int cnt;
ushort isfloat = FALSE;
HSYM hProc = 0;
// M00FLAT32
SYMPTR pProc;
char FAR *pc = NULL;
uint cbTempBuf;
uint FAR *pcbTempBuf = &cbTempBuf;
ushort iRadix;
ADDR addr;
CV_typ_t type;
EEHSTR hStr = 0;
if (*plen < 5 ) {
return;
}
if (EVAL_IS_BITF (pv)) {
// for a bitfield, change the type to the underlying type
SetNodeType (pv, BITF_UTYPE (pv));
}
if (EVAL_IS_CLASS (pv)) {
FormatClass (pv, radix, buf, plen);
return;
}
else if (EVAL_IS_ENUM (pv)) {
SetNodeType (pv, CLASS_UTYPE (pv));
}
if (CV_IS_PRIMITIVE (EVAL_TYP (pv)) && !EVAL_IS_PTR (pv)) {
if (EVAL_TYP (pv) == T_VOID) {
_fstrcpy (tempbuf, "<void>");
}
else {
// establish format string index
switch (radix) {
case 8:
iRadix = 0;
break;
case 10:
iRadix = 1;
break;
default:
DASSERT (FALSE);
// note fall through
case 16:
iRadix = 2;
break;
}
switch (EVAL_TYP (pv)) {
case T_CHAR:
case T_RCHAR:
case T_UCHAR:
if (EVAL_TYP (pv) == T_UCHAR) {
sprintf (tempbuf, fmt_uchar[iRadix], EVAL_CHAR (pv));
} else {
sprintf (tempbuf, fmt_char[iRadix], EVAL_CHAR (pv));
}
if (strlen(tempbuf) > 4) {
strcpy(&tempbuf[2],&tempbuf[strlen(tempbuf)-2]);
}
if (fPtrAndString) {
if (EVAL_CHAR (pv) == 0) {
sprintf( &tempbuf[strlen(tempbuf)], " ''" );
} else {
sprintf( &tempbuf[strlen(tempbuf)], " '%c'", EVAL_CHAR(pv) );
}
}
break;
case T_SHORT:
case T_INT2:
sprintf (tempbuf, fmt_short[iRadix], EVAL_SHORT (pv));
break;
case T_SEGMENT:
case T_USHORT:
case T_UINT2:
default:
sprintf (tempbuf, fmt_ushort[iRadix], EVAL_USHORT (pv));
break;
case T_LONG:
case T_INT4:
sprintf (tempbuf, fmt_long[iRadix], EVAL_LONG (pv));
break;
case T_ULONG:
case T_UINT4:
sprintf (tempbuf, fmt_ulong[iRadix], EVAL_ULONG (pv));
break;
case T_QUAD:
case T_INT8:
EEFormatMemory(tempbuf,
17,
(LPBYTE) &EVAL_QUAD(pv),
64,
fmtInt | fmtZeroPad,
radix);
break;
case T_UQUAD:
case T_UINT8:
EEFormatMemory(tempbuf,
17,
(LPBYTE) &EVAL_QUAD(pv),
64,
fmtUInt | fmtZeroPad,
radix);
break;
case T_REAL32:
sprintf (tempbuf, "%#g", EVAL_FLOAT (pv));
isfloat = TRUE;
break;
case T_REAL64:
sprintf (tempbuf, "%#.15lg", EVAL_DOUBLE (pv));
isfloat = TRUE;
break;
#ifdef LONG_DOUBLE_80
case T_REAL80:
_uldtoa((_ULDOUBLE *) &EVAL_LDOUBLE( pv ), 25, tempbuf);
isfloat = TRUE;
break;
#endif
}
}
}
else if (EVAL_IS_ADDR (pv)) {
addr = EVAL_PTR (pv);
if (EVAL_IS_BASED (pv)) {
cbTempBuf = sprintf (tempbuf, "0x%04lX", (ulong)EVAL_PTR_OFF (pv));
}
else if (EVAL_IS_PTR (pv) && EVAL_IS_REG (pv)) {
if (EVAL_IS_NPTR (pv)) {
EEFormatAddress(pExState->frame.DS, EVAL_PTR_OFF (pv),
tempbuf, sizeof(tempbuf), 0);
cbTempBuf = strlen(tempbuf);
}
else if (EVAL_IS_NPTR32 (pv)) {
EEFormatAddress(pExState->frame.DS, EVAL_PTR_OFF (pv),
tempbuf, sizeof(tempbuf), EEFMT_32);
cbTempBuf = strlen(tempbuf);
}
else {
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
if (EVAL_IS_FPTR32(pv)) {
DASSERT( ADDR_IS_FLAT( addr ) );
}
EEFormatAddr(&addr, tempbuf, sizeof(tempbuf), 0);
cbTempBuf = strlen(tempbuf);
}
}
else if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR (pv)) {
// if it is a near ptr we will treat is as a far ptr
// since we always carry around the seg & offset
// even if it is near.
// DASSERT( EVAL_PTR_SEG (pv) != 0);
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
cbTempBuf = strlen(tempbuf);
}
else if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR32 (pv)) {
// if it is a near ptr we will treat is as a far ptr
// since we always carry around the seg & offset
// even if it is near.
// DASSERT( EVAL_PTR_SEG (pv) != 0);
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
DASSERT (ADDR_IS_FLAT( addr ));
EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
cbTempBuf = strlen(tempbuf);
}
else {
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
cbTempBuf = strlen(tempbuf);
}
if (!EVAL_IS_DPTR (pv)) {
addr = EVAL_PTR (pv);
if (!ADDR_IS_LI (addr)) {
SHUnFixupAddr (&addr);
}
if (SHGetNearestHsym (&addr, EVAL_MOD (pv), EECODE, &hProc) == 0) {
// the address exactly matches a symbol
pProc = (SYMPTR)MHOmfLock( (HDEP)hProc );
switch ( pProc->rectyp ) {
char FAR *TempName;
CV_typ_t TempType;
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
TempName = ((PROCPTR16)pProc)->name;
TempType = ((PROCPTR16)pProc)->typind;
MHOmfUnLock ((HDEP)hProc);
pc = FormatVirtual ( TempName, TempType, pv, &hStr);
break;
case S_THUNK16:
pc = ((THUNKPTR16)pProc)->name;
MHOmfUnLock ((HDEP)hProc);
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED)
case S_LPROC32:
case S_GPROC32:
TempName = ((PROCPTR32)pProc)->name;
TempType = ((PROCPTR32)pProc)->typind;
MHOmfUnLock ((HDEP)hProc);
pc = FormatVirtual ( TempName, TempType, pv, &hStr);
break;
case S_THUNK32:
pc = ((THUNKPTR32)pProc)->name;
MHOmfUnLock ((HDEP)hProc);
break;
#endif
case S_LPROCMIPS:
case S_GPROCMIPS:
TempName = ((PROCPTRMIPS)pProc)->name;
TempType = ((PROCPTRMIPS)pProc)->typind;
MHOmfUnLock ((HDEP)hProc);
pc = FormatVirtual ( TempName, TempType, pv, &hStr);
break;
}
}
}
// M00KLUDGE - display strings of chars
if ((fPtrAndString == TRUE) && (EVAL_IS_PTR (pv))) {
type = EVAL_TYP (pv);
if (EVAL_IS_BASED (pv)) {
type = PTR_UTYPE (pv);
}
if (((type & (CV_TMASK | CV_SMASK)) == T_CHAR) ||
((type & (CV_TMASK | CV_SMASK)) == T_UCHAR) ||
((type & (CV_TMASK | CV_SMASK)) == T_RCHAR)) {
// Need to set Evaluating to 1 to force Normalization
// of based ptrs in CastNode (and reset to 0 immediately
// afterwards)
tempbuf[cbTempBuf] = ' ';
Evaluating = TRUE;
CastNode (pv, T_PFCHAR, T_PFCHAR);
Evaluating = FALSE;
pTempBuf += cbTempBuf + 1;
*pcbTempBuf = FMTSTRMAX - cbTempBuf - 1;
EvalString (pv, &pTempBuf, pcbTempBuf);
} else if ( ((type & (CV_TMASK | CV_SMASK)) == T_WCHAR) ||
((Suffix == 'W') && ((type & (CV_TMASK | CV_SMASK)) == T_USHORT)) ) {
tempbuf[cbTempBuf] = ' ';
Evaluating = TRUE;
CastNode (pv, T_PFWCHAR, T_PFWCHAR);
Evaluating = FALSE;
pTempBuf += cbTempBuf + 1;
*pcbTempBuf = FMTSTRMAX - cbTempBuf - 1;
EvalString (pv, &pTempBuf, pcbTempBuf);
}
}
}
else {
_fstrcpy (tempbuf,"?CANNOT DISPLAY");
}
cnt = (int)_fstrlen (tempbuf);
cnt = min (*plen, ( uint ) cnt);
_fstrncpy (*buf, tempbuf, cnt);
*plen -= cnt;
*buf += cnt;
if (pc != NULL) {
cnt = min (*plen, ( uint ) ( *pc + 1 ));
**buf = ' ';
(*buf)++;
_fstrncpy (*buf, pc + 1, cnt - 1);
*plen -= cnt;
*buf += cnt;
}
if (hStr != 0) {
MHMemUnLock (hStr);
MHMemFree (hStr);
}
return;
}
LOCAL void NEAR PASCAL FormatClass(
peval_t pv,
uint radix,
char **buf,
uint *buflen
)
{
int len;
ADDR addr;
SHREG reg;
addr = pv->addr;
if (EVAL_IS_BPREL(pv)) {
GetAddrOff( addr ) += pExState->frame.BP.off;
GetAddrSeg( addr ) = pExState->frame.SS;
ADDR_IS_LI( addr ) = FALSE;
} else if (EVAL_IS_REGREL(pv)) {
reg.hReg = EVAL_REGREL(pv);
GetReg( &reg, pCxt );
GetAddrOff( addr ) += reg.Byte4;
GetAddrSeg( addr ) = pExState->frame.SS;
ADDR_IS_LI( addr ) = FALSE;
}
SHUnFixupAddr( &addr );
SHFixupAddr( &addr );
**buf = 0;
EEFormatAddr( &addr, *buf, *buflen, EEFMT_32 );
len = strlen( *buf );
*buflen -= len;
*buf += len;
len = min (*buflen, 6);
_fstrncpy (*buf, " {...}", len);
*buflen -= len;
*buf += len;
return;
}
/*
* EvalString
*
* Evaluate an expression whose format string contains an 's'.
*/
LOCAL void PASCAL EvalString (peval_t pv, char FAR *FAR *buf,
uint FAR *buflen)
{
ADDR addr;
short count;
BOOL fUnicode;
ushort *p, *q;
int len;
fUnicode = (EVAL_TYP(pv) == T_PFWCHAR);
if(*buflen < 3) return;
**buf = '\"';
(*buf)++;
(*buflen)--;
addr = EVAL_PTR (pv);
if (ADDR_IS_LI (addr)) {
SHFixupAddr (&addr);
}
if (EVAL_IS_PTR (pv) && (EVAL_IS_NPTR (pv) || EVAL_IS_NPTR32 (pv))) {
addr.addr.seg = pExState->frame.DS;
}
if ( fUnicode ) {
p = q = (ushort *)malloc( *buflen * sizeof(ushort) );
if ( !p ) {
**buf = 0;
return;
}
count = GetDebuggeeBytes (addr, *buflen * sizeof(ushort), p, T_WCHAR );
for (; *q != 0 && count > 0 && *buflen > 0; ) {
len = wctomb( *buf, *q++ );
if ( len == -1 ) {
break;
}
*buf += len;
*buflen -= len;
count -= sizeof( ushort );
}
free(p);
} else {
count = GetDebuggeeBytes (addr, *buflen - 2, *buf, T_RCHAR);
for (; (**buf != 0) && (count > 0); (*buf)++, count--) {
(*buflen)--;
}
}
**buf = '\"';
(*buf)++;
(*buflen)--;
**buf = 0;
(*buf)++;
(*buflen)--;
}
LOCAL char FAR *NEAR PASCAL FormatVirtual (char FAR *pc, CV_typ_t type, peval_t pv,
PEEHSTR phStr)
{
char save;
char FAR *pEnd;
char FAR *bufsave;
char FAR *buf;
uint buflen;
PHDR_TYPE pHdr;
char FAR *pName;
if ((*phStr = MHMemAllocate (TYPESTRMAX + sizeof (HDR_TYPE))) == 0) {
// unable to allocate memory for type string. at least print name
return (pc);
}
bufsave = (char FAR *)MHMemLock (*phStr);
_fmemset (bufsave, 0, TYPESTRMAX + sizeof (HDR_TYPE));
buflen = TYPESTRMAX - 1;
pHdr = (PHDR_TYPE)bufsave;
buf = bufsave + sizeof (HDR_TYPE);
pCxt = &pExState->cxt;
bnCxt = 0;
pEnd = pc + *pc + 1;
save = *pEnd;
*pEnd = 0;
pName = pc + 1;
SetNodeType (pv, type);
FormatType (pv, &buf, &buflen, &pName, 1L, pHdr);
*pEnd = save;
*(bufsave + sizeof (HDR_TYPE) - 1) = TYPESTRMAX - 1 - buflen;
return (bufsave + sizeof (HDR_TYPE) - 1);
}
BOOL UseUnicode (
peval_t pv
)
{
BOOL Ok = FALSE;
TYPPTR TypPtr;
lfBArray *LeafArray;
if (CV_IS_PRIMITIVE(EVAL_TYP(pv))) {
Ok = BaseIs16Bit( EVAL_TYP(pv) );
} else {
TypPtr = MHOmfLock( (HDEP)EVAL_TYPDEF(pv) );
LeafArray = (lfBArray *)&(TypPtr->leaf);
if ( LeafArray->leaf == LF_ARRAY ||
LeafArray->leaf == LF_BARRAY) {
Ok = BaseIs16Bit( LeafArray->utype );
}
MHOmfUnLock( (HDEP)EVAL_TYPDEF(pv) );
}
return Ok;
}
BOOL BaseIs16Bit (
CV_typ_t utype
)
{
switch( utype ) {
case T_WCHAR:
case T_PWCHAR:
case T_PFWCHAR:
case T_PHWCHAR:
case T_32PWCHAR:
case T_32PFWCHAR:
case T_SHORT:
case T_USHORT:
case T_PSHORT:
case T_PUSHORT:
case T_PFSHORT:
case T_PFUSHORT:
case T_PHSHORT:
case T_PHUSHORT:
case T_32PSHORT:
case T_32PUSHORT:
case T_32PFSHORT:
case T_32PFUSHORT:
return TRUE;
default:
return FALSE;
}
}