/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 ]; } }