windows-nt/Source/XPSP1/NT/com/rpc/midl/analysis/analysis.cxx

609 lines
13 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 ];
}
}