609 lines
13 KiB
C++
609 lines
13 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
anainfo.cxx
|
|
|
|
Abstract:
|
|
|
|
Implementation of the analysis classes.
|
|
|
|
Notes:
|
|
|
|
|
|
Author:
|
|
|
|
|
|
History:
|
|
|
|
VibhasC Jul-25-1993 Created.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/****************************************************************************
|
|
* include files
|
|
***************************************************************************/
|
|
#include "allana.hxx"
|
|
#pragma hdrstop
|
|
|
|
/****************************************************************************
|
|
* local definitions
|
|
***************************************************************************/
|
|
/****************************************************************************
|
|
* local data
|
|
***************************************************************************/
|
|
|
|
short TempResourceCounter = 0;
|
|
|
|
/****************************************************************************
|
|
* externs
|
|
***************************************************************************/
|
|
#ifdef MIDL_INTERNAL
|
|
|
|
void
|
|
ANALYSIS_INFO::Dump(
|
|
ANAPHASE A )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Debug dump.
|
|
|
|
Arguments:
|
|
|
|
A - The analysis phase to be dumped.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
FILE * hFile = stdout;
|
|
char * pTemp;
|
|
OPTIM_OPTION Options = OPTIMIZE_NONE;
|
|
|
|
static char Buffer[ 100 ];
|
|
|
|
pTemp = ( A == ANA_PHASE_CLIENT_MARSHALL ) ? "Client Marshall" :
|
|
( A == ANA_PHASE_CLIENT_UNMARSHALL ) ? "Client UnMarshall":
|
|
( A == ANA_PHASE_SERVER_UNMARSHALL ) ? "Server UnMarshall":
|
|
"Server Marshal";
|
|
|
|
sprintf( Buffer, "\nDump of phase :%s\n", pTemp );
|
|
fprintf( hFile, "%s", Buffer );
|
|
|
|
//
|
|
// dump optimisation options.
|
|
//
|
|
|
|
fprintf( hFile, "\nOptimize Options: ( " );
|
|
if( Options )
|
|
{
|
|
if( Options & OPTIMIZE_SIZE )
|
|
{
|
|
fprintf( hFile, "Size " );
|
|
Options &= ~OPTIMIZE_SIZE;
|
|
}
|
|
|
|
if( Options & OPTIMIZE_INTERPRETER )
|
|
{
|
|
fprintf( hFile, "Interpret " );
|
|
Options &= ~OPTIMIZE_INTERPRETER;
|
|
}
|
|
|
|
if( Options & OPTIMIZE_NO_REF_CHECK )
|
|
{
|
|
fprintf( hFile, "NoRef " );
|
|
Options &= ~OPTIMIZE_NO_REF_CHECK;
|
|
}
|
|
|
|
if( Options & OPTIMIZE_NO_CTXT_CHECK )
|
|
{
|
|
fprintf( hFile, "NoCtxt " );
|
|
Options &= ~OPTIMIZE_NO_CTXT_CHECK;
|
|
}
|
|
|
|
if( Options & OPTIMIZE_NO_GEN_HDL_CHECK )
|
|
{
|
|
fprintf( hFile, "NoGenHdl " );
|
|
Options &= ~OPTIMIZE_NO_GEN_HDL_CHECK;
|
|
}
|
|
}
|
|
else
|
|
fprintf( hFile, "default( speed )" );
|
|
|
|
fprintf( hFile, " )" );
|
|
|
|
//
|
|
// all done.
|
|
//
|
|
|
|
fprintf( hFile, "\n" );
|
|
}
|
|
#endif // MIDL_INTERNAL
|
|
|
|
|
|
void
|
|
ANALYSIS_INFO::Reset()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
The Master clear or reset.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
NA.
|
|
|
|
Notes:
|
|
|
|
Create an alignment state machine instance.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
|
|
//
|
|
// Initialize the miscellaneous properties.
|
|
//
|
|
|
|
SetMiscProperties( DEFAULT_MISC_PROPERTIES );
|
|
|
|
//
|
|
// Set the default optimization options.
|
|
//
|
|
|
|
SetOptimOption( DEFAULT_OPTIM_OPTIONS );
|
|
|
|
ResetArrayContext();
|
|
|
|
SetRpcSSAllocateRecommended( 0 );
|
|
}
|
|
|
|
ANALYSIS_INFO::ANALYSIS_INFO()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Constructor for analysis information manager block.
|
|
|
|
Arguments:
|
|
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
|
|
NA.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
|
|
//
|
|
// Initialize and so on.
|
|
//
|
|
|
|
Reset();
|
|
|
|
//
|
|
// Set the analysis phase to be client side marshall by default.
|
|
//
|
|
|
|
SetCurrentPhase( ANA_PHASE_CLIENT_MARSHALL );
|
|
|
|
//
|
|
// Create a resource dictionary data base.
|
|
//
|
|
|
|
pResDictDatabase = new RESOURCE_DICT_DATABASE();
|
|
|
|
OptimOptions = OPTIMIZE_NONE;
|
|
|
|
SetLastPlaceholderClass(0);
|
|
|
|
fRpcSSSwitchSet = 0;
|
|
|
|
}
|
|
|
|
RESOURCE *
|
|
ANALYSIS_INFO::DoAddResource(
|
|
RESOURCE_DICT * pResDict,
|
|
PNAME pName,
|
|
node_skl * pType )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Add a resource to a dictionary.
|
|
|
|
Arguments:
|
|
|
|
pResDict - A pointer to the resource dictionary.
|
|
pName - The resource name.
|
|
pType - The type of the resource.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
If the type of the resource does not indicate a param node, assume it
|
|
is an ID node and create an id node for it.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
RESOURCE * pRes;
|
|
|
|
if( (pRes = pResDict->Search( pName )) == 0 )
|
|
{
|
|
pRes = pResDict->Insert( pName, pType );
|
|
}
|
|
|
|
return pRes;
|
|
}
|
|
|
|
RESOURCE *
|
|
ANALYSIS_INFO::AddStandardResource(
|
|
STANDARD_RES_ID ResID )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Add a standard resource to the appropriate dictionary.
|
|
|
|
Arguments:
|
|
|
|
ResID - The standard resource ID.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
Depending upon the resource in question, locate the correct dictionary
|
|
to insert into, generate the type and insert in the dictionary.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
RESOURCE_DICT * pResDict = 0;
|
|
PNAME pName = 0;
|
|
RESOURCE * pResource;
|
|
node_id * pType;
|
|
PNAME pTName = 0;
|
|
|
|
static struct
|
|
{
|
|
char * pName;
|
|
char * pTypeName;
|
|
} LocalResIDToResName[] =
|
|
{
|
|
{ RPC_MESSAGE_VAR_NAME, RPC_MESSAGE_TYPE_NAME }
|
|
,{ STUB_MESSAGE_VAR_NAME, STUB_MESSAGE_TYPE_NAME }
|
|
,{ STUB_DESC_STRUCT_VAR_NAME, STUB_DESC_STRUCT_TYPE_NAME }
|
|
,{ BUFFER_POINTER_VAR_NAME, BUFFER_POINTER_TYPE_NAME }
|
|
,{ RPC_STATUS_VAR_NAME, RPC_STATUS_TYPE_NAME }
|
|
,{ LENGTH_VAR_NAME, LENGTH_VAR_TYPE_NAME }
|
|
,{ BH_LOCAL_VAR_NAME, BH_LOCAL_VAR_TYPE_NAME }
|
|
,{ PXMIT_VAR_NAME, PXMIT_VAR_TYPE_NAME }
|
|
};
|
|
|
|
static struct
|
|
{
|
|
char * pName;
|
|
char * pTypeName;
|
|
}ParamResIDToResName[] =
|
|
{
|
|
{ PRPC_MESSAGE_VAR_NAME, PRPC_MESSAGE_TYPE_NAME }
|
|
};
|
|
|
|
static struct
|
|
{
|
|
char * pName;
|
|
char * pTypeName;
|
|
} GlobalResIDToResName[] =
|
|
{
|
|
{ AUTO_BH_VAR_NAME, AUTO_BH_TYPE_NAME }
|
|
};
|
|
|
|
if( IS_STANDARD_LOCAL_RESOURCE( ResID ) )
|
|
{
|
|
pResDict= pResDictDatabase->GetLocalResourceDict();
|
|
pName = LocalResIDToResName[ ResID - ST_LOCAL_RESOURCE_START ].pName;
|
|
pTName = LocalResIDToResName[ ResID - ST_LOCAL_RESOURCE_START ].pTypeName;
|
|
}
|
|
else if( IS_STANDARD_PARAM_RESOURCE( ResID ) )
|
|
{
|
|
pResDict= pResDictDatabase->GetParamResourceDict();
|
|
pName = ParamResIDToResName[ ResID - ST_PARAM_RESOURCE_START ].pName;
|
|
pTName = ParamResIDToResName[ ResID - ST_PARAM_RESOURCE_START ].pTypeName;
|
|
}
|
|
else if( IS_STANDARD_GLOBAL_RESOURCE( ResID ) )
|
|
{
|
|
pResDict= pResDictDatabase->GetGlobalResourceDict();
|
|
pName = GlobalResIDToResName[ ResID - ST_GLOBAL_RESOURCE_START ].pName;
|
|
pTName = GlobalResIDToResName[ ResID - ST_GLOBAL_RESOURCE_START ].pTypeName;
|
|
}
|
|
else
|
|
{
|
|
MIDL_ASSERT( FALSE );
|
|
}
|
|
|
|
if( (pResource = pResDict->Search( pName )) == 0 )
|
|
{
|
|
pType = new node_id( pName );
|
|
pType->SetBasicType( new node_def( pTName ) );
|
|
//gaj pType->SetEdgeType( EDGE_USE );
|
|
pType->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
pResource = pResDict->Insert( pName, (node_skl *)pType );
|
|
}
|
|
|
|
return pResource;
|
|
}
|
|
|
|
PNAME
|
|
ANALYSIS_INFO::GenTempResourceName(
|
|
char * pPrefix )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate the name for a temporary resource.
|
|
|
|
Arguments:
|
|
|
|
pPrefix - A null terminated prefix string. If this is null, nothing is
|
|
added.
|
|
|
|
Return Value:
|
|
|
|
A freshly allocated resource name string.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
char TempBuffer[ 30 ];
|
|
|
|
sprintf( TempBuffer,
|
|
"_%sM%d",
|
|
pPrefix ? pPrefix : "",
|
|
GetTempResourceCounter()
|
|
);
|
|
|
|
BumpTempResourceCounter();
|
|
|
|
PNAME pName = (PNAME) new char [ strlen(TempBuffer) + 1 ];
|
|
strcpy( pName, TempBuffer );
|
|
return pName;
|
|
}
|
|
|
|
PNAME
|
|
ANALYSIS_INFO::GenTRNameOffLastParam(
|
|
char * pPrefix )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Generate the name for a temporary resource.
|
|
|
|
Arguments:
|
|
|
|
pPrefix - A null terminated prefix string. If this is null, nothing is
|
|
added.
|
|
|
|
Return Value:
|
|
|
|
A freshly allocated resource name string.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
char TempBuffer[ 30 ];
|
|
|
|
sprintf( TempBuffer,
|
|
"_%sM",
|
|
pPrefix ? pPrefix : ""
|
|
);
|
|
|
|
PNAME pName = (PNAME) new char [ strlen(TempBuffer) + 1 ];
|
|
strcpy( pName, TempBuffer );
|
|
return pName;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Utility functions.
|
|
****************************************************************************/
|
|
//
|
|
// This array defines the action taken when memory has been allocated for
|
|
// a type.
|
|
//
|
|
|
|
|
|
static U_ACTION S_WhenMemoryAllocated[ 2 ] =
|
|
{
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_NONE, // No Allocation needed.
|
|
RA_NONE, // No reference action.
|
|
UA_COPY_INTO_TYPE, // Copy from source to type ( resource )
|
|
PR_TYPE // Presented expression is the type / resource
|
|
}
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_NONE, // No allocation needed.
|
|
RA_NONE, // No action for reference.
|
|
UA_COPY_INTO_TYPE, // No Unmarshalling action.
|
|
PR_TYPE // Presented expression is deref of src.
|
|
}
|
|
|
|
};
|
|
|
|
//
|
|
// This array defines the action taken when a reference has been allocated for
|
|
// a type.
|
|
//
|
|
|
|
static U_ACTION S_WhenRefAllocated[ 2 ] =
|
|
{
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_STACK, // Explicit allocation needed.
|
|
RA_PATCH_TO_ADDR_OF_TYPE,// Patch ref to address of type.
|
|
UA_COPY_INTO_TYPE, // Copy from source to type.
|
|
PR_NONE // Presented expression tbd by caller.
|
|
}
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_NONE, // No allocation needed.
|
|
RA_PATCH_INTO_BUFFER, // Patch ref to position in buffer.
|
|
UA_NONE, // No Unmarshalling action.
|
|
PR_NONE // Presented expression is deref of src.
|
|
}
|
|
|
|
};
|
|
|
|
static U_ACTION S_WhenMemoryAndRefAllocated[ 2 ] =
|
|
{
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_ERROR, // Explicit allocation needed.
|
|
RA_ERROR, // Patch ref to address of type.
|
|
UA_ERROR, // Copy from source to type.
|
|
PR_ERROR // Presented expression tbd by caller.
|
|
}
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_ERROR, // No allocation needed.
|
|
RA_ERROR, // Patch ref to position in buffer.
|
|
UA_ERROR, // No Unmarshalling action.
|
|
PR_ERROR // Presented expression is deref of src.
|
|
}
|
|
};
|
|
|
|
static U_ACTION C_WhenMemoryAllocated[ 2 ] =
|
|
{
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_EXISTS, // No Allocation needed.
|
|
RA_NONE, // No reference action.
|
|
UA_COPY_INTO_DEREF_OF_REF, // Copy from source to type ( resource )
|
|
PR_NONE // Presented expression is the type / resource
|
|
}
|
|
#if 0
|
|
{ AN_NONE, // No Allocation needed.
|
|
RA_NONE, // No reference action.
|
|
UA_COPY_INTO_TYPE, // Copy from source to type ( resource )
|
|
PR_NONE // Presented expression is the type / resource
|
|
}
|
|
#endif // 0
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_ERROR, // This situation must never happen on client
|
|
RA_ERROR,
|
|
UA_ERROR,
|
|
PR_ERROR
|
|
}
|
|
|
|
};
|
|
|
|
//
|
|
// This array defines the action taken when a reference has been allocated for
|
|
// a type.
|
|
//
|
|
|
|
static U_ACTION C_WhenRefAllocated[ 2 ] =
|
|
{
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_NONE, // Explicit allocation needed.
|
|
RA_NONE, // Patch ref to address of type.
|
|
UA_COPY_INTO_DEREF_OF_REF,// Copy from source to type.
|
|
PR_NONE // Presented expression tbd by caller.
|
|
}
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_ERROR, // Must never happen on client
|
|
RA_ERROR,
|
|
UA_ERROR,
|
|
PR_ERROR
|
|
}
|
|
|
|
};
|
|
|
|
static U_ACTION C_WhenMemoryAndRefAllocated[ 2 ] =
|
|
{
|
|
|
|
// Buffer re-use is not possible.
|
|
|
|
{ AN_EXISTS, // No Allocation needed.
|
|
RA_NONE, // No reference action.
|
|
UA_COPY_INTO_DEREF_OF_REF,// Copy from source to type ( resource )
|
|
PR_NONE // Presented expression is the type / resource
|
|
}
|
|
|
|
// When Buffer reuse is possible.
|
|
|
|
,{
|
|
AN_ERROR, // Must never happen on client
|
|
RA_ERROR,
|
|
UA_ERROR,
|
|
PR_ERROR
|
|
}
|
|
|
|
};
|
|
|
|
U_ACTION
|
|
CG_NDR::RecommendUAction(
|
|
SIDE Side,
|
|
BOOL fMemoryAllocated,
|
|
BOOL fRefAllocated,
|
|
BOOL fBufferReUsePossible,
|
|
UAFLAGS )
|
|
{
|
|
BOOL fMemoryAndRefAllocated = (fMemoryAllocated && fRefAllocated);
|
|
|
|
|
|
if( Side == C_SIDE )
|
|
{
|
|
if( fMemoryAndRefAllocated )
|
|
return C_WhenMemoryAndRefAllocated[ fBufferReUsePossible ];
|
|
else if( fMemoryAllocated )
|
|
return C_WhenMemoryAllocated[ fBufferReUsePossible ];
|
|
else
|
|
return C_WhenRefAllocated[ fBufferReUsePossible ];
|
|
}
|
|
else
|
|
{
|
|
if( fMemoryAndRefAllocated )
|
|
{
|
|
MIDL_ASSERT( FALSE &&
|
|
!"Server analysis should never have mem and ref allocated");
|
|
return S_WhenRefAllocated[ fBufferReUsePossible ];
|
|
}
|
|
else if( fMemoryAllocated )
|
|
return S_WhenMemoryAllocated[ fBufferReUsePossible ];
|
|
else
|
|
return S_WhenRefAllocated[ fBufferReUsePossible ];
|
|
}
|
|
}
|