mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|