Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1812 lines
49 KiB

/*** debapi.c - api interface to expression evaluator
*
* API interface between C and C++ expression evaluator and debugger
* kernel.
*/
LOCAL EESTATUS ParseBind (EEHSTR, HTM, PHTM, uint *, uint, SHFLAG, uint);
// defines for version string
#if defined (C_ONLY)
#define LANG "Ansi C "
#define LANGID "C"
#else
#define LANG "C/C++ "
#define LANGID "CPP"
#endif
#if (rmm <= 9)
#define rmmpad "0"
#else
#define rmmpad
#endif
#if (rup <= 9)
#define ruppad "00"
#elif (rup <= 99)
#define ruppad "0"
#else
#define ruppad
#endif
//#define SZVER1(a,b,c) #a "." rmmpad #b "." ruppad #c
#define SZVER1(a,b,c) ".."
#define SZVER2(a,b,c) SZVER1(a, b, c)
#define SZVER SZVER2(rmj,rmm,rup)
#define OPSYS "Windows NT"
// version string.
char EETitle[] = LANGID;
char EECopyright[] = LANG "expression evaluator for " OPSYS "version " SZVER
"\nCopyright(c) 1992 Microsoft Corporation\n"
"\0" __DATE__ " " __TIME__ "\xE0\xEA""01";
PCVF pCVF; // callback routine map
PCRF pCRF;
bool_t FInEvaluate = FALSE; // Catch Re-entrancy problems
bool_t FNtsdEvalType = FALSE;
uchar Evaluating = FALSE; // set not in evaluation phase
uchar BindingBP = FALSE; // true if binding a breakpoint expression
pexstate_t pExState = NULL; // address of locked expression state structure
pstree_t pTree = NULL; // address of locked syntax or evaluation tree
bnode_t bArgList = 0; // based pointer to argument list
HDEP hEStack = 0; // handle of evaluation stack if not zero
pelem_t pEStack = NULL; // address of locked evaluation stack
belem_t StackLen; // length of evaluation stack buffer
belem_t StackMax; // maximum length reached by evaluation stack
belem_t StackOffset; // offset in stack to next element
belem_t StackCkPoint; // checkpointed evaluation stack offset
peval_t ST; // pointer to evaluation stack top
peval_t STP; // pointer to evaluation stack previous
PCXT pCxt = NULL; // pointer to current cxt for bind
bnode_t bnCxt = 0; // based pointer to node containing {...} context
char *pExStr = NULL; // pointer to expression string
CV_typ_t ClassExp = 0; // current explicit class
CV_typ_t ClassImp = 0; // implicit class (set if current context is method)
long ClassThisAdjust = 0;// cmplicit class this adjustor
char *vfuncptr = "\x07""__vfptr";
char *vbaseptr = "\x07""__vbptr";
HTM *pTMList; // pointer to breakpoint return list
PTML pTMLbp; // global pointer to TML for breakpoint
HDEP hBPatch = 0; // handle to back patch data during BP bind
ushort iBPatch; // index into pTMLbp for backpatch data
bool_t GettingChild = FALSE; // true if in EEGetChildTM
BOOL fAutoClassCast;
char Suffix = '\0'; // Suffix for symbol search.
// global handle to the CXT list buffer
HCXTL hCxtl = 0; // handle for context list buffer during GetCXTL
PCXTL pCxtl = NULL; // pointer to context list buffer during GetCXTL
ushort mCxtl = 0; // maximum number of elements in context list
PCXT pBindBPCxt = NULL; // pointer to Bp Binding context
extern EESTATUS EEFormatMemory();
extern EESTATUS EEUnformatMemory();
extern EESTATUS EEFormatEnumerate();
#ifdef DEBUGVER
DEBUG_VERSION('E','E',"Expression Evaluator")
#else
RELEASE_VERSION('E','E',"Expression Evaluator")
#endif
DBGVERSIONCHECK()
void EEInitializeExpr (PCI pCVInfo, PEI pExprinfo)
{
static EXF EXF = {
EEFreeStr,
EEGetError,
EEParse,
EEBindTM,
EEvaluateTM,
EEGetExprFromTM,
EEGetValueFromTM,
EEGetNameFromTM,
EEGetTypeFromTM,
EEFormatCXTFromPCXT,
EEFreeTM,
EEParseBP,
EEFreeTML,
EEInfoFromTM,
EEFreeTI,
EEGetCXTLFromTM,
EEFreeCXTL,
EEAssignTMToTM,
EEIsExpandable,
EEAreTypesEqual,
EEcChildrenTM,
EEGetChildTM,
EEDereferenceTM,
EEcParamTM,
EEGetParmTM,
EEGetTMFromHSYM,
EEFormatAddress,
EEGetHSYMList,
EEFreeHSYMList,
EEFormatAddr,
EEUnFormatAddr,
NULL,
NULL,
NULL,
EEFormatMemory,
EEUnformatMemory,
EEFormatEnumerate,
EEGetHtypeFromTM,
EESetSuffix
};
// assign the callback routines
pCVF = pCVInfo->pStructCVAPI;
pCRF = pCVInfo->pStructCRuntime;
pExprinfo->Version = 1;
pExprinfo->pStructExprAPI = &EXF;
pExprinfo->Language = 0;
pExprinfo->IdCharacters = "_$";
pExprinfo->EETitle = EETitle;
#if defined (C_ONLY)
pExprinfo->EESuffixes = ".c.h";
#else
pExprinfo->EESuffixes = ".cpp.cxx.c.hpp.hxx.h";
#endif
pExprinfo->Assign = "\x001""=";
}
/** Set suffix
*/
void EESetSuffix (char c)
{
Suffix = c;
}
/** EEAreTypesEqual - are TM types equal
*
* flag = EEAreTypesEqual (phTMLeft, phTMRight);
*
* Entry phTMLeft = pointer to handle of left TM
* phTMRight = pointer to handle of right TM
*
* Exit none
*
* Returns TRUE if TMs have identical types
*/
SHFLAG EEAreTypesEqual (PHTM phTMLeft, PHTM phTMRight)
{
return (AreTypesEqual (*phTMLeft, *phTMRight));
}
/** EEGetHtypeFromTM - Get a HTYPE from a TM
*
* hType = EEGetHtypeFromTM ( phTM );
*
* Entry phTM = pointer to handle of TM
*
* Exit none
*
* Returns The HTYPE of the TM result or 0
*/
HTYPE EEGetHtypeFromTM(PHTM phTM )
{
return ( GetHtypeFromTM(*phTM) );
}
/** EEAssignTMToTM - assign TMRight to TMLeft
*
* No longer used
*
* Exit none
*
* Returns EECATASTROPHIC
*/
EESTATUS EEAssignTMToTM (PHTM phTMLeft, PHTM phTMRight)
{
Unreferenced(phTMLeft);
Unreferenced(phTMRight);
return(EECATASTROPHIC);
}
/** EEBindTM - bind syntax tree to a context
*
* ushort EEBindTM (phExState, pCXT, fForceBind, fEnableProlog);
*
* Entry phExState = pointer to expression state structure
* pCXT = pointer to context packet
* fForceBind = TRUE if rebind required.
* fForceBind = FALSE if rebind decision left to expression evaluator.
* fEnableProlog = FALSE if function scoped symbols only after prolog
* fEnableProlog = TRUE if function scoped symbols during prolog
*
* Exit tree rebound if necessary
*
* Returns EENOERROR if no error in bind
* EECATASTROPHIC if null TM pointer
* EENOMEMORY if unable to get memory for buffers
* EEGENERAL if error (pExState->err_num is error)
*/
EESTATUS
EEBindTM(
PHTM phTM,
PCXT pcxt,
SHFLAG fForceBind,
SHFLAG fEnableProlog,
BOOL fSpecialBind
)
{
uint flags = 0;
EESTATUS status;
DASSERT( !FInEvaluate )
if ( FInEvaluate ) return(EECATASTROPHIC);
FInEvaluate = TRUE;
// bind without suppressing overloaded operators
if (fForceBind == TRUE) {
flags |= BIND_fForceBind;
}
if (fEnableProlog == TRUE) {
flags |= BIND_fEnableProlog;
}
/*
* Insure that the address in the context field is really in
* the correct format for the symbol handler
*/
if (!ADDR_IS_LI(pcxt->addr)) {
SHUnFixupAddr(&pcxt->addr);
}
FNtsdEvalType = fSpecialBind;
status = DoBind (phTM, pcxt, flags);
FInEvaluate = FALSE;
return ( status );
}
/** EEcChildren - return number of children for the TM
*
* void EEcChildrenTM (phTM, pcChildren)
*
* Entry phTM = pointer to handle of TM
* pcChildren = pointer to location to store count
*
* Exit *pcChildren = number of children for TM
*
* Returns EENOERROR if no error
* non-zero if error
*/
EESTATUS EEcChildrenTM (PHTM phTM, long *pcChildren, PSHFLAG pVar)
{
return (cChildrenTM (phTM, pcChildren, pVar));
}
/** EEcParamTM - return count of parameters for TM
*
* ushort EEcParamTM (phTM, pcParam, pVarArg)
*
* Entry phTM = pointer to TM
* pcParam = pointer return count
* pVarArg = pointer to vararg flags
*
* Exit *pcParam = count of number of parameters
* *pVarArgs = TRUE if function has varargs
*
* Returns EECATASTROPHIC if fatal error
* EENOERROR if no error
*/
EESTATUS EEcParamTM (PHTM phTM, ushort *pcParam, PSHFLAG pVarArg)
{
return (cParamTM (*phTM, pcParam, pVarArg));
}
/** EEDereferenceTM - generate TM from pointer to data TM
*
* ushort EEDereferenceTM (phTMIn, phTMOut, pEnd)
*
* Entry phTMIn = pointer to handle to TM to dereference
* phTMOut = pointer to handle to dereferencing TM
* pEnd = pointer to int to receive index of char that ended parse
* fCase = case sensitivity (TRUE is case sensitive)
*
* Exit *phTMOut = TM referencing pointer data
* *pEnd = index of character that terminated parse
*
* Returns EECATASTROPHIC if fatal error
* EEGENERAL if TM not dereferencable
* EENOERROR if TM generated
*/
EESTATUS EEDereferenceTM (PHTM phTMIn, PHTM phTMOut,
uint *pEnd, SHFLAG fCase)
{
register EESTATUS retval;
EEHSTR hDStr = 0;
if ((retval = DereferenceTM (*phTMIn, &hDStr)) == EENOERROR) {
// bind with prolog disabled and with operloaded operators suppressed
if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
BIND_fSupOvlOps | BIND_fSupBase, fCase, 10)) == EENOERROR) {
// the result of dereferencing a pointer does not have a name
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTMOut);
pExState->state.noname = TRUE;
pExState->state.childtm = TRUE;
MHMemUnLock (*phTMOut);
pExState = NULL;
}
}
return (retval);
}
/** EEvaluateTM - evaluate syntax tree
*
* ushort EEvaluateTM (phExState, pFrame, style);
*
* Entry phExState = pointer to expression state structure
* pFrame = pointer to context frame
* style = EEHORIZONTAL for horizontal (command) display
* EEVERTICAL for vertical (watch) display
* EEBPADDRESS for bp address (suppresses fcn evaluation)
*
* Exit abstract syntax tree evaluated with the saved
* context and current frame and the result node stored
* in the expression state structure
*
* Returns EENOERROR if no error in evaluation
* error number if error
*/
EESTATUS EEvaluateTM (PHTM phTM, PFRAME pFrame, EEDSP style)
{
EESTATUS status;
DASSERT( !FInEvaluate )
if ( FInEvaluate ) return(EECATASTROPHIC);
FInEvaluate = TRUE;
status = DoEval (phTM, pFrame, style);
FInEvaluate = FALSE;
return ( status );
}
/** EEFormatAddress - format address as an ASCII string
*
* EEFormatAddress (seg, offset, pbuf, flags)
*
* Entry Seg = segment portion of address
* Off = offset portion of address
* pbuf = pointer to buffer for formatted address
* (must be 20 bytes long)
* flags = flags controling formatting
* EEFMT_32 - 32-bit offset
* EEFMT_SEG - display segment
*
* Exit buf = formatted address
*
* Returns EENONE if no errors and EEGENERAL if buffer is not long enough
*/
EESTATUS EEFormatAddress (SHSEG Seg, UOFFSET Off, char *szAddr, uint cch, uint flags)
{
char buf[20];
char chx = (flags & EEFMT_REAL) ? '#' : ':';
if (flags & EEFMT_32) {
if (flags & EEFMT_SEG) {
if (flags & EEFMT_LOWER) {
sprintf (buf, "0x%04x%c0x%08x", Seg, chx, Off);
} else {
sprintf (buf, "0x%04X%c0x%08X", Seg, chx, Off);
}
} else {
if (flags & EEFMT_LOWER) {
sprintf (buf, "0x%08x", Off);
} else {
sprintf (buf, "0x%08X", Off);
}
}
} else {
sprintf (buf, "0x%04X%c0x%04X", Seg, chx, Off);
}
/*
* copy the zero terminated string from the buffer to the buffer
*/
if (strlen(buf)+1 >= cch) {
return EEGENERAL;
}
_fstrcpy (szAddr, buf);
return EENOERROR;
} /* EEFormatAddress() */
EESTATUS
EEFormatAddr(
LPADDR lpaddr,
char * lpch,
uint cch,
uint flags
)
/*++
Routine Description:
This routine takes an ADDR packet and formats it into an ANSI
string. The routine will check for the 32-bit flag in the addr
packet and use this to determine if it is a 32-bit or 16-bit offset.
Arguments:
lpaddr - Supplies the pointer to the address packet to format
lpch - Supplies the buffer to format the string into
cch - count of bytes in the lpch buffer
flags - flags controling the formatting
EEFMT_32 - override the 32-bit flag in the
addr packet and print as a 32-bit offset
EEFMT_SEG - if 32-bit then print segment as well.
Return Value:
EENOERROR - no errors occured
EEGENERAL - result does not fit in buffer
--*/
{
if (!ADDR_IS_FLAT(*lpaddr)) {
flags |= EEFMT_SEG;
}
if (ADDR_IS_OFF32(*lpaddr)) {
flags |= EEFMT_32;
}
if (ADDR_IS_REAL(*lpaddr)) {
flags |= EEFMT_REAL;
}
return EEFormatAddress( GetAddrSeg(*lpaddr), GetAddrOff(*lpaddr),
lpch, cch, flags );
} /* EEFormatAddr() */
EESTATUS
EEUnFormatAddr(
LPADDR lpaddr,
char * lpsz
)
/*++
Routine Description:
This routine takes an address string and converts it into an
ADDR packet. The assumption is that the address is in one of the
following formats:
XXXX:XXXX 16:16 address ( 9)
0xXXXX:0xXXXX 16:16 address (13)
XXXX:XXXXXXXX 16:32 address (13)
0xXXXX:0xXXXXXXXX 16:32 address (17)
0xXXXXXXXX 0:32 address (10)
XXXXXXXX 0:32 address ( 8)
Arguments:
lpaddr - Supplies the address packet to be filled in
lpsz - Supplies the string to be converted into an addr packet.
.
Return Value:
EENOERROR - no errors
EEGENERAL - unable to do unformatting
--*/
{
int i;
SEGMENT seg = 0;
OFFSET off = 0;
BOOL fReal = FALSE;
memset(lpaddr, 0, sizeof(*lpaddr));
if (lpsz == NULL) {
return EEGENERAL;
}
switch( strlen(lpsz) ) {
case 9:
for (i=0; i<9; i++) {
switch( i ) {
case 0:
case 1:
case 2:
case 3:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
seg = seg * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
seg = seg * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
seg = seg * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
case 4:
if (lpsz[i] == '#') {
ADDR_IS_REAL(*lpaddr) = TRUE;
} else if (lpsz[i] != ':') {
return EEGENERAL;
}
break;
case 5:
case 6:
case 7:
case 8:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
break;
case 13:
if (lpsz[1] == 'x') {
for (i=0; i<13; i++) {
switch( i ) {
case 0:
case 7:
if (lpsz[i] != '0') {
return EEGENERAL;
}
break;
case 1:
case 8:
if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
return EEGENERAL;
}
break;
case 2:
case 3:
case 4:
case 5:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
seg = seg * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
seg = seg * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
seg = seg * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
case 6:
if (lpsz[i] == '#') {
ADDR_IS_REAL(*lpaddr) = TRUE;
} else if (lpsz[i] != ':') {
return EEGENERAL;
}
break;
case 9:
case 10:
case 11:
case 12:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
} else {
for (i=0; i<13; i++) {
switch( i ) {
case 0:
case 1:
case 2:
case 3:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
seg = seg * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
seg = seg * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
seg = seg * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
case 4:
if (lpsz[i] == '#') {
fReal = TRUE;
} else if (lpsz[i] != ':') {
return EEGENERAL;
}
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
ADDR_IS_OFF32(*lpaddr) = TRUE;
ADDR_IS_FLAT(*lpaddr) = FALSE;
}
break;
case 17:
for (i=0; i<17; i++) {
switch( i ) {
case 0:
case 7:
if (lpsz[i] != '0') {
return EEGENERAL;
}
break;
case 1:
case 8:
if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
return EEGENERAL;
}
break;
case 2:
case 3:
case 4:
case 5:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
seg = seg * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
seg = seg * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
seg = seg * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
case 6:
if (lpsz[i] != ':') {
return EEGENERAL;
}
break;
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
ADDR_IS_OFF32(*lpaddr) = TRUE;
ADDR_IS_FLAT(*lpaddr) = TRUE;
break;
case 10:
for (i=0; i<10; i++) {
switch( i ) {
case 0:
if (lpsz[i] != '0') {
return EEGENERAL;
}
break;
case 1:
if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
return EEGENERAL;
}
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
break;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
ADDR_IS_OFF32(*lpaddr) = TRUE;
ADDR_IS_FLAT(*lpaddr) = TRUE;
break;
case 8:
for (i=0; i<8; i++) {
if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
off = off * 16 + lpsz[i] - '0';
} else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
off = off * 16 + lpsz[i] - 'a' + 10;
} else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
off = off * 16 + lpsz[i] - 'A' + 10;
} else {
return EEGENERAL;
}
}
SetAddrSeg(lpaddr, seg);
SetAddrOff(lpaddr, off);
ADDR_IS_OFF32(*lpaddr) = TRUE;
ADDR_IS_FLAT(*lpaddr) = TRUE;
break;
default:
return EEGENERAL;
}
return EENOERROR;
} /* EEUnFormatAddr() */
/** EEFormatCXTFromPCXT - format a context operator from a PCXT
*
* ushort EEFormatCXTFromPCXT (pCXT, phStr)
*
* Entry pCXT = pointer to CXT packet
* phStr = pointer for handle for formatted string buffer
*
* Exit *phStr = handle of formatted string buffer
* *phStr = 0 if buffer not allocated
*
* Returns EENOERROR if no error
* error code if error
*/
EESTATUS EEFormatCXTFromPCXT (PCXT pCXT, PEEHSTR phStr, BOOL fAbbreviated)
{
register ushort retval = EECATASTROPHIC;
DASSERT (pCXT != 0);
if (pCXT != 0) {
retval = FormatCXT (pCXT, phStr, fAbbreviated);
}
return (retval);
}
/** EEFreeCXTL - Free CXT list
*
* EEFreeCXTL (phCXTL)
*
* Entry phCXTL = pointer to the CXT list handle
*
* Exit *phCXTL = 0;
*
* Returns none
*/
void EEFreeCXTL (PHCXTL phCXTL)
{
DASSERT (phCXTL != NULL);
if (*phCXTL != 0) {
#ifdef DEBUGKERNEL
DASSERT (!MHIsMemLocked (*phCXTL));
while (MHIsMemLocked (*phCXTL)) {
MHMemUnLock (*phCXTL);
}
#endif
MHMemFree (*phCXTL);
*phCXTL = 0;
}
}
/** EEFreeHSYMList - Free HSYM list
*
* EEFreeCXTL (phSYML)
*
* Entry phSYML = pointer to the HSYM list handle
*
* Exit *phSYML = 0;
*
* Returns none
*/
void EEFreeHSYMList (HDEP *phSYML)
{
PHSL_HEAD pList;
DASSERT (phSYML != NULL);
if (*phSYML != 0) {
#ifdef DEBUGKERNEL
DASSERT (!MHIsMemLocked (*phSYML));
while (MHIsMemLocked (*phSYML)) {
MHMemUnLock (*phSYML);
}
#endif
// lock the buffer and free the restart buffer if necessary
pList = MHMemLock (*phSYML);
if (pList->restart != 0) {
#ifdef DEBUGKERNEL
DASSERT (!MHIsMemLocked (pList->restart));
while (MHIsMemLocked (pList->restart)) {
MHMemUnLock (pList->restart);
}
#endif
MHMemFree (pList->restart);
}
MHMemUnLock (*phSYML);
MHMemFree (*phSYML);
*phSYML = 0;
}
}
/** EEFreeStr - free string buffer memory
*
* ushort EEFreeStr (hszStr);
*
* Entry hszExpr = handle to string buffer
*
* Exit string buffer freed
*
* Returns none
*/
void EEFreeStr (EEHSTR hszStr)
{
if (hszStr != 0) {
#ifdef DEBUGKERNEL
DASSERT (!MHIsMemLocked (hszStr));
while (MHIsMemLocked (hszStr)) {
MHMemUnLock (hszStr);
}
#endif
MHMemFree (hszStr);
}
}
/** EEFreeTM - free expression state structure
*
* void EEFreeTM (phTM);
*
* Entry phTM = pointer to the handle for the expression state structure
*
* Exit expression state structure freed and the handle cleared
*
* Returns none.
*/
void EEFreeTM (PHTM phTM)
{
if (*phTM != 0) {
// DASSERT (!MHIsMemLocked (*phTM));
// lock the expression state structure and free the components
// every component must have no locks active
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTM);
if (pExState->hExStr != 0) {
// DASSERT (!MHIsMemLocked (pExState->hExStr));
MHMemFree (pExState->hExStr);
}
if (pExState->hCName != 0) {
// DASSERT (!MHIsMemLocked (pExState->hCName));
MHMemFree (pExState->hCName);
}
if (pExState->hSTree != 0) {
// DASSERT (!MHIsMemLocked (pExState->hSTree));
MHMemFree (pExState->hSTree);
}
if (pExState->hETree != 0) {
// DASSERT (!MHIsMemLocked (pExState->hETree));
MHMemFree (pExState->hETree);
}
MHMemUnLock (*phTM);
MHMemFree (*phTM);
*phTM = 0;
pExState = NULL;
}
}
/** EEFreeTI - free TM Info buffer
*
* void EEFreeTI (hTI);
*
* Entry hTI = handle to TI Info buffer
*
* Exit TI Info buffer freed
*
* Returns none
*/
void EEFreeTI (PHTI phTI)
{
if (*phTI != 0) {
#ifdef DEBUGKERNEL
DASSERT (!MHIsMemLocked (*phTI));
while (MHIsMemLocked (*phTI)) {
MHMemUnLock (*phTI);
}
#endif
MHMemFree (*phTI);
*phTI = 0;
}
}
/** EEFreeTML - free TM list
*
* void EEFreeTML (phTML);
*
* Entry phTML = pointer to the handle for the TM list
*
* Exit TM list freed and the handle cleared
*
* Returns none.
*/
void EEFreeTML (PTML pTML)
{
uint i;
ushort cTM = 0;
if (pTML != NULL) {
pTMList = (HTM *)MHMemLock (pTML->hTMList);
for (i = 0; i < pTML->cTMListMax; i++) {
if (pTMList[i] != 0) {
EEFreeTM (&pTMList[i]);
cTM++;
}
}
//
// DASSERT (cTM == pTML->cTMListAct);
MHMemUnLock (pTML->hTMList);
MHMemFree (pTML->hTMList);
pTML->hTMList = 0;
}
}
/** EEGetChildTM - get TM representing ith child
*
* status = EEGetChildTM (phTMParent, iChild, phTMChild)
*
* Entry phTMParent = pointer to handle of parent TM
* iChild = child to get TM for
* phTMChild = pointer to handle for returned child
* pEnd = pointer to int to receive index of char that ended parse
* fCase = case sensitivity (TRUE is case sensitive)
*
* Exit *phTMChild = handle of child TM if allocated
* *pEnd = index of character that terminated parse
*
* Returns EENOERROR if no error
* non-zero if error
*/
EESTATUS EEGetChildTM (PHTM phTMIn, long iChild, PHTM phTMOut,
uint *pEnd, SHFLAG fCase, uint radix )
{
register EESTATUS retval;
EEHSTR hDStr = 0;
EEHSTR hName = 0;
if ((retval = GetChildTM (*phTMIn, iChild, &hDStr, &hName, radix)) == EENOERROR) {
DASSERT (hDStr != 0);
// bind with prolog disabled and with operloaded operators suppressed
if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
BIND_fSupOvlOps | BIND_fSupBase, fCase, radix)) == EENOERROR) {
// the result of dereferencing a pointer does not have a name
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTMOut);
pExState->state.childtm = TRUE;
if ((pExState->hCName = hName) == 0) {
pExState->state.noname = TRUE;
}
MHMemUnLock (*phTMOut);
pExState = NULL;
}
}
else {
if (hName != 0) {
MHMemFree (hName);
}
}
return (retval);
}
/** EEGetCXTLFromTM - Gets a list of symbols and contexts for expression
*
* status = EEGetCXTLFromTM (phTM, phCXTL)
*
* Entry phTM = pointer to handle to expression state structure
* phCXTL = pointer to handle for CXT list buffer
*
* Exit *phCXTL = handle for CXT list buffer
*
* Returns EENOERROR if no error
* status code if error
*/
EESTATUS EEGetCXTLFromTM (PHTM phTM, PHCXTL phCXTL)
{
return (DoGetCXTL (phTM, phCXTL));
}
EESTATUS EEGetError (PHTM phTM, EESTATUS Status, PEEHSTR phError)
{
return (GetErrorText (phTM, Status, phError));
}
/** EEGetExprFromTM - get expression representing TM
*
* void EEGetExprFromTM (phTM, radix, phStr, pEnd)
*
* Entry phTM = pointer to handle of TM
* radix = radix to use for formatting
* phStr = pointer to handle for returned string
* pEnd = pointer to int to receive index of char that ended parse
*
* Exit *phStr = handle of formatted string if allocated
* *pEnd = index of character that terminated parse
*
* Returns EENOERROR if no error
* non-zero if error
*/
EESTATUS
EEGetExprFromTM (
PHTM phTM,
PEERADIX pRadix,
PEEHSTR phStr,
ushort * pEnd
)
{
return GetExpr(phTM, *pRadix, phStr, pEnd);
}
/** EEGetHSYMList - Get a list of handle to symbols
*
* status = EEGetHSYMList (phSYML, pCXT, mask, pRE, fEnableProlog)
*
* Entry phSYML = pointer to handle to symbol list
* pCXT = pointer to context
* mask = selection mask
* pRE = pointer to regular expression
* fEnableProlog = FALSE if function scoped symbols only after prolog
* fEnableProlog = TRUE if function scoped symbols during prolog
*
* Exit *phMem = handle for HSYM list buffer
*
* Returns EENOERROR if no error
* status code if error
*/
EESTATUS EEGetHSYMList (HDEP *phSYML, PCXT pCxt, ushort mask,
uchar * pRE, SHFLAG fEnableProlog)
{
return (GetHSYMList (phSYML, pCxt, mask, pRE, fEnableProlog));
}
/** EEGetNameFromTM - get name from TM
*
* ushort EEGetNameFromTM (phExState, phszName);
*
* Entry phExState = pointer to expression state structure
* phszName = pointer to handle for string buffer
*
* Exit phszName = handle for string buffer
*
* Returns 0 if no error in evaluation
* error number if error
*/
EESTATUS EEGetNameFromTM (PHTM phTM, PEEHSTR phszName)
{
return (GetSymName (phTM, phszName));
}
/** EEGetParamTM - get TM representing ith parameter
*
* status = EEGetParamTM (phTMParent, iChild, phTMChild)
*
* Entry phTMparent = pointer to handle of parent TM
* iParam = parameter to get TM for
* phTMParam = pointer to handle for returned parameter
* pEnd = pointer to int to receive index of char that ended parse
* fCase = case sensitivity (TRUE is case sensitive)
*
* Exit *phTMParam = handle of child TM if allocated
* *pEnd = index of character that terminated parse
*
*
* Returns EENOERROR if no error
* non-zero if error
*/
EESTATUS EEGetParmTM (PHTM phTMIn, uint iParam,
PHTM phTMOut, uint *pEnd, SHFLAG fCase, uint radix )
{
register EESTATUS retval;
EEHSTR hDStr = 0;
EEHSTR hName = 0;
if ((retval = GetChildTM (*phTMIn, iParam, &hDStr, &hName, radix)) == EENOERROR) {
DASSERT (hDStr != 0);
if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
BIND_fSupOvlOps | BIND_fSupBase | BIND_fEnableProlog, fCase, radix)) == EENOERROR) {
// the result of dereferencing a pointer does not have a name
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTMOut);
pExState->state.childtm = TRUE;
if ((pExState->hCName = hName) == 0) {
pExState->state.noname = TRUE;
}
MHMemUnLock (*phTMOut);
pExState = NULL;
}
}
else {
if (hName != 0) {
MHMemFree (hName);
}
}
return (retval);
}
/** EEGetTMFromHSYM - create bound TM from handle to symbol
*
* EESTATUS EEGetTMFromHSYM (hSym, pCxt, phTM, pEnd, fEnableProlog);
*
* Entry hSym = symbol handle
* pcxt = pointer to context
* phTM = pointer to the handle for the expression state structure
* pEnd = pointer to int to receive index of char that ended parse
* fEnableProlog = FALSE if function scoped symbols only after prolog
* fEnableProlog = TRUE if function scoped symbols during prolog
*
* Exit bound TM created
* *phTM = handle of TM buffer
* *pEnd = index of character that terminated parse
*
* Returns EECATASTROPHIC if fatal error
* 0 if no error
*/
EESTATUS EEGetTMFromHSYM (HSYM hSym, PCXT pcxt, PHTM phTM,
uint *pEnd, SHFLAG fEnableProlog)
{
register EESTATUS retval;
// allocate, lock and clear expression state structure
DASSERT (hSym != 0);
if (hSym == 0) {
return (EECATASTROPHIC);
}
if ((*phTM = MHMemAllocate (sizeof (struct exstate_t))) == 0) {
return (EECATASTROPHIC);
}
// lock expression state structure, clear and allocate components
DASSERT(pExState == NULL);
pExState = (pexstate_t)MHMemLock (*phTM);
_fmemset (pExState, 0, sizeof (exstate_t));
// allocate buffer for input string and copy
pExState->ExLen = sizeof (char) + sizeof (HSYM);
if ((pExState->hExStr = MHMemAllocate ((uint) pExState->ExLen + 1)) == 0) {
// clean up after error in allocation of input string buffer
MHMemUnLock (*phTM);
pExState = NULL;
EEFreeTM (phTM);
return (EECATASTROPHIC);
}
pExStr = MHMemLock (pExState->hExStr);
*pExStr++ = (unsigned char)0xff;
*((HSYM UNALIGNED *)(pExStr)) = hSym;
pExStr += sizeof (HSYM);
*pExStr = 0;
MHMemUnLock (pExState->hExStr);
pExStr = NULL;
MHMemUnLock (*phTM);
pExState = NULL;
if ((retval = DoParse (phTM, 10, TRUE, pEnd)) == EENOERROR) {
retval = EEBindTM (phTM, pcxt, TRUE, fEnableProlog, FALSE);
}
return (retval);
}
/** EEGetTypeFromTM - get type name from TM
*
* ushort EEGetTypeFromTM (phExState, hszName, phszType, select);
*
* Entry phExState = pointer to expression state structure
* hszName = handle to name to insert into string if non-null
* phszType = pointer to handle for type string buffer
* select = selection mask
*
* Exit phszType = handle for type string buffer
*
* Returns EENOERROR if no error in evaluation
* error number if error
*/
EESTATUS EEGetTypeFromTM (PHTM phTM, EEHSTR hszName,
PEEHSTR phszType, ulong select)
{
char *buf;
uint buflen = TYPESTRMAX - 1 + sizeof (HDR_TYPE);
char *pName;
PHDR_TYPE pHdr;
DASSERT (*phTM != 0);
if (*phTM == 0) {
return (EECATASTROPHIC);
}
if ((*phszType = MHMemAllocate (TYPESTRMAX + sizeof (HDR_TYPE))) == 0) {
// unable to allocate memory for type string
return (EECATASTROPHIC);
}
buf = (char *)MHMemLock (*phszType);
_fmemset (buf, 0, TYPESTRMAX + sizeof (HDR_TYPE));
pHdr = (PHDR_TYPE)buf;
buf += sizeof (HDR_TYPE);
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTM);
pCxt = &pExState->cxt;
bnCxt = 0;
if (hszName != 0) {
pName = MHMemLock (hszName);
}
else {
pName = NULL;
}
FormatType (&pExState->result, &buf, &buflen, &pName, select, pHdr);
if (hszName != 0) {
MHMemUnLock (hszName);
}
MHMemUnLock (*phTM);
pExState = NULL;
MHMemUnLock (*phszType);
return (EENOERROR);
}
/** EEGetValueFromTM - format result of evaluation
*
* ushort EEGetValueFromTM (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 EEGetValueFromTM (PHTM phTM, uint Radix, PEEFORMAT pFormat, PEEHSTR phszValue)
{
return (FormatNode (phTM, Radix, pFormat, phszValue));
}
/** EEInfoFromTM - return information about TM
*
* EESTATUS EEInfoFromTM (phTM, pReqInfo, phTMInfo);
*
* Entry phTM = pointer to the handle for the expression state structure
* reqInfo = info request structure
* phTMInfo = pointer to handle for request info data structure
*
* Exit *phTMInfo = handle of info structure
*
* Returns EECATASTROPHIC if fatal error
* 0 if no error
*/
EESTATUS EEInfoFromTM (PHTM phTM, PRI pReqInfo, PHTI phTMInfo)
{
return (InfoFromTM (phTM, pReqInfo, phTMInfo));
}
/** EEIsExpandable - does TM represent expandable item
*
* fSuccess EEIsExpandable (pHTM);
*
* Entry phTM = pointer to TM handle
*
* Exit none
*
* Returns FALSE if TM does not represent expandable item
* TRUE if TM represents expandable item
* bounded arrays, structs, unions, classes,
* pointers to compound items.
*
*/
EEPDTYP EEIsExpandable (PHTM phTM)
{
eval_t evalT;
peval_t pvT = &evalT;
register ushort retval = EENOTEXP;
// DASSERT (*phTM != 0);
if (*phTM != 0) {
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTM);
*pvT = pExState->result;
#if !defined (C_only)
if (EVAL_IS_REF (pvT)) {
RemoveIndir (pvT);
}
#endif
if (EVAL_STATE (pvT) == EV_type) {
if (EVAL_IS_FCN (pvT) || (
CV_IS_PRIMITIVE (EVAL_TYP (pvT)) && !EVAL_IS_PTR (pvT))) {
retval = EETYPENOTEXP;
}
else {
retval = EETYPE;
}
}
else if (EVAL_IS_ENUM (pvT)) {
retval = EENOTEXP;
}
else if (EVAL_IS_CLASS (pvT) ||
(EVAL_IS_ARRAY (pvT) && (PTR_ARRAYLEN (pvT) != 0))) {
retval = EEAGGREGATE;
}
else {
retval = IsExpandablePtr (pvT);
}
MHMemUnLock (*phTM);
pExState = NULL;
}
return (retval);
}
/** EEParse - parse expression string to abstract syntax tree
*
* ushort EEParse (szExpr, radix, fCase, phTM);
*
* Entry szExpr = pointer to expression string
* radix = default number radix for conversions
* fCase = case sensitive search if TRUE
* phTM = pointer to handle of expression state structure
* pEnd = pointer to int to receive index of char that ended parse
*
* Exit *phTM = handle of expression state structure if allocated
* *phTM = 0 if expression state structure could not be allocated
* *pEnd = index of character that terminated parse
*
* Returns EENOERROR if no error in parse
* EECATASTROPHIC if unable to initialize
* error number if error
*/
EESTATUS EEParse (char *szExpr, uint radix, SHFLAG fCase,
PHTM phTM, uint *pEnd)
{
EESTATUS status;
DASSERT( !FInEvaluate )
if ( FInEvaluate ) return(EECATASTROPHIC);
FInEvaluate = TRUE;
status = Parse( szExpr, radix, fCase, phTM, pEnd );
FInEvaluate = FALSE;
return ( status );
}
/** EEParseBP - parse breakpoint strings
*
* ushort EEParseBP (pExpr, radix, fCase, pcxf, pTML, select, End, fEnableProlog)
*
* Entry pExpr = pointer to breakpoint expression
* radix = default numeric radix
* fCase = case sensitive search if TRUE
* pcxt = pointer to initial context for evaluation
* pTML = pointer to TM list for results
* select = selection mask
* pEnd = pointer to int to receive index of char that ended parse
* fEnableProlog = FALSE if function scoped symbols only after prolog
* fEnableProlog = TRUE if function scoped symbols during prolog
*
* Exit *pTML = breakpoint information
* *pEnd = index of character that terminated parse
*
* Returns EENOERROR if no error in parse
* EECATASTROPHIC if unable to initialize
* EEGENERAL if error
*/
EESTATUS
EEParseBP (
char *pExpr,
uint radix,
SHFLAG fCase,
PCXF pCxf,
PTML pTML,
ulong select,
uint *pEnd,
SHFLAG fEnableProlog
)
{
register EESTATUS retval = EECATASTROPHIC;
ushort i;
Unreferenced(select);
if ((pCxf == NULL) || (pTML == NULL)) {
return (EECATASTROPHIC);
}
// note that pTML is not a pointer to a handle but rather a pointer to an
// actual structure allocated by the caller
pTMLbp = pTML;
_fmemset (pTMLbp, 0, sizeof (TML));
// allocate and initialize the initial list of TMs for overloaded
// entries. The TMList is an array of handles to exstate_t's.
// This list of handles will grow if it is filled.
if ((pTMLbp->hTMList = MHMemAllocate (TMLISTCNT * sizeof (HTM))) != 0) {
pTMList = (HTM *)MHMemLock (pTMLbp->hTMList);
_fmemset (pTMList, 0, TMLISTCNT * sizeof (HTM));
pTMLbp->cTMListMax = TMLISTCNT;
// parse the break point expression
retval = EEParse (pExpr, radix, fCase, &pTMList[0], pEnd);
pTMLbp->cTMListAct++;
// initialize the backpatch index into PTML. If this number remains
// 1 this means that an ambiguous breakpoint was not detected during
// the bind phase. As the binder finds ambiguous symbols, information
// sufficient to resolve each ambiguity is stored in allocated memory
// and the handle is saved in PTML by AmbToList
iBPatch = 1;
if (retval == EENOERROR) {
// bind the breakpoint expression if no parse error
BindingBP = TRUE;
if ((retval = EEBindTM (&pTMList[0], SHpCXTFrompCXF (pCxf),
TRUE, fEnableProlog, FALSE)) != EENOERROR) {
// The binder used the pTMList as a location to
// store information about backpatching. If there
// is an error in the bind, go down the list and
// free all backpatch structure handles.
for (i = 1; i < iBPatch; i++) {
// note that the back patch structure cannot contain
// handles to allocated memory that have to be freed up
// here. Otherwise, memory will be lost
MHMemFree (pTMList[i]);
pTMList[i] = 0;
}
}
else {
// the first form of the expression bound correctly.
// Go down the list, duplicate the expression state
// and rebind using the backpatch symbol information
// to resolve the ambiguous symbol. SearchSym uses the
// fact that hBPatch is non-zero to decide to handle the
// next ambiguous symbol.
for (i = 1; i < iBPatch; i++) {
hBPatch = pTMList[i];
pTMList[i] = 0;
if (DupTM (&pTMList[0], &pTMList[i]) == EENOERROR) {
pTMLbp->cTMListAct++;
EEBindTM (&pTMList[i], SHpCXTFrompCXF (pCxf),
TRUE, fEnableProlog, FALSE);
}
MHMemFree (hBPatch);
hBPatch = 0;
}
}
}
BindingBP = FALSE;
MHMemUnLock (pTMLbp->hTMList);
}
// return the result of parsing and binding the initial expression.
// There may have been errors binding subsequent ambiguous breakpoints.
// It is the caller's responsibility to handle the errors.
return (retval);
}
/** ParseBind - parse and bind generated expression
*
* flag = ParseBind (hExpr, hTMIn, phTMOut, pEnd, flags, fCase)
*
* Entry hExpr = handle of generated expression
* hTMIn = handle to TM dereferenced
* phTMOut = pointer to handle to dereferencing TM
* pEnd = pointer to int to receive index of char that ended parse
* flags.BIND_fForceBind = TRUE if bind to be forced
* flags.BIND_fForceBind = FALSE if rebind decision left to binder
* flags.BIND_fEnableProlog = TRUE if function scope searched during prolog
* flags.BIND_fEnableProlog = FALSE if function scope not searched during prolog
* flags.BIND_fSupOvlOps = FALSE if overloaded operator search enabled
* flags.BIND_fSupOvlOps = TRUE if overloaded operator search suppressed
* flags.BIND_fSupBase = FALSE if base searching is not suppressed
* flags.BIND_fSupBase = TRUE if base searching is suppressed
* fCase = case sensitivity (TRUE is case sensitive)
*
* Exit *phTMOut = TM referencing pointer data
* hExpr buffer freed
* *pEnd = index of character that terminated parse
*
* Returns EECATASTROPHIC if fatal error
* EEGENERAL if TM not dereferencable
* EENOERROR if TM generated
*/
LOCAL EESTATUS ParseBind (EEHSTR hExpr, HTM hTMIn,
PHTM phTMOut, uint *pEnd, uint flags, SHFLAG fCase, uint radix)
{
pexstate_t pTMIn;
register EESTATUS retval;
DASSERT( !FInEvaluate )
if ( FInEvaluate ) return(EECATASTROPHIC);
FInEvaluate = TRUE;
pTMIn = MHMemLock (hTMIn);
if ((retval = Parse (MHMemLock (hExpr), radix, fCase, phTMOut, pEnd)) == EENOERROR) {
retval = DoBind (phTMOut, &pTMIn->cxt, flags);
}
MHMemUnLock (hTMIn);
MHMemUnLock (hExpr);
MHMemFree (hExpr);
FInEvaluate = FALSE;
return (retval);
}
int eedllinit ( HANDLE hMod, ULONG Reason, char * lpch)
{
Unreferenced( hMod );
Unreferenced( Reason );
Unreferenced( lpch );
return TRUE;
}