mirror of https://github.com/lianthony/NT4.0
1890 lines
52 KiB
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( ®, 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;
|
|
}
|
|
}
|